summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/bus
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/bus')
-rw-r--r--src/devices/bus/a1bus/a1bus.cpp13
-rw-r--r--src/devices/bus/a1bus/a1bus.h12
-rw-r--r--src/devices/bus/a2bus/a2arcadebd.cpp4
-rw-r--r--src/devices/bus/a2bus/a2bus.cpp25
-rw-r--r--src/devices/bus/a2bus/a2bus.h11
-rw-r--r--src/devices/bus/a2bus/a2cffa.cpp16
-rw-r--r--src/devices/bus/a2bus/a2diskii.cpp161
-rw-r--r--src/devices/bus/a2bus/a2diskii.h76
-rw-r--r--src/devices/bus/a2bus/a2diskiing.cpp40
-rw-r--r--src/devices/bus/a2bus/a2diskiing.h25
-rw-r--r--src/devices/bus/a2bus/a2eauxslot.cpp22
-rw-r--r--src/devices/bus/a2bus/a2eauxslot.h20
-rw-r--r--src/devices/bus/a2bus/a2echoii.cpp14
-rw-r--r--src/devices/bus/a2bus/a2eext80col.cpp15
-rw-r--r--src/devices/bus/a2bus/a2eext80col.h13
-rw-r--r--src/devices/bus/a2bus/a2eramworks3.cpp21
-rw-r--r--src/devices/bus/a2bus/a2eramworks3.h19
-rw-r--r--src/devices/bus/a2bus/a2estd80col.cpp32
-rw-r--r--src/devices/bus/a2bus/a2estd80col.h13
-rw-r--r--src/devices/bus/a2bus/a2hsscsi.cpp2
-rw-r--r--src/devices/bus/a2bus/a2hsscsi.h2
-rw-r--r--src/devices/bus/a2bus/a2iwm.cpp1
-rw-r--r--src/devices/bus/a2bus/a2iwm.h1
-rw-r--r--src/devices/bus/a2bus/a2mcms.cpp3
-rw-r--r--src/devices/bus/a2bus/a2mcms.h2
-rw-r--r--src/devices/bus/a2bus/a2midi.cpp12
-rw-r--r--src/devices/bus/a2bus/a2mockingboard.cpp337
-rw-r--r--src/devices/bus/a2bus/a2parprn.cpp62
-rw-r--r--src/devices/bus/a2bus/a2parprn.h5
-rw-r--r--src/devices/bus/a2bus/a2pic.cpp16
-rw-r--r--src/devices/bus/a2bus/a2scsi.cpp16
-rw-r--r--src/devices/bus/a2bus/a2scsi.h2
-rw-r--r--src/devices/bus/a2bus/a2sd.cpp3
-rw-r--r--src/devices/bus/a2bus/a2sd.h2
-rw-r--r--src/devices/bus/a2bus/a2ssc.cpp4
-rw-r--r--src/devices/bus/a2bus/a2thunderclock.cpp4
-rw-r--r--src/devices/bus/a2bus/a2ultraterm.cpp4
-rw-r--r--src/devices/bus/a2bus/ace2x00.h1
-rw-r--r--src/devices/bus/a2bus/agat7ports.cpp2
-rw-r--r--src/devices/bus/a2bus/agat7ports.h2
-rw-r--r--src/devices/bus/a2bus/agat840k_hle.cpp4
-rw-r--r--src/devices/bus/a2bus/agat840k_hle.h4
-rw-r--r--src/devices/bus/a2bus/byte8251.cpp2
-rw-r--r--src/devices/bus/a2bus/cards.cpp45
-rw-r--r--src/devices/bus/a2bus/ccs7710.cpp4
-rw-r--r--src/devices/bus/a2bus/ccs7710.h4
-rw-r--r--src/devices/bus/a2bus/cmsscsi.h2
-rw-r--r--src/devices/bus/a2bus/corvfdc01.cpp4
-rw-r--r--src/devices/bus/a2bus/corvfdc01.h5
-rw-r--r--src/devices/bus/a2bus/corvfdc02.cpp4
-rw-r--r--src/devices/bus/a2bus/corvfdc02.h5
-rw-r--r--src/devices/bus/a2bus/ezcgi.cpp12
-rw-r--r--src/devices/bus/a2bus/grappler.cpp24
-rw-r--r--src/devices/bus/a2bus/lancegs.cpp4
-rw-r--r--src/devices/bus/a2bus/mouse.cpp8
-rw-r--r--src/devices/bus/a2bus/nippelclock.cpp13
-rw-r--r--src/devices/bus/a2bus/nippelclock.h2
-rw-r--r--src/devices/bus/a2bus/noisemaker.cpp86
-rw-r--r--src/devices/bus/a2bus/noisemaker.h14
-rw-r--r--src/devices/bus/a2bus/pc_xporter.cpp48
-rw-r--r--src/devices/bus/a2bus/q68.cpp2
-rw-r--r--src/devices/bus/a2bus/romcard.cpp276
-rw-r--r--src/devices/bus/a2bus/romcard.h23
-rw-r--r--src/devices/bus/a2bus/snesmax.cpp97
-rw-r--r--src/devices/bus/a2bus/snesmax.h20
-rw-r--r--src/devices/bus/a2bus/ssprite.cpp4
-rw-r--r--src/devices/bus/a2bus/timemasterho.cpp8
-rw-r--r--src/devices/bus/a2bus/uniprint.cpp4
-rw-r--r--src/devices/bus/a2bus/vistaa800.cpp324
-rw-r--r--src/devices/bus/a2bus/vistaa800.h20
-rw-r--r--src/devices/bus/a2gameio/computereyes.cpp24
-rw-r--r--src/devices/bus/a2gameio/gameio.cpp27
-rw-r--r--src/devices/bus/a2gameio/gameio.h41
-rw-r--r--src/devices/bus/a2gameio/gizmo.cpp16
-rw-r--r--src/devices/bus/a2gameio/joyport.cpp20
-rw-r--r--src/devices/bus/a2gameio/joystick.cpp22
-rw-r--r--src/devices/bus/a2gameio/paddles.cpp16
-rw-r--r--src/devices/bus/a7800/a78_slot.cpp56
-rw-r--r--src/devices/bus/a7800/a78_slot.h28
-rw-r--r--src/devices/bus/a7800/cpuwiz.cpp2
-rw-r--r--src/devices/bus/a7800/hiscore.cpp2
-rw-r--r--src/devices/bus/a7800/rom.cpp53
-rw-r--r--src/devices/bus/a7800/xboard.cpp10
-rw-r--r--src/devices/bus/a800/a5200_supercart.cpp74
-rw-r--r--src/devices/bus/a800/a5200_supercart.h32
-rw-r--r--src/devices/bus/a800/a800_carts.cpp109
-rw-r--r--src/devices/bus/a800/a800_carts.h62
-rw-r--r--src/devices/bus/a800/a800_slot.cpp536
-rw-r--r--src/devices/bus/a800/a800_slot.h172
-rw-r--r--src/devices/bus/a800/a8sio.cpp35
-rw-r--r--src/devices/bus/a800/a8sio.h28
-rw-r--r--src/devices/bus/a800/atari1050.cpp24
-rw-r--r--src/devices/bus/a800/atari1050.h11
-rw-r--r--src/devices/bus/a800/atari810.cpp22
-rw-r--r--src/devices/bus/a800/atari810.h11
-rw-r--r--src/devices/bus/a800/atrax.cpp54
-rw-r--r--src/devices/bus/a800/atrax.h34
-rw-r--r--src/devices/bus/a800/bbsb.cpp136
-rw-r--r--src/devices/bus/a800/bbsb.h52
-rw-r--r--src/devices/bus/a800/cassette.cpp4
-rw-r--r--src/devices/bus/a800/cassette.h2
-rw-r--r--src/devices/bus/a800/corina.cpp135
-rw-r--r--src/devices/bus/a800/corina.h59
-rw-r--r--src/devices/bus/a800/maxflash.cpp123
-rw-r--r--src/devices/bus/a800/maxflash.h53
-rw-r--r--src/devices/bus/a800/oss.cpp315
-rw-r--r--src/devices/bus/a800/oss.h77
-rw-r--r--src/devices/bus/a800/phoenix.cpp176
-rw-r--r--src/devices/bus/a800/phoenix.h70
-rw-r--r--src/devices/bus/a800/rom.cpp415
-rw-r--r--src/devices/bus/a800/rom.h189
-rw-r--r--src/devices/bus/a800/rtime8.cpp26
-rw-r--r--src/devices/bus/a800/rtime8.h9
-rw-r--r--src/devices/bus/a800/sic.cpp114
-rw-r--r--src/devices/bus/a800/sic.h64
-rw-r--r--src/devices/bus/a800/sparta.cpp178
-rw-r--r--src/devices/bus/a800/sparta.h49
-rw-r--r--src/devices/bus/a800/supercharger.cpp94
-rw-r--r--src/devices/bus/a800/supercharger.h35
-rw-r--r--src/devices/bus/a800/telelink2.cpp64
-rw-r--r--src/devices/bus/a800/telelink2.h34
-rw-r--r--src/devices/bus/a800/ultracart.cpp130
-rw-r--r--src/devices/bus/a800/ultracart.h55
-rw-r--r--src/devices/bus/a800/williams.cpp160
-rw-r--r--src/devices/bus/a800/williams.h69
-rw-r--r--src/devices/bus/abcbus/abcbus.cpp12
-rw-r--r--src/devices/bus/abcbus/abcbus.h48
-rw-r--r--src/devices/bus/abcbus/fd2.cpp13
-rw-r--r--src/devices/bus/abcbus/fd2.h4
-rw-r--r--src/devices/bus/abcbus/lux10828.cpp36
-rw-r--r--src/devices/bus/abcbus/lux10828.h15
-rw-r--r--src/devices/bus/abcbus/lux21046.cpp54
-rw-r--r--src/devices/bus/abcbus/lux21046.h16
-rw-r--r--src/devices/bus/abcbus/lux21056.cpp10
-rw-r--r--src/devices/bus/abcbus/lux21056.h10
-rw-r--r--src/devices/bus/abcbus/lux4105.cpp14
-rw-r--r--src/devices/bus/abcbus/lux4105.h10
-rw-r--r--src/devices/bus/abcbus/memcard.cpp42
-rw-r--r--src/devices/bus/abcbus/memcard.h12
-rw-r--r--src/devices/bus/abcbus/ssa.cpp17
-rw-r--r--src/devices/bus/abcbus/ssa.h16
-rw-r--r--src/devices/bus/abckb/abc77.cpp117
-rw-r--r--src/devices/bus/abckb/abc77.h18
-rw-r--r--src/devices/bus/abckb/abc800kb.cpp18
-rw-r--r--src/devices/bus/abckb/abc800kb.h2
-rw-r--r--src/devices/bus/abckb/abc99.cpp327
-rw-r--r--src/devices/bus/abckb/abc99.h37
-rw-r--r--src/devices/bus/abckb/abckb.cpp34
-rw-r--r--src/devices/bus/abckb/abckb.h11
-rw-r--r--src/devices/bus/abckb/r8.cpp160
-rw-r--r--src/devices/bus/abckb/r8.h62
-rw-r--r--src/devices/bus/acorn/atom/discpack.cpp9
-rw-r--r--src/devices/bus/acorn/atom/discpack.h7
-rw-r--r--src/devices/bus/acorn/atom/econet.cpp2
-rw-r--r--src/devices/bus/acorn/atom/econet.h2
-rw-r--r--src/devices/bus/acorn/bus.cpp7
-rw-r--r--src/devices/bus/acorn/bus.h4
-rw-r--r--src/devices/bus/acorn/cms/4080term.cpp2
-rw-r--r--src/devices/bus/acorn/cms/4080term.h2
-rw-r--r--src/devices/bus/acorn/cms/fdc.cpp3
-rw-r--r--src/devices/bus/acorn/cms/fdc.h2
-rw-r--r--src/devices/bus/acorn/cms/ieee.cpp2
-rw-r--r--src/devices/bus/acorn/cms/ieee.h2
-rw-r--r--src/devices/bus/acorn/system/8k.cpp11
-rw-r--r--src/devices/bus/acorn/system/8k.h4
-rw-r--r--src/devices/bus/acorn/system/cass.cpp2
-rw-r--r--src/devices/bus/acorn/system/cass.h2
-rw-r--r--src/devices/bus/acorn/system/econet.cpp2
-rw-r--r--src/devices/bus/acorn/system/econet.h2
-rw-r--r--src/devices/bus/acorn/system/fdc.cpp9
-rw-r--r--src/devices/bus/acorn/system/fdc.h8
-rw-r--r--src/devices/bus/acorn/system/vdu40.cpp2
-rw-r--r--src/devices/bus/acorn/system/vdu40.h2
-rw-r--r--src/devices/bus/acorn/system/vib.cpp4
-rw-r--r--src/devices/bus/acorn/system/vib.h4
-rw-r--r--src/devices/bus/adam/exp.cpp20
-rw-r--r--src/devices/bus/adam/exp.h10
-rw-r--r--src/devices/bus/adamnet/adamnet.cpp8
-rw-r--r--src/devices/bus/adamnet/adamnet.h8
-rw-r--r--src/devices/bus/adamnet/ddp.cpp99
-rw-r--r--src/devices/bus/adamnet/ddp.h7
-rw-r--r--src/devices/bus/adamnet/fdc.cpp6
-rw-r--r--src/devices/bus/adamnet/fdc.h1
-rw-r--r--src/devices/bus/adamnet/kb.cpp21
-rw-r--r--src/devices/bus/adamnet/kb.h2
-rw-r--r--src/devices/bus/adamnet/printer.cpp14
-rw-r--r--src/devices/bus/adamnet/printer.h2
-rw-r--r--src/devices/bus/adamnet/spi.cpp17
-rw-r--r--src/devices/bus/adb/a9m0330.cpp4
-rw-r--r--src/devices/bus/adb/a9m0330.h4
-rw-r--r--src/devices/bus/adb/adb.cpp2
-rw-r--r--src/devices/bus/amiga/keyboard/a1200.cpp4
-rw-r--r--src/devices/bus/amiga/keyboard/a1200.h4
-rw-r--r--src/devices/bus/amiga/keyboard/a2000.cpp371
-rw-r--r--src/devices/bus/amiga/keyboard/keyboard.cpp7
-rw-r--r--src/devices/bus/amiga/keyboard/keyboard.h10
-rw-r--r--src/devices/bus/amiga/keyboard/matrix.cpp756
-rw-r--r--src/devices/bus/amiga/keyboard/mitsumi.cpp10
-rw-r--r--src/devices/bus/amiga/zorro/a2052.cpp2
-rw-r--r--src/devices/bus/amiga/zorro/a2052.h2
-rw-r--r--src/devices/bus/amiga/zorro/a2058.cpp2
-rw-r--r--src/devices/bus/amiga/zorro/a2058.h2
-rw-r--r--src/devices/bus/amiga/zorro/a2065.cpp4
-rw-r--r--src/devices/bus/amiga/zorro/a2065.h4
-rw-r--r--src/devices/bus/amiga/zorro/a2232.cpp33
-rw-r--r--src/devices/bus/amiga/zorro/a2232.h32
-rw-r--r--src/devices/bus/amiga/zorro/a590.cpp10
-rw-r--r--src/devices/bus/amiga/zorro/a590.h12
-rw-r--r--src/devices/bus/amiga/zorro/buddha.cpp6
-rw-r--r--src/devices/bus/amiga/zorro/buddha.h6
-rw-r--r--src/devices/bus/amiga/zorro/zorro.cpp89
-rw-r--r--src/devices/bus/amiga/zorro/zorro.h45
-rw-r--r--src/devices/bus/apf/slot.cpp19
-rw-r--r--src/devices/bus/apf/slot.h20
-rw-r--r--src/devices/bus/apricot/expansion/expansion.cpp25
-rw-r--r--src/devices/bus/apricot/expansion/expansion.h32
-rw-r--r--src/devices/bus/apricot/expansion/winchester.cpp17
-rw-r--r--src/devices/bus/apricot/expansion/winchester.h12
-rw-r--r--src/devices/bus/apricot/keyboard/keyboard.cpp5
-rw-r--r--src/devices/bus/apricot/keyboard/keyboard.h4
-rw-r--r--src/devices/bus/apricot/video/video.cpp3
-rw-r--r--src/devices/bus/apricot/video/video.h2
-rw-r--r--src/devices/bus/aquarius/slot.cpp24
-rw-r--r--src/devices/bus/aquarius/slot.h16
-rw-r--r--src/devices/bus/arcadia/slot.cpp14
-rw-r--r--src/devices/bus/arcadia/slot.h13
-rw-r--r--src/devices/bus/archimedes/econet/slot.cpp3
-rw-r--r--src/devices/bus/archimedes/econet/slot.h2
-rw-r--r--src/devices/bus/archimedes/podule/ether1.cpp14
-rw-r--r--src/devices/bus/archimedes/podule/ether2.cpp134
-rw-r--r--src/devices/bus/archimedes/podule/ether2.h19
-rw-r--r--src/devices/bus/archimedes/podule/ether3.cpp122
-rw-r--r--src/devices/bus/archimedes/podule/ether3.h19
-rw-r--r--src/devices/bus/archimedes/podule/ethera.cpp123
-rw-r--r--src/devices/bus/archimedes/podule/ethera.h19
-rw-r--r--src/devices/bus/archimedes/podule/io.cpp2
-rw-r--r--src/devices/bus/archimedes/podule/io_hccs.cpp2
-rw-r--r--src/devices/bus/archimedes/podule/io_morley.cpp2
-rw-r--r--src/devices/bus/archimedes/podule/io_we.cpp2
-rw-r--r--src/devices/bus/archimedes/podule/rom.cpp68
-rw-r--r--src/devices/bus/archimedes/podule/rom.h1
-rw-r--r--src/devices/bus/archimedes/podule/scsi_a500.cpp130
-rw-r--r--src/devices/bus/archimedes/podule/scsi_a500.h19
-rw-r--r--src/devices/bus/archimedes/podule/scsi_acorn.cpp253
-rw-r--r--src/devices/bus/archimedes/podule/scsi_acorn.h21
-rw-r--r--src/devices/bus/archimedes/podule/scsi_cumana.cpp153
-rw-r--r--src/devices/bus/archimedes/podule/scsi_cumana.h19
-rw-r--r--src/devices/bus/archimedes/podule/scsi_ling.cpp149
-rw-r--r--src/devices/bus/archimedes/podule/scsi_ling.h19
-rw-r--r--src/devices/bus/archimedes/podule/scsi_morley.cpp169
-rw-r--r--src/devices/bus/archimedes/podule/scsi_morley.h19
-rw-r--r--src/devices/bus/archimedes/podule/scsi_oak.cpp263
-rw-r--r--src/devices/bus/archimedes/podule/scsi_oak.h19
-rw-r--r--src/devices/bus/archimedes/podule/scsi_vti.cpp2
-rw-r--r--src/devices/bus/archimedes/podule/slot.cpp46
-rw-r--r--src/devices/bus/archimedes/podule/slot.h7
-rw-r--r--src/devices/bus/astrocde/accessory.cpp2
-rw-r--r--src/devices/bus/astrocde/accessory.h2
-rw-r--r--src/devices/bus/astrocde/ctrl.cpp4
-rw-r--r--src/devices/bus/astrocde/ctrl.h2
-rw-r--r--src/devices/bus/astrocde/slot.cpp14
-rw-r--r--src/devices/bus/astrocde/slot.h16
-rw-r--r--src/devices/bus/ata/atadev.cpp22
-rw-r--r--src/devices/bus/ata/atadev.h67
-rw-r--r--src/devices/bus/ata/atahle.cpp968
-rw-r--r--src/devices/bus/ata/atahle.h221
-rw-r--r--src/devices/bus/ata/ataintf.cpp54
-rw-r--r--src/devices/bus/ata/ataintf.h23
-rw-r--r--src/devices/bus/ata/atapicdr.cpp131
-rw-r--r--src/devices/bus/ata/atapicdr.h56
-rw-r--r--src/devices/bus/ata/atapihle.cpp27
-rw-r--r--src/devices/bus/ata/atapihle.h9
-rw-r--r--src/devices/bus/ata/cp2024.cpp101
-rw-r--r--src/devices/bus/ata/cp2024.h40
-rw-r--r--src/devices/bus/ata/cr589.cpp98
-rw-r--r--src/devices/bus/ata/cr589.h2
-rw-r--r--src/devices/bus/ata/gdrom.cpp721
-rw-r--r--src/devices/bus/ata/gdrom.h21
-rw-r--r--src/devices/bus/ata/hdd.cpp45
-rw-r--r--src/devices/bus/ata/hdd.h92
-rw-r--r--src/devices/bus/ata/idehd.cpp955
-rw-r--r--src/devices/bus/ata/idehd.h141
-rw-r--r--src/devices/bus/ata/px320a.cpp8
-rw-r--r--src/devices/bus/ata/px320a.h8
-rw-r--r--src/devices/bus/ata/xm3301.cpp82
-rw-r--r--src/devices/bus/ata/xm3301.h31
-rw-r--r--src/devices/bus/ata/zip100.cpp100
-rw-r--r--src/devices/bus/ata/zip100.h41
-rw-r--r--src/devices/bus/bbc/1mhzbus/1mhzbus.cpp25
-rw-r--r--src/devices/bus/bbc/1mhzbus/1mhzbus.h8
-rw-r--r--src/devices/bus/bbc/1mhzbus/24bbc.cpp142
-rw-r--r--src/devices/bus/bbc/1mhzbus/24bbc.h51
-rw-r--r--src/devices/bus/bbc/1mhzbus/2ndserial.cpp200
-rw-r--r--src/devices/bus/bbc/1mhzbus/2ndserial.h60
-rw-r--r--src/devices/bus/bbc/1mhzbus/barrybox.cpp101
-rw-r--r--src/devices/bus/bbc/1mhzbus/barrybox.h11
-rw-r--r--src/devices/bus/bbc/1mhzbus/cc500.cpp6
-rw-r--r--src/devices/bus/bbc/1mhzbus/datacentre.cpp13
-rw-r--r--src/devices/bus/bbc/1mhzbus/datacentre.h4
-rw-r--r--src/devices/bus/bbc/1mhzbus/emrmidi.cpp6
-rw-r--r--src/devices/bus/bbc/1mhzbus/emrmidi.h4
-rw-r--r--src/devices/bus/bbc/1mhzbus/ide.cpp2
-rw-r--r--src/devices/bus/bbc/1mhzbus/ide.h2
-rw-r--r--src/devices/bus/bbc/1mhzbus/m2000.cpp2
-rw-r--r--src/devices/bus/bbc/1mhzbus/m2000.h2
-rw-r--r--src/devices/bus/bbc/1mhzbus/opus3.cpp3
-rw-r--r--src/devices/bus/bbc/1mhzbus/opus3.h2
-rw-r--r--src/devices/bus/bbc/1mhzbus/pms64k.cpp25
-rw-r--r--src/devices/bus/bbc/1mhzbus/pms64k.h9
-rw-r--r--src/devices/bus/bbc/1mhzbus/sasi.cpp4
-rw-r--r--src/devices/bus/bbc/1mhzbus/sasi.h4
-rw-r--r--src/devices/bus/bbc/1mhzbus/scsi.cpp4
-rw-r--r--src/devices/bus/bbc/1mhzbus/scsi.h4
-rw-r--r--src/devices/bus/bbc/analogue/analogue.cpp15
-rw-r--r--src/devices/bus/bbc/analogue/analogue.h6
-rw-r--r--src/devices/bus/bbc/analogue/bitstik.cpp8
-rw-r--r--src/devices/bus/bbc/analogue/cfa3000a.cpp8
-rw-r--r--src/devices/bus/bbc/analogue/joystick.cpp16
-rw-r--r--src/devices/bus/bbc/analogue/quinkey.cpp173
-rw-r--r--src/devices/bus/bbc/analogue/quinkey.h120
-rw-r--r--src/devices/bus/bbc/cart/mastersd.cpp77
-rw-r--r--src/devices/bus/bbc/cart/mastersd.h22
-rw-r--r--src/devices/bus/bbc/cart/slot.cpp1
-rw-r--r--src/devices/bus/bbc/exp/exp.cpp7
-rw-r--r--src/devices/bus/bbc/exp/exp.h8
-rw-r--r--src/devices/bus/bbc/exp/mertec.cpp2
-rw-r--r--src/devices/bus/bbc/fdc/acorn.cpp11
-rw-r--r--src/devices/bus/bbc/fdc/acorn.h11
-rw-r--r--src/devices/bus/bbc/fdc/ams.cpp7
-rw-r--r--src/devices/bus/bbc/fdc/ams.h8
-rw-r--r--src/devices/bus/bbc/fdc/cumana.cpp10
-rw-r--r--src/devices/bus/bbc/fdc/cumana.h8
-rw-r--r--src/devices/bus/bbc/fdc/cv1797.cpp8
-rw-r--r--src/devices/bus/bbc/fdc/cv1797.h7
-rw-r--r--src/devices/bus/bbc/fdc/fdc.cpp4
-rw-r--r--src/devices/bus/bbc/fdc/fdc.h4
-rw-r--r--src/devices/bus/bbc/fdc/kenda.cpp5
-rw-r--r--src/devices/bus/bbc/fdc/kenda.h4
-rw-r--r--src/devices/bus/bbc/fdc/opus.cpp6
-rw-r--r--src/devices/bus/bbc/fdc/opus.h4
-rw-r--r--src/devices/bus/bbc/fdc/solidisk.cpp8
-rw-r--r--src/devices/bus/bbc/fdc/solidisk.h7
-rw-r--r--src/devices/bus/bbc/fdc/udm.cpp10
-rw-r--r--src/devices/bus/bbc/fdc/udm.h9
-rw-r--r--src/devices/bus/bbc/fdc/watford.cpp4
-rw-r--r--src/devices/bus/bbc/fdc/watford.h2
-rw-r--r--src/devices/bus/bbc/internal/cumana68k.cpp19
-rw-r--r--src/devices/bus/bbc/internal/cumana68k.h10
-rw-r--r--src/devices/bus/bbc/internal/integrab.cpp9
-rw-r--r--src/devices/bus/bbc/internal/internal.cpp6
-rw-r--r--src/devices/bus/bbc/internal/internal.h8
-rw-r--r--src/devices/bus/bbc/joyport/joyport.cpp4
-rw-r--r--src/devices/bus/bbc/joyport/joyport.h4
-rw-r--r--src/devices/bus/bbc/modem/modem.cpp3
-rw-r--r--src/devices/bus/bbc/modem/modem.h2
-rw-r--r--src/devices/bus/bbc/modem/scsiaiv.cpp14
-rw-r--r--src/devices/bus/bbc/modem/scsiaiv.h20
-rw-r--r--src/devices/bus/bbc/rom/pal.cpp26
-rw-r--r--src/devices/bus/bbc/rom/pal.h14
-rw-r--r--src/devices/bus/bbc/rom/rtc.cpp8
-rw-r--r--src/devices/bus/bbc/rom/slot.cpp16
-rw-r--r--src/devices/bus/bbc/rom/slot.h8
-rw-r--r--src/devices/bus/bbc/tube/tube.cpp9
-rw-r--r--src/devices/bus/bbc/tube/tube.h4
-rw-r--r--src/devices/bus/bbc/tube/tube_32016.cpp2
-rw-r--r--src/devices/bus/bbc/tube/tube_32016.h2
-rw-r--r--src/devices/bus/bbc/tube/tube_6502.cpp17
-rw-r--r--src/devices/bus/bbc/tube/tube_6502.h2
-rw-r--r--src/devices/bus/bbc/tube/tube_80186.cpp2
-rw-r--r--src/devices/bus/bbc/tube/tube_80186.h2
-rw-r--r--src/devices/bus/bbc/tube/tube_80286.cpp2
-rw-r--r--src/devices/bus/bbc/tube/tube_80286.h2
-rw-r--r--src/devices/bus/bbc/tube/tube_a500.cpp157
-rw-r--r--src/devices/bus/bbc/tube/tube_a500.h66
-rw-r--r--src/devices/bus/bbc/tube/tube_arm.cpp2
-rw-r--r--src/devices/bus/bbc/tube/tube_arm.h2
-rw-r--r--src/devices/bus/bbc/tube/tube_arm7.cpp6
-rw-r--r--src/devices/bus/bbc/tube/tube_arm7.h6
-rw-r--r--src/devices/bus/bbc/tube/tube_rc6502.cpp2
-rw-r--r--src/devices/bus/bbc/tube/tube_rc6502.h2
-rw-r--r--src/devices/bus/bbc/tube/tube_z80.cpp2
-rw-r--r--src/devices/bus/bbc/tube/tube_z80.h2
-rw-r--r--src/devices/bus/bbc/userport/beebspch.cpp4
-rw-r--r--src/devices/bus/bbc/userport/beebspch.h4
-rw-r--r--src/devices/bus/bbc/userport/lcd.cpp7
-rw-r--r--src/devices/bus/bbc/userport/lvlecho.cpp278
-rw-r--r--src/devices/bus/bbc/userport/lvlecho.h13
-rw-r--r--src/devices/bus/bbc/userport/m4000.cpp163
-rw-r--r--src/devices/bus/bbc/userport/m4000.h47
-rw-r--r--src/devices/bus/bbc/userport/palext.cpp7
-rw-r--r--src/devices/bus/bbc/userport/sdcard.h2
-rw-r--r--src/devices/bus/bbc/userport/userport.cpp12
-rw-r--r--src/devices/bus/bbc/userport/userport.h6
-rw-r--r--src/devices/bus/bbc/userport/usersplit.cpp8
-rw-r--r--src/devices/bus/bbc/userport/usersplit.h8
-rw-r--r--src/devices/bus/bml3/bml3bus.cpp40
-rw-r--r--src/devices/bus/bml3/bml3bus.h19
-rw-r--r--src/devices/bus/bml3/bml3kanji.cpp15
-rw-r--r--src/devices/bus/bml3/bml3kanji.h4
-rw-r--r--src/devices/bus/bml3/bml3mp1802.cpp69
-rw-r--r--src/devices/bus/bml3/bml3mp1802.h14
-rw-r--r--src/devices/bus/bml3/bml3mp1805.cpp33
-rw-r--r--src/devices/bus/bml3/bml3mp1805.h7
-rw-r--r--src/devices/bus/bml3/bml3rtc.cpp10
-rw-r--r--src/devices/bus/bml3/bml3rtc.h2
-rw-r--r--src/devices/bus/c64/4dxh.h4
-rw-r--r--src/devices/bus/c64/4ksa.h4
-rw-r--r--src/devices/bus/c64/4tba.h4
-rw-r--r--src/devices/bus/c64/bn1541.cpp2
-rw-r--r--src/devices/bus/c64/bn1541.h18
-rw-r--r--src/devices/bus/c64/buscard.cpp2
-rw-r--r--src/devices/bus/c64/buscard.h2
-rw-r--r--src/devices/bus/c64/buscard2.cpp51
-rw-r--r--src/devices/bus/c64/buscard2.h8
-rw-r--r--src/devices/bus/c64/c128_partner.cpp2
-rw-r--r--src/devices/bus/c64/c128_partner.h2
-rw-r--r--src/devices/bus/c64/dqbb.cpp19
-rw-r--r--src/devices/bus/c64/dqbb.h12
-rw-r--r--src/devices/bus/c64/exp.cpp54
-rw-r--r--src/devices/bus/c64/exp.h17
-rw-r--r--src/devices/bus/c64/fcc.cpp19
-rw-r--r--src/devices/bus/c64/fcc.h22
-rw-r--r--src/devices/bus/c64/geocable.h18
-rw-r--r--src/devices/bus/c64/magic_formel.cpp4
-rw-r--r--src/devices/bus/c64/magic_formel.h2
-rw-r--r--src/devices/bus/c64/magic_voice.cpp12
-rw-r--r--src/devices/bus/c64/magic_voice.h12
-rw-r--r--src/devices/bus/c64/midi_maplin.cpp4
-rw-r--r--src/devices/bus/c64/midi_maplin.h4
-rw-r--r--src/devices/bus/c64/midi_namesoft.cpp4
-rw-r--r--src/devices/bus/c64/midi_namesoft.h4
-rw-r--r--src/devices/bus/c64/midi_passport.cpp6
-rw-r--r--src/devices/bus/c64/midi_passport.h6
-rw-r--r--src/devices/bus/c64/midi_sci.cpp4
-rw-r--r--src/devices/bus/c64/midi_sci.h4
-rw-r--r--src/devices/bus/c64/midi_siel.cpp4
-rw-r--r--src/devices/bus/c64/midi_siel.h4
-rw-r--r--src/devices/bus/c64/multiscreen.cpp4
-rw-r--r--src/devices/bus/c64/neoram.cpp19
-rw-r--r--src/devices/bus/c64/neoram.h12
-rw-r--r--src/devices/bus/c64/partner.cpp2
-rw-r--r--src/devices/bus/c64/partner.h2
-rw-r--r--src/devices/bus/c64/sfx_sound_expander.cpp2
-rw-r--r--src/devices/bus/c64/sfx_sound_expander.h2
-rw-r--r--src/devices/bus/c64/speakeasy.cpp2
-rw-r--r--src/devices/bus/c64/swiftlink.cpp2
-rw-r--r--src/devices/bus/c64/swiftlink.h2
-rw-r--r--src/devices/bus/c64/tibdd001.cpp164
-rw-r--r--src/devices/bus/c64/tibdd001.h60
-rw-r--r--src/devices/bus/c64/turbo232.cpp2
-rw-r--r--src/devices/bus/c64/turbo232.h2
-rw-r--r--src/devices/bus/casloopy/rom.cpp117
-rw-r--r--src/devices/bus/casloopy/rom.h58
-rw-r--r--src/devices/bus/casloopy/slot.cpp149
-rw-r--r--src/devices/bus/casloopy/slot.h90
-rw-r--r--src/devices/bus/cbm2/exp.cpp33
-rw-r--r--src/devices/bus/cbm2/exp.h8
-rw-r--r--src/devices/bus/cbm2/user.cpp6
-rw-r--r--src/devices/bus/cbm2/user.h22
-rw-r--r--src/devices/bus/cbmiec/c1526.cpp2
-rw-r--r--src/devices/bus/cbmiec/c1541.cpp17
-rw-r--r--src/devices/bus/cbmiec/c1541.h10
-rw-r--r--src/devices/bus/cbmiec/c1571.cpp18
-rw-r--r--src/devices/bus/cbmiec/c1571.h14
-rw-r--r--src/devices/bus/cbmiec/c1581.cpp7
-rw-r--r--src/devices/bus/cbmiec/c1581.h6
-rw-r--r--src/devices/bus/cbmiec/c64_nl10.cpp24
-rw-r--r--src/devices/bus/cbmiec/c64_nl10.h8
-rw-r--r--src/devices/bus/cbmiec/cbmiec.cpp9
-rw-r--r--src/devices/bus/cbmiec/cbmiec.h20
-rw-r--r--src/devices/bus/cbmiec/fd2000.cpp2
-rw-r--r--src/devices/bus/cbmiec/fd2000.h1
-rw-r--r--src/devices/bus/cbmiec/interpod.cpp6
-rw-r--r--src/devices/bus/cbmiec/interpod.h4
-rw-r--r--src/devices/bus/cbmiec/mps1200.cpp317
-rw-r--r--src/devices/bus/cbmiec/mps1200.h70
-rw-r--r--src/devices/bus/cbmiec/vic1520.cpp129
-rw-r--r--src/devices/bus/cbmiec/vic1520.h16
-rw-r--r--src/devices/bus/cbus/mpu_pc98.cpp2
-rw-r--r--src/devices/bus/cbus/mpu_pc98.h2
-rw-r--r--src/devices/bus/cbus/pc9801_118.cpp2
-rw-r--r--src/devices/bus/cbus/pc9801_118.h2
-rw-r--r--src/devices/bus/cbus/pc9801_26.cpp2
-rw-r--r--src/devices/bus/cbus/pc9801_26.h2
-rw-r--r--src/devices/bus/cbus/pc9801_55.cpp2
-rw-r--r--src/devices/bus/cbus/pc9801_55.h2
-rw-r--r--src/devices/bus/cbus/pc9801_86.cpp2
-rw-r--r--src/devices/bus/cbus/pc9801_86.h2
-rw-r--r--src/devices/bus/cbus/pc9801_cbus.cpp12
-rw-r--r--src/devices/bus/cbus/pc9801_cbus.h3
-rw-r--r--src/devices/bus/centronics/chessmec.h6
-rw-r--r--src/devices/bus/centronics/comxpl80.h16
-rw-r--r--src/devices/bus/centronics/covox.cpp4
-rw-r--r--src/devices/bus/centronics/covox.h36
-rw-r--r--src/devices/bus/centronics/ctronics.cpp57
-rw-r--r--src/devices/bus/centronics/ctronics.h102
-rw-r--r--src/devices/bus/centronics/digiblst.cpp2
-rw-r--r--src/devices/bus/centronics/digiblst.h16
-rw-r--r--src/devices/bus/centronics/dsjoy.h12
-rw-r--r--src/devices/bus/centronics/epson_lx800.cpp16
-rw-r--r--src/devices/bus/centronics/epson_lx800.h16
-rw-r--r--src/devices/bus/centronics/epson_lx810l.cpp4
-rw-r--r--src/devices/bus/centronics/epson_lx810l.h38
-rw-r--r--src/devices/bus/centronics/nlq401.cpp310
-rw-r--r--src/devices/bus/centronics/nlq401.h60
-rw-r--r--src/devices/bus/centronics/printer.cpp6
-rw-r--r--src/devices/bus/centronics/printer.h22
-rw-r--r--src/devices/bus/centronics/samdac.cpp2
-rw-r--r--src/devices/bus/centronics/samdac.h18
-rw-r--r--src/devices/bus/centronics/smartboard.h4
-rw-r--r--src/devices/bus/centronics/spjoy.h16
-rw-r--r--src/devices/bus/cgenie/expansion/expansion.cpp4
-rw-r--r--src/devices/bus/cgenie/expansion/expansion.h6
-rw-r--r--src/devices/bus/cgenie/expansion/floppy.cpp11
-rw-r--r--src/devices/bus/cgenie/expansion/floppy.h2
-rw-r--r--src/devices/bus/cgenie/parallel/printer.cpp8
-rw-r--r--src/devices/bus/cgenie/parallel/printer.h8
-rw-r--r--src/devices/bus/chanf/slot.cpp14
-rw-r--r--src/devices/bus/chanf/slot.h17
-rw-r--r--src/devices/bus/coco/coco_dcmodem.cpp2
-rw-r--r--src/devices/bus/coco/coco_fdc.cpp754
-rw-r--r--src/devices/bus/coco/coco_fdc.h15
-rw-r--r--src/devices/bus/coco/coco_midi.cpp4
-rw-r--r--src/devices/bus/coco/coco_multi.cpp3
-rw-r--r--src/devices/bus/coco/coco_ram.cpp156
-rw-r--r--src/devices/bus/coco/coco_rs232.cpp2
-rw-r--r--src/devices/bus/coco/coco_ssc.cpp4
-rw-r--r--src/devices/bus/coco/coco_stecomp.cpp6
-rw-r--r--src/devices/bus/coco/coco_sym12.cpp2
-rw-r--r--src/devices/bus/coco/coco_t4426.cpp27
-rw-r--r--src/devices/bus/coco/cococart.cpp22
-rw-r--r--src/devices/bus/coco/cococart.h10
-rw-r--r--src/devices/bus/coco/dragon_claw.cpp2
-rw-r--r--src/devices/bus/coco/dragon_claw.h2
-rw-r--r--src/devices/bus/coco/dragon_fdc.cpp51
-rw-r--r--src/devices/bus/coco/dragon_jcbspch.cpp6
-rw-r--r--src/devices/bus/coco/dragon_jcbspch.h4
-rw-r--r--src/devices/bus/coco/dragon_serial.cpp106
-rw-r--r--src/devices/bus/coco/dragon_serial.h41
-rw-r--r--src/devices/bus/coco/dragon_sprites.cpp2
-rw-r--r--src/devices/bus/coco/dragon_sprites.h2
-rw-r--r--src/devices/bus/coco/meb_intrf.cpp187
-rw-r--r--src/devices/bus/coco/meb_intrf.h90
-rw-r--r--src/devices/bus/coco/meb_rtime.cpp173
-rw-r--r--src/devices/bus/coco/meb_rtime.h13
-rw-r--r--src/devices/bus/coleco/cartridge/activision.cpp132
-rw-r--r--src/devices/bus/coleco/cartridge/activision.h65
-rw-r--r--src/devices/bus/coleco/cartridge/exp.cpp30
-rw-r--r--src/devices/bus/coleco/cartridge/exp.h14
-rw-r--r--src/devices/bus/coleco/cartridge/megacart.cpp6
-rw-r--r--src/devices/bus/coleco/cartridge/megacart.h2
-rw-r--r--src/devices/bus/coleco/cartridge/std.cpp6
-rw-r--r--src/devices/bus/coleco/cartridge/std.h2
-rw-r--r--src/devices/bus/coleco/cartridge/xin1.cpp4
-rw-r--r--src/devices/bus/coleco/cartridge/xin1.h2
-rw-r--r--src/devices/bus/coleco/controller/ctrl.cpp2
-rw-r--r--src/devices/bus/coleco/controller/ctrl.h4
-rw-r--r--src/devices/bus/coleco/expansion/cards.cpp18
-rw-r--r--src/devices/bus/coleco/expansion/cards.h16
-rw-r--r--src/devices/bus/coleco/expansion/expansion.cpp61
-rw-r--r--src/devices/bus/coleco/expansion/expansion.h126
-rw-r--r--src/devices/bus/coleco/expansion/sgm.cpp98
-rw-r--r--src/devices/bus/coleco/expansion/sgm.h48
-rw-r--r--src/devices/bus/compis/graphics.cpp3
-rw-r--r--src/devices/bus/compis/graphics.h2
-rw-r--r--src/devices/bus/compucolor/floppy.cpp2
-rw-r--r--src/devices/bus/compucolor/floppy.h5
-rw-r--r--src/devices/bus/comx35/exp.cpp11
-rw-r--r--src/devices/bus/comx35/exp.h10
-rw-r--r--src/devices/bus/comx35/expbox.h8
-rw-r--r--src/devices/bus/comx35/fdc.cpp2
-rw-r--r--src/devices/bus/comx35/fdc.h1
-rw-r--r--src/devices/bus/cpc/cpc_rom.cpp30
-rw-r--r--src/devices/bus/cpc/cpc_rom.h6
-rw-r--r--src/devices/bus/cpc/cpc_rs232.cpp6
-rw-r--r--src/devices/bus/cpc/cpc_rs232.h6
-rw-r--r--src/devices/bus/cpc/cpc_ssa1.cpp32
-rw-r--r--src/devices/bus/cpc/cpc_ssa1.h24
-rw-r--r--src/devices/bus/cpc/cpcexp.cpp15
-rw-r--r--src/devices/bus/cpc/cpcexp.h16
-rw-r--r--src/devices/bus/cpc/ddi1.h2
-rw-r--r--src/devices/bus/cpc/doubler.cpp2
-rw-r--r--src/devices/bus/cpc/doubler.h1
-rw-r--r--src/devices/bus/cpc/hd20.cpp2
-rw-r--r--src/devices/bus/cpc/hd20.h2
-rw-r--r--src/devices/bus/cpc/magicsound.cpp18
-rw-r--r--src/devices/bus/cpc/magicsound.h18
-rw-r--r--src/devices/bus/cpc/musicmachine.cpp2
-rw-r--r--src/devices/bus/cpc/musicmachine.h2
-rw-r--r--src/devices/bus/cpc/playcity.h6
-rw-r--r--src/devices/bus/cpc/symbfac2.cpp12
-rw-r--r--src/devices/bus/cpc/symbfac2.h2
-rw-r--r--src/devices/bus/cpc/transtape.h2
-rw-r--r--src/devices/bus/crvision/slot.cpp21
-rw-r--r--src/devices/bus/crvision/slot.h14
-rw-r--r--src/devices/bus/dmv/dmvbus.cpp9
-rw-r--r--src/devices/bus/dmv/k012.h2
-rw-r--r--src/devices/bus/dmv/k210.cpp16
-rw-r--r--src/devices/bus/dmv/k210.h14
-rw-r--r--src/devices/bus/dmv/k220.cpp6
-rw-r--r--src/devices/bus/dmv/k220.h6
-rw-r--r--src/devices/bus/dmv/k230.h2
-rw-r--r--src/devices/bus/dmv/k801.cpp2
-rw-r--r--src/devices/bus/dmv/k801.h2
-rw-r--r--src/devices/bus/dmv/k803.cpp2
-rw-r--r--src/devices/bus/dmv/k803.h2
-rw-r--r--src/devices/bus/dmv/k806.cpp2
-rw-r--r--src/devices/bus/dmv/k806.h2
-rw-r--r--src/devices/bus/ecbbus/ecbbus.cpp3
-rw-r--r--src/devices/bus/ecbbus/ecbbus.h4
-rw-r--r--src/devices/bus/ecbbus/grip.cpp6
-rw-r--r--src/devices/bus/ecbbus/grip.h6
-rw-r--r--src/devices/bus/econet/e01.cpp67
-rw-r--r--src/devices/bus/econet/e01.h23
-rw-r--r--src/devices/bus/econet/econet.cpp74
-rw-r--r--src/devices/bus/econet/econet.h42
-rw-r--r--src/devices/bus/einstein/pipe/pipe.cpp7
-rw-r--r--src/devices/bus/einstein/pipe/pipe.h8
-rw-r--r--src/devices/bus/einstein/pipe/speculator.cpp4
-rw-r--r--src/devices/bus/einstein/pipe/speculator.h4
-rw-r--r--src/devices/bus/einstein/pipe/tk02.cpp2
-rw-r--r--src/devices/bus/einstein/pipe/tk02.h2
-rw-r--r--src/devices/bus/einstein/userport/userport.cpp5
-rw-r--r--src/devices/bus/einstein/userport/userport.h4
-rw-r--r--src/devices/bus/ekara/rom.cpp26
-rw-r--r--src/devices/bus/ekara/rom.h21
-rw-r--r--src/devices/bus/ekara/slot.cpp26
-rw-r--r--src/devices/bus/ekara/slot.h28
-rw-r--r--src/devices/bus/electron/cart/ap34.cpp3
-rw-r--r--src/devices/bus/electron/cart/ap34.h1
-rw-r--r--src/devices/bus/electron/cart/ap5.cpp16
-rw-r--r--src/devices/bus/electron/cart/ap5.h6
-rw-r--r--src/devices/bus/electron/cart/click.cpp7
-rw-r--r--src/devices/bus/electron/cart/cumana.cpp38
-rw-r--r--src/devices/bus/electron/cart/cumana.h6
-rw-r--r--src/devices/bus/electron/cart/peg400.cpp5
-rw-r--r--src/devices/bus/electron/cart/peg400.h3
-rw-r--r--src/devices/bus/electron/cart/romp144.cpp16
-rw-r--r--src/devices/bus/electron/cart/romp144.h6
-rw-r--r--src/devices/bus/electron/cart/slot.cpp26
-rw-r--r--src/devices/bus/electron/cart/slot.h12
-rw-r--r--src/devices/bus/electron/cart/stlefs.cpp3
-rw-r--r--src/devices/bus/electron/cart/stlefs.h1
-rw-r--r--src/devices/bus/electron/elksd128.cpp2
-rw-r--r--src/devices/bus/electron/elksd64.cpp2
-rw-r--r--src/devices/bus/electron/exp.cpp8
-rw-r--r--src/devices/bus/electron/exp.h4
-rw-r--r--src/devices/bus/electron/m2105.cpp24
-rw-r--r--src/devices/bus/electron/mc68k.cpp6
-rw-r--r--src/devices/bus/electron/mode7.cpp2
-rw-r--r--src/devices/bus/electron/mode7.h2
-rw-r--r--src/devices/bus/electron/plus1.cpp60
-rw-r--r--src/devices/bus/electron/plus1.h17
-rw-r--r--src/devices/bus/electron/plus2.cpp18
-rw-r--r--src/devices/bus/electron/plus2.h4
-rw-r--r--src/devices/bus/electron/plus3.cpp5
-rw-r--r--src/devices/bus/electron/plus3.h1
-rw-r--r--src/devices/bus/electron/pwrjoy.cpp2
-rw-r--r--src/devices/bus/electron/rombox.cpp18
-rw-r--r--src/devices/bus/electron/rombox.h4
-rw-r--r--src/devices/bus/electron/romboxp.cpp18
-rw-r--r--src/devices/bus/electron/romboxp.h4
-rw-r--r--src/devices/bus/electron/sidewndr.cpp18
-rw-r--r--src/devices/bus/electron/sidewndr.h4
-rw-r--r--src/devices/bus/electron/voxbox.cpp100
-rw-r--r--src/devices/bus/electron/voxbox.h54
-rw-r--r--src/devices/bus/ep64/exdos.cpp41
-rw-r--r--src/devices/bus/ep64/exdos.h8
-rw-r--r--src/devices/bus/ep64/exp.cpp5
-rw-r--r--src/devices/bus/ep64/exp.h6
-rw-r--r--src/devices/bus/epson_qx/cqgmem.cpp135
-rw-r--r--src/devices/bus/epson_qx/cqgmem.h59
-rw-r--r--src/devices/bus/epson_qx/cr1510.cpp62
-rw-r--r--src/devices/bus/epson_qx/cr1510.h50
-rw-r--r--src/devices/bus/epson_qx/ide.cpp110
-rw-r--r--src/devices/bus/epson_qx/ide.h61
-rw-r--r--src/devices/bus/epson_qx/keyboard/keyboard.cpp205
-rw-r--r--src/devices/bus/epson_qx/keyboard/keyboard.h114
-rw-r--r--src/devices/bus/epson_qx/keyboard/matrix.cpp300
-rw-r--r--src/devices/bus/epson_qx/keyboard/matrix.h22
-rw-r--r--src/devices/bus/epson_qx/option.cpp52
-rw-r--r--src/devices/bus/epson_qx/option.h18
-rw-r--r--src/devices/bus/epson_qx/sound_card.cpp125
-rw-r--r--src/devices/bus/epson_qx/sound_card.h61
-rw-r--r--src/devices/bus/epson_sio/epson_sio.cpp7
-rw-r--r--src/devices/bus/epson_sio/epson_sio.h8
-rw-r--r--src/devices/bus/epson_sio/pf10.cpp12
-rw-r--r--src/devices/bus/epson_sio/pf10.h8
-rw-r--r--src/devices/bus/epson_sio/tf20.cpp8
-rw-r--r--src/devices/bus/epson_sio/tf20.h8
-rw-r--r--src/devices/bus/fmt_scsi/fmt_scsi.cpp2
-rw-r--r--src/devices/bus/gamate/gamate_protection.cpp4
-rw-r--r--src/devices/bus/gamate/gamate_protection.h4
-rw-r--r--src/devices/bus/gamate/slot.cpp27
-rw-r--r--src/devices/bus/gamate/slot.h14
-rw-r--r--src/devices/bus/gameboy/camera.cpp620
-rw-r--r--src/devices/bus/gameboy/camera.h18
-rw-r--r--src/devices/bus/gameboy/cartbase.cpp537
-rw-r--r--src/devices/bus/gameboy/cartbase.h275
-rw-r--r--src/devices/bus/gameboy/cartbase.ipp406
-rw-r--r--src/devices/bus/gameboy/cartheader.h132
-rw-r--r--src/devices/bus/gameboy/carts.cpp122
-rw-r--r--src/devices/bus/gameboy/carts.h61
-rw-r--r--src/devices/bus/gameboy/gb_slot.cpp832
-rw-r--r--src/devices/bus/gameboy/gb_slot.h209
-rw-r--r--src/devices/bus/gameboy/gbck003.cpp264
-rw-r--r--src/devices/bus/gameboy/gbck003.h18
-rw-r--r--src/devices/bus/gameboy/gbslot.cpp1360
-rw-r--r--src/devices/bus/gameboy/gbslot.h87
-rw-r--r--src/devices/bus/gameboy/gbxfile.cpp59
-rw-r--r--src/devices/bus/gameboy/gbxfile.h130
-rw-r--r--src/devices/bus/gameboy/huc1.cpp192
-rw-r--r--src/devices/bus/gameboy/huc1.h18
-rw-r--r--src/devices/bus/gameboy/huc3.cpp698
-rw-r--r--src/devices/bus/gameboy/huc3.h18
-rw-r--r--src/devices/bus/gameboy/liebao.cpp159
-rw-r--r--src/devices/bus/gameboy/liebao.h18
-rw-r--r--src/devices/bus/gameboy/mbc.cpp2489
-rw-r--r--src/devices/bus/gameboy/mbc.h455
-rw-r--r--src/devices/bus/gameboy/mbc2.cpp225
-rw-r--r--src/devices/bus/gameboy/mbc2.h18
-rw-r--r--src/devices/bus/gameboy/mbc3.cpp854
-rw-r--r--src/devices/bus/gameboy/mbc3.h20
-rw-r--r--src/devices/bus/gameboy/mbc6.cpp529
-rw-r--r--src/devices/bus/gameboy/mbc6.h18
-rw-r--r--src/devices/bus/gameboy/mbc7.cpp379
-rw-r--r--src/devices/bus/gameboy/mbc7.h19
-rw-r--r--src/devices/bus/gameboy/mdslot.cpp141
-rw-r--r--src/devices/bus/gameboy/mdslot.h70
-rw-r--r--src/devices/bus/gameboy/mmm01.cpp349
-rw-r--r--src/devices/bus/gameboy/mmm01.h16
-rw-r--r--src/devices/bus/gameboy/ntnew.cpp179
-rw-r--r--src/devices/bus/gameboy/ntnew.h18
-rw-r--r--src/devices/bus/gameboy/rom.cpp1313
-rw-r--r--src/devices/bus/gameboy/rom.h166
-rw-r--r--src/devices/bus/gameboy/slmulti.cpp417
-rw-r--r--src/devices/bus/gameboy/slmulti.h18
-rw-r--r--src/devices/bus/gameboy/slot.cpp88
-rw-r--r--src/devices/bus/gameboy/slot.h92
-rw-r--r--src/devices/bus/gameboy/tama5.cpp269
-rw-r--r--src/devices/bus/gameboy/tama5.h11
-rw-r--r--src/devices/bus/gamegear/ggext.cpp118
-rw-r--r--src/devices/bus/gamegear/ggext.h109
-rw-r--r--src/devices/bus/gamegear/smsctrladp.h54
-rw-r--r--src/devices/bus/gba/gba_slot.cpp31
-rw-r--r--src/devices/bus/gba/gba_slot.h8
-rw-r--r--src/devices/bus/generic/slot.cpp37
-rw-r--r--src/devices/bus/generic/slot.h83
-rw-r--r--src/devices/bus/gio64/gio64.cpp5
-rw-r--r--src/devices/bus/gio64/gio64.h7
-rw-r--r--src/devices/bus/gio64/newport.cpp185
-rw-r--r--src/devices/bus/gio64/newport.h9
-rw-r--r--src/devices/bus/hexbus/hexbus.cpp6
-rw-r--r--src/devices/bus/hexbus/hexbus.h2
-rw-r--r--src/devices/bus/hexbus/hx5102.cpp89
-rw-r--r--src/devices/bus/hexbus/hx5102.h44
-rw-r--r--src/devices/bus/hexbus/tp0370.cpp17
-rw-r--r--src/devices/bus/hp80_io/82900.cpp2
-rw-r--r--src/devices/bus/hp80_io/82900.h2
-rw-r--r--src/devices/bus/hp80_io/82937.cpp6
-rw-r--r--src/devices/bus/hp80_io/82937.h6
-rw-r--r--src/devices/bus/hp80_io/hp80_io.cpp10
-rw-r--r--src/devices/bus/hp80_io/hp80_io.h8
-rw-r--r--src/devices/bus/hp9845_io/98032.cpp38
-rw-r--r--src/devices/bus/hp9845_io/98032.h36
-rw-r--r--src/devices/bus/hp9845_io/98034.cpp10
-rw-r--r--src/devices/bus/hp9845_io/98034.h2
-rw-r--r--src/devices/bus/hp9845_io/98036.cpp20
-rw-r--r--src/devices/bus/hp9845_io/98036.h20
-rw-r--r--src/devices/bus/hp9845_io/98046.cpp20
-rw-r--r--src/devices/bus/hp9845_io/98046.h20
-rw-r--r--src/devices/bus/hp9845_io/hp9845_io.cpp38
-rw-r--r--src/devices/bus/hp9845_io/hp9845_io.h28
-rw-r--r--src/devices/bus/hp9845_io/hp9871.cpp116
-rw-r--r--src/devices/bus/hp9845_io/hp9871.h54
-rw-r--r--src/devices/bus/hp9845_io/hp9885.cpp207
-rw-r--r--src/devices/bus/hp9845_io/hp9885.h16
-rw-r--r--src/devices/bus/hp_dio/hp98265a.cpp4
-rw-r--r--src/devices/bus/hp_dio/hp98265a.h4
-rw-r--r--src/devices/bus/hp_dio/hp98543.cpp10
-rw-r--r--src/devices/bus/hp_dio/hp98543.h10
-rw-r--r--src/devices/bus/hp_dio/hp98544.cpp4
-rw-r--r--src/devices/bus/hp_dio/hp98544.h4
-rw-r--r--src/devices/bus/hp_dio/hp98550.cpp2
-rw-r--r--src/devices/bus/hp_dio/hp98550.h2
-rw-r--r--src/devices/bus/hp_dio/hp98620.cpp4
-rw-r--r--src/devices/bus/hp_dio/hp98620.h6
-rw-r--r--src/devices/bus/hp_dio/hp98643.cpp2
-rw-r--r--src/devices/bus/hp_dio/hp98643.h2
-rw-r--r--src/devices/bus/hp_dio/hp98644.cpp2
-rw-r--r--src/devices/bus/hp_dio/hp_dio.cpp12
-rw-r--r--src/devices/bus/hp_dio/hp_dio.h78
-rw-r--r--src/devices/bus/hp_dio/human_interface.cpp14
-rw-r--r--src/devices/bus/hp_dio/human_interface.h14
-rw-r--r--src/devices/bus/hp_hil/hp_hil.cpp6
-rw-r--r--src/devices/bus/hp_hil/hp_hil.h2
-rw-r--r--src/devices/bus/hp_ipc_io/82919.cpp22
-rw-r--r--src/devices/bus/hp_ipc_io/82919.h22
-rw-r--r--src/devices/bus/hp_ipc_io/hp_ipc_io.cpp1
-rw-r--r--src/devices/bus/idpartner/bus.cpp87
-rw-r--r--src/devices/bus/idpartner/bus.h141
-rw-r--r--src/devices/bus/idpartner/gdp.cpp239
-rw-r--r--src/devices/bus/idpartner/gdp.h12
-rw-r--r--src/devices/bus/idpartner/sasi.cpp180
-rw-r--r--src/devices/bus/idpartner/sasi.h12
-rw-r--r--src/devices/bus/ieee488/c2031.cpp9
-rw-r--r--src/devices/bus/ieee488/c2031.h6
-rw-r--r--src/devices/bus/ieee488/c2040.cpp31
-rw-r--r--src/devices/bus/ieee488/c2040.h8
-rw-r--r--src/devices/bus/ieee488/c2040fdc.cpp19
-rw-r--r--src/devices/bus/ieee488/c2040fdc.h22
-rw-r--r--src/devices/bus/ieee488/c8050.cpp45
-rw-r--r--src/devices/bus/ieee488/c8050.h8
-rw-r--r--src/devices/bus/ieee488/c8050fdc.cpp69
-rw-r--r--src/devices/bus/ieee488/c8050fdc.h24
-rw-r--r--src/devices/bus/ieee488/c8280.cpp53
-rw-r--r--src/devices/bus/ieee488/c8280.h13
-rw-r--r--src/devices/bus/ieee488/d9060.cpp20
-rw-r--r--src/devices/bus/ieee488/d9060.h10
-rw-r--r--src/devices/bus/ieee488/hp9122c.cpp25
-rw-r--r--src/devices/bus/ieee488/hp9122c.h24
-rw-r--r--src/devices/bus/ieee488/hp9895.cpp23
-rw-r--r--src/devices/bus/ieee488/hp9895.h20
-rw-r--r--src/devices/bus/ieee488/ieee488.cpp10
-rw-r--r--src/devices/bus/ieee488/ieee488.h32
-rw-r--r--src/devices/bus/imi7000/imi5000h.cpp6
-rw-r--r--src/devices/bus/imi7000/imi5000h.h6
-rw-r--r--src/devices/bus/imi7000/imi7000.h8
-rw-r--r--src/devices/bus/intellec4/insdatastor.cpp18
-rw-r--r--src/devices/bus/intellec4/intellec4.cpp11
-rw-r--r--src/devices/bus/intellec4/intellec4.h44
-rw-r--r--src/devices/bus/intellec4/prommemory.cpp14
-rw-r--r--src/devices/bus/intellec4/tapereader.cpp10
-rw-r--r--src/devices/bus/interpro/keyboard/hle.cpp2
-rw-r--r--src/devices/bus/interpro/keyboard/hle.h2
-rw-r--r--src/devices/bus/interpro/keyboard/keyboard.cpp3
-rw-r--r--src/devices/bus/interpro/keyboard/keyboard.h6
-rw-r--r--src/devices/bus/interpro/keyboard/lle.cpp5
-rw-r--r--src/devices/bus/interpro/keyboard/lle.h6
-rw-r--r--src/devices/bus/interpro/mouse/mouse.cpp1
-rw-r--r--src/devices/bus/interpro/sr/edge.cpp11
-rw-r--r--src/devices/bus/interpro/sr/edge.h10
-rw-r--r--src/devices/bus/interpro/sr/gt.cpp3
-rw-r--r--src/devices/bus/interpro/sr/gt.h2
-rw-r--r--src/devices/bus/interpro/sr/sr.cpp9
-rw-r--r--src/devices/bus/interpro/sr/sr.h35
-rw-r--r--src/devices/bus/intv/slot.cpp31
-rw-r--r--src/devices/bus/intv/slot.h12
-rw-r--r--src/devices/bus/iq151/iq151.cpp38
-rw-r--r--src/devices/bus/iq151/iq151.h8
-rw-r--r--src/devices/bus/isa/3c503.cpp13
-rw-r--r--src/devices/bus/isa/3c505.cpp4
-rw-r--r--src/devices/bus/isa/aga.cpp4
-rw-r--r--src/devices/bus/isa/aga.h4
-rw-r--r--src/devices/bus/isa/aha1542b.cpp4
-rw-r--r--src/devices/bus/isa/aha1542b.h4
-rw-r--r--src/devices/bus/isa/asc88.cpp4
-rw-r--r--src/devices/bus/isa/asc88.h4
-rw-r--r--src/devices/bus/isa/bblue2.cpp2
-rw-r--r--src/devices/bus/isa/bblue2.h6
-rw-r--r--src/devices/bus/isa/bt54x.cpp2
-rw-r--r--src/devices/bus/isa/cga.cpp4
-rw-r--r--src/devices/bus/isa/cga.h4
-rw-r--r--src/devices/bus/isa/com.h4
-rw-r--r--src/devices/bus/isa/dectalk.cpp4
-rw-r--r--src/devices/bus/isa/dectalk.h4
-rw-r--r--src/devices/bus/isa/ega.cpp42
-rw-r--r--src/devices/bus/isa/ega.h10
-rw-r--r--src/devices/bus/isa/eis_hgb107x.cpp4
-rw-r--r--src/devices/bus/isa/eis_hgb107x.h4
-rw-r--r--src/devices/bus/isa/ex1280.cpp2
-rw-r--r--src/devices/bus/isa/ex1280.h2
-rw-r--r--src/devices/bus/isa/fdc.cpp11
-rw-r--r--src/devices/bus/isa/fdc.h10
-rw-r--r--src/devices/bus/isa/gus.cpp44
-rw-r--r--src/devices/bus/isa/gus.h24
-rw-r--r--src/devices/bus/isa/hdc.cpp22
-rw-r--r--src/devices/bus/isa/hdc.h6
-rw-r--r--src/devices/bus/isa/hpblp.cpp548
-rw-r--r--src/devices/bus/isa/hpblp.h97
-rw-r--r--src/devices/bus/isa/ibm_mfc.cpp10
-rw-r--r--src/devices/bus/isa/ibm_mfc.h8
-rw-r--r--src/devices/bus/isa/ibm_speech.cpp466
-rw-r--r--src/devices/bus/isa/ibm_speech.h83
-rw-r--r--src/devices/bus/isa/ide.cpp2
-rw-r--r--src/devices/bus/isa/ide.h2
-rw-r--r--src/devices/bus/isa/isa.cpp95
-rw-r--r--src/devices/bus/isa/isa.h52
-rw-r--r--src/devices/bus/isa/isa_cards.cpp24
-rw-r--r--src/devices/bus/isa/lbaenhancer.cpp2
-rw-r--r--src/devices/bus/isa/lpt.cpp2
-rw-r--r--src/devices/bus/isa/lpt.h2
-rw-r--r--src/devices/bus/isa/mach32.cpp358
-rw-r--r--src/devices/bus/isa/mach32.h233
-rw-r--r--src/devices/bus/isa/mc1502_fdc.cpp3
-rw-r--r--src/devices/bus/isa/mc1502_fdc.h2
-rw-r--r--src/devices/bus/isa/mcd.cpp26
-rw-r--r--src/devices/bus/isa/mcd.h2
-rw-r--r--src/devices/bus/isa/mda.cpp6
-rw-r--r--src/devices/bus/isa/mda.h6
-rw-r--r--src/devices/bus/isa/mpu401.cpp2
-rw-r--r--src/devices/bus/isa/mpu401.h2
-rw-r--r--src/devices/bus/isa/mufdc.cpp5
-rw-r--r--src/devices/bus/isa/mufdc.h4
-rw-r--r--src/devices/bus/isa/myb3k_com.cpp16
-rw-r--r--src/devices/bus/isa/myb3k_com.h16
-rw-r--r--src/devices/bus/isa/myb3k_fdc.cpp7
-rw-r--r--src/devices/bus/isa/myb3k_fdc.h5
-rw-r--r--src/devices/bus/isa/ne1000.cpp15
-rw-r--r--src/devices/bus/isa/ne2000.cpp15
-rw-r--r--src/devices/bus/isa/np600.cpp33
-rw-r--r--src/devices/bus/isa/np600.h5
-rw-r--r--src/devices/bus/isa/omti8621.cpp22
-rw-r--r--src/devices/bus/isa/omti8621.h10
-rw-r--r--src/devices/bus/isa/opus100pm.cpp1
-rw-r--r--src/devices/bus/isa/p1_fdc.cpp3
-rw-r--r--src/devices/bus/isa/p1_fdc.h2
-rw-r--r--src/devices/bus/isa/p1_hdc.cpp3
-rw-r--r--src/devices/bus/isa/p1_sound.cpp2
-rw-r--r--src/devices/bus/isa/p1_sound.h2
-rw-r--r--src/devices/bus/isa/pgc.cpp3
-rw-r--r--src/devices/bus/isa/pgc.h2
-rw-r--r--src/devices/bus/isa/s3virge.cpp1624
-rw-r--r--src/devices/bus/isa/s3virge.h252
-rw-r--r--src/devices/bus/isa/sblaster.cpp25
-rw-r--r--src/devices/bus/isa/sblaster.h3
-rw-r--r--src/devices/bus/isa/sc499.cpp10
-rw-r--r--src/devices/bus/isa/sc499.h11
-rw-r--r--src/devices/bus/isa/side116.cpp2
-rw-r--r--src/devices/bus/isa/side116.h2
-rw-r--r--src/devices/bus/isa/svga_cirrus.cpp233
-rw-r--r--src/devices/bus/isa/svga_cirrus.h11
-rw-r--r--src/devices/bus/isa/svga_paradise.cpp649
-rw-r--r--src/devices/bus/isa/svga_paradise.h253
-rw-r--r--src/devices/bus/isa/svga_s3.cpp348
-rw-r--r--src/devices/bus/isa/svga_s3.h90
-rw-r--r--src/devices/bus/isa/svga_trident.cpp99
-rw-r--r--src/devices/bus/isa/svga_trident.h35
-rw-r--r--src/devices/bus/isa/svga_tseng.cpp69
-rw-r--r--src/devices/bus/isa/svga_tseng.h25
-rw-r--r--src/devices/bus/isa/tekram_dc820.cpp2
-rw-r--r--src/devices/bus/isa/trident.cpp1624
-rw-r--r--src/devices/bus/isa/trident.h168
-rw-r--r--src/devices/bus/isa/ultra14f.cpp4
-rw-r--r--src/devices/bus/isa/ultra24f.cpp2
-rw-r--r--src/devices/bus/isa/vga.cpp9
-rw-r--r--src/devices/bus/isa/vga.h2
-rw-r--r--src/devices/bus/isa/vga_ati.cpp40
-rw-r--r--src/devices/bus/isa/vga_ati.h16
-rw-r--r--src/devices/bus/isa/wdxt_gen.cpp8
-rw-r--r--src/devices/bus/isa/wdxt_gen.h8
-rw-r--r--src/devices/bus/isa/xtide.cpp8
-rw-r--r--src/devices/bus/isa/xtide.h2
-rw-r--r--src/devices/bus/isbx/compis_fdc.cpp22
-rw-r--r--src/devices/bus/isbx/compis_fdc.h8
-rw-r--r--src/devices/bus/isbx/isbc_218a.cpp6
-rw-r--r--src/devices/bus/isbx/isbc_218a.h5
-rw-r--r--src/devices/bus/isbx/isbx.cpp6
-rw-r--r--src/devices/bus/isbx/isbx.h22
-rw-r--r--src/devices/bus/jakks_gamekey/slot.cpp16
-rw-r--r--src/devices/bus/jakks_gamekey/slot.h10
-rw-r--r--src/devices/bus/kc/d002.cpp8
-rw-r--r--src/devices/bus/kc/d002.h8
-rw-r--r--src/devices/bus/kc/d004.cpp2
-rw-r--r--src/devices/bus/kc/d004.h2
-rw-r--r--src/devices/bus/kc/kc.cpp22
-rw-r--r--src/devices/bus/kc/kc.h12
-rw-r--r--src/devices/bus/kc/ram.cpp2
-rw-r--r--src/devices/bus/kc/ram.h2
-rw-r--r--src/devices/bus/kc/rom.cpp2
-rw-r--r--src/devices/bus/kc/rom.h2
-rw-r--r--src/devices/bus/kim1/cards.cpp20
-rw-r--r--src/devices/bus/kim1/cards.h16
-rw-r--r--src/devices/bus/kim1/k1008_vismem.cpp128
-rw-r--r--src/devices/bus/kim1/k1008_vismem.h21
-rw-r--r--src/devices/bus/kim1/k1016_16k.cpp48
-rw-r--r--src/devices/bus/kim1/k1016_16k.h21
-rw-r--r--src/devices/bus/kim1/kim1bus.cpp179
-rw-r--r--src/devices/bus/kim1/kim1bus.h131
-rw-r--r--src/devices/bus/lpci/cirrus.cpp9
-rw-r--r--src/devices/bus/lpci/i82371ab.cpp8
-rw-r--r--src/devices/bus/lpci/i82371sb.cpp3
-rw-r--r--src/devices/bus/lpci/i82439tx.cpp2
-rw-r--r--src/devices/bus/lpci/i82439tx.h2
-rw-r--r--src/devices/bus/lpci/mpc105.cpp9
-rw-r--r--src/devices/bus/lpci/pci.cpp15
-rw-r--r--src/devices/bus/lpci/southbridge.cpp46
-rw-r--r--src/devices/bus/lpci/southbridge.h30
-rw-r--r--src/devices/bus/m5/slot.cpp12
-rw-r--r--src/devices/bus/m5/slot.h10
-rw-r--r--src/devices/bus/mackbd/keyboard.cpp55
-rw-r--r--src/devices/bus/mackbd/mackbd.cpp8
-rw-r--r--src/devices/bus/mackbd/mackbd.h9
-rw-r--r--src/devices/bus/mackbd/pluskbd.cpp23
-rw-r--r--src/devices/bus/macpds/macpds.cpp19
-rw-r--r--src/devices/bus/macpds/macpds.h16
-rw-r--r--src/devices/bus/mc10/mc10_cart.cpp38
-rw-r--r--src/devices/bus/mc10/mc10_cart.h22
-rw-r--r--src/devices/bus/mc10/mcx128.cpp2
-rw-r--r--src/devices/bus/mc10/multiports_ext.cpp122
-rw-r--r--src/devices/bus/mc10/multiports_ext.h12
-rw-r--r--src/devices/bus/mc10/pak.cpp16
-rw-r--r--src/devices/bus/mc10/pak.h4
-rw-r--r--src/devices/bus/mc10/ram.cpp2
-rw-r--r--src/devices/bus/mc68000/cards.cpp19
-rw-r--r--src/devices/bus/mc68000/cards.h16
-rw-r--r--src/devices/bus/mc68000/floppy.cpp169
-rw-r--r--src/devices/bus/mc68000/floppy.h48
-rw-r--r--src/devices/bus/mc68000/ram.cpp41
-rw-r--r--src/devices/bus/mc68000/ram.h39
-rw-r--r--src/devices/bus/mc68000/sysbus.cpp169
-rw-r--r--src/devices/bus/mc68000/sysbus.h180
-rw-r--r--src/devices/bus/megadrive/jcart.cpp112
-rw-r--r--src/devices/bus/megadrive/jcart.h26
-rw-r--r--src/devices/bus/megadrive/md_slot.cpp37
-rw-r--r--src/devices/bus/megadrive/md_slot.h33
-rw-r--r--src/devices/bus/midi/midi.cpp3
-rw-r--r--src/devices/bus/midi/midi.h8
-rw-r--r--src/devices/bus/midi/midiinport.h2
-rw-r--r--src/devices/bus/midi/midioutport.h2
-rw-r--r--src/devices/bus/mononcol/carts.cpp13
-rw-r--r--src/devices/bus/mononcol/carts.h11
-rw-r--r--src/devices/bus/mononcol/rom.cpp38
-rw-r--r--src/devices/bus/mononcol/rom.h44
-rw-r--r--src/devices/bus/mononcol/slot.cpp100
-rw-r--r--src/devices/bus/mononcol/slot.h97
-rw-r--r--src/devices/bus/msx/beecard/beecard.cpp58
-rw-r--r--src/devices/bus/msx/beecard/beecard.h12
-rw-r--r--src/devices/bus/msx/cart/arc.cpp78
-rw-r--r--src/devices/bus/msx/cart/arc.h13
-rw-r--r--src/devices/bus/msx/cart/ascii.cpp366
-rw-r--r--src/devices/bus/msx/cart/ascii.h16
-rw-r--r--src/devices/bus/msx/cart/beepack.cpp93
-rw-r--r--src/devices/bus/msx/cart/beepack.h58
-rw-r--r--src/devices/bus/msx/cart/bm_012.cpp (renamed from src/devices/bus/msx_cart/bm_012.cpp)46
-rw-r--r--src/devices/bus/msx/cart/bm_012.h13
-rw-r--r--src/devices/bus/msx/cart/cartridge.cpp241
-rw-r--r--src/devices/bus/msx/cart/cartridge.h28
-rw-r--r--src/devices/bus/msx/cart/crossblaim.cpp63
-rw-r--r--src/devices/bus/msx/cart/crossblaim.h13
-rw-r--r--src/devices/bus/msx/cart/disk.cpp1405
-rw-r--r--src/devices/bus/msx/cart/disk.h10
-rw-r--r--src/devices/bus/msx/cart/dooly.cpp84
-rw-r--r--src/devices/bus/msx/cart/dooly.h13
-rw-r--r--src/devices/bus/msx/cart/easi_speech.cpp98
-rw-r--r--src/devices/bus/msx/cart/easi_speech.h13
-rw-r--r--src/devices/bus/msx/cart/fmpac.cpp178
-rw-r--r--src/devices/bus/msx/cart/fmpac.h13
-rw-r--r--src/devices/bus/msx/cart/fs_sr021.cpp192
-rw-r--r--src/devices/bus/msx/cart/fs_sr021.h13
-rw-r--r--src/devices/bus/msx/cart/fs_sr022.cpp95
-rw-r--r--src/devices/bus/msx/cart/fs_sr022.h13
-rw-r--r--src/devices/bus/msx/cart/halnote.cpp121
-rw-r--r--src/devices/bus/msx/cart/halnote.h13
-rw-r--r--src/devices/bus/msx/cart/hbi55.cpp182
-rw-r--r--src/devices/bus/msx/cart/hbi55.h13
-rw-r--r--src/devices/bus/msx/cart/hfox.cpp76
-rw-r--r--src/devices/bus/msx/cart/hfox.h13
-rw-r--r--src/devices/bus/msx/cart/holy_quran.cpp136
-rw-r--r--src/devices/bus/msx/cart/holy_quran.h13
-rw-r--r--src/devices/bus/msx/cart/ink.cpp92
-rw-r--r--src/devices/bus/msx/cart/ink.h13
-rw-r--r--src/devices/bus/msx/cart/kanji.cpp221
-rw-r--r--src/devices/bus/msx/cart/kanji.h14
-rw-r--r--src/devices/bus/msx/cart/konami.cpp941
-rw-r--r--src/devices/bus/msx/cart/konami.h21
-rw-r--r--src/devices/bus/msx/cart/korean.cpp381
-rw-r--r--src/devices/bus/msx/cart/korean.h17
-rw-r--r--src/devices/bus/msx/cart/loveplus.cpp116
-rw-r--r--src/devices/bus/msx/cart/loveplus.h13
-rw-r--r--src/devices/bus/msx/cart/majutsushi.cpp92
-rw-r--r--src/devices/bus/msx/cart/majutsushi.h13
-rw-r--r--src/devices/bus/msx/cart/matra.cpp98
-rw-r--r--src/devices/bus/msx/cart/matra.h13
-rw-r--r--src/devices/bus/msx/cart/moonsound.cpp (renamed from src/devices/bus/msx_cart/moonsound.cpp)82
-rw-r--r--src/devices/bus/msx/cart/moonsound.h13
-rw-r--r--src/devices/bus/msx/cart/msx_audio.cpp437
-rw-r--r--src/devices/bus/msx/cart/msx_audio.h15
-rw-r--r--src/devices/bus/msx/cart/msx_audio_kb.cpp (renamed from src/devices/bus/msx_cart/msx_audio_kb.cpp)30
-rw-r--r--src/devices/bus/msx/cart/msx_audio_kb.h (renamed from src/devices/bus/msx_cart/msx_audio_kb.h)10
-rw-r--r--src/devices/bus/msx/cart/msxdos2.cpp226
-rw-r--r--src/devices/bus/msx/cart/msxdos2.h14
-rw-r--r--src/devices/bus/msx/cart/nomapper.cpp152
-rw-r--r--src/devices/bus/msx/cart/nomapper.h13
-rw-r--r--src/devices/bus/msx/cart/quickdisk.cpp124
-rw-r--r--src/devices/bus/msx/cart/quickdisk.h13
-rw-r--r--src/devices/bus/msx/cart/ram.cpp349
-rw-r--r--src/devices/bus/msx/cart/ram.h11
-rw-r--r--src/devices/bus/msx/cart/rtype.cpp62
-rw-r--r--src/devices/bus/msx/cart/rtype.h13
-rw-r--r--src/devices/bus/msx/cart/scsi.cpp229
-rw-r--r--src/devices/bus/msx/cart/scsi.h13
-rw-r--r--src/devices/bus/msx/cart/slotexpander.cpp147
-rw-r--r--src/devices/bus/msx/cart/slotexpander.h13
-rw-r--r--src/devices/bus/msx/cart/slotoptions.cpp90
-rw-r--r--src/devices/bus/msx/cart/slotoptions.h94
-rw-r--r--src/devices/bus/msx/cart/softcard.cpp92
-rw-r--r--src/devices/bus/msx/cart/softcard.h58
-rw-r--r--src/devices/bus/msx/cart/super_swangi.cpp59
-rw-r--r--src/devices/bus/msx/cart/super_swangi.h13
-rw-r--r--src/devices/bus/msx/cart/superloderunner.cpp63
-rw-r--r--src/devices/bus/msx/cart/superloderunner.h13
-rw-r--r--src/devices/bus/msx/cart/yamaha_ucn01.cpp65
-rw-r--r--src/devices/bus/msx/cart/yamaha_ucn01.h13
-rw-r--r--src/devices/bus/msx/ctrl/ctrl.cpp61
-rw-r--r--src/devices/bus/msx/ctrl/ctrl.h85
-rw-r--r--src/devices/bus/msx/ctrl/hypershot.cpp85
-rw-r--r--src/devices/bus/msx/ctrl/hypershot.h19
-rw-r--r--src/devices/bus/msx/ctrl/joystick.cpp53
-rw-r--r--src/devices/bus/msx/ctrl/joystick.h19
-rw-r--r--src/devices/bus/msx/ctrl/libbler.cpp79
-rw-r--r--src/devices/bus/msx/ctrl/libbler.h19
-rw-r--r--src/devices/bus/msx/ctrl/magickey.cpp53
-rw-r--r--src/devices/bus/msx/ctrl/magickey.h19
-rw-r--r--src/devices/bus/msx/ctrl/mouse.cpp120
-rw-r--r--src/devices/bus/msx/ctrl/mouse.h19
-rw-r--r--src/devices/bus/msx/ctrl/sgadapt.cpp131
-rw-r--r--src/devices/bus/msx/ctrl/sgadapt.h20
-rw-r--r--src/devices/bus/msx/ctrl/towns6b.cpp90
-rw-r--r--src/devices/bus/msx/ctrl/towns6b.h19
-rw-r--r--src/devices/bus/msx/ctrl/townspad.cpp96
-rw-r--r--src/devices/bus/msx/ctrl/townspad.h20
-rw-r--r--src/devices/bus/msx/ctrl/vaus.cpp115
-rw-r--r--src/devices/bus/msx/ctrl/vaus.h19
-rw-r--r--src/devices/bus/msx/ctrl/xe1ap.cpp101
-rw-r--r--src/devices/bus/msx/ctrl/xe1ap.h19
-rw-r--r--src/devices/bus/msx/minicart/minicart.cpp35
-rw-r--r--src/devices/bus/msx/minicart/minicart.h38
-rw-r--r--src/devices/bus/msx/module/module.cpp41
-rw-r--r--src/devices/bus/msx/module/module.h66
-rw-r--r--src/devices/bus/msx/module/sfg.cpp212
-rw-r--r--src/devices/bus/msx/module/sfg.h14
-rw-r--r--src/devices/bus/msx/module/skw01.cpp176
-rw-r--r--src/devices/bus/msx/module/skw01.h12
-rw-r--r--src/devices/bus/msx/slot/ax230.cpp53
-rw-r--r--src/devices/bus/msx/slot/ax230.h38
-rw-r--r--src/devices/bus/msx/slot/bruc100.cpp50
-rw-r--r--src/devices/bus/msx/slot/bruc100.h35
-rw-r--r--src/devices/bus/msx/slot/bunsetsu.cpp (renamed from src/devices/bus/msx_slot/bunsetsu.cpp)34
-rw-r--r--src/devices/bus/msx/slot/bunsetsu.h (renamed from src/devices/bus/msx_slot/bunsetsu.h)15
-rw-r--r--src/devices/bus/msx/slot/cartridge.cpp130
-rw-r--r--src/devices/bus/msx/slot/cartridge.h113
-rw-r--r--src/devices/bus/msx/slot/disk.cpp1434
-rw-r--r--src/devices/bus/msx/slot/disk.h499
-rw-r--r--src/devices/bus/msx/slot/fs4600.cpp135
-rw-r--r--src/devices/bus/msx/slot/fs4600.h (renamed from src/devices/bus/msx_slot/fs4600.h)31
-rw-r--r--src/devices/bus/msx/slot/fsa1fm.cpp221
-rw-r--r--src/devices/bus/msx/slot/fsa1fm.h83
-rw-r--r--src/devices/bus/msx/slot/msx_rs232.cpp526
-rw-r--r--src/devices/bus/msx/slot/msx_rs232.h168
-rw-r--r--src/devices/bus/msx/slot/msx_write.cpp77
-rw-r--r--src/devices/bus/msx/slot/msx_write.h40
-rw-r--r--src/devices/bus/msx/slot/music.cpp22
-rw-r--r--src/devices/bus/msx/slot/music.h (renamed from src/devices/bus/msx_slot/music.h)20
-rw-r--r--src/devices/bus/msx/slot/panasonic08.cpp132
-rw-r--r--src/devices/bus/msx/slot/panasonic08.h (renamed from src/devices/bus/msx_slot/panasonic08.h)27
-rw-r--r--src/devices/bus/msx/slot/ram.cpp (renamed from src/devices/bus/msx_slot/ram.cpp)22
-rw-r--r--src/devices/bus/msx/slot/ram.h (renamed from src/devices/bus/msx_slot/ram.h)11
-rw-r--r--src/devices/bus/msx/slot/ram_mm.cpp60
-rw-r--r--src/devices/bus/msx/slot/ram_mm.h34
-rw-r--r--src/devices/bus/msx/slot/rom.cpp (renamed from src/devices/bus/msx_slot/rom.cpp)20
-rw-r--r--src/devices/bus/msx/slot/rom.h (renamed from src/devices/bus/msx_slot/rom.h)11
-rw-r--r--src/devices/bus/msx/slot/slot.cpp (renamed from src/devices/bus/msx_slot/slot.cpp)17
-rw-r--r--src/devices/bus/msx/slot/slot.h (renamed from src/devices/bus/msx_slot/slot.h)31
-rw-r--r--src/devices/bus/msx/slot/sony08.cpp87
-rw-r--r--src/devices/bus/msx/slot/sony08.h (renamed from src/devices/bus/msx_slot/sony08.h)26
-rw-r--r--src/devices/bus/msx/softcard/softcard.cpp56
-rw-r--r--src/devices/bus/msx/softcard/softcard.h12
-rw-r--r--src/devices/bus/msx_cart/arc.cpp63
-rw-r--r--src/devices/bus/msx_cart/arc.h35
-rw-r--r--src/devices/bus/msx_cart/ascii.cpp555
-rw-r--r--src/devices/bus/msx_cart/ascii.h148
-rw-r--r--src/devices/bus/msx_cart/bm_012.h39
-rw-r--r--src/devices/bus/msx_cart/cartridge.cpp132
-rw-r--r--src/devices/bus/msx_cart/cartridge.h63
-rw-r--r--src/devices/bus/msx_cart/crossblaim.cpp86
-rw-r--r--src/devices/bus/msx_cart/crossblaim.h40
-rw-r--r--src/devices/bus/msx_cart/disk.cpp613
-rw-r--r--src/devices/bus/msx_cart/disk.h145
-rw-r--r--src/devices/bus/msx_cart/dooly.cpp67
-rw-r--r--src/devices/bus/msx_cart/dooly.h34
-rw-r--r--src/devices/bus/msx_cart/easi_speech.cpp62
-rw-r--r--src/devices/bus/msx_cart/easi_speech.h33
-rw-r--r--src/devices/bus/msx_cart/fmpac.cpp171
-rw-r--r--src/devices/bus/msx_cart/fmpac.h50
-rw-r--r--src/devices/bus/msx_cart/fs_sr022.cpp71
-rw-r--r--src/devices/bus/msx_cart/fs_sr022.h35
-rw-r--r--src/devices/bus/msx_cart/halnote.cpp160
-rw-r--r--src/devices/bus/msx_cart/halnote.h40
-rw-r--r--src/devices/bus/msx_cart/hfox.cpp83
-rw-r--r--src/devices/bus/msx_cart/hfox.h36
-rw-r--r--src/devices/bus/msx_cart/holy_quran.cpp119
-rw-r--r--src/devices/bus/msx_cart/holy_quran.h40
-rw-r--r--src/devices/bus/msx_cart/ink.cpp55
-rw-r--r--src/devices/bus/msx_cart/ink.h36
-rw-r--r--src/devices/bus/msx_cart/konami.cpp944
-rw-r--r--src/devices/bus/msx_cart/konami.h207
-rw-r--r--src/devices/bus/msx_cart/korean.cpp300
-rw-r--r--src/devices/bus/msx_cart/korean.h94
-rw-r--r--src/devices/bus/msx_cart/majutsushi.cpp116
-rw-r--r--src/devices/bus/msx_cart/majutsushi.h43
-rw-r--r--src/devices/bus/msx_cart/moonsound.h42
-rw-r--r--src/devices/bus/msx_cart/msx_audio.cpp379
-rw-r--r--src/devices/bus/msx_cart/msx_audio.h99
-rw-r--r--src/devices/bus/msx_cart/msxdos2.cpp71
-rw-r--r--src/devices/bus/msx_cart/msxdos2.h38
-rw-r--r--src/devices/bus/msx_cart/nomapper.cpp94
-rw-r--r--src/devices/bus/msx_cart/nomapper.h31
-rw-r--r--src/devices/bus/msx_cart/rtype.cpp82
-rw-r--r--src/devices/bus/msx_cart/rtype.h38
-rw-r--r--src/devices/bus/msx_cart/super_swangi.cpp76
-rw-r--r--src/devices/bus/msx_cart/super_swangi.h38
-rw-r--r--src/devices/bus/msx_cart/superloderunner.cpp65
-rw-r--r--src/devices/bus/msx_cart/superloderunner.h38
-rw-r--r--src/devices/bus/msx_cart/yamaha.cpp208
-rw-r--r--src/devices/bus/msx_cart/yamaha.h67
-rw-r--r--src/devices/bus/msx_slot/cartridge.cpp372
-rw-r--r--src/devices/bus/msx_slot/cartridge.h74
-rw-r--r--src/devices/bus/msx_slot/disk.cpp806
-rw-r--r--src/devices/bus/msx_slot/disk.h201
-rw-r--r--src/devices/bus/msx_slot/fs4600.cpp142
-rw-r--r--src/devices/bus/msx_slot/music.cpp48
-rw-r--r--src/devices/bus/msx_slot/panasonic08.cpp164
-rw-r--r--src/devices/bus/msx_slot/ram_mm.cpp82
-rw-r--r--src/devices/bus/msx_slot/ram_mm.h39
-rw-r--r--src/devices/bus/msx_slot/sony08.cpp172
-rw-r--r--src/devices/bus/mtu130/board.cpp37
-rw-r--r--src/devices/bus/mtu130/board.h69
-rw-r--r--src/devices/bus/mtu130/datamover.cpp172
-rw-r--r--src/devices/bus/mtu130/datamover.h72
-rw-r--r--src/devices/bus/mtx/cfx.cpp2
-rw-r--r--src/devices/bus/mtx/exp.cpp18
-rw-r--r--src/devices/bus/mtx/exp.h14
-rw-r--r--src/devices/bus/mtx/sdx.cpp43
-rw-r--r--src/devices/bus/mtx/sdx.h8
-rw-r--r--src/devices/bus/multibus/isbc202.cpp6
-rw-r--r--src/devices/bus/multibus/isbc202.h2
-rw-r--r--src/devices/bus/multibus/labtam_3232.cpp15
-rw-r--r--src/devices/bus/multibus/labtam_vducom.cpp301
-rw-r--r--src/devices/bus/multibus/labtam_vducom.h63
-rw-r--r--src/devices/bus/multibus/labtam_z80sbc.cpp45
-rw-r--r--src/devices/bus/multibus/labtam_z80sbc.h3
-rw-r--r--src/devices/bus/multibus/multibus.cpp2
-rw-r--r--src/devices/bus/multibus/robotron_k7070.cpp423
-rw-r--r--src/devices/bus/multibus/robotron_k7070.h77
-rw-r--r--src/devices/bus/multibus/robotron_k7071.cpp222
-rw-r--r--src/devices/bus/multibus/robotron_k7071.h61
-rw-r--r--src/devices/bus/nabupc/adapter.cpp423
-rw-r--r--src/devices/bus/nabupc/adapter.h153
-rw-r--r--src/devices/bus/nabupc/fdc.cpp167
-rw-r--r--src/devices/bus/nabupc/fdc.h19
-rw-r--r--src/devices/bus/nabupc/hdd.cpp113
-rw-r--r--src/devices/bus/nabupc/hdd.h19
-rw-r--r--src/devices/bus/nabupc/option.cpp135
-rw-r--r--src/devices/bus/nabupc/option.h156
-rw-r--r--src/devices/bus/nabupc/rs232.cpp141
-rw-r--r--src/devices/bus/nabupc/rs232.h20
-rw-r--r--src/devices/bus/nasbus/nasbus.cpp10
-rw-r--r--src/devices/bus/nasbus/nasbus.h22
-rw-r--r--src/devices/bus/neogeo/prot_cmc.cpp39
-rw-r--r--src/devices/bus/neogeo/prot_cmc.h1
-rw-r--r--src/devices/bus/neogeo/prot_mslugx.cpp2
-rw-r--r--src/devices/bus/neogeo/prot_mslugx.h2
-rw-r--r--src/devices/bus/neogeo/sbp.cpp23
-rw-r--r--src/devices/bus/neogeo/slot.cpp7
-rw-r--r--src/devices/bus/neogeo/slot.h9
-rw-r--r--src/devices/bus/nes/2a03pur.cpp11
-rw-r--r--src/devices/bus/nes/act53.cpp11
-rw-r--r--src/devices/bus/nes/aladdin.cpp43
-rw-r--r--src/devices/bus/nes/aladdin.h13
-rw-r--r--src/devices/bus/nes/ave.cpp13
-rw-r--r--src/devices/bus/nes/bandai.cpp35
-rw-r--r--src/devices/bus/nes/batlab.cpp21
-rw-r--r--src/devices/bus/nes/benshieng.cpp9
-rw-r--r--src/devices/bus/nes/bootleg.cpp141
-rw-r--r--src/devices/bus/nes/camerica.cpp13
-rw-r--r--src/devices/bus/nes/cne.cpp15
-rw-r--r--src/devices/bus/nes/cony.cpp19
-rw-r--r--src/devices/bus/nes/datach.cpp35
-rw-r--r--src/devices/bus/nes/datach.h21
-rw-r--r--src/devices/bus/nes/discrete.cpp15
-rw-r--r--src/devices/bus/nes/disksys.cpp23
-rw-r--r--src/devices/bus/nes/event.cpp16
-rw-r--r--src/devices/bus/nes/ggenie.cpp22
-rw-r--r--src/devices/bus/nes/henggedianzi.cpp17
-rw-r--r--src/devices/bus/nes/hes.cpp9
-rw-r--r--src/devices/bus/nes/irem.cpp17
-rw-r--r--src/devices/bus/nes/jaleco.cpp24
-rw-r--r--src/devices/bus/nes/jncota.cpp9
-rw-r--r--src/devices/bus/nes/jy.cpp15
-rw-r--r--src/devices/bus/nes/kaiser.cpp74
-rw-r--r--src/devices/bus/nes/karastudio.cpp17
-rw-r--r--src/devices/bus/nes/karastudio.h17
-rw-r--r--src/devices/bus/nes/konami.cpp33
-rw-r--r--src/devices/bus/nes/legacy.cpp21
-rw-r--r--src/devices/bus/nes/mmc1.cpp21
-rw-r--r--src/devices/bus/nes/mmc1_clones.cpp27
-rw-r--r--src/devices/bus/nes/mmc2.cpp25
-rw-r--r--src/devices/bus/nes/mmc3.cpp30
-rw-r--r--src/devices/bus/nes/mmc3_clones.cpp170
-rw-r--r--src/devices/bus/nes/mmc5.cpp42
-rw-r--r--src/devices/bus/nes/multigame.cpp207
-rw-r--r--src/devices/bus/nes/namcot.cpp33
-rw-r--r--src/devices/bus/nes/nanjing.cpp13
-rw-r--r--src/devices/bus/nes/nes_ines.hxx4
-rw-r--r--src/devices/bus/nes/nes_pcb.hxx6
-rw-r--r--src/devices/bus/nes/nes_slot.cpp39
-rw-r--r--src/devices/bus/nes/nes_slot.h25
-rw-r--r--src/devices/bus/nes/nes_unif.hxx67
-rw-r--r--src/devices/bus/nes/ntdec.cpp13
-rw-r--r--src/devices/bus/nes/nxrom.cpp47
-rw-r--r--src/devices/bus/nes/pirate.cpp57
-rw-r--r--src/devices/bus/nes/pt554.cpp9
-rw-r--r--src/devices/bus/nes/racermate.cpp11
-rw-r--r--src/devices/bus/nes/rcm.cpp18
-rw-r--r--src/devices/bus/nes/rexsoft.cpp13
-rw-r--r--src/devices/bus/nes/sachen.cpp50
-rw-r--r--src/devices/bus/nes/sealie.cpp15
-rw-r--r--src/devices/bus/nes/somari.cpp11
-rw-r--r--src/devices/bus/nes/subor.cpp15
-rw-r--r--src/devices/bus/nes/sunsoft.cpp30
-rw-r--r--src/devices/bus/nes/sunsoft_dcs.cpp30
-rw-r--r--src/devices/bus/nes/sunsoft_dcs.h17
-rw-r--r--src/devices/bus/nes/taito.cpp23
-rw-r--r--src/devices/bus/nes/tengen.cpp13
-rw-r--r--src/devices/bus/nes/txc.cpp33
-rw-r--r--src/devices/bus/nes/vrc_clones.cpp49
-rw-r--r--src/devices/bus/nes/waixing.cpp70
-rw-r--r--src/devices/bus/nes/zemina.cpp9
-rw-r--r--src/devices/bus/nes_ctrl/arkpaddle.cpp18
-rw-r--r--src/devices/bus/nes_ctrl/bandaihs.cpp132
-rw-r--r--src/devices/bus/nes_ctrl/bandaihs.h53
-rw-r--r--src/devices/bus/nes_ctrl/ctrl.cpp4
-rw-r--r--src/devices/bus/nes_ctrl/fckeybrd.cpp221
-rw-r--r--src/devices/bus/nes_ctrl/fckeybrd.h13
-rw-r--r--src/devices/bus/nes_ctrl/rob.cpp25
-rw-r--r--src/devices/bus/nes_ctrl/sharpcass.cpp89
-rw-r--r--src/devices/bus/nes_ctrl/sharpcass.h48
-rw-r--r--src/devices/bus/nes_ctrl/zapper.cpp101
-rw-r--r--src/devices/bus/nes_ctrl/zapper.h31
-rw-r--r--src/devices/bus/newbrain/eim.cpp6
-rw-r--r--src/devices/bus/newbrain/eim.h6
-rw-r--r--src/devices/bus/newbrain/fdc.cpp2
-rw-r--r--src/devices/bus/newbrain/fdc.h2
-rw-r--r--src/devices/bus/nscsi/cd.cpp778
-rw-r--r--src/devices/bus/nscsi/cd.h40
-rw-r--r--src/devices/bus/nscsi/cdd2000.cpp15
-rw-r--r--src/devices/bus/nscsi/cdd2000.h2
-rw-r--r--src/devices/bus/nscsi/cdu415.cpp5
-rw-r--r--src/devices/bus/nscsi/cdu415.h3
-rw-r--r--src/devices/bus/nscsi/cdu75s.cpp5
-rw-r--r--src/devices/bus/nscsi/cdu75s.h3
-rw-r--r--src/devices/bus/nscsi/crd254sh.cpp5
-rw-r--r--src/devices/bus/nscsi/crd254sh.h3
-rw-r--r--src/devices/bus/nscsi/cw7501.cpp2
-rw-r--r--src/devices/bus/nscsi/devices.cpp2
-rw-r--r--src/devices/bus/nscsi/hd.cpp135
-rw-r--r--src/devices/bus/nscsi/hd.h1
-rw-r--r--src/devices/bus/nscsi/s1410.cpp70
-rw-r--r--src/devices/bus/nscsi/s1410.h12
-rw-r--r--src/devices/bus/nscsi/tape.cpp899
-rw-r--r--src/devices/bus/nscsi/tape.h83
-rw-r--r--src/devices/bus/nubus/8lc.cpp421
-rw-r--r--src/devices/bus/nubus/8lc.h12
-rw-r--r--src/devices/bus/nubus/cards.cpp51
-rw-r--r--src/devices/bus/nubus/cards.h5
-rw-r--r--src/devices/bus/nubus/laserview.cpp273
-rw-r--r--src/devices/bus/nubus/laserview.h40
-rw-r--r--src/devices/bus/nubus/nubus.cpp68
-rw-r--r--src/devices/bus/nubus/nubus.h38
-rw-r--r--src/devices/bus/nubus/nubus_48gc.cpp4
-rw-r--r--src/devices/bus/nubus/nubus_asntmc3b.cpp200
-rw-r--r--src/devices/bus/nubus/nubus_asntmc3b.h58
-rw-r--r--src/devices/bus/nubus/nubus_cb264.cpp205
-rw-r--r--src/devices/bus/nubus/nubus_cb264.h42
-rw-r--r--src/devices/bus/nubus/nubus_image.cpp29
-rw-r--r--src/devices/bus/nubus/nubus_spec8.cpp4
-rw-r--r--src/devices/bus/nubus/nubus_specpdq.cpp4
-rw-r--r--src/devices/bus/nubus/nubus_vikbw.cpp154
-rw-r--r--src/devices/bus/nubus/nubus_vikbw.h40
-rw-r--r--src/devices/bus/nubus/nubus_wsportrait.cpp217
-rw-r--r--src/devices/bus/nubus/nubus_wsportrait.h46
-rw-r--r--src/devices/bus/nubus/pds30_cb264.cpp6
-rw-r--r--src/devices/bus/nubus/thunder4gx.cpp807
-rw-r--r--src/devices/bus/nubus/thunder4gx.h12
-rw-r--r--src/devices/bus/odyssey2/4in1.cpp32
-rw-r--r--src/devices/bus/odyssey2/4in1.h31
-rw-r--r--src/devices/bus/odyssey2/chess.cpp91
-rw-r--r--src/devices/bus/odyssey2/chess.h42
-rw-r--r--src/devices/bus/odyssey2/homecomp.cpp127
-rw-r--r--src/devices/bus/odyssey2/homecomp.h51
-rw-r--r--src/devices/bus/odyssey2/ktaa.cpp31
-rw-r--r--src/devices/bus/odyssey2/ktaa.h30
-rw-r--r--src/devices/bus/odyssey2/rally.cpp31
-rw-r--r--src/devices/bus/odyssey2/rally.h30
-rw-r--r--src/devices/bus/odyssey2/rom.cpp30
-rw-r--r--src/devices/bus/odyssey2/rom.h29
-rw-r--r--src/devices/bus/odyssey2/slot.cpp44
-rw-r--r--src/devices/bus/odyssey2/slot.h12
-rw-r--r--src/devices/bus/odyssey2/test.cpp33
-rw-r--r--src/devices/bus/odyssey2/test.h32
-rw-r--r--src/devices/bus/odyssey2/voice.cpp92
-rw-r--r--src/devices/bus/odyssey2/voice.h44
-rw-r--r--src/devices/bus/oricext/jasmin.cpp67
-rw-r--r--src/devices/bus/oricext/jasmin.h13
-rw-r--r--src/devices/bus/oricext/microdisc.cpp71
-rw-r--r--src/devices/bus/oricext/microdisc.h25
-rw-r--r--src/devices/bus/oricext/oricext.cpp65
-rw-r--r--src/devices/bus/oricext/oricext.h27
-rw-r--r--src/devices/bus/pasopia/rampac2.cpp8
-rw-r--r--src/devices/bus/pc1512/mouse.cpp6
-rw-r--r--src/devices/bus/pc8801/README.md39
-rw-r--r--src/devices/bus/pc8801/hmb20.cpp42
-rw-r--r--src/devices/bus/pc8801/hmb20.h28
-rw-r--r--src/devices/bus/pc8801/jmbx1.cpp2
-rw-r--r--src/devices/bus/pc8801/pc8801_23.cpp2
-rw-r--r--src/devices/bus/pc8801/pc8801_23.h2
-rw-r--r--src/devices/bus/pc8801/pc8801_31.cpp6
-rw-r--r--src/devices/bus/pc8801/pc8801_31.h3
-rw-r--r--src/devices/bus/pc8801/pc8801_exp.cpp56
-rw-r--r--src/devices/bus/pc8801/pc8801_exp.h9
-rw-r--r--src/devices/bus/pc_joy/pc_joy.cpp15
-rw-r--r--src/devices/bus/pc_joy/pc_joy.h5
-rw-r--r--src/devices/bus/pc_joy/pc_joy_magnum6.cpp41
-rw-r--r--src/devices/bus/pc_joy/pc_joy_magnum6.h24
-rw-r--r--src/devices/bus/pc_kbd/cherry_mx1500.cpp42
-rw-r--r--src/devices/bus/pc_kbd/cherry_mx1500.h2
-rw-r--r--src/devices/bus/pc_kbd/ec1841.cpp29
-rw-r--r--src/devices/bus/pc_kbd/ec1841.h6
-rw-r--r--src/devices/bus/pc_kbd/hle_mouse.cpp1
-rw-r--r--src/devices/bus/pc_kbd/iskr1030.cpp11
-rw-r--r--src/devices/bus/pc_kbd/iskr1030.h6
-rw-r--r--src/devices/bus/pc_kbd/keytro.cpp4
-rw-r--r--src/devices/bus/pc_kbd/keytro.h4
-rw-r--r--src/devices/bus/pc_kbd/msnat.cpp4
-rw-r--r--src/devices/bus/pc_kbd/msnat.h4
-rw-r--r--src/devices/bus/pc_kbd/pc83.cpp2
-rw-r--r--src/devices/bus/pc_kbd/pc83.h6
-rw-r--r--src/devices/bus/pc_kbd/pc_kbdc.cpp15
-rw-r--r--src/devices/bus/pc_kbd/pc_kbdc.h12
-rw-r--r--src/devices/bus/pc_kbd/pcat101.cpp1
-rw-r--r--src/devices/bus/pc_kbd/pcat84.cpp12
-rw-r--r--src/devices/bus/pc_kbd/pcat84.h8
-rw-r--r--src/devices/bus/pc_kbd/pcxt83.cpp16
-rw-r--r--src/devices/bus/pc_kbd/pcxt83.h8
-rw-r--r--src/devices/bus/pce/pce_acard.cpp232
-rw-r--r--src/devices/bus/pce/pce_acard.h114
-rw-r--r--src/devices/bus/pce/pce_rom.cpp151
-rw-r--r--src/devices/bus/pce/pce_rom.h46
-rw-r--r--src/devices/bus/pce/pce_scdsys.cpp98
-rw-r--r--src/devices/bus/pce/pce_scdsys.h83
-rw-r--r--src/devices/bus/pce/pce_slot.cpp66
-rw-r--r--src/devices/bus/pce/pce_slot.h33
-rw-r--r--src/devices/bus/pce_ctrl/joypad2.cpp94
-rw-r--r--src/devices/bus/pce_ctrl/joypad2.h76
-rw-r--r--src/devices/bus/pce_ctrl/joypad6.cpp96
-rw-r--r--src/devices/bus/pce_ctrl/joypad6.h91
-rw-r--r--src/devices/bus/pce_ctrl/mouse.cpp137
-rw-r--r--src/devices/bus/pce_ctrl/mouse.h18
-rw-r--r--src/devices/bus/pce_ctrl/pcectrl.cpp21
-rw-r--r--src/devices/bus/pce_ctrl/xhe3.cpp92
-rw-r--r--src/devices/bus/pce_ctrl/xhe3.h18
-rw-r--r--src/devices/bus/pci/aha2940au.cpp96
-rw-r--r--src/devices/bus/pci/aha2940au.h40
-rw-r--r--src/devices/bus/pci/audiowerk2.cpp93
-rw-r--r--src/devices/bus/pci/audiowerk2.h38
-rw-r--r--src/devices/bus/pci/clgd5446.cpp146
-rw-r--r--src/devices/bus/pci/clgd5446.h47
-rw-r--r--src/devices/bus/pci/clgd546x_laguna.cpp205
-rw-r--r--src/devices/bus/pci/clgd546x_laguna.h48
-rw-r--r--src/devices/bus/pci/ds2416.cpp23
-rw-r--r--src/devices/bus/pci/ds2416.h22
-rw-r--r--src/devices/bus/pci/ess_maestro.cpp117
-rw-r--r--src/devices/bus/pci/ess_maestro.h44
-rw-r--r--src/devices/bus/pci/geforce.cpp114
-rw-r--r--src/devices/bus/pci/geforce.h52
-rw-r--r--src/devices/bus/pci/mga2064w.cpp720
-rw-r--r--src/devices/bus/pci/mga2064w.h97
-rw-r--r--src/devices/bus/pci/opti82c861.cpp81
-rw-r--r--src/devices/bus/pci/opti82c861.h33
-rw-r--r--src/devices/bus/pci/oti_spitfire.cpp146
-rw-r--r--src/devices/bus/pci/oti_spitfire.h48
-rw-r--r--src/devices/bus/pci/pci_slot.cpp177
-rw-r--r--src/devices/bus/pci/pci_slot.h92
-rw-r--r--src/devices/bus/pci/pdc20262.cpp263
-rw-r--r--src/devices/bus/pci/pdc20262.h65
-rw-r--r--src/devices/bus/pci/promotion.cpp153
-rw-r--r--src/devices/bus/pci/promotion.h49
-rw-r--r--src/devices/bus/pci/riva128.cpp250
-rw-r--r--src/devices/bus/pci/riva128.h65
-rw-r--r--src/devices/bus/pci/rivatnt.cpp231
-rw-r--r--src/devices/bus/pci/rivatnt.h73
-rw-r--r--src/devices/bus/pci/rtl8029as_pci.cpp79
-rw-r--r--src/devices/bus/pci/rtl8029as_pci.h38
-rw-r--r--src/devices/bus/pci/rtl8139_pci.cpp86
-rw-r--r--src/devices/bus/pci/rtl8139_pci.h38
-rw-r--r--src/devices/bus/pci/sis6326.cpp202
-rw-r--r--src/devices/bus/pci/sis6326.h59
-rw-r--r--src/devices/bus/pci/sonicvibes.cpp163
-rw-r--r--src/devices/bus/pci/sonicvibes.h44
-rw-r--r--src/devices/bus/pci/sw1000xg.cpp94
-rw-r--r--src/devices/bus/pci/sw1000xg.h35
-rw-r--r--src/devices/bus/pci/virge_pci.cpp251
-rw-r--r--src/devices/bus/pci/virge_pci.h93
-rw-r--r--src/devices/bus/pci/vision.cpp286
-rw-r--r--src/devices/bus/pci/vision.h76
-rw-r--r--src/devices/bus/pci/vt6306.cpp97
-rw-r--r--src/devices/bus/pci/vt6306.h38
-rw-r--r--src/devices/bus/pci/wd9710_pci.cpp132
-rw-r--r--src/devices/bus/pci/wd9710_pci.h49
-rw-r--r--src/devices/bus/pci/ymp21.cpp219
-rw-r--r--src/devices/bus/pci/ymp21.h58
-rw-r--r--src/devices/bus/pci/zr36057.cpp87
-rw-r--r--src/devices/bus/pci/zr36057.h39
-rw-r--r--src/devices/bus/pet/2joysnd.cpp2
-rw-r--r--src/devices/bus/pet/2joysnd.h14
-rw-r--r--src/devices/bus/pet/c2n.cpp2
-rw-r--r--src/devices/bus/pet/c2n.h1
-rw-r--r--src/devices/bus/pet/cass.cpp13
-rw-r--r--src/devices/bus/pet/cass.h10
-rw-r--r--src/devices/bus/pet/cb2snd.cpp2
-rw-r--r--src/devices/bus/pet/cb2snd.h2
-rw-r--r--src/devices/bus/pet/diag.h26
-rw-r--r--src/devices/bus/pet/exp.cpp10
-rw-r--r--src/devices/bus/pet/exp.h4
-rw-r--r--src/devices/bus/pet/petuja.h12
-rw-r--r--src/devices/bus/pet/superpet.cpp2
-rw-r--r--src/devices/bus/pet/superpet.h2
-rw-r--r--src/devices/bus/pet/user.cpp58
-rw-r--r--src/devices/bus/pet/user.h114
-rw-r--r--src/devices/bus/plg1x0/plg100-vl.cpp96
-rw-r--r--src/devices/bus/plg1x0/plg100-vl.h15
-rw-r--r--src/devices/bus/plg1x0/plg150-ap.cpp92
-rw-r--r--src/devices/bus/plg1x0/plg150-ap.h15
-rw-r--r--src/devices/bus/plg1x0/plg1x0.cpp51
-rw-r--r--src/devices/bus/plg1x0/plg1x0.h82
-rw-r--r--src/devices/bus/plus4/c1551.cpp4
-rw-r--r--src/devices/bus/plus4/diag264_lb_user.h34
-rw-r--r--src/devices/bus/plus4/exp.cpp18
-rw-r--r--src/devices/bus/plus4/exp.h12
-rw-r--r--src/devices/bus/pofo/ccm.cpp18
-rw-r--r--src/devices/bus/pofo/ccm.h8
-rw-r--r--src/devices/bus/pofo/exp.cpp11
-rw-r--r--src/devices/bus/pofo/exp.h16
-rw-r--r--src/devices/bus/pofo/hpc104.cpp19
-rw-r--r--src/devices/bus/pofo/hpc104.h20
-rw-r--r--src/devices/bus/pofo/ram.cpp19
-rw-r--r--src/devices/bus/pofo/ram.h12
-rw-r--r--src/devices/bus/psi_kbd/psi_kbd.cpp6
-rw-r--r--src/devices/bus/psi_kbd/psi_kbd.h6
-rw-r--r--src/devices/bus/psion/honda/slot.cpp124
-rw-r--r--src/devices/bus/psion/honda/slot.h119
-rw-r--r--src/devices/bus/psion/honda/ssd.cpp56
-rw-r--r--src/devices/bus/psion/honda/ssd.h51
-rw-r--r--src/devices/bus/psion/module/slot.cpp113
-rw-r--r--src/devices/bus/psion/module/slot.h116
-rw-r--r--src/devices/bus/psion/sibo/3fax.cpp (renamed from src/devices/bus/gamegear/smsctrladp.cpp)76
-rw-r--r--src/devices/bus/psion/sibo/3fax.h54
-rw-r--r--src/devices/bus/psion/sibo/3link.cpp151
-rw-r--r--src/devices/bus/psion/sibo/3link.h83
-rw-r--r--src/devices/bus/psion/sibo/slot.cpp98
-rw-r--r--src/devices/bus/psion/sibo/slot.h90
-rw-r--r--src/devices/bus/psx/ctlrport.cpp16
-rw-r--r--src/devices/bus/psx/ctlrport.h31
-rw-r--r--src/devices/bus/psx/gamebooster.cpp126
-rw-r--r--src/devices/bus/psx/gamebooster.h31
-rw-r--r--src/devices/bus/psx/memcard.cpp34
-rw-r--r--src/devices/bus/psx/memcard.h4
-rw-r--r--src/devices/bus/psx/multitap.cpp8
-rw-r--r--src/devices/bus/qbus/dvk_mx.cpp770
-rw-r--r--src/devices/bus/qbus/dvk_mx.h176
-rw-r--r--src/devices/bus/qbus/pc11.cpp7
-rw-r--r--src/devices/bus/qbus/pc11.h10
-rw-r--r--src/devices/bus/qbus/qbus.cpp55
-rw-r--r--src/devices/bus/qbus/qbus.h48
-rw-r--r--src/devices/bus/qbus/qg640.cpp106
-rw-r--r--src/devices/bus/qbus/qg640.h54
-rw-r--r--src/devices/bus/qbus/qtx.cpp2
-rw-r--r--src/devices/bus/qbus/qtx.h2
-rw-r--r--src/devices/bus/qbus/uknc_kmd.cpp87
-rw-r--r--src/devices/bus/qbus/uknc_kmd.h43
-rw-r--r--src/devices/bus/ql/cst_q_plus4.cpp2
-rw-r--r--src/devices/bus/ql/cst_q_plus4.h8
-rw-r--r--src/devices/bus/ql/exp.cpp6
-rw-r--r--src/devices/bus/ql/exp.h10
-rw-r--r--src/devices/bus/ql/rom.cpp14
-rw-r--r--src/devices/bus/ql/rom.h10
-rw-r--r--src/devices/bus/ql/sandy_superdisk.cpp15
-rw-r--r--src/devices/bus/ql/sandy_superdisk.h6
-rw-r--r--src/devices/bus/ql/sandy_superqboard.cpp15
-rw-r--r--src/devices/bus/ql/sandy_superqboard.h6
-rw-r--r--src/devices/bus/ql/trumpcard.cpp12
-rw-r--r--src/devices/bus/ql/trumpcard.h4
-rw-r--r--src/devices/bus/rc2014/cf.cpp2
-rw-r--r--src/devices/bus/rc2014/clock.cpp14
-rw-r--r--src/devices/bus/rc2014/fdc.cpp17
-rw-r--r--src/devices/bus/rc2014/micro.cpp27
-rw-r--r--src/devices/bus/rc2014/ram.cpp22
-rw-r--r--src/devices/bus/rc2014/rc2014.cpp176
-rw-r--r--src/devices/bus/rc2014/rc2014.h145
-rw-r--r--src/devices/bus/rc2014/serial.cpp70
-rw-r--r--src/devices/bus/rc2014/z180cpu.cpp26
-rw-r--r--src/devices/bus/rc2014/z80cpu.cpp21
-rw-r--r--src/devices/bus/rs232/exorterm.cpp6
-rw-r--r--src/devices/bus/rs232/exorterm.h6
-rw-r--r--src/devices/bus/rs232/hlemouse.cpp6
-rw-r--r--src/devices/bus/rs232/hlemouse.h4
-rw-r--r--src/devices/bus/rs232/ie15.cpp2
-rw-r--r--src/devices/bus/rs232/keyboard.cpp4
-rw-r--r--src/devices/bus/rs232/keyboard.h4
-rw-r--r--src/devices/bus/rs232/loopback.cpp18
-rw-r--r--src/devices/bus/rs232/loopback.h14
-rw-r--r--src/devices/bus/rs232/mboardd.cpp4
-rw-r--r--src/devices/bus/rs232/nss_tvinterface.cpp249
-rw-r--r--src/devices/bus/rs232/nss_tvinterface.h18
-rw-r--r--src/devices/bus/rs232/null_modem.cpp20
-rw-r--r--src/devices/bus/rs232/null_modem.h8
-rw-r--r--src/devices/bus/rs232/patchbox.cpp12
-rw-r--r--src/devices/bus/rs232/printer.cpp4
-rw-r--r--src/devices/bus/rs232/printer.h6
-rw-r--r--src/devices/bus/rs232/pty.cpp69
-rw-r--r--src/devices/bus/rs232/pty.h10
-rw-r--r--src/devices/bus/rs232/rs232.cpp23
-rw-r--r--src/devices/bus/rs232/rs232.h63
-rw-r--r--src/devices/bus/rs232/rs232_sync_io.cpp8
-rw-r--r--src/devices/bus/rs232/rs232_sync_io.h6
-rw-r--r--src/devices/bus/rs232/scorpion.cpp199
-rw-r--r--src/devices/bus/rs232/scorpion.h13
-rw-r--r--src/devices/bus/rs232/sun_kbd.cpp2
-rw-r--r--src/devices/bus/rs232/swtpc8212.cpp6
-rw-r--r--src/devices/bus/rs232/swtpc8212.h6
-rw-r--r--src/devices/bus/rs232/terminal.cpp6
-rw-r--r--src/devices/bus/rs232/xvd701.cpp2
-rw-r--r--src/devices/bus/rs232/xvd701.h2
-rw-r--r--src/devices/bus/rtpc/kbd.cpp5
-rw-r--r--src/devices/bus/rtpc/kbd_con.cpp8
-rw-r--r--src/devices/bus/rtpc/kbd_con.h1
-rw-r--r--src/devices/bus/s100/ascsasi.cpp8
-rw-r--r--src/devices/bus/s100/dj2db.cpp4
-rw-r--r--src/devices/bus/s100/dj2db.h4
-rw-r--r--src/devices/bus/s100/polyvti.cpp4
-rw-r--r--src/devices/bus/s100/s100.cpp69
-rw-r--r--src/devices/bus/s100/s100.h52
-rw-r--r--src/devices/bus/s100/seals8k.cpp8
-rw-r--r--src/devices/bus/s100/vectordualmode.cpp327
-rw-r--r--src/devices/bus/s100/vectordualmode.h55
-rw-r--r--src/devices/bus/s100/wunderbus.cpp4
-rw-r--r--src/devices/bus/s100/wunderbus.h4
-rw-r--r--src/devices/bus/saitek_osa/expansion.cpp20
-rw-r--r--src/devices/bus/saitek_osa/expansion.h12
-rw-r--r--src/devices/bus/saitek_osa/maestro.cpp396
-rw-r--r--src/devices/bus/saitek_osa/maestro.h76
-rw-r--r--src/devices/bus/saitek_osa/maestroa.cpp157
-rw-r--r--src/devices/bus/saitek_osa/maestroa.h45
-rw-r--r--src/devices/bus/saitek_osa/sparc.cpp162
-rw-r--r--src/devices/bus/saitek_osa/sparc.h48
-rw-r--r--src/devices/bus/samcoupe/drive/atom.cpp2
-rw-r--r--src/devices/bus/samcoupe/drive/drive.cpp2
-rw-r--r--src/devices/bus/samcoupe/drive/drive.h2
-rw-r--r--src/devices/bus/samcoupe/drive/floppy.cpp2
-rw-r--r--src/devices/bus/samcoupe/expansion/dallas.cpp11
-rw-r--r--src/devices/bus/samcoupe/expansion/expansion.cpp9
-rw-r--r--src/devices/bus/samcoupe/expansion/expansion.h6
-rw-r--r--src/devices/bus/samcoupe/expansion/spi.cpp2
-rw-r--r--src/devices/bus/samcoupe/expansion/spi.h2
-rw-r--r--src/devices/bus/samcoupe/mouse/mouse.cpp2
-rw-r--r--src/devices/bus/samcoupe/mouse/mouseport.cpp5
-rw-r--r--src/devices/bus/samcoupe/mouse/mouseport.h2
-rw-r--r--src/devices/bus/sat_ctrl/keybd.cpp2
-rw-r--r--src/devices/bus/saturn/bram.cpp8
-rw-r--r--src/devices/bus/saturn/sat_slot.cpp24
-rw-r--r--src/devices/bus/saturn/sat_slot.h17
-rw-r--r--src/devices/bus/sbus/cgsix.cpp2
-rw-r--r--src/devices/bus/sbus/cgsix.h2
-rw-r--r--src/devices/bus/sbus/sbus.cpp7
-rw-r--r--src/devices/bus/sbus/sbus.h5
-rw-r--r--src/devices/bus/scsi/omti5100.cpp12
-rw-r--r--src/devices/bus/scsi/s1410.cpp9
-rw-r--r--src/devices/bus/scsi/s1410.h2
-rw-r--r--src/devices/bus/scsi/scsi.cpp52
-rw-r--r--src/devices/bus/scsi/scsi.h104
-rw-r--r--src/devices/bus/scsi/scsicd.cpp14
-rw-r--r--src/devices/bus/scsi/scsicd.h3
-rw-r--r--src/devices/bus/scsi/scsihd.cpp5
-rw-r--r--src/devices/bus/scsi/scsihd.h2
-rw-r--r--src/devices/bus/scsi/scsihle.cpp12
-rw-r--r--src/devices/bus/scsi/scsihle.h24
-rw-r--r--src/devices/bus/scv/slot.cpp27
-rw-r--r--src/devices/bus/scv/slot.h19
-rw-r--r--src/devices/bus/sdk85/memexp.cpp14
-rw-r--r--src/devices/bus/sdk85/memexp.h8
-rw-r--r--src/devices/bus/sega8/sega8_slot.cpp90
-rw-r--r--src/devices/bus/sega8/sega8_slot.h24
-rw-r--r--src/devices/bus/segaai/rom.cpp93
-rw-r--r--src/devices/bus/segaai/rom.h14
-rw-r--r--src/devices/bus/segaai/segaai_exp.cpp48
-rw-r--r--src/devices/bus/segaai/segaai_exp.h63
-rw-r--r--src/devices/bus/segaai/segaai_slot.cpp99
-rw-r--r--src/devices/bus/segaai/segaai_slot.h73
-rw-r--r--src/devices/bus/segaai/soundbox.cpp320
-rw-r--r--src/devices/bus/segaai/soundbox.h14
-rw-r--r--src/devices/bus/sg1000_exp/kblink.h10
-rw-r--r--src/devices/bus/sg1000_exp/sk1100.cpp14
-rw-r--r--src/devices/bus/sg1000_exp/sk1100.h1
-rw-r--r--src/devices/bus/sg1000_exp/sk1100prn.cpp10
-rw-r--r--src/devices/bus/sg1000_exp/sk1100prn.h20
-rw-r--r--src/devices/bus/sgikbd/hlekbd.cpp406
-rw-r--r--src/devices/bus/sgikbd/hlekbd.h113
-rw-r--r--src/devices/bus/sgikbd/sgikbd.cpp69
-rw-r--r--src/devices/bus/sgikbd/sgikbd.h81
-rw-r--r--src/devices/bus/sms_ctrl/controllers.cpp82
-rw-r--r--src/devices/bus/sms_ctrl/controllers.h35
-rw-r--r--src/devices/bus/sms_ctrl/diypaddle.cpp227
-rw-r--r--src/devices/bus/sms_ctrl/diypaddle.h18
-rw-r--r--src/devices/bus/sms_ctrl/graphic.cpp161
-rw-r--r--src/devices/bus/sms_ctrl/graphic.h42
-rw-r--r--src/devices/bus/sms_ctrl/hypershot.cpp66
-rw-r--r--src/devices/bus/sms_ctrl/hypershot.h18
-rw-r--r--src/devices/bus/sms_ctrl/joypad.cpp64
-rw-r--r--src/devices/bus/sms_ctrl/joypad.h35
-rw-r--r--src/devices/bus/sms_ctrl/lphaser.cpp193
-rw-r--r--src/devices/bus/sms_ctrl/lphaser.h49
-rw-r--r--src/devices/bus/sms_ctrl/md6bt.cpp170
-rw-r--r--src/devices/bus/sms_ctrl/md6bt.h18
-rw-r--r--src/devices/bus/sms_ctrl/mdpad.cpp82
-rw-r--r--src/devices/bus/sms_ctrl/mdpad.h18
-rw-r--r--src/devices/bus/sms_ctrl/mouse.cpp264
-rw-r--r--src/devices/bus/sms_ctrl/mouse.h19
-rw-r--r--src/devices/bus/sms_ctrl/multitap.cpp166
-rw-r--r--src/devices/bus/sms_ctrl/multitap.h40
-rw-r--r--src/devices/bus/sms_ctrl/paddle.cpp149
-rw-r--r--src/devices/bus/sms_ctrl/paddle.h44
-rw-r--r--src/devices/bus/sms_ctrl/rfu.cpp164
-rw-r--r--src/devices/bus/sms_ctrl/rfu.h44
-rw-r--r--src/devices/bus/sms_ctrl/rs232adapt.cpp56
-rw-r--r--src/devices/bus/sms_ctrl/rs232adapt.h18
-rw-r--r--src/devices/bus/sms_ctrl/smsctrl.cpp106
-rw-r--r--src/devices/bus/sms_ctrl/smsctrl.h157
-rw-r--r--src/devices/bus/sms_ctrl/sports.cpp232
-rw-r--r--src/devices/bus/sms_ctrl/sports.h52
-rw-r--r--src/devices/bus/sms_ctrl/sportsjp.cpp149
-rw-r--r--src/devices/bus/sms_ctrl/sportsjp.h48
-rw-r--r--src/devices/bus/sms_ctrl/teamplayer.cpp556
-rw-r--r--src/devices/bus/sms_ctrl/teamplayer.h18
-rw-r--r--src/devices/bus/sms_ctrl/xe1ap.cpp107
-rw-r--r--src/devices/bus/sms_ctrl/xe1ap.h19
-rw-r--r--src/devices/bus/snes/profighter.cpp266
-rw-r--r--src/devices/bus/snes/profighter.h70
-rw-r--r--src/devices/bus/snes/sfx.cpp2
-rw-r--r--src/devices/bus/snes/sfx.h2
-rw-r--r--src/devices/bus/snes/sgb.cpp96
-rw-r--r--src/devices/bus/snes/sgb.h18
-rw-r--r--src/devices/bus/snes/snes_carts.cpp11
-rw-r--r--src/devices/bus/snes/snes_slot.cpp52
-rw-r--r--src/devices/bus/snes/snes_slot.h22
-rw-r--r--src/devices/bus/snes_ctrl/ctrl.cpp4
-rw-r--r--src/devices/bus/snes_ctrl/ctrl.h4
-rw-r--r--src/devices/bus/spc1000/vdp.cpp2
-rw-r--r--src/devices/bus/spc1000/vdp.h2
-rw-r--r--src/devices/bus/spectrum/beta.cpp6
-rw-r--r--src/devices/bus/spectrum/beta.h7
-rw-r--r--src/devices/bus/spectrum/beta128.cpp6
-rw-r--r--src/devices/bus/spectrum/beta128.h5
-rw-r--r--src/devices/bus/spectrum/d40.cpp2
-rw-r--r--src/devices/bus/spectrum/d40.h5
-rw-r--r--src/devices/bus/spectrum/exp.cpp11
-rw-r--r--src/devices/bus/spectrum/exp.h8
-rw-r--r--src/devices/bus/spectrum/floppyone.cpp6
-rw-r--r--src/devices/bus/spectrum/floppyone.h8
-rw-r--r--src/devices/bus/spectrum/fuller.h2
-rw-r--r--src/devices/bus/spectrum/intf1.cpp4
-rw-r--r--src/devices/bus/spectrum/intf1.h4
-rw-r--r--src/devices/bus/spectrum/intf2.cpp11
-rw-r--r--src/devices/bus/spectrum/intf2.h4
-rw-r--r--src/devices/bus/spectrum/kempdisc.cpp4
-rw-r--r--src/devices/bus/spectrum/kempdisc.h5
-rw-r--r--src/devices/bus/spectrum/logitek.cpp2
-rw-r--r--src/devices/bus/spectrum/logitek.h4
-rw-r--r--src/devices/bus/spectrum/lprint.cpp8
-rw-r--r--src/devices/bus/spectrum/lprint.h20
-rw-r--r--src/devices/bus/spectrum/melodik.h2
-rw-r--r--src/devices/bus/spectrum/mface.cpp6
-rw-r--r--src/devices/bus/spectrum/mface.h6
-rw-r--r--src/devices/bus/spectrum/mgt.cpp11
-rw-r--r--src/devices/bus/spectrum/mgt.h9
-rw-r--r--src/devices/bus/spectrum/mikroplus.cpp2
-rw-r--r--src/devices/bus/spectrum/mikroplus.h2
-rw-r--r--src/devices/bus/spectrum/mpoker.cpp2
-rw-r--r--src/devices/bus/spectrum/mpoker.h4
-rw-r--r--src/devices/bus/spectrum/nemoide.cpp85
-rw-r--r--src/devices/bus/spectrum/nemoide.h14
-rw-r--r--src/devices/bus/spectrum/neogs.cpp484
-rw-r--r--src/devices/bus/spectrum/neogs.h14
-rw-r--r--src/devices/bus/spectrum/opus.cpp22
-rw-r--r--src/devices/bus/spectrum/opus.h10
-rw-r--r--src/devices/bus/spectrum/plus2test.cpp2
-rw-r--r--src/devices/bus/spectrum/plus2test.h2
-rw-r--r--src/devices/bus/spectrum/sdi.cpp2
-rw-r--r--src/devices/bus/spectrum/sdi.h4
-rw-r--r--src/devices/bus/spectrum/sixword.cpp6
-rw-r--r--src/devices/bus/spectrum/sixword.h7
-rw-r--r--src/devices/bus/spectrum/smuc.cpp140
-rw-r--r--src/devices/bus/spectrum/smuc.h14
-rw-r--r--src/devices/bus/spectrum/speccydos.cpp6
-rw-r--r--src/devices/bus/spectrum/speccydos.h5
-rw-r--r--src/devices/bus/spectrum/specmate.cpp4
-rw-r--r--src/devices/bus/spectrum/specmate.h4
-rw-r--r--src/devices/bus/spectrum/uslot.cpp4
-rw-r--r--src/devices/bus/spectrum/uslot.h2
-rw-r--r--src/devices/bus/spectrum/usource.cpp2
-rw-r--r--src/devices/bus/spectrum/usource.h4
-rw-r--r--src/devices/bus/spectrum/uspeech.cpp2
-rw-r--r--src/devices/bus/spectrum/uspeech.h4
-rw-r--r--src/devices/bus/spectrum/vtx5000.cpp170
-rw-r--r--src/devices/bus/spectrum/vtx5000.h11
-rw-r--r--src/devices/bus/spectrum/wafa.cpp4
-rw-r--r--src/devices/bus/spectrum/wafa.h4
-rw-r--r--src/devices/bus/spectrum/zxbus.cpp78
-rw-r--r--src/devices/bus/spectrum/zxbus.h128
-rw-r--r--src/devices/bus/ss50/dc5.cpp48
-rw-r--r--src/devices/bus/ss50/interface.cpp13
-rw-r--r--src/devices/bus/ss50/interface.h24
-rw-r--r--src/devices/bus/ss50/mpc.cpp26
-rw-r--r--src/devices/bus/ss50/mps.cpp28
-rw-r--r--src/devices/bus/ss50/mps2.cpp20
-rw-r--r--src/devices/bus/ss50/mpt.cpp12
-rw-r--r--src/devices/bus/ss50/piaide.cpp2
-rw-r--r--src/devices/bus/sunkbd/hlekbd.cpp2
-rw-r--r--src/devices/bus/sunkbd/hlekbd.h2
-rw-r--r--src/devices/bus/sunkbd/sunkbd.cpp8
-rw-r--r--src/devices/bus/sunkbd/sunkbd.h9
-rw-r--r--src/devices/bus/sunmouse/hlemouse.cpp1
-rw-r--r--src/devices/bus/sunmouse/sunmouse.cpp4
-rw-r--r--src/devices/bus/sunmouse/sunmouse.h8
-rw-r--r--src/devices/bus/svi3x8/expander/expander.cpp40
-rw-r--r--src/devices/bus/svi3x8/expander/expander.h41
-rw-r--r--src/devices/bus/svi3x8/expander/sv601.cpp6
-rw-r--r--src/devices/bus/svi3x8/expander/sv601.h6
-rw-r--r--src/devices/bus/svi3x8/expander/sv602.cpp6
-rw-r--r--src/devices/bus/svi3x8/expander/sv602.h6
-rw-r--r--src/devices/bus/svi3x8/expander/sv603.cpp29
-rw-r--r--src/devices/bus/svi3x8/expander/sv603.h6
-rw-r--r--src/devices/bus/svi3x8/slot/slot.cpp88
-rw-r--r--src/devices/bus/svi3x8/slot/slot.h39
-rw-r--r--src/devices/bus/svi3x8/slot/sv801.cpp4
-rw-r--r--src/devices/bus/svi3x8/slot/sv801.h4
-rw-r--r--src/devices/bus/svi3x8/slot/sv802.cpp2
-rw-r--r--src/devices/bus/svi3x8/slot/sv802.h2
-rw-r--r--src/devices/bus/svi3x8/slot/sv805.cpp2
-rw-r--r--src/devices/bus/svi3x8/slot/sv805.h2
-rw-r--r--src/devices/bus/tanbus/etirtc.cpp88
-rw-r--r--src/devices/bus/tanbus/etirtc.h47
-rw-r--r--src/devices/bus/tanbus/etisnd.cpp153
-rw-r--r--src/devices/bus/tanbus/etisnd.h53
-rw-r--r--src/devices/bus/tanbus/keyboard/keyboard.cpp104
-rw-r--r--src/devices/bus/tanbus/keyboard/keyboard.h82
-rw-r--r--src/devices/bus/tanbus/keyboard/mt006.cpp118
-rw-r--r--src/devices/bus/tanbus/keyboard/mt006.h50
-rw-r--r--src/devices/bus/tanbus/keyboard/mt009.cpp389
-rw-r--r--src/devices/bus/tanbus/keyboard/mt009.h63
-rw-r--r--src/devices/bus/tanbus/keyboard/spinveti.cpp97
-rw-r--r--src/devices/bus/tanbus/keyboard/spinveti.h49
-rw-r--r--src/devices/bus/tanbus/mpvdu.cpp2
-rw-r--r--src/devices/bus/tanbus/mpvdu.h2
-rw-r--r--src/devices/bus/tanbus/ra32k.cpp143
-rw-r--r--src/devices/bus/tanbus/ra32k.h59
-rw-r--r--src/devices/bus/tanbus/radisc.cpp92
-rw-r--r--src/devices/bus/tanbus/radisc.h22
-rw-r--r--src/devices/bus/tanbus/ravdu.cpp2
-rw-r--r--src/devices/bus/tanbus/ravdu.h2
-rw-r--r--src/devices/bus/tanbus/tanbus.cpp62
-rw-r--r--src/devices/bus/tanbus/tanbus.h18
-rw-r--r--src/devices/bus/tanbus/tandos.cpp52
-rw-r--r--src/devices/bus/tanbus/tandos.h22
-rw-r--r--src/devices/bus/tanbus/tanex.cpp12
-rw-r--r--src/devices/bus/tanbus/tanex.h12
-rw-r--r--src/devices/bus/tanbus/tanram.cpp20
-rw-r--r--src/devices/bus/tanbus/tanrtc.cpp86
-rw-r--r--src/devices/bus/tanbus/tanrtc.h47
-rw-r--r--src/devices/bus/tanbus/tug8082.cpp4
-rw-r--r--src/devices/bus/tanbus/tug8082.h4
-rw-r--r--src/devices/bus/tanbus/tugcombo.cpp270
-rw-r--r--src/devices/bus/tanbus/tugcombo.h142
-rw-r--r--src/devices/bus/thomson/cc90_232.cpp135
-rw-r--r--src/devices/bus/thomson/cc90_232.h48
-rw-r--r--src/devices/bus/thomson/cd90_015.cpp45
-rw-r--r--src/devices/bus/thomson/cd90_015.h2
-rw-r--r--src/devices/bus/thomson/cd90_351.cpp20
-rw-r--r--src/devices/bus/thomson/cd90_640.cpp6
-rw-r--r--src/devices/bus/thomson/cd90_640.h2
-rw-r--r--src/devices/bus/thomson/cq90_028.cpp10
-rw-r--r--src/devices/bus/thomson/cq90_028.h2
-rw-r--r--src/devices/bus/thomson/extension.cpp18
-rw-r--r--src/devices/bus/thomson/extension.h22
-rw-r--r--src/devices/bus/thomson/md90_120.cpp94
-rw-r--r--src/devices/bus/thomson/md90_120.h38
-rw-r--r--src/devices/bus/thomson/midipak.cpp61
-rw-r--r--src/devices/bus/thomson/midipak.h25
-rw-r--r--src/devices/bus/thomson/nanoreseau.cpp4
-rw-r--r--src/devices/bus/thomson/rf57_932.cpp55
-rw-r--r--src/devices/bus/thomson/rf57_932.h25
-rw-r--r--src/devices/bus/thomson/speech.cpp43
-rw-r--r--src/devices/bus/thomson/speech.h25
-rw-r--r--src/devices/bus/ti8x/bitsocket.cpp8
-rw-r--r--src/devices/bus/ti8x/teeconn.cpp24
-rw-r--r--src/devices/bus/ti8x/ti8x.cpp16
-rw-r--r--src/devices/bus/ti8x/ti8x.h20
-rw-r--r--src/devices/bus/ti8x/tispeaker.cpp8
-rw-r--r--src/devices/bus/ti99/colorbus/busmouse.cpp8
-rw-r--r--src/devices/bus/ti99/colorbus/colorbus.cpp17
-rw-r--r--src/devices/bus/ti99/gromport/cartridges.cpp72
-rw-r--r--src/devices/bus/ti99/gromport/cartridges.h25
-rw-r--r--src/devices/bus/ti99/gromport/gkracker.cpp76
-rw-r--r--src/devices/bus/ti99/gromport/gkracker.h8
-rw-r--r--src/devices/bus/ti99/gromport/gromport.cpp30
-rw-r--r--src/devices/bus/ti99/gromport/gromport.h31
-rw-r--r--src/devices/bus/ti99/gromport/multiconn.cpp135
-rw-r--r--src/devices/bus/ti99/gromport/multiconn.h12
-rw-r--r--src/devices/bus/ti99/gromport/singleconn.cpp19
-rw-r--r--src/devices/bus/ti99/gromport/singleconn.h9
-rw-r--r--src/devices/bus/ti99/internal/992board.cpp61
-rw-r--r--src/devices/bus/ti99/internal/992board.h7
-rw-r--r--src/devices/bus/ti99/internal/998board.cpp150
-rw-r--r--src/devices/bus/ti99/internal/998board.h112
-rw-r--r--src/devices/bus/ti99/internal/buffram.cpp8
-rw-r--r--src/devices/bus/ti99/internal/datamux.cpp25
-rw-r--r--src/devices/bus/ti99/internal/datamux.h8
-rw-r--r--src/devices/bus/ti99/internal/evpcconn.cpp9
-rw-r--r--src/devices/bus/ti99/internal/evpcconn.h2
-rw-r--r--src/devices/bus/ti99/internal/genboard.cpp96
-rw-r--r--src/devices/bus/ti99/internal/genboard.h58
-rw-r--r--src/devices/bus/ti99/internal/genkbd.cpp14
-rw-r--r--src/devices/bus/ti99/internal/genkbd.h6
-rw-r--r--src/devices/bus/ti99/internal/ioport.cpp18
-rw-r--r--src/devices/bus/ti99/internal/ioport.h26
-rw-r--r--src/devices/bus/ti99/joyport/handset.cpp10
-rw-r--r--src/devices/bus/ti99/joyport/joyport.cpp5
-rw-r--r--src/devices/bus/ti99/joyport/joyport.h4
-rw-r--r--src/devices/bus/ti99/peb/bwg.cpp96
-rw-r--r--src/devices/bus/ti99/peb/bwg.h39
-rw-r--r--src/devices/bus/ti99/peb/cc_fdc.cpp158
-rw-r--r--src/devices/bus/ti99/peb/cc_fdc.h89
-rw-r--r--src/devices/bus/ti99/peb/evpc.cpp22
-rw-r--r--src/devices/bus/ti99/peb/evpc.h4
-rw-r--r--src/devices/bus/ti99/peb/forti.cpp6
-rw-r--r--src/devices/bus/ti99/peb/forti.h2
-rw-r--r--src/devices/bus/ti99/peb/hfdc.cpp98
-rw-r--r--src/devices/bus/ti99/peb/hfdc.h12
-rw-r--r--src/devices/bus/ti99/peb/horizon.cpp50
-rw-r--r--src/devices/bus/ti99/peb/horizon.h4
-rw-r--r--src/devices/bus/ti99/peb/hsgpl.cpp24
-rw-r--r--src/devices/bus/ti99/peb/memex.cpp12
-rw-r--r--src/devices/bus/ti99/peb/myarcfdc.cpp83
-rw-r--r--src/devices/bus/ti99/peb/myarcfdc.h37
-rw-r--r--src/devices/bus/ti99/peb/pcode.cpp22
-rw-r--r--src/devices/bus/ti99/peb/pcode.h8
-rw-r--r--src/devices/bus/ti99/peb/peribox.cpp69
-rw-r--r--src/devices/bus/ti99/peb/peribox.h43
-rw-r--r--src/devices/bus/ti99/peb/pgram.cpp20
-rw-r--r--src/devices/bus/ti99/peb/samsmem.cpp4
-rw-r--r--src/devices/bus/ti99/peb/samsmem.h4
-rw-r--r--src/devices/bus/ti99/peb/scsicard.cpp61
-rw-r--r--src/devices/bus/ti99/peb/scsicard.h31
-rw-r--r--src/devices/bus/ti99/peb/sidmaster.cpp6
-rw-r--r--src/devices/bus/ti99/peb/spchsyn.cpp14
-rw-r--r--src/devices/bus/ti99/peb/spchsyn.h2
-rw-r--r--src/devices/bus/ti99/peb/ti_fdc.cpp87
-rw-r--r--src/devices/bus/ti99/peb/ti_fdc.h33
-rw-r--r--src/devices/bus/ti99/peb/ti_rs232.cpp75
-rw-r--r--src/devices/bus/ti99/peb/ti_rs232.h45
-rw-r--r--src/devices/bus/ti99/peb/tipi.cpp30
-rw-r--r--src/devices/bus/ti99/peb/tipi.h2
-rw-r--r--src/devices/bus/ti99/peb/tn_ide.cpp22
-rw-r--r--src/devices/bus/ti99/peb/tn_ide.h6
-rw-r--r--src/devices/bus/ti99/peb/tn_usbsm.cpp4
-rw-r--r--src/devices/bus/ti99x/990_dk.cpp1
-rw-r--r--src/devices/bus/ti99x/990_hd.cpp74
-rw-r--r--src/devices/bus/ti99x/990_hd.h7
-rw-r--r--src/devices/bus/ti99x/990_tap.cpp16
-rw-r--r--src/devices/bus/ti99x/990_tap.h2
-rw-r--r--src/devices/bus/tiki100/8088.cpp4
-rw-r--r--src/devices/bus/tiki100/exp.cpp64
-rw-r--r--src/devices/bus/tiki100/exp.h29
-rw-r--r--src/devices/bus/tim011/aycard.cpp84
-rw-r--r--src/devices/bus/tim011/aycard.h12
-rw-r--r--src/devices/bus/tim011/exp.cpp54
-rw-r--r--src/devices/bus/tim011/exp.h102
-rw-r--r--src/devices/bus/tvc/hbf.cpp2
-rw-r--r--src/devices/bus/tvc/hbf.h1
-rw-r--r--src/devices/bus/tvc/tvc.cpp4
-rw-r--r--src/devices/bus/uts_kbd/400kbd.cpp12
-rw-r--r--src/devices/bus/uts_kbd/400kbd.h6
-rw-r--r--src/devices/bus/uts_kbd/extw.cpp6
-rw-r--r--src/devices/bus/uts_kbd/extw.h6
-rw-r--r--src/devices/bus/uts_kbd/uts_kbd.cpp5
-rw-r--r--src/devices/bus/uts_kbd/uts_kbd.h13
-rw-r--r--src/devices/bus/vboy/rom.cpp18
-rw-r--r--src/devices/bus/vboy/rom.h4
-rw-r--r--src/devices/bus/vboy/slot.cpp75
-rw-r--r--src/devices/bus/vboy/slot.h23
-rw-r--r--src/devices/bus/vc4000/slot.cpp19
-rw-r--r--src/devices/bus/vc4000/slot.h12
-rw-r--r--src/devices/bus/vcs/rom.cpp4
-rw-r--r--src/devices/bus/vcs/vcs_slot.cpp16
-rw-r--r--src/devices/bus/vcs/vcs_slot.h10
-rw-r--r--src/devices/bus/vcs_ctrl/ctrl.cpp10
-rw-r--r--src/devices/bus/vcs_ctrl/ctrl.h13
-rw-r--r--src/devices/bus/vcs_ctrl/cx85.cpp126
-rw-r--r--src/devices/bus/vcs_ctrl/cx85.h54
-rw-r--r--src/devices/bus/vcs_ctrl/joybooster.cpp14
-rw-r--r--src/devices/bus/vcs_ctrl/joybooster.h14
-rw-r--r--src/devices/bus/vcs_ctrl/joystick.cpp2
-rw-r--r--src/devices/bus/vcs_ctrl/joystick.h8
-rw-r--r--src/devices/bus/vcs_ctrl/keypad.cpp63
-rw-r--r--src/devices/bus/vcs_ctrl/keypad.h24
-rw-r--r--src/devices/bus/vcs_ctrl/lightpen.h8
-rw-r--r--src/devices/bus/vcs_ctrl/mouse.cpp2
-rw-r--r--src/devices/bus/vcs_ctrl/mouse.h14
-rw-r--r--src/devices/bus/vcs_ctrl/paddles.cpp19
-rw-r--r--src/devices/bus/vcs_ctrl/paddles.h16
-rw-r--r--src/devices/bus/vcs_ctrl/wheel.cpp4
-rw-r--r--src/devices/bus/vcs_ctrl/wheel.h8
-rw-r--r--src/devices/bus/vectrex/slot.cpp30
-rw-r--r--src/devices/bus/vectrex/slot.h19
-rw-r--r--src/devices/bus/vic10/exp.cpp49
-rw-r--r--src/devices/bus/vic10/exp.h21
-rw-r--r--src/devices/bus/vic20/4cga.cpp2
-rw-r--r--src/devices/bus/vic20/4cga.h18
-rw-r--r--src/devices/bus/vic20/exp.cpp157
-rw-r--r--src/devices/bus/vic20/exp.h16
-rw-r--r--src/devices/bus/vic20/megacart.cpp19
-rw-r--r--src/devices/bus/vic20/megacart.h16
-rw-r--r--src/devices/bus/vic20/speakeasy.cpp2
-rw-r--r--src/devices/bus/vic20/vic1011.cpp2
-rw-r--r--src/devices/bus/vic20/vic1011.h10
-rw-r--r--src/devices/bus/vic20/vic1112.cpp4
-rw-r--r--src/devices/bus/vic20/vic1112.h4
-rw-r--r--src/devices/bus/vidbrain/comp_language.cpp101
-rw-r--r--src/devices/bus/vidbrain/comp_language.h46
-rw-r--r--src/devices/bus/vidbrain/exp.cpp33
-rw-r--r--src/devices/bus/vidbrain/exp.h20
-rw-r--r--src/devices/bus/vidbrain/info_manager.cpp77
-rw-r--r--src/devices/bus/vidbrain/info_manager.h43
-rw-r--r--src/devices/bus/vidbrain/money_minder.cpp12
-rw-r--r--src/devices/bus/vidbrain/money_minder.h5
-rw-r--r--src/devices/bus/vidbrain/std.cpp15
-rw-r--r--src/devices/bus/vidbrain/std.h5
-rw-r--r--src/devices/bus/vidbrain/timeshare.cpp10
-rw-r--r--src/devices/bus/vidbrain/timeshare.h5
-rw-r--r--src/devices/bus/vip/byteio.cpp9
-rw-r--r--src/devices/bus/vip/byteio.h8
-rw-r--r--src/devices/bus/vip/exp.cpp17
-rw-r--r--src/devices/bus/vip/exp.h18
-rw-r--r--src/devices/bus/vip/vp575.h34
-rw-r--r--src/devices/bus/vip/vp590.cpp6
-rw-r--r--src/devices/bus/vip/vp590.h6
-rw-r--r--src/devices/bus/vme/cp31.cpp (renamed from src/devices/bus/vme/vme_cp31.cpp)13
-rw-r--r--src/devices/bus/vme/cp31.h (renamed from src/devices/bus/vme/vme_cp31.h)12
-rw-r--r--src/devices/bus/vme/enp10.cpp221
-rw-r--r--src/devices/bus/vme/enp10.h58
-rw-r--r--src/devices/bus/vme/hcpu30.cpp (renamed from src/devices/bus/vme/vme_hcpu30.cpp)23
-rw-r--r--src/devices/bus/vme/hcpu30.h (renamed from src/devices/bus/vme/vme_hcpu30.h)23
-rw-r--r--src/devices/bus/vme/hk68v10.cpp364
-rw-r--r--src/devices/bus/vme/hk68v10.h44
-rw-r--r--src/devices/bus/vme/mvme120.cpp (renamed from src/devices/bus/vme/vme_mvme120.cpp)25
-rw-r--r--src/devices/bus/vme/mvme120.h (renamed from src/devices/bus/vme/vme_mvme120.h)12
-rw-r--r--src/devices/bus/vme/mvme147.cpp672
-rw-r--r--src/devices/bus/vme/mvme147.h59
-rw-r--r--src/devices/bus/vme/mvme180.cpp132
-rw-r--r--src/devices/bus/vme/mvme180.h52
-rw-r--r--src/devices/bus/vme/mvme181.cpp162
-rw-r--r--src/devices/bus/vme/mvme181.h52
-rw-r--r--src/devices/bus/vme/mvme187.cpp138
-rw-r--r--src/devices/bus/vme/mvme187.h51
-rw-r--r--src/devices/bus/vme/mvme327a.cpp129
-rw-r--r--src/devices/bus/vme/mvme327a.h48
-rw-r--r--src/devices/bus/vme/mvme350.cpp (renamed from src/devices/bus/vme/vme_mvme350.cpp)24
-rw-r--r--src/devices/bus/vme/mvme350.h (renamed from src/devices/bus/vme/vme_mvme350.h)6
-rw-r--r--src/devices/bus/vme/mzr8105.cpp237
-rw-r--r--src/devices/bus/vme/mzr8105.h32
-rw-r--r--src/devices/bus/vme/mzr8300.cpp (renamed from src/devices/bus/vme/vme_mzr8300.cpp)99
-rw-r--r--src/devices/bus/vme/mzr8300.h (renamed from src/devices/bus/vme/vme_mzr8300.h)12
-rw-r--r--src/devices/bus/vme/smvme2000.cpp (renamed from src/devices/bus/vme/vme_smvme2000.cpp)24
-rw-r--r--src/devices/bus/vme/smvme2000.h (renamed from src/devices/bus/vme/vme_smvme2000.h)6
-rw-r--r--src/devices/bus/vme/sys68k_cpu1.cpp670
-rw-r--r--src/devices/bus/vme/sys68k_cpu1.h97
-rw-r--r--src/devices/bus/vme/sys68k_cpu20.cpp (renamed from src/devices/bus/vme/vme_fccpu20.cpp)221
-rw-r--r--src/devices/bus/vme/sys68k_cpu20.h188
-rw-r--r--src/devices/bus/vme/sys68k_cpu30.cpp952
-rw-r--r--src/devices/bus/vme/sys68k_cpu30.h157
-rw-r--r--src/devices/bus/vme/sys68k_iscsi.cpp (renamed from src/devices/bus/vme/vme_fcscsi.cpp)133
-rw-r--r--src/devices/bus/vme/sys68k_iscsi.h (renamed from src/devices/bus/vme/vme_fcscsi.h)26
-rw-r--r--src/devices/bus/vme/sys68k_isio.cpp (renamed from src/devices/bus/vme/vme_fcisio.cpp)79
-rw-r--r--src/devices/bus/vme/sys68k_isio.h (renamed from src/devices/bus/vme/vme_fcisio.h)21
-rw-r--r--src/devices/bus/vme/tp881v.cpp349
-rw-r--r--src/devices/bus/vme/tp881v.h59
-rw-r--r--src/devices/bus/vme/vme.cpp526
-rw-r--r--src/devices/bus/vme/vme.h279
-rw-r--r--src/devices/bus/vme/vme_cards.cpp65
-rw-r--r--src/devices/bus/vme/vme_cards.h11
-rw-r--r--src/devices/bus/vme/vme_fccpu20.h191
-rw-r--r--src/devices/bus/vme/vme_mzr8105.cpp70
-rw-r--r--src/devices/bus/vme/vme_mzr8105.h27
-rw-r--r--src/devices/bus/vsmile/vsmile_ctrl.cpp3
-rw-r--r--src/devices/bus/vsmile/vsmile_slot.cpp31
-rw-r--r--src/devices/bus/vsmile/vsmile_slot.h14
-rw-r--r--src/devices/bus/vtech/ioexp/printer.cpp2
-rw-r--r--src/devices/bus/vtech/ioexp/printer.h2
-rw-r--r--src/devices/bus/vtech/memexp/floppy.cpp62
-rw-r--r--src/devices/bus/vtech/memexp/floppy.h4
-rw-r--r--src/devices/bus/vtech/memexp/memexp.cpp5
-rw-r--r--src/devices/bus/vtech/memexp/memexp.h6
-rw-r--r--src/devices/bus/vtech/memexp/sdloader.cpp1
-rw-r--r--src/devices/bus/wangpc/lvc.cpp2
-rw-r--r--src/devices/bus/wangpc/lvc.h2
-rw-r--r--src/devices/bus/wangpc/mvc.cpp2
-rw-r--r--src/devices/bus/wangpc/mvc.h2
-rw-r--r--src/devices/bus/wangpc/wangpc.cpp93
-rw-r--r--src/devices/bus/wangpc/wangpc.h42
-rw-r--r--src/devices/bus/waveblaster/db50xg.cpp104
-rw-r--r--src/devices/bus/waveblaster/db50xg.h15
-rw-r--r--src/devices/bus/waveblaster/db60xg.cpp102
-rw-r--r--src/devices/bus/waveblaster/db60xg.h15
-rw-r--r--src/devices/bus/waveblaster/omniwave.cpp71
-rw-r--r--src/devices/bus/waveblaster/omniwave.h15
-rw-r--r--src/devices/bus/waveblaster/waveblaster.cpp56
-rw-r--r--src/devices/bus/waveblaster/waveblaster.h60
-rw-r--r--src/devices/bus/waveblaster/wg130.cpp117
-rw-r--r--src/devices/bus/waveblaster/wg130.h15
-rw-r--r--src/devices/bus/wswan/slot.cpp20
-rw-r--r--src/devices/bus/wswan/slot.h19
-rw-r--r--src/devices/bus/wysekbd/wysegakb.cpp730
-rw-r--r--src/devices/bus/wysekbd/wysegakb.h135
-rw-r--r--src/devices/bus/wysekbd/wysekbd.cpp79
-rw-r--r--src/devices/bus/wysekbd/wysekbd.h92
-rw-r--r--src/devices/bus/x68k/x68k_neptunex.cpp14
-rw-r--r--src/devices/bus/x68k/x68k_scsiext.cpp63
-rw-r--r--src/devices/bus/x68k/x68k_scsiext.h7
-rw-r--r--src/devices/bus/x68k/x68kexp.cpp14
-rw-r--r--src/devices/bus/x68k/x68kexp.h8
-rw-r--r--src/devices/bus/z29_kbd/he191_3425.cpp4
-rw-r--r--src/devices/bus/z29_kbd/he191_3425.h4
-rw-r--r--src/devices/bus/z29_kbd/keyboard.cpp6
-rw-r--r--src/devices/bus/z29_kbd/keyboard.h7
-rw-r--r--src/devices/bus/z29_kbd/md_kbd.cpp2
-rw-r--r--src/devices/bus/z29_kbd/md_kbd.h2
-rw-r--r--src/devices/bus/z88/ram.cpp107
-rw-r--r--src/devices/bus/z88/ram.h85
-rw-r--r--src/devices/bus/z88/rom.cpp98
-rw-r--r--src/devices/bus/z88/rom.h74
-rw-r--r--src/devices/bus/z88/z88.cpp28
-rw-r--r--src/devices/bus/z88/z88.h8
2152 files changed, 88821 insertions, 38516 deletions
diff --git a/src/devices/bus/a1bus/a1bus.cpp b/src/devices/bus/a1bus/a1bus.cpp
index 21549f5a171..5386f185897 100644
--- a/src/devices/bus/a1bus/a1bus.cpp
+++ b/src/devices/bus/a1bus/a1bus.cpp
@@ -87,13 +87,6 @@ a1bus_device::a1bus_device(const machine_config &mconfig, device_type type, cons
// device_start - device-specific startup
//-------------------------------------------------
-void a1bus_device::device_resolve_objects()
-{
- // resolve callbacks
- m_out_irq_cb.resolve_safe();
- m_out_nmi_cb.resolve_safe();
-}
-
void a1bus_device::device_start()
{
// clear slot
@@ -140,8 +133,8 @@ void a1bus_device::install_bank(offs_t start, offs_t end, uint8_t *data)
}
// interrupt request from a1bus card
-WRITE_LINE_MEMBER( a1bus_device::irq_w ) { m_out_irq_cb(state); }
-WRITE_LINE_MEMBER( a1bus_device::nmi_w ) { m_out_nmi_cb(state); }
+void a1bus_device::irq_w(int state) { m_out_irq_cb(state); }
+void a1bus_device::nmi_w(int state) { m_out_nmi_cb(state); }
//**************************************************************************
// DEVICE CONFIG A1BUS CARD INTERFACE
@@ -159,7 +152,7 @@ WRITE_LINE_MEMBER( a1bus_device::nmi_w ) { m_out_nmi_cb(state); }
device_a1bus_card_interface::device_a1bus_card_interface(const machine_config &mconfig, device_t &device)
: device_interface(device, "a1bus")
, m_a1bus_finder(device, finder_base::DUMMY_TAG), m_a1bus(nullptr)
- , m_a1bus_slottag(nullptr), m_next(nullptr)
+ , m_a1bus_slottag(nullptr)
{
}
diff --git a/src/devices/bus/a1bus/a1bus.h b/src/devices/bus/a1bus/a1bus.h
index d1d4860113d..a5c1e98db9b 100644
--- a/src/devices/bus/a1bus/a1bus.h
+++ b/src/devices/bus/a1bus/a1bus.h
@@ -38,7 +38,7 @@ public:
protected:
a1bus_slot_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
- // device-level overrides
+ // device_t implementation
virtual void device_resolve_objects() override;
virtual void device_start() override;
@@ -71,14 +71,13 @@ public:
void install_device(offs_t start, offs_t end, read8sm_delegate rhandler, write8sm_delegate whandler);
void install_bank(offs_t start, offs_t end, uint8_t *data);
- DECLARE_WRITE_LINE_MEMBER( irq_w );
- DECLARE_WRITE_LINE_MEMBER( nmi_w );
+ void irq_w(int state);
+ void nmi_w(int state);
protected:
a1bus_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
- // device-level overrides
- virtual void device_resolve_objects() override;
+ // device_t implementation
virtual void device_start() override;
virtual void device_reset() override;
@@ -105,8 +104,6 @@ public:
// construction/destruction
virtual ~device_a1bus_card_interface();
- device_a1bus_card_interface *next() const { return m_next; }
-
// inline configuration
void set_a1bus(a1bus_device *a1bus, const char *slottag) { m_a1bus = a1bus; m_a1bus_slottag = slottag; }
template <typename T> void set_onboard(T &&a1bus) { m_a1bus_finder.set_tag(std::forward<T>(a1bus)); m_a1bus_slottag = device().tag(); }
@@ -129,7 +126,6 @@ private:
optional_device<a1bus_device> m_a1bus_finder;
a1bus_device *m_a1bus;
const char *m_a1bus_slottag;
- device_a1bus_card_interface *m_next;
};
#endif // MAME_BUS_A1BUS_A1BUS_H
diff --git a/src/devices/bus/a2bus/a2arcadebd.cpp b/src/devices/bus/a2bus/a2arcadebd.cpp
index 85c0cfc02d2..9dbdfe44e8f 100644
--- a/src/devices/bus/a2bus/a2arcadebd.cpp
+++ b/src/devices/bus/a2bus/a2arcadebd.cpp
@@ -56,7 +56,7 @@ protected:
virtual void write_c0nx(uint8_t offset, uint8_t data) override;
private:
- DECLARE_WRITE_LINE_MEMBER( tms_irq_w );
+ void tms_irq_w(int state);
required_device<tms9918a_device> m_tms;
required_device<ay8910_device> m_ay;
@@ -157,7 +157,7 @@ void a2bus_arcboard_device::write_c0nx(uint8_t offset, uint8_t data)
}
}
-WRITE_LINE_MEMBER( a2bus_arcboard_device::tms_irq_w )
+void a2bus_arcboard_device::tms_irq_w(int state)
{
if (state)
{
diff --git a/src/devices/bus/a2bus/a2bus.cpp b/src/devices/bus/a2bus/a2bus.cpp
index deb322f67a8..d591accf73e 100644
--- a/src/devices/bus/a2bus/a2bus.cpp
+++ b/src/devices/bus/a2bus/a2bus.cpp
@@ -152,15 +152,6 @@ a2bus_device::a2bus_device(const machine_config &mconfig, device_type type, cons
// device_start - device-specific startup
//-------------------------------------------------
-void a2bus_device::device_resolve_objects()
-{
- // resolve callbacks
- m_out_irq_cb.resolve_safe();
- m_out_nmi_cb.resolve_safe();
- m_out_inh_cb.resolve_safe();
- m_out_dma_cb.resolve_safe();
-}
-
void a2bus_device::device_start()
{
// clear slots
@@ -197,6 +188,18 @@ void a2bus_device::add_a2bus_card(int slot, device_a2bus_card_interface *card)
m_device_list[slot] = card;
}
+void a2bus_device::reset_bus()
+{
+ for (int slot = 0; slot <= 7; slot++)
+ {
+ auto card = get_a2bus_card(slot);
+ if (card != nullptr)
+ {
+ card->bus_reset();
+ }
+ }
+}
+
uint8_t a2bus_device::get_a2bus_irq_mask()
{
return m_slot_irq_mask;
@@ -257,8 +260,8 @@ void a2bus_device::recalc_inh(int slot)
}
// interrupt request from a2bus card
-WRITE_LINE_MEMBER( a2bus_device::irq_w ) { m_out_irq_cb(state); }
-WRITE_LINE_MEMBER( a2bus_device::nmi_w ) { m_out_nmi_cb(state); }
+void a2bus_device::irq_w(int state) { m_out_irq_cb(state); }
+void a2bus_device::nmi_w(int state) { m_out_nmi_cb(state); }
//**************************************************************************
// DEVICE CONFIG A2BUS CARD INTERFACE
diff --git a/src/devices/bus/a2bus/a2bus.h b/src/devices/bus/a2bus/a2bus.h
index 5a10f06de39..32b280fd006 100644
--- a/src/devices/bus/a2bus/a2bus.h
+++ b/src/devices/bus/a2bus/a2bus.h
@@ -59,7 +59,7 @@ public:
protected:
a2bus_slot_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
- // device-level overrides
+ // device_t implementation
virtual void device_resolve_objects() override;
virtual void device_start() override;
@@ -98,15 +98,15 @@ public:
void recalc_inh(int slot);
uint8_t dma_r(uint16_t offset);
void dma_w(uint16_t offset, uint8_t data);
+ void reset_bus();
- DECLARE_WRITE_LINE_MEMBER( irq_w );
- DECLARE_WRITE_LINE_MEMBER( nmi_w );
+ void irq_w(int state);
+ void nmi_w(int state);
protected:
a2bus_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
- // device-level overrides
- virtual void device_resolve_objects() override;
+ // device_t implementation
virtual void device_start() override;
virtual void device_reset() override;
@@ -151,6 +151,7 @@ public:
virtual uint16_t inh_end() { return INH_END_INVALID; }
virtual bool inh_check(uint16_t offset, bool bIsWrite) { return false; }
virtual int inh_type() { return INH_NONE; }
+ virtual void bus_reset() { }
device_a2bus_card_interface *next() const { return m_next; }
diff --git a/src/devices/bus/a2bus/a2cffa.cpp b/src/devices/bus/a2bus/a2cffa.cpp
index 3839b338ae1..6aa0a2c904a 100644
--- a/src/devices/bus/a2bus/a2cffa.cpp
+++ b/src/devices/bus/a2bus/a2cffa.cpp
@@ -297,14 +297,14 @@ void a2bus_cffa2_device::nvram_default()
bool a2bus_cffa2_device::nvram_read(util::read_stream &file)
{
- size_t actual;
- return !file.read(m_eeprom, 0x1000, actual) && actual == 0x1000;
+ auto const [err, actual] = read(file, m_eeprom, 0x1000);
+ return !err && (actual == 0x1000);
}
bool a2bus_cffa2_device::nvram_write(util::write_stream &file)
{
- size_t actual;
- return !file.write(m_eeprom, 0x1000, actual) && actual == 0x1000;
+ auto const [err, actual] = write(file, m_eeprom, 0x1000);
+ return !err;
}
void a2bus_cffa2_6502_device::nvram_default()
@@ -314,14 +314,14 @@ void a2bus_cffa2_6502_device::nvram_default()
bool a2bus_cffa2_6502_device::nvram_read(util::read_stream &file)
{
- size_t actual;
- return !file.read(m_eeprom, 0x1000, actual) && actual == 0x1000;
+ auto const [err, actual] = read(file, m_eeprom, 0x1000);
+ return !err && (actual == 0x1000);
}
bool a2bus_cffa2_6502_device::nvram_write(util::write_stream &file)
{
- size_t actual;
- return !file.write(m_eeprom, 0x1000, actual) && actual == 0x1000;
+ auto const [err, actual] = write(file, m_eeprom, 0x1000);
+ return !err;
}
} // anonymous namespace
diff --git a/src/devices/bus/a2bus/a2diskii.cpp b/src/devices/bus/a2bus/a2diskii.cpp
deleted file mode 100644
index 2c06ee5136f..00000000000
--- a/src/devices/bus/a2bus/a2diskii.cpp
+++ /dev/null
@@ -1,161 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:R. Belmont
-/*********************************************************************
-
- a2diskii.c
-
- Implementation of the Apple II Disk II controller card
-
-*********************************************************************/
-
-#include "emu.h"
-#include "imagedev/flopdrv.h"
-#include "formats/ap2_dsk.h"
-#include "machine/appldriv.h"
-#include "a2diskii.h"
-
-
-/***************************************************************************
- PARAMETERS
-***************************************************************************/
-
-//**************************************************************************
-// GLOBAL VARIABLES
-//**************************************************************************
-
-DEFINE_DEVICE_TYPE(A2BUS_DISKII, a2bus_diskii_device, "a2diskii", "Apple Disk II controller")
-DEFINE_DEVICE_TYPE(A2BUS_AGAT7_FDC, a2bus_agat7flop_device, "agat7_flop", "Agat-7 140K floppy card")
-DEFINE_DEVICE_TYPE(A2BUS_AGAT9_FDC, a2bus_agat9flop_device, "agat9_flop", "Agat-9 140K floppy card")
-
-#define DISKII_ROM_REGION "diskii_rom"
-#define FDC_TAG "diskii_fdc"
-
-const applefdc_interface fdc_interface =
-{
- apple525_set_lines, /* set_lines */
- apple525_set_enable_lines, /* set_enable_lines */
-
- apple525_read_data, /* read_data */
- apple525_write_data, /* write_data */
- apple525_read_status /* read_status */
-};
-
-static const floppy_interface floppy_interface =
-{
- FLOPPY_STANDARD_5_25_DSHD,
- LEGACY_FLOPPY_OPTIONS_NAME(apple2),
- "floppy_5_25"
-};
-
-ROM_START( diskii )
- ROM_REGION(0x100, DISKII_ROM_REGION, 0)
- ROM_LOAD( "341-0027-a.p5", 0x000000, 0x000100, CRC(ce7144f6) SHA1(d4181c9f046aafc3fb326b381baac809d9e38d16) )
-ROM_END
-
-ROM_START( agat7 )
- ROM_REGION(0x100, DISKII_ROM_REGION, 0)
- ROM_LOAD( "shugart7.rom", 0x0000, 0x0100, CRC(c6e4850c) SHA1(71626d3d2d4bbeeac2b77585b45a5566d20b8d34) )
-ROM_END
-
-ROM_START( agat9 )
- ROM_REGION(0x100, DISKII_ROM_REGION, 0)
- ROM_LOAD( "shugart9.rom", 0x0000, 0x0100, CRC(964a0ce2) SHA1(bf955189ebffe874c20ef649a3db8177dc16af61) )
-ROM_END
-
-//-------------------------------------------------
-// device_add_mconfig - add device configuration
-//-------------------------------------------------
-
-void a2bus_floppy_device::device_add_mconfig(machine_config &config)
-{
- LEGACY_APPLEFDC(config, m_fdc, &fdc_interface);
- FLOPPY_APPLE(config, FLOPPY_0, &floppy_interface, 15, 16);
- FLOPPY_APPLE(config, FLOPPY_1, &floppy_interface, 15, 16);
-}
-
-//-------------------------------------------------
-// rom_region - device-specific ROM region
-//-------------------------------------------------
-
-const tiny_rom_entry *a2bus_floppy_device::device_rom_region() const
-{
- return ROM_NAME( diskii );
-}
-
-const tiny_rom_entry *a2bus_agat7flop_device::device_rom_region() const
-{
- return ROM_NAME( agat7 );
-}
-
-const tiny_rom_entry *a2bus_agat9flop_device::device_rom_region() const
-{
- return ROM_NAME( agat9 );
-}
-
-//**************************************************************************
-// LIVE DEVICE
-//**************************************************************************
-
-a2bus_floppy_device::a2bus_floppy_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, type, tag, owner, clock),
- device_a2bus_card_interface(mconfig, *this),
- m_fdc(*this, FDC_TAG), m_rom(nullptr)
-{
-}
-
-a2bus_diskii_device::a2bus_diskii_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- a2bus_floppy_device(mconfig, A2BUS_DISKII, tag, owner, clock)
-{
-}
-
-a2bus_agat7flop_device::a2bus_agat7flop_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- a2bus_floppy_device(mconfig, A2BUS_AGAT7_FDC, tag, owner, clock)
-{
-}
-
-a2bus_agat9flop_device::a2bus_agat9flop_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- a2bus_floppy_device(mconfig, A2BUS_AGAT9_FDC, tag, owner, clock)
-{
-}
-
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-
-void a2bus_floppy_device::device_start()
-{
- m_rom = device().machine().root_device().memregion(this->subtag(DISKII_ROM_REGION).c_str())->base();
-}
-
-void a2bus_floppy_device::device_reset()
-{
-}
-
-
-/*-------------------------------------------------
- read_c0nx - called for reads from this card's c0nx space
--------------------------------------------------*/
-
-uint8_t a2bus_floppy_device::read_c0nx(uint8_t offset)
-{
- return m_fdc->read(offset);
-}
-
-
-/*-------------------------------------------------
- write_c0nx - called for writes to this card's c0nx space
--------------------------------------------------*/
-
-void a2bus_floppy_device::write_c0nx(uint8_t offset, uint8_t data)
-{
- m_fdc->write(offset, data);
-}
-
-/*-------------------------------------------------
- read_cnxx - called for reads from this card's c0nx space
--------------------------------------------------*/
-
-uint8_t a2bus_floppy_device::read_cnxx(uint8_t offset)
-{
- return m_rom[offset];
-}
diff --git a/src/devices/bus/a2bus/a2diskii.h b/src/devices/bus/a2bus/a2diskii.h
deleted file mode 100644
index 01aff07b4da..00000000000
--- a/src/devices/bus/a2bus/a2diskii.h
+++ /dev/null
@@ -1,76 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:R. Belmont
-/*********************************************************************
-
- a2diskii.h
-
- Apple II Disk II Controller Card
-
-*********************************************************************/
-
-#ifndef MAME_BUS_A2BUS_A2DISKII_H
-#define MAME_BUS_A2BUS_A2DISKII_H
-
-#pragma once
-
-#include "a2bus.h"
-#include "machine/applefdc.h"
-
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-class a2bus_floppy_device:
- public device_t,
- public device_a2bus_card_interface
-{
-protected:
- // construction/destruction
- a2bus_floppy_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
-
- // overrides of standard a2bus slot functions
- virtual uint8_t read_c0nx(uint8_t offset) override;
- virtual void write_c0nx(uint8_t offset, uint8_t data) override;
- virtual uint8_t read_cnxx(uint8_t offset) override;
-
- required_device<applefdc_base_device> m_fdc;
-
-private:
- uint8_t *m_rom;
-};
-
-class a2bus_diskii_device: public a2bus_floppy_device
-{
-public:
- a2bus_diskii_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-};
-
-class a2bus_agat7flop_device: public a2bus_floppy_device
-{
-public:
- a2bus_agat7flop_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- virtual const tiny_rom_entry *device_rom_region() const override;
-};
-
-class a2bus_agat9flop_device: public a2bus_floppy_device
-{
-public:
- a2bus_agat9flop_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- virtual const tiny_rom_entry *device_rom_region() const override;
-};
-
-// device type definition
-DECLARE_DEVICE_TYPE(A2BUS_DISKII, a2bus_diskii_device)
-DECLARE_DEVICE_TYPE(A2BUS_AGAT7_FDC, a2bus_agat7flop_device)
-DECLARE_DEVICE_TYPE(A2BUS_AGAT9_FDC, a2bus_agat9flop_device)
-
-#endif // MAME_BUS_A2BUS_A2DISKII_H
diff --git a/src/devices/bus/a2bus/a2diskiing.cpp b/src/devices/bus/a2bus/a2diskiing.cpp
index 10fbec3e016..bba1144fcda 100644
--- a/src/devices/bus/a2bus/a2diskiing.cpp
+++ b/src/devices/bus/a2bus/a2diskiing.cpp
@@ -9,10 +9,12 @@
*********************************************************************/
#include "emu.h"
-#include "imagedev/floppy.h"
-#include "formats/ap2_dsk.h"
#include "a2diskiing.h"
+#include "formats/ap2_dsk.h"
+#include "formats/as_dsk.h"
+#include "formats/fs_prodos.h"
+
/***************************************************************************
PARAMETERS
***************************************************************************/
@@ -24,6 +26,8 @@
DEFINE_DEVICE_TYPE(A2BUS_DISKIING, a2bus_diskiing_device, "a2diskiing", "Apple Disk II NG controller (16-sector)")
DEFINE_DEVICE_TYPE(A2BUS_DISKIING13, a2bus_diskiing13_device, "diskii13", "Apple Disk II NG controller (13-sector)")
DEFINE_DEVICE_TYPE(A2BUS_APPLESURANCE, a2bus_applesurance_device, "a2surance", "Applesurance Diagnostic Controller")
+DEFINE_DEVICE_TYPE(A2BUS_AGAT7_FDC, a2bus_agat7flop_device, "agat7_flop", "Agat-7 140K floppy card")
+DEFINE_DEVICE_TYPE(A2BUS_AGAT9_FDC, a2bus_agat9flop_device, "agat9_flop", "Agat-9 140K floppy card")
#define WOZFDC_TAG "wozfdc"
#define DISKII_ROM_REGION "diskii_rom"
@@ -48,6 +52,16 @@ ROM_START( applesurance )
ROM_LOAD( "applesurance 3.0 - 2732.bin", 0x000000, 0x001000, CRC(64eafec7) SHA1(723dc6cd32de5a0f27af7503764185ac58904c05) )
ROM_END
+ROM_START( agat7 )
+ ROM_REGION(0x100, DISKII_ROM_REGION, 0)
+ ROM_LOAD( "shugart7.rom", 0x0000, 0x0100, CRC(c6e4850c) SHA1(71626d3d2d4bbeeac2b77585b45a5566d20b8d34) )
+ROM_END
+
+ROM_START( agat9 )
+ ROM_REGION(0x100, DISKII_ROM_REGION, 0)
+ ROM_LOAD( "shugart9.rom", 0x0000, 0x0100, CRC(964a0ce2) SHA1(bf955189ebffe874c20ef649a3db8177dc16af61) )
+ROM_END
+
void diskiing_device::floppy_formats(format_registration &fr)
{
fr.add(FLOPPY_A216S_DOS_FORMAT);
@@ -56,6 +70,8 @@ void diskiing_device::floppy_formats(format_registration &fr)
fr.add(FLOPPY_EDD_FORMAT);
fr.add(FLOPPY_WOZ_FORMAT);
fr.add(FLOPPY_NIB_FORMAT);
+
+ fr.add(fs::PRODOS);
}
void a2bus_diskiing13_device::floppy_formats(format_registration &fr)
@@ -102,6 +118,16 @@ const tiny_rom_entry *a2bus_applesurance_device::device_rom_region() const
return ROM_NAME( applesurance );
}
+const tiny_rom_entry *a2bus_agat7flop_device::device_rom_region() const
+{
+ return ROM_NAME(agat7);
+}
+
+const tiny_rom_entry *a2bus_agat9flop_device::device_rom_region() const
+{
+ return ROM_NAME(agat9);
+}
+
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
@@ -131,6 +157,16 @@ a2bus_applesurance_device::a2bus_applesurance_device(const machine_config &mconf
{
}
+a2bus_agat7flop_device::a2bus_agat7flop_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ diskiing_device(mconfig, A2BUS_AGAT7_FDC, tag, owner, clock)
+{
+}
+
+a2bus_agat9flop_device::a2bus_agat9flop_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ diskiing_device(mconfig, A2BUS_AGAT9_FDC, tag, owner, clock)
+{
+}
+
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
diff --git a/src/devices/bus/a2bus/a2diskiing.h b/src/devices/bus/a2bus/a2diskiing.h
index a3b07e78063..1292249333e 100644
--- a/src/devices/bus/a2bus/a2diskiing.h
+++ b/src/devices/bus/a2bus/a2diskiing.h
@@ -14,13 +14,10 @@
#pragma once
#include "a2bus.h"
-#include "a2diskii.h"
#include "machine/wozfdc.h"
#include "imagedev/floppy.h"
-#include "formats/flopimg.h"
-
//**************************************************************************
// TYPE DEFINITIONS
@@ -58,8 +55,6 @@ class a2bus_diskiing_device: public diskiing_device
{
public:
a2bus_diskiing_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- static auto parent_rom_device_type() { return &A2BUS_DISKII; }
};
class a2bus_diskiing13_device: public diskiing_device
@@ -102,9 +97,29 @@ private:
int m_c800_bank;
};
+class a2bus_agat7flop_device : public diskiing_device
+{
+public:
+ a2bus_agat7flop_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual const tiny_rom_entry *device_rom_region() const override;
+};
+
+class a2bus_agat9flop_device : public diskiing_device
+{
+public:
+ a2bus_agat9flop_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual const tiny_rom_entry *device_rom_region() const override;
+};
+
// device type definition
DECLARE_DEVICE_TYPE(A2BUS_DISKIING, a2bus_diskiing_device)
DECLARE_DEVICE_TYPE(A2BUS_DISKIING13, a2bus_diskiing13_device)
DECLARE_DEVICE_TYPE(A2BUS_APPLESURANCE, a2bus_applesurance_device)
+DECLARE_DEVICE_TYPE(A2BUS_AGAT7_FDC, a2bus_agat7flop_device)
+DECLARE_DEVICE_TYPE(A2BUS_AGAT9_FDC, a2bus_agat9flop_device)
#endif // MAME_BUS_A2BUS_A2DISKIING_H
diff --git a/src/devices/bus/a2bus/a2eauxslot.cpp b/src/devices/bus/a2bus/a2eauxslot.cpp
index 135496dc0d0..1b37eecde0a 100644
--- a/src/devices/bus/a2bus/a2eauxslot.cpp
+++ b/src/devices/bus/a2bus/a2eauxslot.cpp
@@ -2,9 +2,8 @@
// copyright-holders:R. Belmont
/***************************************************************************
- a2eauxslot.c - Apple IIe auxiliary slot and card emulation
-
- by R. Belmont
+ a2eauxslot.cpp - Apple IIe auxiliary slot and card emulation
+ by R. Belmont
***************************************************************************/
@@ -73,19 +72,6 @@ a2eauxslot_device::a2eauxslot_device(const machine_config &mconfig, device_type
}
//-------------------------------------------------
-// device_resolve_objects - resolve objects that
-// may be needed for other devices to set
-// initial conditions at start time
-//-------------------------------------------------
-
-void a2eauxslot_device::device_resolve_objects()
-{
- // resolve callbacks
- m_out_irq_cb.resolve_safe();
- m_out_nmi_cb.resolve_safe();
-}
-
-//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
@@ -114,8 +100,8 @@ void a2eauxslot_device::set_nmi_line(int state)
}
// interrupt request from a2eauxslot card
-WRITE_LINE_MEMBER( a2eauxslot_device::irq_w ) { m_out_irq_cb(state); }
-WRITE_LINE_MEMBER( a2eauxslot_device::nmi_w ) { m_out_nmi_cb(state); }
+void a2eauxslot_device::irq_w(int state) { m_out_irq_cb(state); }
+void a2eauxslot_device::nmi_w(int state) { m_out_nmi_cb(state); }
//**************************************************************************
// DEVICE CONFIG A2EAUXSLOT CARD INTERFACE
diff --git a/src/devices/bus/a2bus/a2eauxslot.h b/src/devices/bus/a2bus/a2eauxslot.h
index 8e88d18ff8e..185e1deede5 100644
--- a/src/devices/bus/a2bus/a2eauxslot.h
+++ b/src/devices/bus/a2bus/a2eauxslot.h
@@ -42,7 +42,7 @@ public:
a2eauxslot_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
- // device-level overrides
+ // device_t implementation
virtual void device_resolve_objects() override;
virtual void device_start() override { }
@@ -75,14 +75,13 @@ public:
void set_irq_line(int state);
void set_nmi_line(int state);
- DECLARE_WRITE_LINE_MEMBER( irq_w );
- DECLARE_WRITE_LINE_MEMBER( nmi_w );
+ void irq_w(int state);
+ void nmi_w(int state);
protected:
a2eauxslot_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
- // device-level overrides
- virtual void device_resolve_objects() override;
+ // device_t implementation
virtual void device_start() override;
// internal state
@@ -108,11 +107,12 @@ public:
// construction/destruction
virtual ~device_a2eauxslot_card_interface();
- virtual uint8_t read_auxram(uint16_t offset) { printf("a2eauxslot: unhandled auxram read @ %04x\n", offset); return 0xff; }
- virtual void write_auxram(uint16_t offset, uint8_t data) { printf("a2eauxslot: unhandled auxram write %02x @ %04x\n", data, offset); }
- virtual void write_c07x(uint8_t offset, uint8_t data) {}
- virtual uint8_t *get_vram_ptr() = 0;
- virtual uint8_t *get_auxbank_ptr() = 0;
+ virtual u8 read_auxram(u16 offset) { printf("a2eauxslot: unhandled auxram read @ %04x\n", offset); return 0xff; }
+ virtual void write_auxram(u16 offset, u8 data) { printf("a2eauxslot: unhandled auxram write %02x @ %04x\n", data, offset); }
+ virtual void write_c07x(u8 offset, u8 data) {}
+ virtual u8 *get_vram_ptr() = 0;
+ virtual u8 *get_auxbank_ptr() = 0;
+ virtual u16 get_auxbank_mask() = 0;
virtual bool allow_dhr() { return true; }
device_a2eauxslot_card_interface *next() const { return m_next; }
diff --git a/src/devices/bus/a2bus/a2echoii.cpp b/src/devices/bus/a2bus/a2echoii.cpp
index 604dc7ae1c6..f87d48ac74b 100644
--- a/src/devices/bus/a2bus/a2echoii.cpp
+++ b/src/devices/bus/a2bus/a2echoii.cpp
@@ -27,9 +27,9 @@
#include "sound/tms5220.h"
#include "speaker.h"
-#define LOG_READYQ (1 << 0)
-#define LOG_READ (1 << 1)
-#define LOG_WRITE (1 << 2)
+#define LOG_READYQ (1U << 1)
+#define LOG_READ (1U << 2)
+#define LOG_WRITE (1U << 3)
//#define VERBOSE (LOG_READYQ | LOG_READ | LOG_WRITE)
#include "logmacro.h"
@@ -70,8 +70,8 @@ protected:
virtual bool take_c800() override;
private:
- //DECLARE_WRITE_LINE_MEMBER(tms_irq_callback);
- DECLARE_WRITE_LINE_MEMBER(tms_readyq_callback);
+ //void tms_irq_callback(int state);
+ void tms_readyq_callback(int state);
uint8_t m_writelatch_data; // 74ls373 latch
bool m_readlatch_flag; // 74c74 1st half
bool m_writelatch_flag; // 74c74 2nd half
@@ -140,13 +140,13 @@ void a2bus_echoii_device::device_reset()
}
/*
-WRITE_LINE_MEMBER(a2bus_echoii_device::tms_irq_callback)
+void a2bus_echoii_device::tms_irq_callback(int state)
{
update_irq_to_maincpu();
}
*/
-WRITE_LINE_MEMBER(a2bus_echoii_device::tms_readyq_callback)
+void a2bus_echoii_device::tms_readyq_callback(int state)
{
if (state == ASSERT_LINE)
{
diff --git a/src/devices/bus/a2bus/a2eext80col.cpp b/src/devices/bus/a2bus/a2eext80col.cpp
index 2ddb4a0b476..1c7a4fe77b3 100644
--- a/src/devices/bus/a2bus/a2eext80col.cpp
+++ b/src/devices/bus/a2bus/a2eext80col.cpp
@@ -2,7 +2,7 @@
// copyright-holders:R. Belmont
/*********************************************************************
- a2eext80col.c
+ a2eext80col.cpp
Apple IIe Extended 80 Column Card (64K of RAM, double-hi-res)
@@ -51,22 +51,27 @@ void a2eaux_ext80col_device::device_reset()
{
}
-uint8_t a2eaux_ext80col_device::read_auxram(uint16_t offset)
+u8 a2eaux_ext80col_device::read_auxram(uint16_t offset)
{
return m_ram[offset];
}
-void a2eaux_ext80col_device::write_auxram(uint16_t offset, uint8_t data)
+void a2eaux_ext80col_device::write_auxram(uint16_t offset, u8 data)
{
m_ram[offset] = data;
}
-uint8_t *a2eaux_ext80col_device::get_vram_ptr()
+u8 *a2eaux_ext80col_device::get_vram_ptr()
{
return &m_ram[0];
}
-uint8_t *a2eaux_ext80col_device::get_auxbank_ptr()
+u8 *a2eaux_ext80col_device::get_auxbank_ptr()
{
return &m_ram[0];
}
+
+u16 a2eaux_ext80col_device::get_auxbank_mask()
+{
+ return 0xffff;
+}
diff --git a/src/devices/bus/a2bus/a2eext80col.h b/src/devices/bus/a2bus/a2eext80col.h
index 2aa89586f5b..239a22e1484 100644
--- a/src/devices/bus/a2bus/a2eext80col.h
+++ b/src/devices/bus/a2bus/a2eext80col.h
@@ -2,7 +2,7 @@
// copyright-holders:R. Belmont
/*********************************************************************
- a2eext80col.c
+ a2eext80col.h
Apple IIe Extended 80 Column Card
@@ -33,14 +33,15 @@ protected:
virtual void device_start() override;
virtual void device_reset() override;
- virtual uint8_t read_auxram(uint16_t offset) override;
- virtual void write_auxram(uint16_t offset, uint8_t data) override;
- virtual uint8_t *get_vram_ptr() override;
- virtual uint8_t *get_auxbank_ptr() override;
+ virtual u8 read_auxram(uint16_t offset) override;
+ virtual void write_auxram(uint16_t offset, u8 data) override;
+ virtual u8 *get_vram_ptr() override;
+ virtual u8 *get_auxbank_ptr() override;
+ virtual u16 get_auxbank_mask() override;
virtual bool allow_dhr() override { return true; }
private:
- uint8_t m_ram[64*1024];
+ u8 m_ram[64*1024];
};
// device type definition
diff --git a/src/devices/bus/a2bus/a2eramworks3.cpp b/src/devices/bus/a2bus/a2eramworks3.cpp
index c10a85d884c..11dcf3cae68 100644
--- a/src/devices/bus/a2bus/a2eramworks3.cpp
+++ b/src/devices/bus/a2bus/a2eramworks3.cpp
@@ -2,7 +2,7 @@
// copyright-holders:R. Belmont
/*********************************************************************
- a2eramworks3.c
+ a2eramworks3.cpp
Applied Engineering RamWorks III
@@ -67,26 +67,31 @@ void a2eaux_ramworks3_device::device_reset()
m_bank = 0;
}
-uint8_t a2eaux_ramworks3_device::read_auxram(uint16_t offset)
+u8 a2eaux_ramworks3_device::read_auxram(uint16_t offset)
{
return m_ram[offset+m_bank];
}
-void a2eaux_ramworks3_device::write_auxram(uint16_t offset, uint8_t data)
+void a2eaux_ramworks3_device::write_auxram(uint16_t offset, u8 data)
{
m_ram[offset+m_bank] = data;
}
-uint8_t *a2eaux_ramworks3_device::get_vram_ptr()
+u8 *a2eaux_ramworks3_device::get_vram_ptr()
{
return &m_ram[0];
}
-uint8_t *a2eaux_ramworks3_device::get_auxbank_ptr()
+u8 *a2eaux_ramworks3_device::get_auxbank_ptr()
{
return &m_ram[m_bank];
}
+u16 a2eaux_ramworks3_device::get_auxbank_mask()
+{
+ return 0xffff;
+}
+
/*
These cards are split into 64k logical banks.
@@ -100,7 +105,7 @@ uint8_t *a2eaux_ramworks3_device::get_auxbank_ptr()
However, the software will recognize and correctly use a configuration in which
all of banks 00-7F are populated for a total of 8 megabytes. So that's what we do.
*/
-void a2eaux_ramworks3_device::write_c07x(uint8_t offset, uint8_t data)
+void a2eaux_ramworks3_device::write_c07x(u8 offset, u8 data)
{
// write to C071/3/5/7?
if ((offset & 0x9) == 1)
@@ -109,7 +114,7 @@ void a2eaux_ramworks3_device::write_c07x(uint8_t offset, uint8_t data)
}
}
-void a2eaux_franklin384_device::write_c07x(uint8_t offset, uint8_t data)
+void a2eaux_franklin384_device::write_c07x(u8 offset, u8 data)
{
if ((offset & 0x9) == 1)
{
@@ -123,7 +128,7 @@ void a2eaux_franklin384_device::write_c07x(uint8_t offset, uint8_t data)
}
}
-void a2eaux_franklin512_device::write_c07x(uint8_t offset, uint8_t data)
+void a2eaux_franklin512_device::write_c07x(u8 offset, u8 data)
{
if ((offset & 0x9) == 1)
{
diff --git a/src/devices/bus/a2bus/a2eramworks3.h b/src/devices/bus/a2bus/a2eramworks3.h
index e43b83b537f..fc083445e3c 100644
--- a/src/devices/bus/a2bus/a2eramworks3.h
+++ b/src/devices/bus/a2bus/a2eramworks3.h
@@ -2,7 +2,7 @@
// copyright-holders:R. Belmont
/*********************************************************************
- a2eramworks3.c
+ a2eramworks3.h
Applied Engineering RamWorks III
@@ -31,17 +31,18 @@ protected:
virtual void device_start() override;
virtual void device_reset() override;
- virtual uint8_t read_auxram(uint16_t offset) override;
- virtual void write_auxram(uint16_t offset, uint8_t data) override;
- virtual uint8_t *get_vram_ptr() override;
- virtual uint8_t *get_auxbank_ptr() override;
+ virtual u8 read_auxram(uint16_t offset) override;
+ virtual void write_auxram(uint16_t offset, u8 data) override;
+ virtual u8 *get_vram_ptr() override;
+ virtual u8 *get_auxbank_ptr() override;
+ virtual u16 get_auxbank_mask() override;
virtual bool allow_dhr() override { return true; }
- virtual void write_c07x(uint8_t offset, uint8_t data) override;
+ virtual void write_c07x(u8 offset, u8 data) override;
int m_bank;
private:
- uint8_t m_ram[8*1024*1024];
+ u8 m_ram[8*1024*1024];
};
class a2eaux_franklin384_device: public a2eaux_ramworks3_device
@@ -50,7 +51,7 @@ public:
a2eaux_franklin384_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
- virtual void write_c07x(uint8_t offset, uint8_t data) override;
+ virtual void write_c07x(u8 offset, u8 data) override;
};
class a2eaux_franklin512_device: public a2eaux_ramworks3_device
@@ -59,7 +60,7 @@ public:
a2eaux_franklin512_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
- virtual void write_c07x(uint8_t offset, uint8_t data) override;
+ virtual void write_c07x(u8 offset, u8 data) override;
};
// device type definition
diff --git a/src/devices/bus/a2bus/a2estd80col.cpp b/src/devices/bus/a2bus/a2estd80col.cpp
index 8eecf223c48..ab5d4bc48d1 100644
--- a/src/devices/bus/a2bus/a2estd80col.cpp
+++ b/src/devices/bus/a2bus/a2estd80col.cpp
@@ -2,7 +2,7 @@
// copyright-holders:R. Belmont
/*********************************************************************
- a2estd80col.c
+ a2estd80col.cpp
Apple IIe Standard 80 Column Card (2K of RAM, no double-hi-res)
@@ -11,11 +11,6 @@
#include "emu.h"
#include "a2estd80col.h"
-
-/***************************************************************************
- PARAMETERS
-***************************************************************************/
-
//**************************************************************************
// GLOBAL VARIABLES
//**************************************************************************
@@ -50,30 +45,27 @@ void a2eaux_std80col_device::device_reset()
{
}
-uint8_t a2eaux_std80col_device::read_auxram(uint16_t offset)
+u8 a2eaux_std80col_device::read_auxram(uint16_t offset)
{
- if (offset < 0x800)
- {
- return m_ram[offset];
- }
-
- return 0xff;
+ return m_ram[offset & 0x3ff];
}
-void a2eaux_std80col_device::write_auxram(uint16_t offset, uint8_t data)
+void a2eaux_std80col_device::write_auxram(uint16_t offset, u8 data)
{
- if (offset < 0x800)
- {
- m_ram[offset] = data;
- }
+ m_ram[offset & 0x3ff] = data;
}
-uint8_t *a2eaux_std80col_device::get_vram_ptr()
+u8 *a2eaux_std80col_device::get_vram_ptr()
{
return &m_ram[0];
}
-uint8_t *a2eaux_std80col_device::get_auxbank_ptr()
+u8 *a2eaux_std80col_device::get_auxbank_ptr()
{
return &m_ram[0];
}
+
+u16 a2eaux_std80col_device::get_auxbank_mask()
+{
+ return 0x3ff;
+}
diff --git a/src/devices/bus/a2bus/a2estd80col.h b/src/devices/bus/a2bus/a2estd80col.h
index 6f81860487d..d66a42a7495 100644
--- a/src/devices/bus/a2bus/a2estd80col.h
+++ b/src/devices/bus/a2bus/a2estd80col.h
@@ -2,7 +2,7 @@
// copyright-holders:R. Belmont
/*********************************************************************
- a2estd80col.c
+ a2estd80col.h
Apple IIe Standard 80 Column Card
@@ -33,14 +33,15 @@ protected:
virtual void device_start() override;
virtual void device_reset() override;
- virtual uint8_t read_auxram(uint16_t offset) override;
- virtual void write_auxram(uint16_t offset, uint8_t data) override;
- virtual uint8_t *get_vram_ptr() override;
- virtual uint8_t *get_auxbank_ptr() override;
+ virtual u8 read_auxram(uint16_t offset) override;
+ virtual void write_auxram(uint16_t offset, u8 data) override;
+ virtual u8 *get_vram_ptr() override;
+ virtual u8 *get_auxbank_ptr() override;
+ virtual u16 get_auxbank_mask() override;
virtual bool allow_dhr() override { return false; } // we don't allow DHR
private:
- uint8_t m_ram[2*1024];
+ u8 m_ram[0x400];
};
// device type definition
diff --git a/src/devices/bus/a2bus/a2hsscsi.cpp b/src/devices/bus/a2bus/a2hsscsi.cpp
index b2043c20f30..2d015cf5d36 100644
--- a/src/devices/bus/a2bus/a2hsscsi.cpp
+++ b/src/devices/bus/a2bus/a2hsscsi.cpp
@@ -329,7 +329,7 @@ void a2bus_hsscsi_device::write_c800(uint16_t offset, uint8_t data)
}
}
-WRITE_LINE_MEMBER( a2bus_hsscsi_device::drq_w )
+void a2bus_hsscsi_device::drq_w(int state)
{
m_drq = (state ? 0x80 : 0x00);
// printf("DRQ to %d\n", state);
diff --git a/src/devices/bus/a2bus/a2hsscsi.h b/src/devices/bus/a2bus/a2hsscsi.h
index be200ccde0d..3878ffac370 100644
--- a/src/devices/bus/a2bus/a2hsscsi.h
+++ b/src/devices/bus/a2bus/a2hsscsi.h
@@ -30,7 +30,7 @@ public:
static constexpr feature_type unemulated_features() { return feature::DISK; }
- DECLARE_WRITE_LINE_MEMBER( drq_w );
+ void drq_w(int state);
protected:
a2bus_hsscsi_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
diff --git a/src/devices/bus/a2bus/a2iwm.cpp b/src/devices/bus/a2bus/a2iwm.cpp
index 9e61ac28daa..74adc23ffa8 100644
--- a/src/devices/bus/a2bus/a2iwm.cpp
+++ b/src/devices/bus/a2bus/a2iwm.cpp
@@ -16,6 +16,7 @@
#include "machine/applefdintf.h"
#include "formats/ap2_dsk.h"
+#include "formats/as_dsk.h"
//**************************************************************************
diff --git a/src/devices/bus/a2bus/a2iwm.h b/src/devices/bus/a2bus/a2iwm.h
index 3f0fe974d3a..1ffd1b8160b 100644
--- a/src/devices/bus/a2bus/a2iwm.h
+++ b/src/devices/bus/a2bus/a2iwm.h
@@ -15,7 +15,6 @@
#include "a2bus.h"
#include "imagedev/floppy.h"
-#include "formats/flopimg.h"
#include "machine/iwm.h"
//**************************************************************************
diff --git a/src/devices/bus/a2bus/a2mcms.cpp b/src/devices/bus/a2bus/a2mcms.cpp
index f23a647f4a8..3455fa3d8fc 100644
--- a/src/devices/bus/a2bus/a2mcms.cpp
+++ b/src/devices/bus/a2bus/a2mcms.cpp
@@ -123,7 +123,7 @@ mcms_device *a2bus_mcms1_device::get_engine(void)
return m_mcms;
}
-WRITE_LINE_MEMBER(a2bus_mcms1_device::irq_w)
+void a2bus_mcms1_device::irq_w(int state)
{
if (state == ASSERT_LINE)
{
@@ -205,7 +205,6 @@ mcms_device::mcms_device(const machine_config &mconfig, const char *tag, device_
void mcms_device::device_start()
{
- m_write_irq.resolve();
m_stream = stream_alloc(0, 2, 31250);
m_timer = timer_alloc(FUNC(mcms_device::set_irq_tick), this);
m_clrtimer = timer_alloc(FUNC(mcms_device::clr_irq_tick), this);
diff --git a/src/devices/bus/a2bus/a2mcms.h b/src/devices/bus/a2bus/a2mcms.h
index 371c74c54fa..a696455ffad 100644
--- a/src/devices/bus/a2bus/a2mcms.h
+++ b/src/devices/bus/a2bus/a2mcms.h
@@ -88,7 +88,7 @@ protected:
virtual bool take_c800() override { return false; }
private:
- DECLARE_WRITE_LINE_MEMBER(irq_w);
+ void irq_w(int state);
};
// card 2
diff --git a/src/devices/bus/a2bus/a2midi.cpp b/src/devices/bus/a2bus/a2midi.cpp
index f1cc7ecb2a6..941800180ed 100644
--- a/src/devices/bus/a2bus/a2midi.cpp
+++ b/src/devices/bus/a2bus/a2midi.cpp
@@ -53,9 +53,9 @@ protected:
required_device<acia6850_device> m_acia;
private:
- DECLARE_WRITE_LINE_MEMBER( acia_irq_w );
- DECLARE_WRITE_LINE_MEMBER( ptm_irq_w );
- DECLARE_WRITE_LINE_MEMBER( write_acia_clock );
+ void acia_irq_w(int state);
+ void ptm_irq_w(int state);
+ void write_acia_clock(int state);
bool m_acia_irq, m_ptm_irq;
};
@@ -149,7 +149,7 @@ void a2bus_midi_device::write_c0nx(uint8_t offset, uint8_t data)
}
}
-WRITE_LINE_MEMBER( a2bus_midi_device::acia_irq_w )
+void a2bus_midi_device::acia_irq_w(int state)
{
m_acia_irq = state ? true : false;
@@ -163,7 +163,7 @@ WRITE_LINE_MEMBER( a2bus_midi_device::acia_irq_w )
}
}
-WRITE_LINE_MEMBER( a2bus_midi_device::ptm_irq_w )
+void a2bus_midi_device::ptm_irq_w(int state)
{
m_acia_irq = state ? true : false;
@@ -177,7 +177,7 @@ WRITE_LINE_MEMBER( a2bus_midi_device::ptm_irq_w )
}
}
-WRITE_LINE_MEMBER( a2bus_midi_device::write_acia_clock )
+void a2bus_midi_device::write_acia_clock(int state)
{
m_acia->write_txc(state);
m_acia->write_rxc(state);
diff --git a/src/devices/bus/a2bus/a2mockingboard.cpp b/src/devices/bus/a2bus/a2mockingboard.cpp
index 0968d55c9a0..f002e129136 100644
--- a/src/devices/bus/a2bus/a2mockingboard.cpp
+++ b/src/devices/bus/a2bus/a2mockingboard.cpp
@@ -22,51 +22,47 @@
namespace {
-/***************************************************************************
- PARAMETERS
-***************************************************************************/
-
-#define VIA1_TAG "mockbd_via1"
-#define VIA2_TAG "mockbd_via2"
-#define AY1_TAG "mockbd_ay1"
-#define AY2_TAG "mockbd_ay2"
-#define AY3_TAG "mockbd_ay3"
-#define AY4_TAG "mockbd_ay4"
-#define E2P_TMS_TAG "tms5220"
-
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
class a2bus_ayboard_device:
- public device_t,
- public device_a2bus_card_interface
+ public device_t,
+ public device_a2bus_card_interface
{
-public:
- DECLARE_WRITE_LINE_MEMBER( via1_irq_w );
- DECLARE_WRITE_LINE_MEMBER( via2_irq_w );
- u8 via1_in_a() { return m_porta1; }
- u8 via2_in_a() { return m_porta2; }
- void via1_out_a(u8 data);
- virtual void via1_out_b(u8 data);
- void via2_out_a(u8 data);
- virtual void via2_out_b(u8 data);
-
protected:
// construction/destruction
- a2bus_ayboard_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_add_mconfig(machine_config &config) override;
-
- // overrides of standard a2bus slot functions
+ a2bus_ayboard_device(
+ const machine_config &mconfig,
+ device_type type,
+ const char *tag,
+ device_t *owner,
+ uint32_t clock) ATTR_COLD;
+
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ // device_a2bus_card_interface implementation
virtual u8 read_c0nx(u8 offset) override { return 0xff; }
virtual void write_c0nx(u8 offset, u8 data) override { }
virtual u8 read_cnxx(u8 offset) override;
virtual void write_cnxx(u8 offset, u8 data) override;
- void add_common_devices(machine_config &config);
+ static void via_psg_ctrl(ay8913_device &psg, u8 &latch, u8 data);
+
+ void via1_irq_w(int state);
+ void via2_irq_w(int state);
+ u8 via1_in_a() { return m_porta1; }
+ u8 via2_in_a() { return m_porta2; }
+ void via1_out_a(u8 data);
+ void via1_out_b(u8 data);
+ void via2_out_a(u8 data);
+ void via2_out_b(u8 data);
+
+ // machine configuration fragments
+ void single_via_devices(machine_config &config) ATTR_COLD;
required_device<via6522_device> m_via1;
optional_device<via6522_device> m_via2;
@@ -80,17 +76,19 @@ protected:
class a2bus_mockingboard_device : public a2bus_ayboard_device
{
public:
- a2bus_mockingboard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ a2bus_mockingboard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) ATTR_COLD;
- virtual void via1_out_b(u8 data) override;
protected:
- virtual void device_add_mconfig(machine_config &config) override;
- virtual void device_reset() override;
+ // device_t implementation
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ void via1_out_b(u8 data);
required_device<votrax_sc01_device> m_sc01;
private:
- DECLARE_WRITE_LINE_MEMBER(write_via1_cb2);
+ void write_via1_cb2(int state);
u8 m_portb1;
int m_last_cb2_state;
@@ -99,19 +97,21 @@ private:
class a2bus_phasor_device : public a2bus_ayboard_device
{
public:
- a2bus_phasor_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- void via1_out_b(u8 data) override;
- void via2_out_b(u8 data) override;
+ a2bus_phasor_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) ATTR_COLD;
protected:
- virtual void device_add_mconfig(machine_config &config) override;
+ // device_t implementation
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ // device_a2bus_card_interface implementation
virtual u8 read_c0nx(u8 offset) override;
virtual void write_c0nx(u8 offset, u8 data) override;
virtual u8 read_cnxx(u8 offset) override;
virtual void write_cnxx(u8 offset, u8 data) override;
+ void via1_out_b(u8 data);
+ void via2_out_b(u8 data);
+
required_device<ay8913_device> m_ay3;
required_device<ay8913_device> m_ay4;
@@ -124,26 +124,29 @@ private:
class a2bus_echoplus_device : public a2bus_ayboard_device
{
public:
- a2bus_echoplus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ a2bus_echoplus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) ATTR_COLD;
protected:
- virtual void device_add_mconfig(machine_config &config) override;
-
- virtual void via1_out_b(u8 data) override;
+ // device_t implementation
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ // device_a2bus_card_interface implementation
virtual u8 read_c0nx(u8 offset) override;
virtual void write_c0nx(u8 offset, u8 data) override;
virtual u8 read_cnxx(u8 offset) override;
virtual void write_cnxx(u8 offset, u8 data) override;
+ void via1_out_b(u8 data);
+
required_device<tms5220_device> m_tms;
};
+
//-------------------------------------------------
// device_add_mconfig - add device configuration
//-------------------------------------------------
-void a2bus_ayboard_device::add_common_devices(machine_config &config)
+void a2bus_ayboard_device::single_via_devices(machine_config &config)
{
MOS6522(config, m_via1, 1022727);
m_via1->readpa_handler().set(FUNC(a2bus_ayboard_device::via1_in_a));
@@ -151,37 +154,35 @@ void a2bus_ayboard_device::add_common_devices(machine_config &config)
m_via1->writepb_handler().set(FUNC(a2bus_ayboard_device::via1_out_b));
m_via1->irq_handler().set(FUNC(a2bus_ayboard_device::via1_irq_w));
- MOS6522(config, m_via2, 1022727);
- m_via2->readpa_handler().set(FUNC(a2bus_ayboard_device::via2_in_a));
- m_via2->writepa_handler().set(FUNC(a2bus_ayboard_device::via2_out_a));
- m_via2->writepb_handler().set(FUNC(a2bus_ayboard_device::via2_out_b));
- m_via2->irq_handler().set(FUNC(a2bus_ayboard_device::via2_irq_w));
-
SPEAKER(config, "lspeaker").front_left();
SPEAKER(config, "rspeaker").front_right();
+
AY8913(config, m_ay1, 1022727);
m_ay1->add_route(ALL_OUTPUTS, "lspeaker", 0.5);
+
+ AY8913(config, m_ay2, 1022727);
+ m_ay2->add_route(ALL_OUTPUTS, "rspeaker", 0.5);
}
void a2bus_ayboard_device::device_add_mconfig(machine_config &config)
{
- add_common_devices(config);
+ single_via_devices(config);
- AY8913(config, m_ay2, 1022727);
- m_ay2->add_route(ALL_OUTPUTS, "rspeaker", 0.5);
+ MOS6522(config, m_via2, 1022727);
+ m_via2->readpa_handler().set(FUNC(a2bus_ayboard_device::via2_in_a));
+ m_via2->writepa_handler().set(FUNC(a2bus_ayboard_device::via2_out_a));
+ m_via2->writepb_handler().set(FUNC(a2bus_ayboard_device::via2_out_b));
+ m_via2->irq_handler().set(FUNC(a2bus_ayboard_device::via2_irq_w));
}
void a2bus_mockingboard_device::device_add_mconfig(machine_config &config)
{
- add_common_devices(config);
+ a2bus_ayboard_device::device_add_mconfig(config);
m_via1->writepb_handler().set(FUNC(a2bus_mockingboard_device::via1_out_b));
m_via1->cb2_handler().set(FUNC(a2bus_mockingboard_device::write_via1_cb2));
- AY8913(config, m_ay2, 1022727);
- m_ay2->add_route(ALL_OUTPUTS, "rspeaker", 0.5);
-
- VOTRAX_SC01(config, m_sc01, 1022727);
+ VOTRAX_SC01A(config, m_sc01, 1022727);
m_sc01->ar_callback().set(m_via1, FUNC(via6522_device::write_cb1));
m_sc01->add_route(ALL_OUTPUTS, "lspeaker", 1.0);
m_sc01->add_route(ALL_OUTPUTS, "rspeaker", 1.0);
@@ -189,33 +190,31 @@ void a2bus_mockingboard_device::device_add_mconfig(machine_config &config)
void a2bus_phasor_device::device_add_mconfig(machine_config &config)
{
- add_common_devices(config);
+ a2bus_ayboard_device::device_add_mconfig(config);
m_via1->writepb_handler().set(FUNC(a2bus_phasor_device::via1_out_b));
m_via2->writepb_handler().set(FUNC(a2bus_phasor_device::via2_out_b));
SPEAKER(config, "lspeaker2").front_left();
SPEAKER(config, "rspeaker2").front_right();
- AY8913(config, m_ay2, 1022727);
+
+ m_ay2->reset_routes().add_route(ALL_OUTPUTS, "lspeaker2", 0.5);
+
AY8913(config, m_ay3, 1022727);
- AY8913(config, m_ay4, 1022727);
- m_ay2->add_route(ALL_OUTPUTS, "lspeaker2", 0.5);
m_ay3->add_route(ALL_OUTPUTS, "rspeaker", 0.5);
+
+ AY8913(config, m_ay4, 1022727);
m_ay4->add_route(ALL_OUTPUTS, "rspeaker2", 0.5);
}
void a2bus_echoplus_device::device_add_mconfig(machine_config &config)
{
- add_common_devices(config);
+ single_via_devices(config);
- config.device_remove(VIA2_TAG);
- m_via1->writepb_handler().set(FUNC(a2bus_ayboard_device::via1_out_b));
-
- AY8913(config, m_ay2, 1022727);
- m_ay2->add_route(ALL_OUTPUTS, "rspeaker", 0.5);
+ m_via1->writepb_handler().set(FUNC(a2bus_echoplus_device::via1_out_b));
SPEAKER(config, "echosp").front_center();
- TMS5220(config, m_tms, 640000);
+ TMS5220C(config, m_tms, 640000);
// echo+ has a TSP5220C soldered down on it
m_tms->add_route(ALL_OUTPUTS, "echosp", 1.0);
}
@@ -227,10 +226,10 @@ void a2bus_echoplus_device::device_add_mconfig(machine_config &config)
a2bus_ayboard_device::a2bus_ayboard_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, type, tag, owner, clock),
device_a2bus_card_interface(mconfig, *this),
- m_via1(*this, VIA1_TAG),
- m_via2(*this, VIA2_TAG),
- m_ay1(*this, AY1_TAG),
- m_ay2(*this, AY2_TAG),
+ m_via1(*this, "via1"),
+ m_via2(*this, "via2"),
+ m_ay1(*this, "ay1"),
+ m_ay2(*this, "ay2"),
m_porta1(0),
m_porta2(0)
{
@@ -244,15 +243,15 @@ a2bus_mockingboard_device::a2bus_mockingboard_device(const machine_config &mconf
a2bus_phasor_device::a2bus_phasor_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
a2bus_ayboard_device(mconfig, A2BUS_PHASOR, tag, owner, clock),
- m_ay3(*this, AY3_TAG),
- m_ay4(*this, AY4_TAG),
+ m_ay3(*this, "ay3"),
+ m_ay4(*this, "ay4"),
m_native(false)
{
}
a2bus_echoplus_device::a2bus_echoplus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
a2bus_ayboard_device(mconfig, A2BUS_ECHOPLUS, tag, owner, clock),
- m_tms(*this, E2P_TMS_TAG)
+ m_tms(*this, "tms5220")
{
}
@@ -373,7 +372,28 @@ void a2bus_phasor_device::write_cnxx(u8 offset, u8 data)
}
}
-WRITE_LINE_MEMBER( a2bus_ayboard_device::via1_irq_w )
+inline void a2bus_ayboard_device::via_psg_ctrl(ay8913_device &psg, u8 &latch, u8 data)
+{
+ switch (data & 3)
+ {
+ case 0: // BDIR=0, BC1=0 (inactive)
+ break;
+
+ case 1: // BDIR=0, BC1=1 (read PSG)
+ latch = psg.data_r();
+ break;
+
+ case 2: // BDIR=1, BC1=0 (write PSG)
+ psg.data_w(latch);
+ break;
+
+ case 3: // BDIR=1, BC1=1 (latch)
+ psg.address_w(latch);
+ break;
+ }
+}
+
+void a2bus_ayboard_device::via1_irq_w(int state)
{
if (state)
{
@@ -385,7 +405,7 @@ WRITE_LINE_MEMBER( a2bus_ayboard_device::via1_irq_w )
}
}
-WRITE_LINE_MEMBER( a2bus_ayboard_device::via2_irq_w )
+void a2bus_ayboard_device::via2_irq_w(int state)
{
if (state)
{
@@ -410,23 +430,7 @@ void a2bus_ayboard_device::via1_out_b(u8 data)
}
else
{
- switch (data & 3)
- {
- case 0: // BDIR=0, BC1=0 (inactive)
- break;
-
- case 1: // BDIR=0, BC1=1 (read PSG)
- m_porta1 = m_ay1->data_r();
- break;
-
- case 2: // BDIR=1, BC1=0 (write PSG)
- m_ay1->data_w(m_porta1);
- break;
-
- case 3: // BDIR=1, BC1=1 (latch)
- m_ay1->address_w(m_porta1);
- break;
- }
+ via_psg_ctrl(*m_ay1, m_porta1, data);
}
}
@@ -439,45 +443,14 @@ void a2bus_echoplus_device::via1_out_b(u8 data)
}
else
{
+ // TODO: reading with both PSGs selected should fight for the latch
if (BIT(data, 3)) // BC2_1=1 (PSG1 active)
{
- switch (data & 3)
- {
- case 0: // BDIR=0, BC1=0 (inactive)
- break;
-
- case 1: // BDIR=0, BC1=1 (read PSG)
- m_porta1 = m_ay1->data_r();
- break;
-
- case 2: // BDIR=1, BC1=0 (write PSG)
- m_ay1->data_w(m_porta1);
- break;
-
- case 3: // BDIR=1, BC1=1 (latch)
- m_ay1->address_w(m_porta1);
- break;
- }
+ via_psg_ctrl(*m_ay1, m_porta1, data);
}
if (BIT(data, 4)) // BC2_2_=1 (PSG2 active)
{
- switch (data & 3)
- {
- case 0: // BDIR=0, BC1=0 (inactive)
- break;
-
- case 1: // BDIR=0, BC1=1 (read PSG)
- m_porta1 = m_ay2->data_r();
- break;
-
- case 2: // BDIR=1, BC1=0 (write PSG)
- m_ay2->data_w(m_porta1);
- break;
-
- case 3: // BDIR=1, BC1=1 (latch)
- m_ay2->address_w(m_porta1);
- break;
- }
+ via_psg_ctrl(*m_ay2, m_porta1, data);
}
}
}
@@ -502,32 +475,11 @@ void a2bus_phasor_device::via1_out_b(u8 data)
chip_sel = 1;
// logerror("Phasor: %02x to AY1/2 CS %02x (BDIR/BC1 %02x, data %02x)\n", m_porta1, chipSel, data & 3, data);
- switch (data & 3)
- {
- case 0: // BDIR=0, BC1=0 (inactive)
- break;
-
- case 1: // BDIR=0, BC1=1 (read PSG)
- if (BIT(chip_sel, 0))
- m_porta1 = m_ay1->data_r();
- if (BIT(chip_sel, 1))
- m_porta1 = m_ay2->data_r();
- break;
-
- case 2: // BDIR=1, BC1=0 (write PSG)
- if (BIT(chip_sel, 0))
- m_ay1->data_w(m_porta1);
- if (BIT(chip_sel, 1))
- m_ay2->data_w(m_porta1);
- break;
-
- case 3: // BDIR=1, BC1=1 (latch)
- if (BIT(chip_sel, 0))
- m_ay1->address_w(m_porta1);
- if (BIT(chip_sel, 1))
- m_ay2->address_w(m_porta1);
- break;
- }
+ // TODO: reading with both PSGs selected should fight for the latch
+ if (BIT(chip_sel, 0))
+ via_psg_ctrl(*m_ay1, m_porta1, data);
+ if (BIT(chip_sel, 1))
+ via_psg_ctrl(*m_ay2, m_porta1, data);
}
}
@@ -544,23 +496,7 @@ void a2bus_ayboard_device::via2_out_b(u8 data)
}
else
{
- switch (data & 3)
- {
- case 0: // BDIR=0, BC1=0 (inactive)
- break;
-
- case 1: // BDIR=0, BC1=1 (read PSG)
- m_porta2 = m_ay2->data_r();
- break;
-
- case 2: // BDIR=1, BC1=0 (write PSG)
- m_ay2->data_w(m_porta2);
- break;
-
- case 3: // BDIR=1, BC1=1 (latch)
- m_ay2->address_w(m_porta2);
- break;
- }
+ via_psg_ctrl(*m_ay2, m_porta2, data);
}
}
@@ -588,32 +524,11 @@ void a2bus_phasor_device::via2_out_b(u8 data)
chip_sel = 1;
// logerror("Phasor: %02x to AY3/4 CS %02x (BDIR/BC1 %02x, data %02x)\n", m_porta2, chipSel, data & 3, data);
- switch (data & 3)
- {
- case 0: // BDIR=0, BC1=0 (inactive)
- break;
-
- case 1: // BDIR=0, BC1=1 (read PSG)
- if (BIT(chip_sel, 0))
- m_porta2 = m_ay3->data_r();
- if (BIT(chip_sel, 1))
- m_porta2 = m_ay4->data_r();
- break;
-
- case 2: // BDIR=1, BC1=0 (write PSG)
- if (BIT(chip_sel, 0))
- m_ay3->data_w(m_porta2);
- if (BIT(chip_sel, 1))
- m_ay4->data_w(m_porta2);
- break;
-
- case 3: // BDIR=1, BC1=1 (latch)
- if (BIT(chip_sel, 0))
- m_ay3->address_w(m_porta2);
- if (BIT(chip_sel, 1))
- m_ay4->address_w(m_porta2);
- break;
- }
+ // TODO: reading with both PSGs selected should fight for the latch
+ if (BIT(chip_sel, 0))
+ via_psg_ctrl(*m_ay3, m_porta2, data);
+ if (BIT(chip_sel, 1))
+ via_psg_ctrl(*m_ay4, m_porta2, data);
}
}
@@ -675,7 +590,7 @@ void a2bus_mockingboard_device::device_reset()
m_last_cb2_state = ASSERT_LINE;
}
-WRITE_LINE_MEMBER( a2bus_mockingboard_device::write_via1_cb2 )
+void a2bus_mockingboard_device::write_via1_cb2(int state)
{
if ((state == CLEAR_LINE) && (m_last_cb2_state == ASSERT_LINE))
{
@@ -695,23 +610,7 @@ void a2bus_mockingboard_device::via1_out_b(u8 data)
}
else
{
- switch (data & 3)
- {
- case 0: // BDIR=0, BC1=0 (inactive)
- break;
-
- case 1: // BDIR=0, BC1=1 (read PSG)
- m_porta1 = m_ay1->data_r();
- break;
-
- case 2: // BDIR=1, BC1=0 (write PSG)
- m_ay1->data_w(m_porta1);
- break;
-
- case 3: // BDIR=1, BC1=1 (latch)
- m_ay1->address_w(m_porta1);
- break;
- }
+ via_psg_ctrl(*m_ay1, m_porta1, data);
}
}
diff --git a/src/devices/bus/a2bus/a2parprn.cpp b/src/devices/bus/a2bus/a2parprn.cpp
index c79f04f6da8..6f09e83dc26 100644
--- a/src/devices/bus/a2bus/a2parprn.cpp
+++ b/src/devices/bus/a2bus/a2parprn.cpp
@@ -20,8 +20,11 @@ public:
virtual u8 read_c0nx(u8 offset) override;
virtual void write_c0nx(u8 offset, u8 data) override;
virtual u8 read_cnxx(u8 offset) override;
+ virtual bool take_c800() override { return false; }
protected:
+ a2bus_parprn_device(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock);
+
// device_t implementation
virtual tiny_rom_entry const *device_rom_region() const override;
virtual void device_add_mconfig(machine_config &config) override;
@@ -31,7 +34,7 @@ protected:
private:
// printer status inputs
- DECLARE_WRITE_LINE_MEMBER(ack_w);
+ void ack_w(int state);
// timer handlers
TIMER_CALLBACK_MEMBER(update_strobe);
@@ -39,7 +42,11 @@ private:
required_device<centronics_device> m_printer_conn;
required_device<output_latch_device> m_printer_out;
required_ioport m_input_config;
+
+protected:
required_region_ptr<u8> m_prom;
+
+private:
emu_timer * m_strobe_timer;
u8 m_next_strobe; // B3 pin 13
@@ -48,6 +55,18 @@ private:
};
+class a2bus_4dparprn_device : public a2bus_parprn_device
+{
+public:
+ a2bus_4dparprn_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+protected:
+ // device_t implementation
+ virtual tiny_rom_entry const *device_rom_region() const override;
+ virtual void device_start() override;
+};
+
+
// FIXME: get proper PROM dumps.
/*
@@ -83,6 +102,12 @@ ROM_START(parprn)
ROM_LOAD( "prom.b4", 0x0000, 0x0100, BAD_DUMP CRC(00b742ca) SHA1(c67888354aa013f9cb882eeeed924e292734e717) )
ROM_END
+ROM_START(4dparprn)
+ ROM_REGION(0x100, "prom", 0)
+ ROM_LOAD( "rom.bin", 0x0000, 0x0100, CRC(189262c9) SHA1(d6179664d6860df5ed26fce72f253e28f933b01a) )
+ ROM_IGNORE(0x700) // same data is repeated 8 times
+ROM_END
+
INPUT_PORTS_START(parprn)
PORT_START("CFG")
@@ -104,8 +129,8 @@ INPUT_PORTS_END
-a2bus_parprn_device::a2bus_parprn_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) :
- device_t(mconfig, A2BUS_PARPRN, tag, owner, clock),
+a2bus_parprn_device::a2bus_parprn_device(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock) :
+ device_t(mconfig, type, tag, owner, clock),
device_a2bus_card_interface(mconfig, *this),
m_printer_conn(*this, "prn"),
m_printer_out(*this, "prn_out"),
@@ -119,6 +144,17 @@ a2bus_parprn_device::a2bus_parprn_device(machine_config const &mconfig, char con
}
+a2bus_parprn_device::a2bus_parprn_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) :
+ a2bus_parprn_device(mconfig, A2BUS_PARPRN, tag, owner, clock)
+{
+}
+
+
+a2bus_4dparprn_device::a2bus_4dparprn_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) :
+ a2bus_parprn_device(mconfig, A2BUS_4DPARPRN, tag, owner, clock)
+{
+}
+
//----------------------------------------------
// device_a2bus_card_interface implementation
@@ -149,7 +185,7 @@ void a2bus_parprn_device::write_c0nx(u8 offset, u8 data)
ioport_value const cfg(m_input_config->read());
- m_printer_out->write(data & (BIT(cfg, 8) ? 0xffU : 0x7fU));
+ m_printer_out->write(data & (BIT(cfg, 4) ? 0xffU : 0x7fU));
m_printer_conn->write_strobe(BIT(~cfg, 3));
m_next_strobe = BIT(cfg, 3);
m_ack_latch = 0U;
@@ -195,6 +231,12 @@ tiny_rom_entry const *a2bus_parprn_device::device_rom_region() const
}
+tiny_rom_entry const *a2bus_4dparprn_device::device_rom_region() const
+{
+ return ROM_NAME(4dparprn);
+}
+
+
void a2bus_parprn_device::device_add_mconfig(machine_config &config)
{
CENTRONICS(config, m_printer_conn, centronics_devices, "printer");
@@ -221,6 +263,15 @@ void a2bus_parprn_device::device_start()
}
+void a2bus_4dparprn_device::device_start()
+{
+ for (unsigned i = 0U; 0x100 > i; ++i)
+ m_prom[i] = (m_prom[i] << 4) | (m_prom[i] >> 4);
+
+ a2bus_parprn_device::device_start();
+}
+
+
void a2bus_parprn_device::device_reset()
{
m_ack_latch = 1U;
@@ -232,7 +283,7 @@ void a2bus_parprn_device::device_reset()
// printer status inputs
//----------------------------------------------
-WRITE_LINE_MEMBER(a2bus_parprn_device::ack_w)
+void a2bus_parprn_device::ack_w(int state)
{
if (bool(state) != bool(m_ack_in))
{
@@ -271,3 +322,4 @@ TIMER_CALLBACK_MEMBER(a2bus_parprn_device::update_strobe)
DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_PARPRN, device_a2bus_card_interface, a2bus_parprn_device, "a2parprn", "Apple II Parallel Printer Interface Card")
+DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_4DPARPRN, device_a2bus_card_interface, a2bus_4dparprn_device, "4dparprn", "Fourth Dimension Parallel Printer Interface")
diff --git a/src/devices/bus/a2bus/a2parprn.h b/src/devices/bus/a2bus/a2parprn.h
index 668f0c89ca4..66681a3c395 100644
--- a/src/devices/bus/a2bus/a2parprn.h
+++ b/src/devices/bus/a2bus/a2parprn.h
@@ -46,6 +46,10 @@
packages. Common modifications included stretching strobe
and/or acknowledge pulses to improve reliability.
+ The Fourth Dimension board uses a larger EPROM, but still only
+ 256 bytes are used. Instead of the 20-pin header, it has a 16-pin
+ DIP socket, and no jumper block.
+
***********************************************************************/
#ifndef MAME_BUS_A2BUS_A2PARPRN_H
#define MAME_BUS_A2BUS_A2PARPRN_H
@@ -55,5 +59,6 @@
#include "a2bus.h"
DECLARE_DEVICE_TYPE(A2BUS_PARPRN, device_a2bus_card_interface)
+DECLARE_DEVICE_TYPE(A2BUS_4DPARPRN, device_a2bus_card_interface)
#endif // MAME_BUS_A2BUS_A2PARPRN_H
diff --git a/src/devices/bus/a2bus/a2pic.cpp b/src/devices/bus/a2bus/a2pic.cpp
index 321155f2cf8..32ec527b254 100644
--- a/src/devices/bus/a2bus/a2pic.cpp
+++ b/src/devices/bus/a2bus/a2pic.cpp
@@ -40,10 +40,10 @@ protected:
private:
// printer status inputs
- DECLARE_WRITE_LINE_MEMBER(ack_w);
- DECLARE_WRITE_LINE_MEMBER(perror_w);
- DECLARE_WRITE_LINE_MEMBER(select_w);
- DECLARE_WRITE_LINE_MEMBER(fault_w);
+ void ack_w(int state);
+ void perror_w(int state);
+ void select_w(int state);
+ void fault_w(int state);
// timer handlers
TIMER_CALLBACK_MEMBER(release_strobe);
@@ -384,25 +384,25 @@ void a2bus_pic_device::device_reset()
// printer status inputs
//----------------------------------------------
-WRITE_LINE_MEMBER(a2bus_pic_device::ack_w)
+void a2bus_pic_device::ack_w(int state)
{
machine().scheduler().synchronize(timer_expired_delegate(FUNC(a2bus_pic_device::set_ack_in), this), state ? 1 : 0);
}
-WRITE_LINE_MEMBER(a2bus_pic_device::perror_w)
+void a2bus_pic_device::perror_w(int state)
{
machine().scheduler().synchronize(timer_expired_delegate(FUNC(a2bus_pic_device::set_perror_in), this), state ? 1 : 0);
}
-WRITE_LINE_MEMBER(a2bus_pic_device::select_w)
+void a2bus_pic_device::select_w(int state)
{
machine().scheduler().synchronize(timer_expired_delegate(FUNC(a2bus_pic_device::set_select_in), this), state ? 1 : 0);
}
-WRITE_LINE_MEMBER(a2bus_pic_device::fault_w)
+void a2bus_pic_device::fault_w(int state)
{
machine().scheduler().synchronize(timer_expired_delegate(FUNC(a2bus_pic_device::set_fault_in), this), state ? 1 : 0);
}
diff --git a/src/devices/bus/a2bus/a2scsi.cpp b/src/devices/bus/a2bus/a2scsi.cpp
index fb3e7e8e222..cebfbd31565 100644
--- a/src/devices/bus/a2bus/a2scsi.cpp
+++ b/src/devices/bus/a2bus/a2scsi.cpp
@@ -33,7 +33,9 @@
#include "emu.h"
#include "a2scsi.h"
+#include "bus/nscsi/cd.h"
#include "bus/nscsi/devices.h"
+#include "speaker.h"
/***************************************************************************
PARAMETERS
@@ -64,9 +66,19 @@ ROM_END
void a2bus_scsi_device::device_add_mconfig(machine_config &config)
{
+ // These machines were strictly external CD-ROMs so sound didn't route back into them; the AppleCD SC had
+ // RCA jacks for connection to speakers/a stereo.
+ SPEAKER(config, "lspeaker").front_left();
+ SPEAKER(config, "rspeaker").front_right();
+
NSCSI_BUS(config, m_scsibus);
NSCSI_CONNECTOR(config, "scsibus:0", default_scsi_devices, nullptr, false);
- NSCSI_CONNECTOR(config, "scsibus:1", default_scsi_devices, "aplcdsc", false);
+ NSCSI_CONNECTOR(config, "scsibus:1").option_set("cdrom", NSCSI_CDROM_APPLE).machine_config(
+ [](device_t *device)
+ {
+ device->subdevice<cdda_device>("cdda")->add_route(0, "^^lspeaker", 1.0);
+ device->subdevice<cdda_device>("cdda")->add_route(1, "^^rspeaker", 1.0);
+ });
NSCSI_CONNECTOR(config, "scsibus:2", default_scsi_devices, nullptr, false);
NSCSI_CONNECTOR(config, "scsibus:3", default_scsi_devices, nullptr, false);
NSCSI_CONNECTOR(config, "scsibus:4", default_scsi_devices, nullptr, false);
@@ -290,7 +302,7 @@ void a2bus_scsi_device::write_c800(uint16_t offset, uint8_t data)
}
}
-WRITE_LINE_MEMBER( a2bus_scsi_device::drq_w )
+void a2bus_scsi_device::drq_w(int state)
{
m_drq = (state ? 0x80 : 0x00);
}
diff --git a/src/devices/bus/a2bus/a2scsi.h b/src/devices/bus/a2bus/a2scsi.h
index 098e7848563..e45d0171975 100644
--- a/src/devices/bus/a2bus/a2scsi.h
+++ b/src/devices/bus/a2bus/a2scsi.h
@@ -28,7 +28,7 @@ public:
// construction/destruction
a2bus_scsi_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_WRITE_LINE_MEMBER( drq_w );
+ void drq_w(int state);
protected:
a2bus_scsi_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
diff --git a/src/devices/bus/a2bus/a2sd.cpp b/src/devices/bus/a2bus/a2sd.cpp
index c5f1e743d0f..e415ece84bc 100644
--- a/src/devices/bus/a2bus/a2sd.cpp
+++ b/src/devices/bus/a2bus/a2sd.cpp
@@ -22,7 +22,6 @@
#include "emu.h"
#include "a2sd.h"
-#define LOG_GENERAL (1U << 0)
#define LOG_SPI (1U << 1)
//#define VERBOSE (LOG_COMMAND)
@@ -238,7 +237,7 @@ void a2bus_a2sd_device::write_c0nx(u8 offset, u8 data)
m_c0n3 |= (data & 0x91);
m_sdcard->spi_ss_w(BIT(data, C0N3_BIT_SS));
- LOGMASKED(LOG_GENERAL, "/SS is %x\n", BIT(data, C0N3_BIT_SS));
+ LOG("/SS is %x\n", BIT(data, C0N3_BIT_SS));
break;
default:
diff --git a/src/devices/bus/a2bus/a2sd.h b/src/devices/bus/a2bus/a2sd.h
index 88414ec39d3..481761c42ab 100644
--- a/src/devices/bus/a2bus/a2sd.h
+++ b/src/devices/bus/a2bus/a2sd.h
@@ -46,7 +46,7 @@ protected:
virtual void write_c800(uint16_t offset, u8 data) override;
// SPI 4-wire interface
- WRITE_LINE_MEMBER(spi_miso_w) { m_in_bit = state; }
+ void spi_miso_w(int state) { m_in_bit = state; }
TIMER_CALLBACK_MEMBER(shift_tick);
private:
diff --git a/src/devices/bus/a2bus/a2ssc.cpp b/src/devices/bus/a2bus/a2ssc.cpp
index 61ab1efc30b..1d6d286fd6e 100644
--- a/src/devices/bus/a2bus/a2ssc.cpp
+++ b/src/devices/bus/a2bus/a2ssc.cpp
@@ -56,7 +56,7 @@ protected:
required_region_ptr<uint8_t> m_rom;
private:
- DECLARE_WRITE_LINE_MEMBER( acia_irq_w );
+ void acia_irq_w(int state);
};
class apricorn_ssi_device : public a2bus_ssc_device
@@ -419,7 +419,7 @@ void apricorn_ssi_device::write_c0nx(uint8_t offset, uint8_t data)
m_alt_bank = true;
}
-WRITE_LINE_MEMBER( a2bus_ssc_device::acia_irq_w )
+void a2bus_ssc_device::acia_irq_w(int state)
{
if (machine().ioport().safe_to_read())
{
diff --git a/src/devices/bus/a2bus/a2thunderclock.cpp b/src/devices/bus/a2bus/a2thunderclock.cpp
index c109be5c276..5f264ee261e 100644
--- a/src/devices/bus/a2bus/a2thunderclock.cpp
+++ b/src/devices/bus/a2bus/a2thunderclock.cpp
@@ -75,7 +75,7 @@ protected:
required_region_ptr<uint8_t> m_rom;
private:
- DECLARE_WRITE_LINE_MEMBER( upd_dataout_w );
+ void upd_dataout_w(int state);
int m_dataout;
};
@@ -192,7 +192,7 @@ uint8_t a2bus_thunderclock_device::read_c800(uint16_t offset)
return m_rom[offset];
}
-WRITE_LINE_MEMBER( a2bus_thunderclock_device::upd_dataout_w )
+void a2bus_thunderclock_device::upd_dataout_w(int state)
{
if (state)
{
diff --git a/src/devices/bus/a2bus/a2ultraterm.cpp b/src/devices/bus/a2bus/a2ultraterm.cpp
index 468c7402c46..1f2c09c3b73 100644
--- a/src/devices/bus/a2bus/a2ultraterm.cpp
+++ b/src/devices/bus/a2bus/a2ultraterm.cpp
@@ -126,7 +126,7 @@ protected:
required_region_ptr<uint8_t> m_rom, m_chrrom;
private:
- DECLARE_WRITE_LINE_MEMBER(vsync_changed);
+ void vsync_changed(int state);
MC6845_UPDATE_ROW(crtc_update_row);
int m_rambank;
@@ -436,7 +436,7 @@ MC6845_UPDATE_ROW( a2bus_videx160_device::crtc_update_row )
}
}
-WRITE_LINE_MEMBER( a2bus_videx160_device::vsync_changed )
+void a2bus_videx160_device::vsync_changed(int state)
{
if ( state )
{
diff --git a/src/devices/bus/a2bus/ace2x00.h b/src/devices/bus/a2bus/ace2x00.h
index 9714f5aa965..faa769ddcbc 100644
--- a/src/devices/bus/a2bus/ace2x00.h
+++ b/src/devices/bus/a2bus/ace2x00.h
@@ -15,7 +15,6 @@
#include "a2bus.h"
#include "imagedev/floppy.h"
-#include "formats/flopimg.h"
#include "machine/iwm.h"
//**************************************************************************
diff --git a/src/devices/bus/a2bus/agat7ports.cpp b/src/devices/bus/a2bus/agat7ports.cpp
index afd196d6549..417840b0164 100644
--- a/src/devices/bus/a2bus/agat7ports.cpp
+++ b/src/devices/bus/a2bus/agat7ports.cpp
@@ -178,7 +178,7 @@ uint8_t a2bus_agat7_ports_device::read_portc()
return (m_centronics_busy << 7) | m_printer_cfg->read();
}
-WRITE_LINE_MEMBER(a2bus_agat7_ports_device::write_centronics_busy)
+void a2bus_agat7_ports_device::write_centronics_busy(int state)
{
m_centronics_busy = state;
}
diff --git a/src/devices/bus/a2bus/agat7ports.h b/src/devices/bus/a2bus/agat7ports.h
index 2ee4f38b4dd..1d587c9f747 100644
--- a/src/devices/bus/a2bus/agat7ports.h
+++ b/src/devices/bus/a2bus/agat7ports.h
@@ -52,7 +52,7 @@ protected:
void write_portb(uint8_t data);
uint8_t read_portc();
- DECLARE_WRITE_LINE_MEMBER(write_centronics_busy);
+ void write_centronics_busy(int state);
private:
bool m_centronics_busy;
diff --git a/src/devices/bus/a2bus/agat840k_hle.cpp b/src/devices/bus/a2bus/agat840k_hle.cpp
index cd6d01389b4..0a0fd511a95 100644
--- a/src/devices/bus/a2bus/agat840k_hle.cpp
+++ b/src/devices/bus/a2bus/agat840k_hle.cpp
@@ -100,12 +100,12 @@ a2bus_agat840k_hle_device::a2bus_agat840k_hle_device(const machine_config &mconf
{
}
-WRITE_LINE_MEMBER(a2bus_agat840k_hle_device::index_0_w)
+void a2bus_agat840k_hle_device::index_0_w(int state)
{
index_callback(0, state);
}
-WRITE_LINE_MEMBER(a2bus_agat840k_hle_device::index_1_w)
+void a2bus_agat840k_hle_device::index_1_w(int state)
{
index_callback(1, state);
}
diff --git a/src/devices/bus/a2bus/agat840k_hle.h b/src/devices/bus/a2bus/agat840k_hle.h
index a497f2bc7aa..61d2f8f267b 100644
--- a/src/devices/bus/a2bus/agat840k_hle.h
+++ b/src/devices/bus/a2bus/agat840k_hle.h
@@ -44,8 +44,8 @@ public:
void d15_o_b(uint8_t data);
void d15_o_c(uint8_t data);
- DECLARE_WRITE_LINE_MEMBER(index_0_w);
- DECLARE_WRITE_LINE_MEMBER(index_1_w);
+ void index_0_w(int state);
+ void index_1_w(int state);
void index_callback(int unit, int state);
diff --git a/src/devices/bus/a2bus/byte8251.cpp b/src/devices/bus/a2bus/byte8251.cpp
index ffe6c6325c0..301ed5bd536 100644
--- a/src/devices/bus/a2bus/byte8251.cpp
+++ b/src/devices/bus/a2bus/byte8251.cpp
@@ -142,7 +142,7 @@ void a2bus_byte8251_device::device_add_mconfig(machine_config &config)
rs232.rxd_handler().set(m_usart, FUNC(i8251_device::write_rxd));
}
-} // aonymous namespace
+} // anonymous namespace
// device type definition
diff --git a/src/devices/bus/a2bus/cards.cpp b/src/devices/bus/a2bus/cards.cpp
index b2ace857a5f..5ab855ddf5e 100644
--- a/src/devices/bus/a2bus/cards.cpp
+++ b/src/devices/bus/a2bus/cards.cpp
@@ -18,10 +18,10 @@
#include "a2arcadebd.h"
#include "a2cffa.h"
#include "a2corvus.h"
-#include "a2diskii.h"
#include "a2diskiing.h"
#include "a2dx1.h"
#include "a2echoii.h"
+#include "a2hsscsi.h"
#include "a2iwm.h"
#include "a2mcms.h"
#include "a2memexp.h"
@@ -31,6 +31,7 @@
#include "a2pic.h"
#include "a2sam.h"
#include "a2scsi.h"
+#include "a2sd.h"
#include "a2softcard.h"
#include "a2ssc.h"
#include "a2superdrive.h"
@@ -39,48 +40,52 @@
#include "a2thunderclock.h"
#include "a2ultraterm.h"
#include "a2videoterm.h"
+#include "a2vulcan.h"
#include "a2zipdrive.h"
+#include "booti.h"
#include "byte8251.h"
-#include "computereyes2.h"
#include "ccs7710.h"
+#include "cmsscsi.h"
+#include "computereyes2.h"
#include "excel9.h"
#include "ezcgi.h"
#include "grafex.h"
#include "grappler.h"
+#include "lancegs.h"
#include "laser128.h"
#include "mouse.h"
+#include "noisemaker.h"
+#include "pc_xporter.h"
#include "prodosromdrive.h"
+#include "q68.h"
#include "ramcard128k.h"
#include "ramcard16k.h"
+#include "romcard.h"
+#include "sider.h"
+#include "snesmax.h"
+#include "softcard3.h"
#include "ssbapple.h"
#include "ssprite.h"
#include "suprterminal.h"
#include "timemasterho.h"
+#include "titan3plus2.h"
#include "transwarp.h"
#include "uniprint.h"
-#include "booti.h"
-#include "q68.h"
-#include "pc_xporter.h"
-#include "cmsscsi.h"
-#include "a2vulcan.h"
#include "uthernet.h"
-#include "a2hsscsi.h"
-#include "a2sd.h"
-#include "sider.h"
-#include "lancegs.h"
-#include "titan3plus2.h"
-#include "softcard3.h"
+#include "vistaa800.h"
void apple2_slot0_cards(device_slot_interface &device)
{
device.option_add("lang", A2BUS_RAMCARD16K); // Apple II RAM Language Card
device.option_add("ssram", A2BUS_RAMCARD128K); // Saturn Systems 128K extended language card
+ device.option_add("romcard", A2BUS_ROMCARDUSER); // Apple II ROM Card that loads a custom ROM image
+ device.option_add("romcardfp", A2BUS_ROMCARDFP); // Apple II ROM Card with Autostart Monitor + Applesoft BASIC
+ device.option_add("romcardint", A2BUS_ROMCARDINT); // Apple II ROM Card with Autostart Monitor + Integer BASIC
}
void apple2_cards(device_slot_interface &device)
{
- device.option_add("diskii", A2BUS_DISKII); // Disk II Controller Card
device.option_add("diskiing", A2BUS_DISKIING); // Disk II Controller Card, cycle-accurate version
device.option_add("diskiing13", A2BUS_DISKIING13); // Disk II Controller Card, cycle-accurate version
device.option_add("diskiiiwm", A2BUS_IWM_CARD); // IWM Disk II Controller Card
@@ -114,6 +119,7 @@ void apple2_cards(device_slot_interface &device)
device.option_add("ultratermenh", A2BUS_ULTRATERMENH); // Videx UltraTerm (enhanced //e)
device.option_add("aevm80", A2BUS_AEVIEWMASTER80); // Applied Engineering ViewMaster 80
device.option_add("parprn", A2BUS_PARPRN); // Apple II Parallel Printer Interface Card
+ device.option_add("4dparprn", A2BUS_4DPARPRN); // Fourth Dimension Parallel Printer Interface
device.option_add("parallel", A2BUS_PIC); // Apple II Parallel Interface Card
device.option_add("grappler", A2BUS_GRAPPLER); // Orange Micro Grappler Printer Interface card
device.option_add("grapplus", A2BUS_GRAPPLERPLUS); // Orange Micro Grappler+ Printer Interface card
@@ -131,11 +137,13 @@ void apple2_cards(device_slot_interface &device)
device.option_add("ssprite", A2BUS_SSPRITE); // Synetix SuperSprite Board
device.option_add("ssbapple", A2BUS_SSBAPPLE); // SSB Apple speech board
device.option_add("4play", A2BUS_4PLAY); // 4Play Joystick Card (Rev. B)
+ device.option_add("snesmax", A2BUS_SNES_MAX); // SNES MAX controller adapter
device.option_add("ceyes2", A2BUS_COMPUTEREYES2); // ComputerEyes/2 Video Digitizer
device.option_add("twarp", A2BUS_TRANSWARP); // AE TransWarp accelerator
device.option_add("applesurance", A2BUS_APPLESURANCE); // Applesurance Diagnostic Controller
// device.option_add("magicmusician", A2BUS_MAGICMUSICIAN); // Magic Musician Card
device.option_add("byte8251", A2BUS_BYTE8251); // BYTE Magazine 8251 serial card
+ device.option_add("noisemaker", A2BUS_NOISEMAKER); // ADS Noisemaker II
device.option_add("suprterm", A2BUS_SUPRTERMINAL); // M&R Enterprises SUP'R'TERMINAL 80-column card
device.option_add("uniprint", A2BUS_UNIPRINT); // Videx Uniprint parallel printer card
device.option_add("ccs7710", A2BUS_CCS7710); // California Computer Systems Model 7710 Asynchronous Serial Interface
@@ -144,11 +152,11 @@ void apple2_cards(device_slot_interface &device)
device.option_add("q68plus", A2BUS_Q68PLUS); // Stellation Q68 Plus 68000 card
device.option_add("grafex", A2BUS_GRAFEX); // Grafex card (uPD7220 graphics)
device.option_add("excel9", A2BUS_EXCEL9); // Excel-9 (6809 coprocessor)
+ device.option_add("vistaa800", A2BUS_VISTAA800); // Vista A800 8" Disk Controller Card
}
void apple2e_cards(device_slot_interface &device)
{
- device.option_add("diskii", A2BUS_DISKII); // Disk II Controller Card
device.option_add("diskiing", A2BUS_DISKIING); // Disk II Controller Card, cycle-accurate version
device.option_add("diskiing13", A2BUS_DISKIING13); // Disk II Controller Card, cycle-accurate version
device.option_add("diskiiiwm", A2BUS_IWM_CARD); // IWM Disk II Controller Card
@@ -184,6 +192,7 @@ void apple2e_cards(device_slot_interface &device)
device.option_add("ultratermenh", A2BUS_ULTRATERMENH); // Videx UltraTerm (enhanced //e)
device.option_add("aevm80", A2BUS_AEVIEWMASTER80); // Applied Engineering ViewMaster 80
device.option_add("parprn", A2BUS_PARPRN); // Apple II Parallel Printer Interface Card
+ device.option_add("4dparprn", A2BUS_4DPARPRN); // Fourth Dimension Parallel Printer Interface
device.option_add("parallel", A2BUS_PIC); // Apple II Parallel Interface Card
device.option_add("grappler", A2BUS_GRAPPLER); // Orange Micro Grappler Printer Interface card
device.option_add("grapplus", A2BUS_GRAPPLERPLUS); // Orange Micro Grappler+ Printer Interface card
@@ -205,9 +214,11 @@ void apple2e_cards(device_slot_interface &device)
device.option_add("twarp", A2BUS_TRANSWARP); // AE TransWarp accelerator
device.option_add("vulcan", A2BUS_VULCANIIE); // Applied Engineering Vulcan IDE drive
device.option_add("4play", A2BUS_4PLAY); // 4Play Joystick Card (Rev. B)
+ device.option_add("snesmax", A2BUS_SNES_MAX); // SNES MAX controller adapter
device.option_add("ceyes2", A2BUS_COMPUTEREYES2); // ComputerEyes/2 Video Digitizer
device.option_add("applesurance", A2BUS_APPLESURANCE); // Applesurance Diagnostic Controller
device.option_add("byte8251", A2BUS_BYTE8251); // BYTE Magazine 8251 serial card
+ device.option_add("noisemaker", A2BUS_NOISEMAKER); // ADS Noisemaker II
device.option_add("cmsscsi", A2BUS_CMSSCSI); // CMS Apple II SCSI Card
device.option_add("uthernet", A2BUS_UTHERNET); // A2RetroSystems Uthernet card
device.option_add("sider2", A2BUS_SIDER2); // Advanced Tech Systems / First Class Peripherals Sider 2 SASI card
@@ -222,6 +233,7 @@ void apple2e_cards(device_slot_interface &device)
device.option_add("grafex", A2BUS_GRAFEX); // Grafex card (uPD7220 graphics)
device.option_add("pdromdrive", A2BUS_PRODOSROMDRIVE); // ProDOS ROM Drive
device.option_add("superdrive", A2BUS_SUPERDRIVE); // Apple II 3.5" Disk Controller
+ device.option_add("vistaa800", A2BUS_VISTAA800); // Vista A800 8" Disk Controller Card
}
void apple2gs_cards(device_slot_interface &device)
@@ -259,6 +271,7 @@ void apple2gs_cards(device_slot_interface &device)
device.option_add("ultratermenh", A2BUS_ULTRATERMENH); // Videx UltraTerm (enhanced //e)
device.option_add("aevm80", A2BUS_AEVIEWMASTER80); // Applied Engineering ViewMaster 80
device.option_add("parprn", A2BUS_PARPRN); // Apple II Parallel Printer Interface Card
+ device.option_add("4dparprn", A2BUS_4DPARPRN); // Fourth Dimension Parallel Printer Interface
device.option_add("parallel", A2BUS_PIC); // Apple Parallel Interface Card
device.option_add("grappler", A2BUS_GRAPPLER); // Orange Micro Grappler Printer Interface card
device.option_add("grapplus", A2BUS_GRAPPLERPLUS); // Orange Micro Grappler+ Printer Interface card
@@ -276,9 +289,11 @@ void apple2gs_cards(device_slot_interface &device)
device.option_add("vulcan", A2BUS_VULCAN); // Applied Engineering Vulcan IDE drive
device.option_add("vulcangold", A2BUS_VULCANGOLD); // Applied Engineering Vulcan Gold IDE drive
device.option_add("4play", A2BUS_4PLAY); // 4Play Joystick Card (Rev. B)
+ device.option_add("snesmax", A2BUS_SNES_MAX); // SNES MAX controller adapter
// device.option_add("magicmusician", A2BUS_MAGICMUSICIAN); // Magic Musician Card
// device.option_add("pcxport", A2BUS_PCXPORTER); // Applied Engineering PC Transporter
device.option_add("byte8251", A2BUS_BYTE8251); // BYTE Magazine 8251 serial card
+ device.option_add("noisemaker", A2BUS_NOISEMAKER); // ADS Noisemaker II
// device.option_add("hostram", A2BUS_HOSTRAM); // Slot 7 RAM for GS Plus host protocol
// device.option_add("ramfast", A2BUS_RAMFAST); // C.V. Technologies RAMFast SCSI card
device.option_add("cmsscsi", A2BUS_CMSSCSI); // CMS Apple II SCSI Card
diff --git a/src/devices/bus/a2bus/ccs7710.cpp b/src/devices/bus/a2bus/ccs7710.cpp
index 17f8cdfe80e..3a6d1449fbb 100644
--- a/src/devices/bus/a2bus/ccs7710.cpp
+++ b/src/devices/bus/a2bus/ccs7710.cpp
@@ -69,7 +69,7 @@ u8 ccs7710_device::read_cnxx(u8 offset)
return m_firmware[offset];
}
-WRITE_LINE_MEMBER(ccs7710_device::acia_irq_w)
+void ccs7710_device::acia_irq_w(int state)
{
if (state == ASSERT_LINE)
raise_slot_irq();
@@ -77,7 +77,7 @@ WRITE_LINE_MEMBER(ccs7710_device::acia_irq_w)
lower_slot_irq();
}
-WRITE_LINE_MEMBER(ccs7710_device::external_clock_w)
+void ccs7710_device::external_clock_w(int state)
{
m_external_clock = state;
if (!BIT(m_baud_select->read(), 0))
diff --git a/src/devices/bus/a2bus/ccs7710.h b/src/devices/bus/a2bus/ccs7710.h
index db2a7616891..0a5a7ea34e2 100644
--- a/src/devices/bus/a2bus/ccs7710.h
+++ b/src/devices/bus/a2bus/ccs7710.h
@@ -36,8 +36,8 @@ protected:
private:
// miscellaneous handlers
- DECLARE_WRITE_LINE_MEMBER(acia_irq_w);
- DECLARE_WRITE_LINE_MEMBER(external_clock_w);
+ void acia_irq_w(int state);
+ void external_clock_w(int state);
u8 baud_select_r(offs_t offset);
// object finders
diff --git a/src/devices/bus/a2bus/cmsscsi.h b/src/devices/bus/a2bus/cmsscsi.h
index 8e417d76bc0..67f79120f9c 100644
--- a/src/devices/bus/a2bus/cmsscsi.h
+++ b/src/devices/bus/a2bus/cmsscsi.h
@@ -28,7 +28,7 @@ public:
// construction/destruction
a2bus_cmsscsi_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_WRITE_LINE_MEMBER( drq_w );
+ void drq_w(int state);
protected:
a2bus_cmsscsi_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
diff --git a/src/devices/bus/a2bus/corvfdc01.cpp b/src/devices/bus/a2bus/corvfdc01.cpp
index 212f49ed20b..4511aa29a88 100644
--- a/src/devices/bus/a2bus/corvfdc01.cpp
+++ b/src/devices/bus/a2bus/corvfdc01.cpp
@@ -249,7 +249,7 @@ uint8_t a2bus_corvfdc01_device::read_cnxx(uint8_t offset)
return m_rom[offset & 0x1f];
}
-WRITE_LINE_MEMBER(a2bus_corvfdc01_device::intrq_w)
+void a2bus_corvfdc01_device::intrq_w(int state)
{
if (state)
m_fdc_local_status |= LS_INT_mask;
@@ -257,7 +257,7 @@ WRITE_LINE_MEMBER(a2bus_corvfdc01_device::intrq_w)
m_fdc_local_status &= ~LS_INT_mask;
}
-WRITE_LINE_MEMBER(a2bus_corvfdc01_device::drq_w)
+void a2bus_corvfdc01_device::drq_w(int state)
{
if (state)
m_fdc_local_status |= LS_DRQ_mask;
diff --git a/src/devices/bus/a2bus/corvfdc01.h b/src/devices/bus/a2bus/corvfdc01.h
index 5c92107fcbe..29670de473f 100644
--- a/src/devices/bus/a2bus/corvfdc01.h
+++ b/src/devices/bus/a2bus/corvfdc01.h
@@ -15,7 +15,6 @@
#include "a2bus.h"
#include "machine/wd_fdc.h"
-#include "formats/imd_dsk.h"
#include "imagedev/floppy.h"
//**************************************************************************
@@ -50,8 +49,8 @@ protected:
required_device<floppy_connector> m_con4;
private:
- DECLARE_WRITE_LINE_MEMBER(intrq_w);
- DECLARE_WRITE_LINE_MEMBER(drq_w);
+ void intrq_w(int state);
+ void drq_w(int state);
uint8_t *m_rom;
uint8_t m_fdc_local_status, m_fdc_local_command;
diff --git a/src/devices/bus/a2bus/corvfdc02.cpp b/src/devices/bus/a2bus/corvfdc02.cpp
index 12c7aed06ac..3a1b4c433b5 100644
--- a/src/devices/bus/a2bus/corvfdc02.cpp
+++ b/src/devices/bus/a2bus/corvfdc02.cpp
@@ -243,7 +243,7 @@ uint8_t a2bus_corvfdc02_device::read_cnxx(uint8_t offset)
return m_rom[offset & 0x1f];
}
-WRITE_LINE_MEMBER(a2bus_corvfdc02_device::intrq_w)
+void a2bus_corvfdc02_device::intrq_w(int state)
{
if (state)
{
@@ -260,7 +260,7 @@ WRITE_LINE_MEMBER(a2bus_corvfdc02_device::intrq_w)
}
}
-WRITE_LINE_MEMBER(a2bus_corvfdc02_device::drq_w)
+void a2bus_corvfdc02_device::drq_w(int state)
{
if (state)
{
diff --git a/src/devices/bus/a2bus/corvfdc02.h b/src/devices/bus/a2bus/corvfdc02.h
index 825d68d564b..24e25d159fd 100644
--- a/src/devices/bus/a2bus/corvfdc02.h
+++ b/src/devices/bus/a2bus/corvfdc02.h
@@ -16,7 +16,6 @@
#include "a2bus.h"
#include "imagedev/floppy.h"
#include "machine/upd765.h"
-#include "formats/imd_dsk.h"
//**************************************************************************
// TYPE DEFINITIONS
@@ -52,8 +51,8 @@ protected:
required_device<floppy_connector> m_con4;
private:
- DECLARE_WRITE_LINE_MEMBER(intrq_w);
- DECLARE_WRITE_LINE_MEMBER(drq_w);
+ void intrq_w(int state);
+ void drq_w(int state);
static void corv_floppy_formats(format_registration &fr);
diff --git a/src/devices/bus/a2bus/ezcgi.cpp b/src/devices/bus/a2bus/ezcgi.cpp
index 3ebccb45518..bbbe2931f56 100644
--- a/src/devices/bus/a2bus/ezcgi.cpp
+++ b/src/devices/bus/a2bus/ezcgi.cpp
@@ -52,7 +52,7 @@ protected:
required_device<tms9918a_device> m_tms;
private:
- DECLARE_WRITE_LINE_MEMBER( tms_irq_w );
+ void tms_irq_w(int state);
};
class a2bus_ezcgi_9938_device:
@@ -77,7 +77,7 @@ protected:
required_device<v9938_device> m_tms;
private:
- DECLARE_WRITE_LINE_MEMBER( tms_irq_w );
+ void tms_irq_w(int state);
};
class a2bus_ezcgi_9958_device:
@@ -102,7 +102,7 @@ protected:
required_device<v9958_device> m_tms;
private:
- DECLARE_WRITE_LINE_MEMBER( tms_irq_w );
+ void tms_irq_w(int state);
};
#define MSX2_XBORDER_PIXELS 16
@@ -328,7 +328,7 @@ void a2bus_ezcgi_9958_device::write_c0nx(uint8_t offset, uint8_t data)
}
}
-WRITE_LINE_MEMBER( a2bus_ezcgi_device::tms_irq_w )
+void a2bus_ezcgi_device::tms_irq_w(int state)
{
if (state)
{
@@ -340,7 +340,7 @@ WRITE_LINE_MEMBER( a2bus_ezcgi_device::tms_irq_w )
}
}
-WRITE_LINE_MEMBER( a2bus_ezcgi_9938_device::tms_irq_w )
+void a2bus_ezcgi_9938_device::tms_irq_w(int state)
{
if (state)
{
@@ -352,7 +352,7 @@ WRITE_LINE_MEMBER( a2bus_ezcgi_9938_device::tms_irq_w )
}
}
-WRITE_LINE_MEMBER( a2bus_ezcgi_9958_device::tms_irq_w )
+void a2bus_ezcgi_9958_device::tms_irq_w(int state)
{
if (state)
{
diff --git a/src/devices/bus/a2bus/grappler.cpp b/src/devices/bus/a2bus/grappler.cpp
index c09ff95e8fc..057e9718667 100644
--- a/src/devices/bus/a2bus/grappler.cpp
+++ b/src/devices/bus/a2bus/grappler.cpp
@@ -84,9 +84,9 @@ protected:
private:
// printer status inputs
- DECLARE_WRITE_LINE_MEMBER(busy_w);
- DECLARE_WRITE_LINE_MEMBER(pe_w);
- DECLARE_WRITE_LINE_MEMBER(slct_w);
+ void busy_w(int state);
+ void pe_w(int state);
+ void slct_w(int state);
// synchronised printer status inputs
void set_busy_in(s32 param);
@@ -169,19 +169,19 @@ void a2bus_grappler_device_base::set_rom_bank(u16 rom_bank)
// printer status inputs
//--------------------------------------------------
-WRITE_LINE_MEMBER(a2bus_grappler_device_base::busy_w)
+void a2bus_grappler_device_base::busy_w(int state)
{
machine().scheduler().synchronize(timer_expired_delegate(FUNC(a2bus_grappler_device_base::set_busy_in), this), state ? 1 : 0);
}
-WRITE_LINE_MEMBER(a2bus_grappler_device_base::pe_w)
+void a2bus_grappler_device_base::pe_w(int state)
{
machine().scheduler().synchronize(timer_expired_delegate(FUNC(a2bus_grappler_device_base::set_pe_in), this), state ? 1 : 0);
}
-WRITE_LINE_MEMBER(a2bus_grappler_device_base::slct_w)
+void a2bus_grappler_device_base::slct_w(int state)
{
machine().scheduler().synchronize(timer_expired_delegate(FUNC(a2bus_grappler_device_base::set_slct_in), this), state ? 1 : 0);
}
@@ -247,7 +247,7 @@ protected:
private:
// printer status inputs
- DECLARE_WRITE_LINE_MEMBER(ack_w);
+ void ack_w(int state);
// synchronised signals
void set_data(s32 param);
@@ -362,7 +362,7 @@ void a2bus_grappler_device::device_reset()
// printer status inputs
//--------------------------------------------------
-WRITE_LINE_MEMBER(a2bus_grappler_device::ack_w)
+void a2bus_grappler_device::ack_w(int state)
{
machine().scheduler().synchronize(timer_expired_delegate(FUNC(a2bus_grappler_device::set_ack_in), this), state ? 1 : 0);
}
@@ -451,7 +451,7 @@ protected:
virtual void device_reset() override;
// ACK latch set input
- DECLARE_WRITE_LINE_MEMBER(ack_w);
+ void ack_w(int state);
// signal state
u8 ack_latch() const { return m_ack_latch; }
@@ -581,7 +581,7 @@ void a2bus_grapplerplus_device_base::write_cnxx(u8 offset, u8 data)
// ACK latch set input
//--------------------------------------------------
-WRITE_LINE_MEMBER(a2bus_grapplerplus_device_base::ack_w)
+void a2bus_grapplerplus_device_base::ack_w(int state)
{
machine().scheduler().synchronize(timer_expired_delegate(FUNC(a2bus_grapplerplus_device_base::set_ack_in), this), state ? 1 : 0);
}
@@ -868,7 +868,7 @@ private:
virtual void data_latched(u8 data) override;
// printer status inputs
- DECLARE_WRITE_LINE_MEMBER(buf_ack_w);
+ void buf_ack_w(int state);
// MCU I/O handlers
void mcu_io(address_map &map);
@@ -1039,7 +1039,7 @@ void a2bus_buf_grapplerplus_device::data_latched(u8 data)
// printer status inputs
//--------------------------------------------------
-DECLARE_WRITE_LINE_MEMBER(a2bus_buf_grapplerplus_device::buf_ack_w)
+void a2bus_buf_grapplerplus_device::buf_ack_w(int state)
{
machine().scheduler().synchronize(timer_expired_delegate(FUNC(a2bus_buf_grapplerplus_device::set_buf_ack_in), this), state ? 1 : 0);
}
diff --git a/src/devices/bus/a2bus/lancegs.cpp b/src/devices/bus/a2bus/lancegs.cpp
index cca53536c2e..a1559596727 100644
--- a/src/devices/bus/a2bus/lancegs.cpp
+++ b/src/devices/bus/a2bus/lancegs.cpp
@@ -81,7 +81,7 @@ private:
required_device<i2c_24c04_device> m_i2cmem;
bool m_shadow;
- DECLARE_WRITE_LINE_MEMBER( netinf_irq_w );
+ void netinf_irq_w(int state);
};
@@ -185,7 +185,7 @@ void a2bus_lancegs_device::write_c0nx(uint8_t offset, uint8_t data)
}
}
-WRITE_LINE_MEMBER( a2bus_lancegs_device::netinf_irq_w )
+void a2bus_lancegs_device::netinf_irq_w(int state)
{
if (state) {
raise_slot_irq();
diff --git a/src/devices/bus/a2bus/mouse.cpp b/src/devices/bus/a2bus/mouse.cpp
index 6a40c244a40..144c6ed23b8 100644
--- a/src/devices/bus/a2bus/mouse.cpp
+++ b/src/devices/bus/a2bus/mouse.cpp
@@ -115,8 +115,8 @@ protected:
void pia_out_a(uint8_t data);
void pia_out_b(uint8_t data);
- DECLARE_WRITE_LINE_MEMBER(pia_irqa_w);
- DECLARE_WRITE_LINE_MEMBER(pia_irqb_w);
+ void pia_irqa_w(int state);
+ void pia_irqb_w(int state);
uint8_t mcu_port_a_r();
uint8_t mcu_port_b_r();
@@ -287,11 +287,11 @@ void a2bus_mouse_device::pia_out_b(uint8_t data)
m_rom_bank = (data & 0xe) << 7;
}
-WRITE_LINE_MEMBER(a2bus_mouse_device::pia_irqa_w)
+void a2bus_mouse_device::pia_irqa_w(int state)
{
}
-WRITE_LINE_MEMBER(a2bus_mouse_device::pia_irqb_w)
+void a2bus_mouse_device::pia_irqb_w(int state)
{
}
diff --git a/src/devices/bus/a2bus/nippelclock.cpp b/src/devices/bus/a2bus/nippelclock.cpp
index 047e13422e0..cca2af8b29c 100644
--- a/src/devices/bus/a2bus/nippelclock.cpp
+++ b/src/devices/bus/a2bus/nippelclock.cpp
@@ -39,7 +39,7 @@ void a2bus_nippelclock_device::device_add_mconfig(machine_config &config)
m_rtc->set_binary(true);
}
-WRITE_LINE_MEMBER(a2bus_nippelclock_device::irq_w)
+void a2bus_nippelclock_device::irq_w(int state)
{
if (state == ASSERT_LINE)
{
@@ -88,8 +88,8 @@ uint8_t a2bus_nippelclock_device::read_c0nx(uint8_t offset)
{
switch (offset)
{
- case 6: case 7:
- return m_rtc->read(offset - 6);
+ case 7:
+ return m_rtc->data_r();
break;
}
@@ -105,8 +105,11 @@ void a2bus_nippelclock_device::write_c0nx(uint8_t offset, uint8_t data)
{
switch (offset)
{
- case 6: case 7:
- m_rtc->write(offset - 6, data);
+ case 6:
+ m_rtc->address_w(data);
+ break;
+ case 7:
+ m_rtc->data_w(data);
break;
}
}
diff --git a/src/devices/bus/a2bus/nippelclock.h b/src/devices/bus/a2bus/nippelclock.h
index d2ac6f14c7f..3601ca14df8 100644
--- a/src/devices/bus/a2bus/nippelclock.h
+++ b/src/devices/bus/a2bus/nippelclock.h
@@ -42,7 +42,7 @@ protected:
required_device<mc146818_device> m_rtc;
private:
- DECLARE_WRITE_LINE_MEMBER(irq_w);
+ void irq_w(int state);
};
// device type definition
diff --git a/src/devices/bus/a2bus/noisemaker.cpp b/src/devices/bus/a2bus/noisemaker.cpp
new file mode 100644
index 00000000000..2a18ec15396
--- /dev/null
+++ b/src/devices/bus/a2bus/noisemaker.cpp
@@ -0,0 +1,86 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/**********************************************************************
+
+ ADS (Ackerman Digital Systems) Noisemaker II
+
+ This board provides a very simple interface to a AY-3-8910
+ Programmable Sound Generator through two I/O addresses, and has
+ a dedicated audio amplifier and speaker connector for the combined
+ output of its three channels. The manual gives the option of using
+ 8T26 inverting buffers instead of 8T28 noninverting buffers, which
+ changes the programming interface somewhat, though both schematics
+ and actual boards have 8T28s.
+
+ The PSG's two 8-bit parallel ports are not emulated here, though
+ the actual PCB brings all 16 signals out to a generic DIP socket.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "noisemaker.h"
+
+#include "sound/ay8910.h"
+#include "speaker.h"
+
+
+namespace {
+
+class a2bus_noisemaker_device : public device_t, public device_a2bus_card_interface
+{
+public:
+ // construction/destruction
+ a2bus_noisemaker_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+
+ // device_a2bus_card_interface overrides
+ virtual u8 read_c0nx(u8 offset) override;
+ virtual void write_c0nx(u8 offset, u8 data) override;
+ virtual bool take_c800() override { return false; }
+
+private:
+ // object finders
+ required_device<ay8910_device> m_psg;
+};
+
+a2bus_noisemaker_device::a2bus_noisemaker_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, A2BUS_NOISEMAKER, tag, owner, clock)
+ , device_a2bus_card_interface(mconfig, *this)
+ , m_psg(*this, "psg")
+{
+}
+
+void a2bus_noisemaker_device::device_start()
+{
+}
+
+u8 a2bus_noisemaker_device::read_c0nx(u8 offset)
+{
+ if (BIT(offset, 0))
+ return m_psg->data_r();
+ else
+ return 0xff; // BDIR1 = BC1 = 0, so this should be open bus
+}
+
+void a2bus_noisemaker_device::write_c0nx(u8 offset, u8 data)
+{
+ m_psg->address_data_w(offset & 1, data);
+}
+
+void a2bus_noisemaker_device::device_add_mconfig(machine_config &config)
+{
+ AY8910(config, m_psg, 1021800); // CLK tied to ϕ1 signal from bus pin 38
+ m_psg->add_route(ALL_OUTPUTS, "speaker", 0.5);
+
+ SPEAKER(config, "speaker").front_center();
+}
+
+} // anonymous namespace
+
+
+// device type definition
+DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_NOISEMAKER, device_a2bus_card_interface, a2bus_noisemaker_device, "a2bus_noisemaker", "ADS Noisemaker II")
diff --git a/src/devices/bus/a2bus/noisemaker.h b/src/devices/bus/a2bus/noisemaker.h
new file mode 100644
index 00000000000..a3f2d18cb3d
--- /dev/null
+++ b/src/devices/bus/a2bus/noisemaker.h
@@ -0,0 +1,14 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+
+#ifndef MAME_BUS_A2BUS_NOISEMAKER_H
+#define MAME_BUS_A2BUS_NOISEMAKER_H
+
+#pragma once
+
+#include "a2bus.h"
+
+// device type declaration
+DECLARE_DEVICE_TYPE(A2BUS_NOISEMAKER, device_a2bus_card_interface)
+
+#endif // MAME_BUS_A2BUS_NOISEMAKER_H
diff --git a/src/devices/bus/a2bus/pc_xporter.cpp b/src/devices/bus/a2bus/pc_xporter.cpp
index 06a87cc1820..3d0937e0832 100644
--- a/src/devices/bus/a2bus/pc_xporter.cpp
+++ b/src/devices/bus/a2bus/pc_xporter.cpp
@@ -155,14 +155,14 @@ private:
uint8_t m_6845_reg;
// interface to the keyboard
- DECLARE_WRITE_LINE_MEMBER( keyboard_clock_w );
- DECLARE_WRITE_LINE_MEMBER( keyboard_data_w );
+ void keyboard_clock_w(int state);
+ void keyboard_data_w(int state);
- DECLARE_WRITE_LINE_MEMBER( pc_pit8253_out1_changed );
- DECLARE_WRITE_LINE_MEMBER( pc_pit8253_out2_changed );
+ void pc_pit8253_out1_changed(int state);
+ void pc_pit8253_out2_changed(int state);
- DECLARE_WRITE_LINE_MEMBER( pc_dma_hrq_changed );
- DECLARE_WRITE_LINE_MEMBER( pc_dma8237_out_eop );
+ void pc_dma_hrq_changed(int state);
+ void pc_dma8237_out_eop(int state);
uint8_t pc_dma_read_byte(offs_t offset);
void pc_dma_write_byte(offs_t offset, uint8_t data);
uint8_t pc_dma8237_1_dack_r();
@@ -172,19 +172,19 @@ private:
void pc_dma8237_2_dack_w(uint8_t data);
void pc_dma8237_3_dack_w(uint8_t data);
void pc_dma8237_0_dack_w(uint8_t data);
- DECLARE_WRITE_LINE_MEMBER( pc_dack0_w );
- DECLARE_WRITE_LINE_MEMBER( pc_dack1_w );
- DECLARE_WRITE_LINE_MEMBER( pc_dack2_w );
- DECLARE_WRITE_LINE_MEMBER( pc_dack3_w );
+ void pc_dack0_w(int state);
+ void pc_dack1_w(int state);
+ void pc_dack2_w(int state);
+ void pc_dack3_w(int state);
uint8_t kbd_6502_r(offs_t offset);
void kbd_6502_w(offs_t offset, uint8_t data);
- [[maybe_unused]] DECLARE_WRITE_LINE_MEMBER( pc_speaker_set_spkrdata ); // TODO: hook up to something?
+ [[maybe_unused]] void pc_speaker_set_spkrdata(int state); // TODO: hook up to something?
void pc_page_w(offs_t offset, uint8_t data);
void nmi_enable_w(uint8_t data);
- [[maybe_unused]] DECLARE_WRITE_LINE_MEMBER(iochck_w); // TODO: hook up to something?
+ [[maybe_unused]] void iochck_w(int state); // TODO: hook up to something?
void pc_select_dma_channel(int channel, bool state);
@@ -580,7 +580,7 @@ void a2bus_pcxporter_device::pc_page_w(offs_t offset, uint8_t data)
}
-WRITE_LINE_MEMBER( a2bus_pcxporter_device::pc_dma_hrq_changed )
+void a2bus_pcxporter_device::pc_dma_hrq_changed(int state)
{
m_v30->set_input_line(INPUT_LINE_HALT, state ? ASSERT_LINE : CLEAR_LINE);
@@ -651,7 +651,7 @@ void a2bus_pcxporter_device::pc_dma8237_0_dack_w(uint8_t data)
}
-WRITE_LINE_MEMBER( a2bus_pcxporter_device::pc_dma8237_out_eop )
+void a2bus_pcxporter_device::pc_dma8237_out_eop(int state)
{
m_cur_eop = state == ASSERT_LINE;
if(m_dma_channel != -1 && m_cur_eop)
@@ -672,10 +672,10 @@ void a2bus_pcxporter_device::pc_select_dma_channel(int channel, bool state)
}
}
-WRITE_LINE_MEMBER( a2bus_pcxporter_device::pc_dack0_w ) { pc_select_dma_channel(0, state); }
-WRITE_LINE_MEMBER( a2bus_pcxporter_device::pc_dack1_w ) { pc_select_dma_channel(1, state); }
-WRITE_LINE_MEMBER( a2bus_pcxporter_device::pc_dack2_w ) { pc_select_dma_channel(2, state); }
-WRITE_LINE_MEMBER( a2bus_pcxporter_device::pc_dack3_w ) { pc_select_dma_channel(3, state); }
+void a2bus_pcxporter_device::pc_dack0_w(int state) { pc_select_dma_channel(0, state); }
+void a2bus_pcxporter_device::pc_dack1_w(int state) { pc_select_dma_channel(1, state); }
+void a2bus_pcxporter_device::pc_dack2_w(int state) { pc_select_dma_channel(2, state); }
+void a2bus_pcxporter_device::pc_dack3_w(int state) { pc_select_dma_channel(3, state); }
/*************************************************************
*
@@ -683,7 +683,7 @@ WRITE_LINE_MEMBER( a2bus_pcxporter_device::pc_dack3_w ) { pc_select_dma_channel(
*
*************************************************************/
-WRITE_LINE_MEMBER(a2bus_pcxporter_device::pc_speaker_set_spkrdata)
+void a2bus_pcxporter_device::pc_speaker_set_spkrdata(int state)
{
m_pc_spkrdata = state ? 1 : 0;
m_speaker->level_w(m_pc_spkrdata & m_pit_out2);
@@ -696,7 +696,7 @@ WRITE_LINE_MEMBER(a2bus_pcxporter_device::pc_speaker_set_spkrdata)
*
*************************************************************/
-WRITE_LINE_MEMBER( a2bus_pcxporter_device::pc_pit8253_out1_changed )
+void a2bus_pcxporter_device::pc_pit8253_out1_changed(int state)
{
/* Trigger DMA channel #0 */
if ( m_out1 == 0 && state == 1 && m_u73_q2 == 0 )
@@ -708,19 +708,19 @@ WRITE_LINE_MEMBER( a2bus_pcxporter_device::pc_pit8253_out1_changed )
}
-WRITE_LINE_MEMBER( a2bus_pcxporter_device::pc_pit8253_out2_changed )
+void a2bus_pcxporter_device::pc_pit8253_out2_changed(int state)
{
m_pit_out2 = state ? 1 : 0;
m_speaker->level_w(m_pc_spkrdata & m_pit_out2);
}
-WRITE_LINE_MEMBER( a2bus_pcxporter_device::keyboard_clock_w )
+void a2bus_pcxporter_device::keyboard_clock_w(int state)
{
}
-WRITE_LINE_MEMBER( a2bus_pcxporter_device::keyboard_data_w )
+void a2bus_pcxporter_device::keyboard_data_w(int state)
{
}
@@ -737,7 +737,7 @@ void a2bus_pcxporter_device::nmi_enable_w(uint8_t data)
m_v30->set_input_line(INPUT_LINE_NMI, CLEAR_LINE);
}
-WRITE_LINE_MEMBER( a2bus_pcxporter_device::iochck_w )
+void a2bus_pcxporter_device::iochck_w(int state)
{
if (m_nmi_enabled && !state)
m_v30->set_input_line(INPUT_LINE_NMI, ASSERT_LINE);
diff --git a/src/devices/bus/a2bus/q68.cpp b/src/devices/bus/a2bus/q68.cpp
index 683bb975d05..4729f450e4a 100644
--- a/src/devices/bus/a2bus/q68.cpp
+++ b/src/devices/bus/a2bus/q68.cpp
@@ -41,7 +41,7 @@
#include "emu.h"
#include "q68.h"
-#include "cpu/m68000/m68000.h"
+#include "cpu/m68000/m68008.h"
/***************************************************************************
diff --git a/src/devices/bus/a2bus/romcard.cpp b/src/devices/bus/a2bus/romcard.cpp
new file mode 100644
index 00000000000..d2ae02bbf86
--- /dev/null
+++ b/src/devices/bus/a2bus/romcard.cpp
@@ -0,0 +1,276 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+/*********************************************************************
+
+ romcard.cpp
+
+ Implemention of the Apple II ROM card. This is like a language
+ card, but with 12K instead of 16K, and ROM instead of RAM.
+
+ Apple at various points called it both "ROM Card" and
+ "Firmware Card",
+
+*********************************************************************/
+
+#include "emu.h"
+#include "a2bus.h"
+#include "romcard.h"
+#include <errno.h>
+
+namespace {
+
+class a2bus_romcard_device:
+ public device_t,
+ public device_a2bus_card_interface
+{
+public:
+ a2bus_romcard_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void device_start() override;
+ virtual void bus_reset() override;
+ virtual ioport_constructor device_input_ports() const override;
+
+ // overrides of standard a2bus slot functions
+ virtual uint8_t read_c0nx(uint8_t offset) override;
+ virtual void write_c0nx(uint8_t offset, uint8_t data) override;
+ virtual uint8_t read_inh_rom(uint16_t offset) override;
+ virtual void write_inh_rom(uint16_t offset, uint8_t data) override;
+ virtual uint16_t inh_start() override { return 0xd000; }
+ virtual uint16_t inh_end() override { return 0xffff; }
+ virtual int inh_type() override;
+
+protected:
+ u8 *m_rom;
+ required_ioport m_config;
+
+private:
+ void do_io(int offset);
+
+ int m_inh_state;
+};
+
+class a2bus_romcardfp_device: public a2bus_romcard_device
+{
+public:
+ a2bus_romcardfp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void device_start() override;
+
+protected:
+ virtual const tiny_rom_entry *device_rom_region() const override;
+};
+
+class a2bus_romcardint_device: public a2bus_romcard_device
+{
+public:
+ a2bus_romcardint_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void device_start() override;
+
+protected:
+ virtual const tiny_rom_entry *device_rom_region() const override;
+};
+
+class a2bus_romcarduser_device: public a2bus_romcard_device, public device_image_interface
+{
+public:
+ a2bus_romcarduser_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ // device_image_interface overrides
+ virtual std::pair<std::error_condition, std::string> call_load() override;
+
+ virtual bool is_readable() const noexcept override { return true; }
+ virtual bool is_writeable() const noexcept override { return false; }
+ virtual bool is_creatable() const noexcept override { return false; }
+ virtual bool is_reset_on_load() const noexcept override { return false; }
+ virtual const char *file_extensions() const noexcept override { return "bin,rom"; }
+ virtual const char *image_type_name() const noexcept override { return "romimage"; }
+ virtual const char *image_brief_type_name() const noexcept override { return "rom"; }
+
+protected:
+};
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+ROM_START( romcardfp )
+ ROM_REGION(0x3000, "romcard", 0)
+ ROM_LOAD ( "341-0011.d0", 0x0000, 0x0800, CRC(6f05f949) SHA1(0287ebcef2c1ce11dc71be15a99d2d7e0e128b1e))
+ ROM_LOAD ( "341-0012.d8", 0x0800, 0x0800, CRC(1f08087c) SHA1(a75ce5aab6401355bf1ab01b04e4946a424879b5))
+ ROM_LOAD ( "341-0013.e0", 0x1000, 0x0800, CRC(2b8d9a89) SHA1(8d82a1da63224859bd619005fab62c4714b25dd7))
+ ROM_LOAD ( "341-0014.e8", 0x1800, 0x0800, CRC(5719871a) SHA1(37501be96d36d041667c15d63e0c1eff2f7dd4e9))
+ ROM_LOAD ( "341-0015.f0", 0x2000, 0x0800, CRC(9a04eecf) SHA1(e6bf91ed28464f42b807f798fc6422e5948bf581))
+ ROM_LOAD ( "341-0020-00.f8", 0x2800, 0x0800, CRC(079589c4) SHA1(a28852ff997b4790e53d8d0352112c4b1a395098))
+ROM_END
+
+ROM_START( romcardint )
+ /* Integer ROM card: Integer BASIC, the old Monitor, and Programmer's Aid #1 */
+ ROM_REGION(0x3000, "romcard", 0)
+ ROM_LOAD ( "341-0016-00.d0", 0x0000, 0x0800, CRC(4234e88a) SHA1(c9a81d704dc2f0c3416c20f9c4ab71fedda937ed))
+ ROM_LOAD ( "341-0001-00.e0", 0x1000, 0x0800, CRC(c0a4ad3b) SHA1(bf32195efcb34b694c893c2d342321ec3a24b98f))
+ ROM_LOAD ( "341-0002-00.e8", 0x1800, 0x0800, CRC(a99c2cf6) SHA1(9767d92d04fc65c626223f25564cca31f5248980))
+ ROM_LOAD ( "341-0003-00.f0", 0x2000, 0x0800, CRC(62230d38) SHA1(f268022da555e4c809ca1ae9e5d2f00b388ff61c))
+ ROM_LOAD ( "341-0004-00.f8", 0x2800, 0x0800, CRC(020a86d0) SHA1(52a18bd578a4694420009cad7a7a5779a8c00226))
+ROM_END
+
+static INPUT_PORTS_START( romcard )
+ PORT_START("CONFIG")
+ PORT_CONFNAME(0x01, 0x00, "Enable at boot")
+ PORT_CONFSETTING(0x00, DEF_STR(No))
+ PORT_CONFSETTING(0x01, DEF_STR(Yes))
+INPUT_PORTS_END
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+a2bus_romcard_device::a2bus_romcard_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, type, tag, owner, clock),
+ device_a2bus_card_interface(mconfig, *this),
+ m_rom(nullptr),
+ m_config(*this, "CONFIG"),
+ m_inh_state(0)
+{
+}
+
+a2bus_romcardfp_device::a2bus_romcardfp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ a2bus_romcard_device(mconfig, A2BUS_ROMCARDFP, tag, owner, clock)
+{
+}
+
+a2bus_romcardint_device::a2bus_romcardint_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ a2bus_romcard_device(mconfig, A2BUS_ROMCARDINT, tag, owner, clock)
+{
+}
+
+a2bus_romcarduser_device::a2bus_romcarduser_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ a2bus_romcard_device(mconfig, A2BUS_ROMCARDUSER, tag, owner, clock),
+ device_image_interface(mconfig, *this)
+{
+}
+
+const tiny_rom_entry *a2bus_romcardfp_device::device_rom_region() const
+{
+ return ROM_NAME( romcardfp );
+}
+
+const tiny_rom_entry *a2bus_romcardint_device::device_rom_region() const
+{
+ return ROM_NAME( romcardint );
+}
+
+ioport_constructor a2bus_romcard_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( romcard );
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void a2bus_romcard_device::device_start()
+{
+ save_item(NAME(m_inh_state));
+}
+
+void a2bus_romcardfp_device::device_start()
+{
+ m_rom = device().machine().root_device().memregion(this->subtag("romcard"))->base();
+ a2bus_romcard_device::device_start();
+}
+
+void a2bus_romcardint_device::device_start()
+{
+ m_rom = device().machine().root_device().memregion(this->subtag("romcard"))->base();
+ a2bus_romcard_device::device_start();
+}
+
+void a2bus_romcard_device::bus_reset()
+{
+ if ((m_config->read() == 1) && (m_rom != nullptr))
+ {
+ m_inh_state = INH_READ;
+ }
+ else
+ {
+ m_inh_state = 0;
+ }
+ recalc_slot_inh();
+}
+
+void a2bus_romcard_device::do_io(int offset)
+{
+ int old_inh_state = m_inh_state;
+
+ // any even access enables ROM reading
+ if (((offset & 1) == 1) && (m_rom != nullptr))
+ {
+ m_inh_state |= INH_READ;
+ }
+ else
+ {
+ m_inh_state &= ~INH_READ;
+ }
+
+ if (m_inh_state != old_inh_state)
+ {
+ recalc_slot_inh();
+ }
+}
+
+
+/*-------------------------------------------------
+ read_c0nx - called for reads from this card's c0nx space
+-------------------------------------------------*/
+
+uint8_t a2bus_romcard_device::read_c0nx(uint8_t offset)
+{
+ do_io(offset & 0xf);
+ return 0xff;
+}
+
+
+/*-------------------------------------------------
+ write_c0nx - called for writes to this card's c0nx space
+-------------------------------------------------*/
+
+void a2bus_romcard_device::write_c0nx(uint8_t offset, uint8_t data)
+{
+ do_io(offset & 0xf);
+}
+
+uint8_t a2bus_romcard_device::read_inh_rom(uint16_t offset)
+{
+ assert(m_inh_state & INH_READ); // this should never happen
+ return m_rom[offset-0xd000];
+}
+
+void a2bus_romcard_device::write_inh_rom(uint16_t offset, uint8_t data)
+{
+}
+
+int a2bus_romcard_device::inh_type()
+{
+ return m_inh_state;
+}
+
+std::pair<std::error_condition, std::string> a2bus_romcarduser_device::call_load()
+{
+ if (is_open())
+ {
+ m_rom = (u8 *)malloc(12*1024*1024);
+ fread(m_rom, 12*1024*1024);
+ }
+ else
+ {
+ return std::make_pair(std::error_condition(ENOENT, std::generic_category()), std::string());
+ }
+ return std::make_pair(std::error_condition(), std::string());
+}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_ROMCARDUSER, device_a2bus_card_interface, a2bus_romcarduser_device, "a2romusr", "Apple II ROM Card (Custom)")
+DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_ROMCARDFP, device_a2bus_card_interface, a2bus_romcardfp_device, "a2romfp", "Apple II ROM Card (Applesoft BASIC)")
+DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_ROMCARDINT, device_a2bus_card_interface, a2bus_romcardint_device, "a2romint", "Apple II ROM Card (Integer BASIC)")
diff --git a/src/devices/bus/a2bus/romcard.h b/src/devices/bus/a2bus/romcard.h
new file mode 100644
index 00000000000..8ff831d13e2
--- /dev/null
+++ b/src/devices/bus/a2bus/romcard.h
@@ -0,0 +1,23 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+/*********************************************************************
+
+ romcard.h
+
+ Implemention of the Apple II ROM card/firmware card
+
+*********************************************************************/
+
+#ifndef MAME_BUS_A2BUS_ROMCARD_H
+#define MAME_BUS_A2BUS_ROMCARD_H
+
+#pragma once
+
+#include "a2bus.h"
+
+// device type definition
+DECLARE_DEVICE_TYPE(A2BUS_ROMCARDUSER, device_a2bus_card_interface)
+DECLARE_DEVICE_TYPE(A2BUS_ROMCARDFP, device_a2bus_card_interface)
+DECLARE_DEVICE_TYPE(A2BUS_ROMCARDINT, device_a2bus_card_interface)
+
+#endif // MAME_BUS_A2BUS_ROMCARD_H
diff --git a/src/devices/bus/a2bus/snesmax.cpp b/src/devices/bus/a2bus/snesmax.cpp
new file mode 100644
index 00000000000..25638da62ed
--- /dev/null
+++ b/src/devices/bus/a2bus/snesmax.cpp
@@ -0,0 +1,97 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+#include "emu.h"
+#include "snesmax.h"
+
+#include "bus/snes_ctrl/ctrl.h"
+
+namespace {
+
+class a2bus_snes_max_device : public device_t, public device_a2bus_card_interface
+{
+public:
+ a2bus_snes_max_device(
+ machine_config const &mconfig,
+ char const *tag,
+ device_t *owner,
+ u32 clock) :
+ device_t(mconfig, A2BUS_SNES_MAX, tag, owner, clock),
+ device_a2bus_card_interface(mconfig, *this),
+ m_controllers(*this, "%u", 1U),
+ m_latch_timer(nullptr),
+ m_data(0xff)
+ {
+ }
+
+ virtual u8 read_c0nx(u8 offset) override
+ {
+ return m_data;
+ }
+
+ virtual void write_c0nx(u8 offset, u8 data) override
+ {
+ if (BIT(offset, 0))
+ {
+ m_data =
+ (m_controllers[0]->read_pin4() ? 0x00 : 0x80) |
+ (m_controllers[1]->read_pin4() ? 0x00 : 0x40) |
+ 0x3f;
+ }
+ else
+ {
+ machine().scheduler().synchronize(timer_expired_delegate(FUNC(a2bus_snes_max_device::set_latch), this), 0);
+ }
+ }
+
+ virtual bool take_c800() override
+ {
+ return false;
+ }
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD
+ {
+ SNES_CONTROL_PORT(config, m_controllers[0], snes_control_port_devices, "joypad");
+ SNES_CONTROL_PORT(config, m_controllers[1], snes_control_port_devices, "joypad");
+ }
+
+ virtual void device_start() override ATTR_COLD
+ {
+ m_latch_timer = timer_alloc(FUNC(a2bus_snes_max_device::reset_latch), this);
+
+ m_data = 0xff;
+
+ save_item(NAME(m_data));
+
+ m_controllers[0]->write_strobe(0);
+ m_controllers[1]->write_strobe(0);
+ }
+
+private:
+ TIMER_CALLBACK_MEMBER(set_latch)
+ {
+ m_controllers[0]->write_strobe(1);
+ m_controllers[1]->write_strobe(1);
+ m_latch_timer->adjust(attotime::from_ticks(7, clock()));
+ }
+
+ TIMER_CALLBACK_MEMBER(reset_latch)
+ {
+ m_controllers[0]->write_strobe(0);
+ m_controllers[1]->write_strobe(0);
+
+ m_data =
+ (m_controllers[0]->read_pin4() ? 0x00 : 0x80) |
+ (m_controllers[1]->read_pin4() ? 0x00 : 0x40) |
+ 0x3f;
+ }
+
+ required_device_array<snes_control_port_device, 2> m_controllers;
+ emu_timer *m_latch_timer;
+ u8 m_data;
+};
+
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_SNES_MAX, device_a2bus_card_interface, a2bus_snes_max_device, "a2snesmax", "SNES MAX Game Controller Interface")
diff --git a/src/devices/bus/a2bus/snesmax.h b/src/devices/bus/a2bus/snesmax.h
new file mode 100644
index 00000000000..3cf381242dc
--- /dev/null
+++ b/src/devices/bus/a2bus/snesmax.h
@@ -0,0 +1,20 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/***********************************************************************
+
+ Homebrew dual SNES controller interface by Lukazi
+
+ https://lukazi.blogspot.com/2021/06/game-controller-snes-max-snes.html
+
+***********************************************************************/
+#ifndef MAME_BUS_A2BUS_SNESMAX_H
+#define MAME_BUS_A2BUS_SNESMAX_H
+
+#pragma once
+
+#include "a2bus.h"
+
+
+DECLARE_DEVICE_TYPE(A2BUS_SNES_MAX, device_a2bus_card_interface)
+
+#endif // MAME_BUS_A2BUS_SNESMAX_H
diff --git a/src/devices/bus/a2bus/ssprite.cpp b/src/devices/bus/a2bus/ssprite.cpp
index 2fdecb117c9..c34a0a90748 100644
--- a/src/devices/bus/a2bus/ssprite.cpp
+++ b/src/devices/bus/a2bus/ssprite.cpp
@@ -53,7 +53,7 @@ protected:
virtual void write_c0nx(uint8_t offset, uint8_t data) override;
private:
- DECLARE_WRITE_LINE_MEMBER( tms_irq_w );
+ void tms_irq_w(int state);
required_device<tms9918a_device> m_tms;
required_device<ay8910_device> m_ay;
@@ -165,7 +165,7 @@ void a2bus_ssprite_device::write_c0nx(uint8_t offset, uint8_t data)
}
}
-WRITE_LINE_MEMBER( a2bus_ssprite_device::tms_irq_w )
+void a2bus_ssprite_device::tms_irq_w(int state)
{
if (state)
raise_slot_irq();
diff --git a/src/devices/bus/a2bus/timemasterho.cpp b/src/devices/bus/a2bus/timemasterho.cpp
index 8dbef3a5a37..b8f2b511971 100644
--- a/src/devices/bus/a2bus/timemasterho.cpp
+++ b/src/devices/bus/a2bus/timemasterho.cpp
@@ -112,8 +112,8 @@ private:
void update_irqs();
void pia_out_a(uint8_t data);
void pia_out_b(uint8_t data);
- DECLARE_WRITE_LINE_MEMBER(pia_irqa_w);
- DECLARE_WRITE_LINE_MEMBER(pia_irqb_w);
+ void pia_irqa_w(int state);
+ void pia_irqb_w(int state);
bool m_irqa = false, m_irqb = false;
bool m_started = false;
@@ -297,13 +297,13 @@ void a2bus_timemasterho_device::update_irqs()
}
}
-WRITE_LINE_MEMBER(a2bus_timemasterho_device::pia_irqa_w)
+void a2bus_timemasterho_device::pia_irqa_w(int state)
{
m_irqa = state;
update_irqs();
}
-WRITE_LINE_MEMBER(a2bus_timemasterho_device::pia_irqb_w)
+void a2bus_timemasterho_device::pia_irqb_w(int state)
{
m_irqb = state;
update_irqs();
diff --git a/src/devices/bus/a2bus/uniprint.cpp b/src/devices/bus/a2bus/uniprint.cpp
index d451a45fe89..6af2662a846 100644
--- a/src/devices/bus/a2bus/uniprint.cpp
+++ b/src/devices/bus/a2bus/uniprint.cpp
@@ -36,7 +36,7 @@ protected:
private:
// printer status inputs
- DECLARE_WRITE_LINE_MEMBER(ack_w);
+ void ack_w(int state);
required_device<centronics_device> m_printer_conn;
required_device<output_latch_device> m_printer_out;
@@ -209,7 +209,7 @@ void a2bus_uniprint_device::device_reset()
// printer status inputs
//----------------------------------------------
-WRITE_LINE_MEMBER(a2bus_uniprint_device::ack_w)
+void a2bus_uniprint_device::ack_w(int state)
{
if (bool(state) != bool(m_ack_in))
{
diff --git a/src/devices/bus/a2bus/vistaa800.cpp b/src/devices/bus/a2bus/vistaa800.cpp
new file mode 100644
index 00000000000..47bd9a0ad27
--- /dev/null
+++ b/src/devices/bus/a2bus/vistaa800.cpp
@@ -0,0 +1,324 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Justice
+/*********************************************************************
+
+ vistaa800.c
+
+ Implementation of the Vista A800 8" disk Controller Card for the Apple II
+
+ This supported up to four double sided/double density 8inch drives.
+ With DMA support for the data transfers, and booting from the first 8inch drive.
+
+ The card looks like it was released in 1981. The schematic is dated 19th Mar 1981 for the initial drawing, with a later revision date marked, however the month is not readable for it.
+
+ Manual available here:
+ http://mirrors.apple2.org.za/Apple%20II%20Documentation%20Project/Interface%20Cards/Disk%20Drive%20Controllers/Vista%20A800%20Disk%20Controller/Manuals/Vista%20A800%20Disk%20Controller%20Manual.pdf
+
+ I/O address details:
+ Addr Write Read
+ ---- ----- ----
+ C0n0 1797 cmd reg 1797 status reg
+ C0n1 1797 track reg 1797 track reg
+ C0n2 1797 sector reg 1797 sector reg
+ C0n3 1797 data reg 1797 data reg
+ C0n4 --same as 0--
+ C0n5 --same as 1--
+ C0n6 --same as 2--
+ C0n7 --same as 3--
+ C0n8 low DMA address not allowed
+ C0n9 high DMA address not allowed
+ C0nA DMA ON:Disk read (same as write)
+ C0nB DMA ON:Disk write (same as write)
+ C0nC DMA OFF (same as write)
+
+ bit
+ 7 6 5 4 3 2 1 0
+ C0nD sngl side x x fd fd fd fd not allowed
+ dens sel x x 3 2 1 0
+ C0nE --spare--
+
+ bit
+ 7 6 543210
+ C0nF not allowed DMA one xxxxxx
+ on side
+
+
+*********************************************************************/
+
+#include "emu.h"
+#include "vistaa800.h"
+
+#include "machine/wd_fdc.h"
+#include "imagedev/floppy.h"
+
+namespace {
+
+class a2bus_vistaa800_device : public device_t, public device_a2bus_card_interface
+{
+public:
+ a2bus_vistaa800_device(machine_config const &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ // device_a2bus_card_interface implementation
+ virtual uint8_t read_c0nx(uint8_t offset) override;
+ virtual void write_c0nx(uint8_t offset, uint8_t data) override;
+ virtual uint8_t read_cnxx(uint8_t offset) override;
+ virtual uint8_t read_c800(uint16_t offset) override;
+
+protected:
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+private:
+ static void floppy_formats(format_registration &fr);
+
+ // fdc handlers
+ void fdc_intrq_w(uint8_t state);
+ void fdc_drq_w(uint8_t state);
+
+ required_device<fd1797_device> m_fdc;
+ required_device<floppy_connector> m_floppy0;
+ required_device<floppy_connector> m_floppy1;
+ required_device<floppy_connector> m_floppy2;
+ required_device<floppy_connector> m_floppy3;
+ required_region_ptr<uint8_t> m_rom;
+
+ uint16_t m_dmaaddr;
+ bool m_dmaenable_read;
+ bool m_dmaenable_write;
+ uint8_t m_density;
+ uint8_t m_side;
+ uint8_t m_twosided;
+};
+
+
+
+static void vistaa800_floppies(device_slot_interface &device)
+{
+ device.option_add("8sssd", FLOPPY_8_SSSD); // 77 trks ss sd 8"
+ device.option_add("8dssd", FLOPPY_8_DSSD); // 77 trks ds sd 8"
+ device.option_add("8ssdd", FLOPPY_8_SSDD); // 77 trks ss dd 8"
+ device.option_add("8dsdd", FLOPPY_8_DSDD); // 77 trks ds dd 8"
+}
+
+ROM_START(vistaa800)
+ ROM_REGION(0x0800, "vistaa800_rom", 0)
+ ROM_LOAD( "vista a800 boot 3.1.bin", 0x000000, 0x000800, CRC(22df90b8) SHA1(8e0b4f4c6c467e2280bd250ee54f471728640964) )
+ROM_END
+
+
+a2bus_vistaa800_device::a2bus_vistaa800_device(machine_config const &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, A2BUS_VISTAA800, tag, owner, clock),
+ device_a2bus_card_interface(mconfig, *this),
+ m_fdc(*this, "fdc"),
+ m_floppy0(*this, "fdc:0"),
+ m_floppy1(*this, "fdc:1"),
+ m_floppy2(*this, "fdc:2"),
+ m_floppy3(*this, "fdc:3"),
+ m_rom(*this, "vistaa800_rom")
+{
+}
+
+//----------------------------------------------
+// device_t implementation
+//----------------------------------------------
+
+const tiny_rom_entry *a2bus_vistaa800_device::device_rom_region() const
+{
+ return ROM_NAME(vistaa800);
+}
+
+void a2bus_vistaa800_device::device_add_mconfig(machine_config &config)
+{
+ FD1797(config, m_fdc, 2'000'000);
+ FLOPPY_CONNECTOR(config, m_floppy0, vistaa800_floppies, "8dsdd", floppy_image_device::default_mfm_floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy1, vistaa800_floppies, "8dsdd", floppy_image_device::default_mfm_floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy2, vistaa800_floppies, "8dsdd", floppy_image_device::default_mfm_floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy3, vistaa800_floppies, "8dsdd", floppy_image_device::default_mfm_floppy_formats).enable_sound(true);
+
+ m_fdc->intrq_wr_callback().set(FUNC(a2bus_vistaa800_device::fdc_intrq_w));
+ m_fdc->drq_wr_callback().set(FUNC(a2bus_vistaa800_device::fdc_drq_w));
+}
+
+void a2bus_vistaa800_device::device_start()
+{
+ save_item(NAME(m_dmaaddr));
+ save_item(NAME(m_dmaenable_read));
+ save_item(NAME(m_dmaenable_write));
+ save_item(NAME(m_density));
+ save_item(NAME(m_side));
+ save_item(NAME(m_twosided));
+}
+
+void a2bus_vistaa800_device::device_reset()
+{
+ m_dmaaddr = 0;
+ m_dmaenable_read = false;
+ m_dmaenable_write = false;
+ m_density = 0;
+ m_side = 0;
+ m_twosided = 0;
+}
+
+//----------------------------------------------
+// device_a2bus_card_interface implementation
+//----------------------------------------------
+
+uint8_t a2bus_vistaa800_device::read_c0nx(uint8_t offset)
+{
+ uint8_t result = 0;
+
+ switch (offset)
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ result = m_fdc->fd1797_device::read(offset & 0x03);
+ break;
+
+ case 0xa:
+ if (!machine().side_effects_disabled())
+ m_dmaenable_read = true;
+ break;
+
+ case 0xb:
+ if (!machine().side_effects_disabled())
+ m_dmaenable_write = true;
+ break;
+
+ case 0xc:
+ if (!machine().side_effects_disabled())
+ {
+ m_dmaenable_read = false;
+ m_dmaenable_write = false;
+ }
+ break;
+
+ case 0xf:
+ if (m_dmaenable_read || m_dmaenable_write)
+ result |= 0x80;
+
+ result |= (m_twosided << 6); // 0 = two sided disk
+ break;
+
+ default:
+ logerror("Read c0n%x (%s)\n", offset, machine().describe_context());
+ break;
+ }
+
+ return result;
+}
+
+void a2bus_vistaa800_device::write_c0nx(uint8_t offset, uint8_t data)
+{
+ floppy_image_device *floppy = nullptr;
+
+ switch (offset)
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ m_fdc->fd1797_device::write(offset & 0x03, data);
+ break;
+
+ case 8:
+ m_dmaaddr = (m_dmaaddr & 0xff00) + data;
+ break;
+
+ case 9:
+ m_dmaaddr = (m_dmaaddr & 0x00ff) + (data << 8);
+ break;
+
+ case 0xa:
+ m_dmaenable_read = true;
+ break;
+
+ case 0xb:
+ m_dmaenable_write = true;
+ break;
+
+ case 0xc:
+ m_dmaenable_read = false;
+ m_dmaenable_write = false;
+ break;
+
+ case 0xd:
+ m_density = BIT(data, 7);
+ m_fdc->dden_w(m_density);
+
+ m_side = BIT(data, 6);
+
+ if (BIT(data, 0)) floppy = m_floppy0->get_device();
+ if (BIT(data, 1)) floppy = m_floppy1->get_device();
+ if (BIT(data, 2)) floppy = m_floppy2->get_device();
+ if (BIT(data, 3)) floppy = m_floppy3->get_device();
+ m_fdc->set_floppy(floppy);
+
+ if (floppy)
+ {
+ floppy->ss_w(m_side);
+ floppy->mon_w(0);
+ m_twosided = floppy->twosid_r();
+ }
+ break;
+
+ default:
+ logerror("Write %02x to c0n%x (%s)\n", data, offset, machine().describe_context());
+ break;
+ }
+}
+
+uint8_t a2bus_vistaa800_device::read_cnxx(uint8_t offset)
+{
+ return m_rom[offset];
+}
+
+uint8_t a2bus_vistaa800_device::read_c800(uint16_t offset)
+{
+ return m_rom[offset];
+}
+
+//-------------------------------------------------
+// fdc handlers
+//-------------------------------------------------
+
+void a2bus_vistaa800_device::fdc_intrq_w(uint8_t state)
+{
+ m_dmaenable_read = false;
+ m_dmaenable_write = false;
+}
+
+void a2bus_vistaa800_device::fdc_drq_w(uint8_t state)
+{
+ if (state)
+ {
+ if (m_dmaenable_read) // read has priority if both were enabled
+ {
+ uint8_t data = m_fdc->data_r();
+ slot_dma_write(m_dmaaddr, data);
+ m_dmaaddr++;
+ }
+ else if (m_dmaenable_write)
+ {
+ uint8_t data = slot_dma_read(m_dmaaddr);
+ m_fdc->data_w(data);
+ m_dmaaddr++;
+ }
+ }
+}
+
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(A2BUS_VISTAA800, device_a2bus_card_interface, a2bus_vistaa800_device, "a2vistaa800", "Vista A800 8inch disk Controller Card")
diff --git a/src/devices/bus/a2bus/vistaa800.h b/src/devices/bus/a2bus/vistaa800.h
new file mode 100644
index 00000000000..d95d414c942
--- /dev/null
+++ b/src/devices/bus/a2bus/vistaa800.h
@@ -0,0 +1,20 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Justice
+/*********************************************************************
+
+ vistaa800.h
+
+ Vista A800 8" disk Controller Card
+
+*********************************************************************/
+
+#ifndef MAME_BUS_A2BUS_VISTAA800_H
+#define MAME_BUS_A2BUS_VISTAA800_H
+
+#pragma once
+
+#include "a2bus.h"
+
+DECLARE_DEVICE_TYPE(A2BUS_VISTAA800, device_a2bus_card_interface)
+
+#endif // MAME_BUS_A2BUS_VISTAA800_H
diff --git a/src/devices/bus/a2gameio/computereyes.cpp b/src/devices/bus/a2gameio/computereyes.cpp
index 38b100586e4..0e7613260d4 100644
--- a/src/devices/bus/a2gameio/computereyes.cpp
+++ b/src/devices/bus/a2gameio/computereyes.cpp
@@ -31,12 +31,12 @@ protected:
virtual void device_reset() override;
// device_a2gameio_interface overrides
- virtual DECLARE_READ_LINE_MEMBER(sw0_r) override;
- virtual DECLARE_READ_LINE_MEMBER(sw1_r) override;
- virtual DECLARE_WRITE_LINE_MEMBER(an0_w) override;
- virtual DECLARE_WRITE_LINE_MEMBER(an1_w) override;
- virtual DECLARE_WRITE_LINE_MEMBER(an2_w) override;
- virtual DECLARE_WRITE_LINE_MEMBER(an3_w) override;
+ virtual int sw0_r() override;
+ virtual int sw1_r() override;
+ virtual void an0_w(int state) override;
+ virtual void an1_w(int state) override;
+ virtual void an2_w(int state) override;
+ virtual void an3_w(int state) override;
private:
required_device<picture_image_device> m_picture;
@@ -75,12 +75,12 @@ void apple2_compeyes_device::device_reset()
m_x = m_y = m_an1 = m_an2 = m_an3 = m_level = 0;
}
-READ_LINE_MEMBER(apple2_compeyes_device::sw0_r)
+int apple2_compeyes_device::sw0_r()
{
return 0;
}
-READ_LINE_MEMBER(apple2_compeyes_device::sw1_r)
+int apple2_compeyes_device::sw1_r()
{
// to avoid triggering the self-test on //e, return only 0
// for the first 2 seconds of emulation.
@@ -104,7 +104,7 @@ READ_LINE_MEMBER(apple2_compeyes_device::sw1_r)
return res;
}
-WRITE_LINE_MEMBER(apple2_compeyes_device::an0_w)
+void apple2_compeyes_device::an0_w(int state)
{
m_x = m_y = 0;
@@ -131,19 +131,19 @@ WRITE_LINE_MEMBER(apple2_compeyes_device::an0_w)
}
}
-WRITE_LINE_MEMBER(apple2_compeyes_device::an1_w)
+void apple2_compeyes_device::an1_w(int state)
{
m_an1 = state;
m_level = (128 * m_an2) + (64 * m_an1) + (32 * m_an3);
}
-WRITE_LINE_MEMBER(apple2_compeyes_device::an2_w)
+void apple2_compeyes_device::an2_w(int state)
{
m_an2 = state;
m_level = (128 * m_an2) + (64 * m_an1) + (32 * m_an3);
}
-WRITE_LINE_MEMBER(apple2_compeyes_device::an3_w)
+void apple2_compeyes_device::an3_w(int state)
{
m_an3 = state;
m_level = (128 * m_an2) + (64 * m_an1) + (32 * m_an3);
diff --git a/src/devices/bus/a2gameio/gameio.cpp b/src/devices/bus/a2gameio/gameio.cpp
index 9a600776a90..6645458f523 100644
--- a/src/devices/bus/a2gameio/gameio.cpp
+++ b/src/devices/bus/a2gameio/gameio.cpp
@@ -25,6 +25,7 @@
The Apple IIe, IIc and IIgs also have an external DE-9 connector
that carries a subset of the signals, excluding the annunciator
outputs and utility strobe (which the IIc and IIgs do not have).
+ The Laser 3000 provides only the 9-pin connector.
**********************************************************************
____________
@@ -87,6 +88,12 @@ void apple2_gameio_device::default_options(device_slot_interface &slot)
slot.option_add("compeyes", APPLE2_COMPUTEREYES);
}
+void apple2_gameio_device::joystick_options(device_slot_interface &slot)
+{
+ slot.option_add("joy", APPLE2_JOYSTICK);
+ slot.option_add("paddles", APPLE2_PADDLES);
+}
+
void apple2_gameio_device::device_config_complete()
{
m_intf = get_card_device();
@@ -139,7 +146,7 @@ u8 apple2_gameio_device::pdl3_r()
return 0;
}
-READ_LINE_MEMBER(apple2_gameio_device::sw0_r)
+int apple2_gameio_device::sw0_r()
{
if (m_intf != nullptr)
return m_intf->sw0_r();
@@ -147,7 +154,7 @@ READ_LINE_MEMBER(apple2_gameio_device::sw0_r)
return m_sw_pullups ? 1 : 0;
}
-READ_LINE_MEMBER(apple2_gameio_device::sw1_r)
+int apple2_gameio_device::sw1_r()
{
if (m_intf != nullptr)
return m_intf->sw1_r();
@@ -155,7 +162,7 @@ READ_LINE_MEMBER(apple2_gameio_device::sw1_r)
return m_sw_pullups ? 1 : 0;
}
-READ_LINE_MEMBER(apple2_gameio_device::sw2_r)
+int apple2_gameio_device::sw2_r()
{
if (m_intf != nullptr)
return m_intf->sw2_r();
@@ -163,7 +170,7 @@ READ_LINE_MEMBER(apple2_gameio_device::sw2_r)
return m_sw_pullups ? 1 : 0;
}
-READ_LINE_MEMBER(apple2_gameio_device::sw3_r)
+int apple2_gameio_device::sw3_r()
{
if (m_intf != nullptr)
return m_intf->sw3_r();
@@ -171,37 +178,37 @@ READ_LINE_MEMBER(apple2_gameio_device::sw3_r)
return m_sw_pullups ? 1 : 0;
}
-WRITE_LINE_MEMBER(apple2_gameio_device::an0_w)
+void apple2_gameio_device::an0_w(int state)
{
if (m_intf != nullptr)
m_intf->an0_w(state);
}
-WRITE_LINE_MEMBER(apple2_gameio_device::an1_w)
+void apple2_gameio_device::an1_w(int state)
{
if (m_intf != nullptr)
m_intf->an1_w(state);
}
-WRITE_LINE_MEMBER(apple2_gameio_device::an2_w)
+void apple2_gameio_device::an2_w(int state)
{
if (m_intf != nullptr)
m_intf->an2_w(state);
}
-WRITE_LINE_MEMBER(apple2_gameio_device::an3_w)
+void apple2_gameio_device::an3_w(int state)
{
if (m_intf != nullptr)
m_intf->an3_w(state);
}
-WRITE_LINE_MEMBER(apple2_gameio_device::an4_w)
+void apple2_gameio_device::an4_w(int state)
{
if (m_intf != nullptr)
m_intf->an4_w(state);
}
-WRITE_LINE_MEMBER(apple2_gameio_device::strobe_w)
+void apple2_gameio_device::strobe_w(int state)
{
if (m_intf != nullptr)
m_intf->strobe_w(state);
diff --git a/src/devices/bus/a2gameio/gameio.h b/src/devices/bus/a2gameio/gameio.h
index 7ff1771b17b..1f8d53a8c20 100644
--- a/src/devices/bus/a2gameio/gameio.h
+++ b/src/devices/bus/a2gameio/gameio.h
@@ -44,6 +44,7 @@ public:
// standard options
static void default_options(device_slot_interface &slot);
static void iiandplus_options(device_slot_interface &slot);
+ static void joystick_options(device_slot_interface &slot);
// analog paddles
u8 pdl0_r();
@@ -52,20 +53,20 @@ public:
u8 pdl3_r();
// digital switches
- DECLARE_READ_LINE_MEMBER(sw0_r);
- DECLARE_READ_LINE_MEMBER(sw1_r);
- DECLARE_READ_LINE_MEMBER(sw2_r);
- DECLARE_READ_LINE_MEMBER(sw3_r);
+ int sw0_r();
+ int sw1_r();
+ int sw2_r();
+ int sw3_r();
// annunciator outputs
- DECLARE_WRITE_LINE_MEMBER(an0_w);
- DECLARE_WRITE_LINE_MEMBER(an1_w);
- DECLARE_WRITE_LINE_MEMBER(an2_w);
- DECLARE_WRITE_LINE_MEMBER(an3_w);
- DECLARE_WRITE_LINE_MEMBER(an4_w);
+ void an0_w(int state);
+ void an1_w(int state);
+ void an2_w(int state);
+ void an3_w(int state);
+ void an4_w(int state);
// utility strobe (active low)
- DECLARE_WRITE_LINE_MEMBER(strobe_w);
+ void strobe_w(int state);
// check if a device is connected
bool is_device_connected() { return (m_intf != nullptr); }
@@ -101,18 +102,18 @@ protected:
virtual u8 pdl1_r() { return 0; }
virtual u8 pdl2_r() { return 0; }
virtual u8 pdl3_r() { return 0; }
- virtual DECLARE_READ_LINE_MEMBER(sw0_r) { return m_connector->has_sw_pullups() ? 1 : 0; }
- virtual DECLARE_READ_LINE_MEMBER(sw1_r) { return m_connector->has_sw_pullups() ? 1 : 0; }
- virtual DECLARE_READ_LINE_MEMBER(sw2_r) { return m_connector->has_sw_pullups() ? 1 : 0; }
- virtual DECLARE_READ_LINE_MEMBER(sw3_r) { return m_connector->has_sw_pullups() ? 1 : 0; }
+ virtual int sw0_r() { return m_connector->has_sw_pullups() ? 1 : 0; }
+ virtual int sw1_r() { return m_connector->has_sw_pullups() ? 1 : 0; }
+ virtual int sw2_r() { return m_connector->has_sw_pullups() ? 1 : 0; }
+ virtual int sw3_r() { return m_connector->has_sw_pullups() ? 1 : 0; }
// optional output overrides
- virtual DECLARE_WRITE_LINE_MEMBER(an0_w) { }
- virtual DECLARE_WRITE_LINE_MEMBER(an1_w) { }
- virtual DECLARE_WRITE_LINE_MEMBER(an2_w) { }
- virtual DECLARE_WRITE_LINE_MEMBER(an3_w) { }
- virtual DECLARE_WRITE_LINE_MEMBER(an4_w) { }
- virtual DECLARE_WRITE_LINE_MEMBER(strobe_w) { }
+ virtual void an0_w(int state) { }
+ virtual void an1_w(int state) { }
+ virtual void an2_w(int state) { }
+ virtual void an3_w(int state) { }
+ virtual void an4_w(int state) { }
+ virtual void strobe_w(int state) { }
private:
apple2_gameio_device *m_connector;
diff --git a/src/devices/bus/a2gameio/gizmo.cpp b/src/devices/bus/a2gameio/gizmo.cpp
index 999fdf94ded..c7bcbac826b 100644
--- a/src/devices/bus/a2gameio/gizmo.cpp
+++ b/src/devices/bus/a2gameio/gizmo.cpp
@@ -27,10 +27,10 @@ protected:
virtual void device_start() override;
// device_a2gameio_interface overrides
- virtual DECLARE_READ_LINE_MEMBER(sw0_r) override;
- virtual DECLARE_WRITE_LINE_MEMBER(an0_w) override;
- virtual DECLARE_WRITE_LINE_MEMBER(an1_w) override;
- virtual DECLARE_WRITE_LINE_MEMBER(an2_w) override;
+ virtual int sw0_r() override;
+ virtual void an0_w(int state) override;
+ virtual void an1_w(int state) override;
+ virtual void an2_w(int state) override;
private:
// input ports
@@ -74,23 +74,23 @@ void apple2_gizmo_device::device_start()
save_item(NAME(m_an2));
}
-READ_LINE_MEMBER(apple2_gizmo_device::sw0_r)
+int apple2_gizmo_device::sw0_r()
{
static const int gizmo_bits[8] = { 1,3,2,0,4,5,5,5 };
return BIT(m_player1->read(),gizmo_bits[m_an0+(m_an1<<1)+(m_an2<<2)]);
}
-WRITE_LINE_MEMBER(apple2_gizmo_device::an0_w)
+void apple2_gizmo_device::an0_w(int state)
{
m_an0 = state;
}
-WRITE_LINE_MEMBER(apple2_gizmo_device::an1_w)
+void apple2_gizmo_device::an1_w(int state)
{
m_an1 = state;
}
-WRITE_LINE_MEMBER(apple2_gizmo_device::an2_w)
+void apple2_gizmo_device::an2_w(int state)
{
m_an2 = state;
}
diff --git a/src/devices/bus/a2gameio/joyport.cpp b/src/devices/bus/a2gameio/joyport.cpp
index 1c2f1118216..3d00fe504c3 100644
--- a/src/devices/bus/a2gameio/joyport.cpp
+++ b/src/devices/bus/a2gameio/joyport.cpp
@@ -33,11 +33,11 @@ protected:
virtual void device_start() override;
// device_a2gameio_interface overrides
- virtual DECLARE_READ_LINE_MEMBER(sw0_r) override;
- virtual DECLARE_READ_LINE_MEMBER(sw1_r) override;
- virtual DECLARE_READ_LINE_MEMBER(sw2_r) override;
- virtual DECLARE_WRITE_LINE_MEMBER(an0_w) override;
- virtual DECLARE_WRITE_LINE_MEMBER(an1_w) override;
+ virtual int sw0_r() override;
+ virtual int sw1_r() override;
+ virtual int sw2_r() override;
+ virtual void an0_w(int state) override;
+ virtual void an1_w(int state) override;
private:
// input ports
@@ -88,33 +88,33 @@ void apple2_joyport_device::device_start()
save_item(NAME(m_an1));
}
-READ_LINE_MEMBER(apple2_joyport_device::sw0_r)
+int apple2_joyport_device::sw0_r()
{
u8 port_read = m_an0 ? m_player2->read() : m_player1->read();
return BIT(port_read, 4);
}
-READ_LINE_MEMBER(apple2_joyport_device::sw1_r)
+int apple2_joyport_device::sw1_r()
{
u8 port_read = m_an0 ? m_player2->read() : m_player1->read();
return m_an1 ? BIT(port_read, 0) : BIT(port_read, 3);
}
-READ_LINE_MEMBER(apple2_joyport_device::sw2_r)
+int apple2_joyport_device::sw2_r()
{
u8 port_read = m_an0 ? m_player2->read() : m_player1->read();
return m_an1 ? BIT(port_read, 2) : BIT(port_read, 1);
}
-WRITE_LINE_MEMBER(apple2_joyport_device::an0_w)
+void apple2_joyport_device::an0_w(int state)
{
m_an0 = state;
}
-WRITE_LINE_MEMBER(apple2_joyport_device::an1_w)
+void apple2_joyport_device::an1_w(int state)
{
m_an1 = state;
}
diff --git a/src/devices/bus/a2gameio/joystick.cpp b/src/devices/bus/a2gameio/joystick.cpp
index 9ed2a9555ba..b4a2d397322 100644
--- a/src/devices/bus/a2gameio/joystick.cpp
+++ b/src/devices/bus/a2gameio/joystick.cpp
@@ -29,10 +29,10 @@ protected:
virtual u8 pdl1_r() override;
virtual u8 pdl2_r() override;
virtual u8 pdl3_r() override;
- virtual DECLARE_READ_LINE_MEMBER(sw0_r) override;
- virtual DECLARE_READ_LINE_MEMBER(sw1_r) override;
- virtual DECLARE_READ_LINE_MEMBER(sw2_r) override;
- virtual DECLARE_READ_LINE_MEMBER(sw3_r) override;
+ virtual int sw0_r() override;
+ virtual int sw1_r() override;
+ virtual int sw2_r() override;
+ virtual int sw3_r() override;
private:
// input ports
@@ -60,8 +60,6 @@ static INPUT_PORTS_START( apple2_joystick )
PORT_KEYDELTA(JOYSTICK_DELTA)
PORT_CENTERDELTA(JOYSTICK_AUTOCENTER)
PORT_MINMAX(0,0xff) PORT_PLAYER(1)
- PORT_CODE_DEC(KEYCODE_4_PAD) PORT_CODE_INC(KEYCODE_6_PAD)
- PORT_CODE_DEC(JOYCODE_X_LEFT_SWITCH) PORT_CODE_INC(JOYCODE_X_RIGHT_SWITCH)
PORT_START("joystick_1_y") /* Joystick 1 Y Axis */
PORT_BIT( 0xff, 0x80, IPT_AD_STICK_Y) PORT_NAME("P1 Joystick Y")
@@ -69,8 +67,6 @@ static INPUT_PORTS_START( apple2_joystick )
PORT_KEYDELTA(JOYSTICK_DELTA)
PORT_CENTERDELTA(JOYSTICK_AUTOCENTER)
PORT_MINMAX(0,0xff) PORT_PLAYER(1)
- PORT_CODE_DEC(KEYCODE_8_PAD) PORT_CODE_INC(KEYCODE_2_PAD)
- PORT_CODE_DEC(JOYCODE_Y_UP_SWITCH) PORT_CODE_INC(JOYCODE_Y_DOWN_SWITCH)
PORT_START("joystick_2_x") /* Joystick 2 X Axis */
PORT_BIT( 0xff, 0x80, IPT_AD_STICK_X) PORT_NAME("P2 Joystick X")
@@ -78,7 +74,6 @@ static INPUT_PORTS_START( apple2_joystick )
PORT_KEYDELTA(JOYSTICK_DELTA)
PORT_CENTERDELTA(JOYSTICK_AUTOCENTER)
PORT_MINMAX(0,0xff) PORT_PLAYER(2)
- PORT_CODE_DEC(JOYCODE_X_LEFT_SWITCH) PORT_CODE_INC(JOYCODE_X_RIGHT_SWITCH)
PORT_START("joystick_2_y") /* Joystick 2 Y Axis */
PORT_BIT( 0xff, 0x80, IPT_AD_STICK_Y) PORT_NAME("P2 Joystick Y")
@@ -86,7 +81,6 @@ static INPUT_PORTS_START( apple2_joystick )
PORT_KEYDELTA(JOYSTICK_DELTA)
PORT_CENTERDELTA(JOYSTICK_AUTOCENTER)
PORT_MINMAX(0,0xff) PORT_PLAYER(2)
- PORT_CODE_DEC(JOYCODE_Y_UP_SWITCH) PORT_CODE_INC(JOYCODE_Y_DOWN_SWITCH)
PORT_START("joystick_buttons")
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_PLAYER(1) PORT_CODE(KEYCODE_0_PAD) PORT_CODE(JOYCODE_BUTTON1)
@@ -137,22 +131,22 @@ u8 apple2_joystick_device::pdl3_r()
return m_joy_y[1]->read();
}
-READ_LINE_MEMBER(apple2_joystick_device::sw0_r)
+int apple2_joystick_device::sw0_r()
{
return BIT(m_buttons->read(), 4);
}
-READ_LINE_MEMBER(apple2_joystick_device::sw1_r)
+int apple2_joystick_device::sw1_r()
{
return BIT(m_buttons->read(), 5);
}
-READ_LINE_MEMBER(apple2_joystick_device::sw2_r)
+int apple2_joystick_device::sw2_r()
{
return BIT(m_buttons->read(), 6);
}
-READ_LINE_MEMBER(apple2_joystick_device::sw3_r)
+int apple2_joystick_device::sw3_r()
{
return BIT(m_buttons->read(), 7);
}
diff --git a/src/devices/bus/a2gameio/paddles.cpp b/src/devices/bus/a2gameio/paddles.cpp
index 5f0955fba89..fd5d106f53d 100644
--- a/src/devices/bus/a2gameio/paddles.cpp
+++ b/src/devices/bus/a2gameio/paddles.cpp
@@ -29,10 +29,10 @@ protected:
virtual u8 pdl1_r() override;
virtual u8 pdl2_r() override;
virtual u8 pdl3_r() override;
- virtual DECLARE_READ_LINE_MEMBER(sw0_r) override;
- virtual DECLARE_READ_LINE_MEMBER(sw1_r) override;
- virtual DECLARE_READ_LINE_MEMBER(sw2_r) override;
- virtual DECLARE_READ_LINE_MEMBER(sw3_r) override;
+ virtual int sw0_r() override;
+ virtual int sw1_r() override;
+ virtual int sw2_r() override;
+ virtual int sw3_r() override;
private:
// input ports
@@ -105,22 +105,22 @@ u8 apple2_paddles_device::pdl3_r()
return m_pdl[3]->read();
}
-READ_LINE_MEMBER(apple2_paddles_device::sw0_r)
+int apple2_paddles_device::sw0_r()
{
return BIT(m_buttons->read(), 4);
}
-READ_LINE_MEMBER(apple2_paddles_device::sw1_r)
+int apple2_paddles_device::sw1_r()
{
return BIT(m_buttons->read(), 5);
}
-READ_LINE_MEMBER(apple2_paddles_device::sw2_r)
+int apple2_paddles_device::sw2_r()
{
return BIT(m_buttons->read(), 6);
}
-READ_LINE_MEMBER(apple2_paddles_device::sw3_r)
+int apple2_paddles_device::sw3_r()
{
return BIT(m_buttons->read(), 7);
}
diff --git a/src/devices/bus/a7800/a78_slot.cpp b/src/devices/bus/a7800/a78_slot.cpp
index 14127b69759..2f407adb374 100644
--- a/src/devices/bus/a7800/a78_slot.cpp
+++ b/src/devices/bus/a7800/a78_slot.cpp
@@ -28,6 +28,8 @@
#include "emu.h"
#include "a78_slot.h"
+#include "multibyte.h"
+
//**************************************************************************
// GLOBAL VARIABLES
//**************************************************************************
@@ -61,11 +63,11 @@ device_a78_cart_interface::~device_a78_cart_interface ()
// rom_alloc - alloc the space for the cart
//-------------------------------------------------
-void device_a78_cart_interface::rom_alloc(uint32_t size, const char *tag)
+void device_a78_cart_interface::rom_alloc(uint32_t size)
{
if (m_rom == nullptr)
{
- m_rom = device().machine().memory().region_alloc(std::string(tag).append(A78SLOT_ROM_REGION_TAG).c_str(), size, 1, ENDIANNESS_LITTLE)->base();
+ m_rom = device().machine().memory().region_alloc(device().subtag("^cart:rom"), size, 1, ENDIANNESS_LITTLE)->base();
m_rom_size = size;
// setup other helpers
@@ -332,7 +334,7 @@ static const char *a78_get_slot(int type)
return "a78_rom";
}
-image_init_result a78_cart_slot_device::call_load()
+std::pair<std::error_condition, std::string> a78_cart_slot_device::call_load()
{
if (m_cart)
{
@@ -345,7 +347,7 @@ image_init_result a78_cart_slot_device::call_load()
bool has_nvram = get_software_region("nvram") ? true : false;
len = get_software_region_length("rom");
- m_cart->rom_alloc(len, tag());
+ m_cart->rom_alloc(len);
memcpy(m_cart->get_rom_base(), get_software_region("rom"), len);
if ((pcb_name = get_feature("slot")) != nullptr)
@@ -365,13 +367,14 @@ image_init_result a78_cart_slot_device::call_load()
{
// Load and check the header
int mapper;
- char head[128];
+ uint8_t head[128];
fread(head, 128);
- if (verify_header((char *)head) != image_verify_result::PASS)
- return image_init_result::FAIL;
+ auto err = verify_header(head);
+ if (err.first)
+ return err;
- len = (head[49] << 24) | (head[50] << 16) | (head[51] << 8) | head[52];
+ len = get_u32be(&head[49]);
if (len + 128 > length())
{
logerror("Invalid length in the header. The game might be corrupted.\n");
@@ -379,7 +382,7 @@ image_init_result a78_cart_slot_device::call_load()
}
// let's try to auto-fix some common errors in the header
- mapper = validate_header((head[53] << 8) | head[54], true);
+ mapper = validate_header(get_u16be(&head[53]), true);
switch (mapper & 0x2e)
{
@@ -443,9 +446,9 @@ image_init_result a78_cart_slot_device::call_load()
osd_printf_info("Run it through the expansion to exploit this feature.\n");
}
- internal_header_logging((uint8_t *)head, length());
+ internal_header_logging(head, length());
- m_cart->rom_alloc(len, tag());
+ m_cart->rom_alloc(len);
fread(m_cart->get_rom_base(), len);
if (m_type == A78_TYPE6 || m_type == A78_TYPE8)
@@ -463,7 +466,7 @@ image_init_result a78_cart_slot_device::call_load()
//printf("Type: %s\n", a78_get_slot(m_type));
}
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
@@ -484,19 +487,15 @@ void a78_cart_slot_device::call_unload()
has an admissible header
-------------------------------------------------*/
-image_verify_result a78_cart_slot_device::verify_header(char *header)
+std::pair<std::error_condition, std::string> a78_cart_slot_device::verify_header(const uint8_t *header)
{
const char *magic = "ATARI7800";
- if (strncmp(magic, header + 1, 9))
- {
- logerror("Not a valid A7800 image\n");
- seterror(image_error::INVALIDIMAGE, "File is not a valid A7800 image");
- return image_verify_result::FAIL;
- }
+ if (strncmp(magic, reinterpret_cast<const char *>(header + 1), 9))
+ return std::make_pair(image_error::INVALIDIMAGE, "Not a valid A7800 image");
logerror("returning ID_OK\n");
- return image_verify_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
@@ -513,11 +512,10 @@ std::string a78_cart_slot_device::get_default_card_software(get_default_card_sof
// Load and check the header
uint8_t head[128];
- std::size_t actual;
- hook.image_file()->read(&head[0], 128, actual); // FIXME: check error return or read returning short
+ /*auto const [err, actual] =*/ read(*hook.image_file(), &head[0], 128); // FIXME: check error return or read returning short
// let's try to auto-fix some common errors in the header
- int const mapper = validate_header((head[53] << 8) | head[54], false);
+ int const mapper = validate_header(get_u16be(&head[53]), false);
int type = A78_TYPE0;
switch (mapper & 0x2e)
@@ -702,11 +700,11 @@ void a78_cart_slot_device::write_40xx(offs_t offset, uint8_t data)
-------------------------------------------------*/
-void a78_cart_slot_device::internal_header_logging(uint8_t *header, uint32_t len)
+void a78_cart_slot_device::internal_header_logging(const uint8_t *header, uint32_t len)
{
char head_title[35];
- uint32_t head_length = (header[49] << 24) | (header[50] << 16) | (header[51] << 8) | header[52];
- uint16_t head_mapper = (header[53] << 8) | header[54];
+ uint32_t head_length = get_u32be(&header[49]);
+ uint16_t head_mapper = get_u16be(&header[53]);
uint8_t head_ctrl1 = header[55];
uint8_t head_ctrl2 = header[56];
uint8_t head_ispal = header[57];
@@ -792,7 +790,7 @@ void a78_cart_slot_device::internal_header_logging(uint8_t *header, uint32_t len
logerror( "==============\n\n" );
logerror( "\tTitle: %.32s\n", head_title);
logerror( "\tLength: 0x%X [real 0x%X]\n", head_length, len);
- logerror( "\tMapper: %s [0x%X]\n", cart_mapper.c_str(), head_mapper);
+ logerror( "\tMapper: %s [0x%X]\n", cart_mapper, head_mapper);
logerror( "\t\tPOKEY: %s\n", BIT(head_mapper, 0) ? "Yes" : "No");
logerror( "\t\tSC Bankswitch: %s\n", BIT(head_mapper, 1) ? "Yes" : "No");
logerror( "\t\tRAM at $4000: %s\n", BIT(head_mapper, 2) ? "Yes" : "No");
@@ -809,7 +807,7 @@ void a78_cart_slot_device::internal_header_logging(uint8_t *header, uint32_t len
}
else
logerror( "\n");
- logerror( "\tController 1: 0x%.2X [%s]\n", head_ctrl1, ctrl1.c_str());
- logerror( "\tController 2: 0x%.2X [%s]\n", head_ctrl2, ctrl2.c_str());
+ logerror( "\tController 1: 0x%.2X [%s]\n", head_ctrl1, ctrl1);
+ logerror( "\tController 2: 0x%.2X [%s]\n", head_ctrl2, ctrl2);
logerror( "\tVideo: %s\n", (head_ispal) ? "PAL" : "NTSC");
}
diff --git a/src/devices/bus/a7800/a78_slot.h b/src/devices/bus/a7800/a78_slot.h
index 678de644f0d..9f9b8126c82 100644
--- a/src/devices/bus/a7800/a78_slot.h
+++ b/src/devices/bus/a7800/a78_slot.h
@@ -12,8 +12,6 @@
TYPE DEFINITIONS
***************************************************************************/
-#define A78SLOT_ROM_REGION_TAG ":cart:rom"
-
/* PCB */
enum
{
@@ -58,7 +56,7 @@ public:
virtual void write_30xx(offs_t offset, uint8_t data) {}
virtual void write_40xx(offs_t offset, uint8_t data) {}
- void rom_alloc(uint32_t size, const char *tag);
+ void rom_alloc(uint32_t size);
void ram_alloc(uint32_t size);
void nvram_alloc(uint32_t size);
uint8_t* get_rom_base() { return m_rom; }
@@ -91,19 +89,19 @@ class a78_cart_slot_device : public device_t,
public:
// construction/destruction
template <typename T>
- a78_cart_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts, char const *dflt)
- : a78_cart_slot_device(mconfig, tag, owner, (uint32_t)0)
+ a78_cart_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock, T &&opts, char const *dflt)
+ : a78_cart_slot_device(mconfig, tag, owner, clock)
{
option_reset();
opts(*this);
set_default_option(dflt);
set_fixed(false);
}
- a78_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
+ a78_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual ~a78_cart_slot_device();
- // image-level overrides
- virtual image_init_result call_load() override;
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
virtual void call_unload() override;
virtual bool is_reset_on_load() const noexcept override { return true; }
@@ -111,7 +109,7 @@ public:
virtual const char *file_extensions() const noexcept override { return "a78"; }
virtual u32 unhashed_header_length() const noexcept override { return 128; }
- // slot interface overrides
+ // device_slot_interface implementation
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
int get_cart_type() { return m_type; }
@@ -128,15 +126,15 @@ public:
void write_40xx(offs_t offset, uint8_t data);
private:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
- device_a78_cart_interface* m_cart;
- int m_type;
-
- image_verify_result verify_header(char *header);
+ std::pair<std::error_condition, std::string> verify_header(const uint8_t *header);
int validate_header(int head, bool log) const;
- void internal_header_logging(uint8_t *header, uint32_t len);
+ void internal_header_logging(const uint8_t *header, uint32_t len);
+
+ device_a78_cart_interface *m_cart;
+ int m_type;
};
diff --git a/src/devices/bus/a7800/cpuwiz.cpp b/src/devices/bus/a7800/cpuwiz.cpp
index 3a8c3cc1546..44f3d05027e 100644
--- a/src/devices/bus/a7800/cpuwiz.cpp
+++ b/src/devices/bus/a7800/cpuwiz.cpp
@@ -124,5 +124,5 @@ void a78_rom_p450_vb_device::device_add_mconfig(machine_config &config)
{
SPEAKER(config, "addon").front_center();
- POKEY(config, m_pokey450, XTAL(14'318'181)/8).add_route(ALL_OUTPUTS, "addon", 1.00);
+ POKEY(config, m_pokey450, DERIVED_CLOCK(1, 1)).add_route(ALL_OUTPUTS, "addon", 1.00);
}
diff --git a/src/devices/bus/a7800/hiscore.cpp b/src/devices/bus/a7800/hiscore.cpp
index a0c821552d8..9d42358c624 100644
--- a/src/devices/bus/a7800/hiscore.cpp
+++ b/src/devices/bus/a7800/hiscore.cpp
@@ -29,7 +29,7 @@ a78_hiscore_device::a78_hiscore_device(const machine_config &mconfig, const char
void a78_hiscore_device::device_add_mconfig(machine_config &config)
{
- A78_CART_SLOT(config, "hsc_slot", a7800_cart, nullptr);
+ A78_CART_SLOT(config, m_hscslot, DERIVED_CLOCK(1, 1), a7800_cart, nullptr);
}
diff --git a/src/devices/bus/a7800/rom.cpp b/src/devices/bus/a7800/rom.cpp
index 9e715ddcf2c..45293f4260f 100644
--- a/src/devices/bus/a7800/rom.cpp
+++ b/src/devices/bus/a7800/rom.cpp
@@ -243,12 +243,11 @@ void a78_rom_pokey_device::write_40xx(offs_t offset, uint8_t data)
m_pokey->write(offset & 0x0f, data);
}
-// TO DO: do we need a PAL variant?!?
void a78_rom_pokey_device::device_add_mconfig(machine_config &config)
{
SPEAKER(config, "addon").front_center();
- POKEY(config, m_pokey, XTAL(14'318'181)/8).add_route(ALL_OUTPUTS, "addon", 1.00);
+ POKEY(config, m_pokey, DERIVED_CLOCK(1, 1)).add_route(ALL_OUTPUTS, "addon", 1.00);
}
/*-------------------------------------------------
@@ -346,7 +345,7 @@ void a78_rom_sg_pokey_device::device_add_mconfig(machine_config &config)
{
SPEAKER(config, "addon").front_center();
- POKEY(config, m_pokey, XTAL(14'318'181)/8).add_route(ALL_OUTPUTS, "addon", 1.00);
+ POKEY(config, m_pokey, DERIVED_CLOCK(1, 1)).add_route(ALL_OUTPUTS, "addon", 1.00);
}
@@ -445,13 +444,12 @@ void a78_rom_abs_device::write_40xx(offs_t offset, uint8_t data)
Carts with Activision bankswitch:
128K games. 8 x 16K banks (0-7) to be mapped at
- 0xa000-0xdfff. Bank is selected depending on the
- address written in 0xff80-0xff87.
+ 0xa000-0xdfff. Bank is selected by writing above
+ 0xe000 and depends on A2-A0.
The rest of the memory is as follows:
- 0x4000-0x5fff second 8kb of bank 6
- 0x6000-0x7fff first 8kb of bank 6
- 0x8000-0x9fff second 8kb of bank 7
- 0xe000-0xffff first 8kb of bank 7
+ 0x4000-0x7fff bank 6
+ 0x8000-0x9fff first 8K of bank 7
+ 0xe000-0xffff second 8K of bank 7
GAMES: Double Dragon, Rampage.
@@ -459,38 +457,25 @@ void a78_rom_abs_device::write_40xx(offs_t offset, uint8_t data)
uint8_t a78_rom_act_device::read_40xx(offs_t offset)
{
- uint8_t data = 0xff;
- uint16_t addr = offset & 0x1fff;
-
- // offset goes from 0 to 0xc000
+ // offset goes from 0 to 0xbfff
switch (offset & 0xe000)
{
+ default: // unreachable: appease compiler
case 0x0000:
- data = m_rom[addr + 0x1a000];
- break;
case 0x2000:
- data = m_rom[addr + 0x18000];
- break;
- case 0x4000:
- data = m_rom[addr + 0x1e000];
- break;
+ return m_rom[offset | 0x18000];
case 0x6000:
- data = m_rom[addr + (m_bank * 0x4000)];
- break;
case 0x8000:
- data = m_rom[addr + (m_bank * 0x4000) + 0x2000];
- break;
+ return m_rom[(offset & 0x3fff) | (m_bank * 0x4000)];
+ case 0x4000:
case 0xa000:
- data = m_rom[addr + 0x1c000];
- break;
+ return m_rom[offset | 0x1c000];
}
-
- return data;
}
void a78_rom_act_device::write_40xx(offs_t offset, uint8_t data)
{
- if (offset >= 0xbf80 && offset <= 0xbf8f)
+ if (offset >= 0xa000)
m_bank = offset & 7;
}
@@ -501,16 +486,16 @@ void a78_rom_p450_device::device_add_mconfig(machine_config &config)
{
SPEAKER(config, "pokey_450").front_center();
- POKEY(config, m_pokey450, XTAL(14'318'181)/8).add_route(ALL_OUTPUTS, "pokey_450", 1.00);
+ POKEY(config, m_pokey450, DERIVED_CLOCK(1, 1)).add_route(ALL_OUTPUTS, "pokey_450", 1.00);
}
void a78_rom_p450_pokey_device::device_add_mconfig(machine_config &config)
{
SPEAKER(config, "addon").front_center();
- POKEY(config, m_pokey, XTAL(14'318'181)/8).add_route(ALL_OUTPUTS, "addon", 1.00);
+ POKEY(config, m_pokey, DERIVED_CLOCK(1, 1)).add_route(ALL_OUTPUTS, "addon", 1.00);
- POKEY(config, m_pokey450, XTAL(14'318'181)/8).add_route(ALL_OUTPUTS, "addon", 1.00);
+ POKEY(config, m_pokey450, DERIVED_CLOCK(1, 1)).add_route(ALL_OUTPUTS, "addon", 1.00);
}
@@ -518,12 +503,12 @@ void a78_rom_p450_sg_ram_device::device_add_mconfig(machine_config &config)
{
SPEAKER(config, "pokey_450").front_center();
- POKEY(config, m_pokey450, XTAL(14'318'181)/8).add_route(ALL_OUTPUTS, "pokey_450", 1.00);
+ POKEY(config, m_pokey450, DERIVED_CLOCK(1, 1)).add_route(ALL_OUTPUTS, "pokey_450", 1.00);
}
void a78_rom_p450_sg9_device::device_add_mconfig(machine_config &config)
{
SPEAKER(config, "pokey_450").front_center();
- POKEY(config, m_pokey450, XTAL(14'318'181)/8).add_route(ALL_OUTPUTS, "pokey_450", 1.00);
+ POKEY(config, m_pokey450, DERIVED_CLOCK(1, 1)).add_route(ALL_OUTPUTS, "pokey_450", 1.00);
}
diff --git a/src/devices/bus/a7800/xboard.cpp b/src/devices/bus/a7800/xboard.cpp
index bee85d76c98..2b8e0a6530d 100644
--- a/src/devices/bus/a7800/xboard.cpp
+++ b/src/devices/bus/a7800/xboard.cpp
@@ -108,24 +108,24 @@ void a78_xm_device::device_reset()
void a78_xboard_device::device_add_mconfig(machine_config &config)
{
- A78_CART_SLOT(config, m_xbslot, a7800_cart, nullptr);
+ A78_CART_SLOT(config, m_xbslot, DERIVED_CLOCK(1, 1), a7800_cart, nullptr);
SPEAKER(config, "xb_speaker").front_center();
- POKEY(config, m_pokey, XTAL(14'318'181)/8);
+ POKEY(config, m_pokey, DERIVED_CLOCK(1, 1));
m_pokey->add_route(ALL_OUTPUTS, "xb_speaker", 1.00);
}
void a78_xm_device::device_add_mconfig(machine_config &config)
{
- A78_CART_SLOT(config, m_xbslot, a7800_cart, nullptr);
+ A78_CART_SLOT(config, m_xbslot, DERIVED_CLOCK(1, 1), a7800_cart, nullptr);
SPEAKER(config, "xb_speaker").front_center();
- POKEY(config, m_pokey, XTAL(14'318'181)/8);
+ POKEY(config, m_pokey, DERIVED_CLOCK(1, 1));
m_pokey->add_route(ALL_OUTPUTS, "xb_speaker", 1.00);
- YM2151(config, m_ym, XTAL(14'318'181)/4).add_route(ALL_OUTPUTS, "xb_speaker", 1.00);
+ YM2151(config, m_ym, DERIVED_CLOCK(2, 1)).add_route(ALL_OUTPUTS, "xb_speaker", 1.00);
}
diff --git a/src/devices/bus/a800/a5200_supercart.cpp b/src/devices/bus/a800/a5200_supercart.cpp
new file mode 100644
index 00000000000..563095f6b59
--- /dev/null
+++ b/src/devices/bus/a800/a5200_supercart.cpp
@@ -0,0 +1,74 @@
+// license: BSD-3-Clause
+// copyright-holders: Angelo Salese
+/**************************************************************************************************
+
+A5200 Bryan Edewaard's Super Cart
+
+Maps on the full A5200 cart space, uses $bfc0-$bfff reading for banking.
+A5200 BIOS will read to $bfe0-$bfff range, this will automatically fallback to the last
+available bank for convenience.
+
+TODO:
+- Checkout if support for non-512K carts works right, supposedly M.U.L.E. conversion
+ runs on a 64K ROM version, should be right in theory.
+
+**************************************************************************************************/
+
+#include "emu.h"
+#include "a5200_supercart.h"
+
+DEFINE_DEVICE_TYPE(A5200_ROM_SUPERCART, a5200_rom_supercart_device, "a5200_supercart", "Atari 5200 Super Cart")
+
+
+a5200_rom_supercart_device::a5200_rom_supercart_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : a5200_rom_device(mconfig, A5200_ROM_SUPERCART, tag, owner, clock)
+ , m_bank(0)
+{
+}
+
+void a5200_rom_supercart_device::device_start()
+{
+ save_item(NAME(m_bank));
+}
+
+void a5200_rom_supercart_device::device_reset()
+{
+ m_bank_mask = (m_rom_size / 0x8000) - 1;
+ m_bank = m_bank_mask;
+}
+
+/*
+ * --1- ---- fallback to last available bank
+ * ---1 xx-- selects lower banks
+ * ---0 xx-- selects upper banks
+ *
+ * On non-512K carts upper lines will just be ignored
+ * i.e. a 64K will only respond to bits 5 or 4 high, with bit 2 as bank selector for latter.
+ */
+u8 a5200_rom_supercart_device::bank_r(offs_t offset)
+{
+ if (!machine().side_effects_disabled())
+ {
+ if (BIT(offset, 5))
+ m_bank = m_bank_mask;
+ else
+ {
+ if (BIT(offset, 4))
+ m_bank = (m_bank & 0xc) | ((offset & 0xc) >> 2);
+ else
+ m_bank = (m_bank & 3) | (offset & 0xc);
+ }
+
+ m_bank &= m_bank_mask;
+ }
+
+ return m_rom[(offset & 0x3f) + (m_bank * 0x8000) + 0x7fc0];
+}
+
+void a5200_rom_supercart_device::cart_map(address_map &map)
+{
+ map(0x0000, 0x7fff).lr8(
+ NAME([this](offs_t offset) { return m_rom[(offset & 0x7fff) + (m_bank * 0x8000)]; })
+ );
+ map(0x7fc0, 0x7fff).r(FUNC(a5200_rom_supercart_device::bank_r));
+}
diff --git a/src/devices/bus/a800/a5200_supercart.h b/src/devices/bus/a800/a5200_supercart.h
new file mode 100644
index 00000000000..cc9baead23b
--- /dev/null
+++ b/src/devices/bus/a800/a5200_supercart.h
@@ -0,0 +1,32 @@
+// license: BSD-3-Clause
+// copyright-holders: Angelo Salese
+
+#ifndef MAME_BUS_A5200_SUPERCART_H
+#define MAME_BUS_A5200_SUPERCART_H
+
+#pragma once
+
+#include "rom.h"
+
+
+class a5200_rom_supercart_device : public a5200_rom_device
+{
+public:
+ a5200_rom_supercart_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void cart_map(address_map &map) override;
+
+protected:
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ u8 m_bank;
+ u8 m_bank_mask;
+
+ u8 bank_r(offs_t offset);
+};
+
+DECLARE_DEVICE_TYPE(A5200_ROM_SUPERCART, a5200_rom_supercart_device)
+
+#endif // MAME_BUS_A5200_SUPERCART_H
+
diff --git a/src/devices/bus/a800/a800_carts.cpp b/src/devices/bus/a800/a800_carts.cpp
new file mode 100644
index 00000000000..a497da257d9
--- /dev/null
+++ b/src/devices/bus/a800/a800_carts.cpp
@@ -0,0 +1,109 @@
+// license:BSD-3-Clause
+// copyright-holders:Fabio Priuli, Angelo Salese
+
+#include "emu.h"
+#include "a800_carts.h"
+
+// (#num) denotes the canonical number from .car specs for unemulated/undumped variants
+void a800_left(device_slot_interface &device)
+{
+ device.option_add_internal("a800_8k", A800_ROM);
+ device.option_add_internal("a800_8k_right", A800_ROM_RIGHT);
+ device.option_add_internal("a800_16k", A800_ROM_16KB);
+ device.option_add_internal("a800_phoenix", A800_ROM_PHOENIX);
+ device.option_add_internal("a800_blizzard", A800_ROM_BLIZZARD_16KB);
+ device.option_add_internal("a800_phoenix_ast2k", A800_ROM_PHOENIX_AST2K);
+ device.option_add_internal("a800_bbsb", A800_ROM_BBSB);
+ device.option_add_internal("a800_oss8k", A800_ROM_OSS8K);
+ device.option_add_internal("a800_oss034m", A800_ROM_OSS34);
+ device.option_add_internal("a800_oss043m", A800_ROM_OSS43);
+ device.option_add_internal("a800_ossm091", A800_ROM_OSS91);
+ // OSS cart with subslot
+// device.option_add_internal("a800_mddos", A800_ROM_MDDOS);
+ device.option_add_internal("a800_williams", A800_ROM_WILLIAMS);
+ device.option_add_internal("a800_diamond", A800_ROM_DIAMOND);
+ device.option_add_internal("a800_express", A800_ROM_EXPRESS);
+ device.option_add_internal("a800_turbo", A800_ROM_TURBO);
+ device.option_add_internal("a800_tlink2", A800_ROM_TELELINK2);
+ device.option_add_internal("a800_ultracart", A800_ROM_ULTRACART);
+ device.option_add_internal("a800_blizzard_32kb", A800_ROM_BLIZZARD_32KB);
+ device.option_add_internal("a800_adawliah", A800_ROM_ADAWLIAH);
+ device.option_add_internal("a800_atrax", A800_ROM_ATRAX);
+ device.option_add_internal("a800_sparta", A800_ROM_SPARTADOS);
+ device.option_add_internal("a800_sparta_128kb", A800_ROM_SPARTADOS_128KB);
+ // (#48-#49 / #68) SDX 64KB/128KB variants
+// device.option_add_internal("a800_sdx_atrax_64kb", A800_ROM_SDX_ATRAX_64KB);
+// device.option_add_internal("a800_sdx_atrax_128kb", A800_ROM_SDX_ATRAX_128KB);
+ // (#5) DB "Dave Bennett" homebrew cartridge, vaporware? cfr. https://forums.atariage.com/topic/307663-32k-db-cart/
+// device.option_add_internal("a800_db", A800_ROM_DB);
+ // (#47) "Atari Super Turbo" 32 KB Polish cart with exotic banking scheme (256 bytes at a time) that maps to CCTL
+// device.option_add_internal("a800_ast", A800_ROM_AST);
+ // TOOLBOX III / RAMBOX 2 Polish carts with additional 256KB RAM
+// device.option_add_internal("a800_jrc", A800_ROM_JRC);
+ // Czech cart, some kind of toolkit with bankswitch that rolls back after set time
+// device.option_add_internal("a800_cos32", A800_ROM_COS32);
+
+ // XEGS carts
+ device.option_add_internal("xegs", XEGS_ROM);
+ // "XEGS demo cartridge", 4 games in 1 with binary counter applied at reset for each reboot
+// device.option_add_internal("xegs_demo", XEGS_ROM_DEMO);
+ // (#33-#38) Carts sold by Nir Dary in the '90s, has fixed last bank to RD5 and selectable RD4 bank. 32KB to 1MB ROM size options
+// device.option_add_internal("xegs_switch", XEGS_ROM_SWITCHABLE);
+
+ // flash carts
+ device.option_add_internal("a800_corina", A800_ROM_CORINA);
+ device.option_add_internal("a800_corina_sram", A800_ROM_CORINA_SRAM);
+ device.option_add( "maxflash_128kb", A800_MAXFLASH_128KB);
+ device.option_add( "maxflash_1mb", A800_MAXFLASH_1MB);
+ // (#61) MegaMax, has switch that toggles between Atarimax 1MB mode and 2MB
+// device.option_add( "megamax", A800_MEGAMAX);
+ device.option_add( "sic_128kb", A800_SIC_128KB);
+ device.option_add( "sic_256kb", A800_SIC_256KB);
+ device.option_add( "sic_512kb", A800_SIC_512KB);
+ // (#26-#32 / #63-#64) MegaCart 16KB up to 4MB variant too
+// device.option_add( "megacart", A800_MEGACART);
+ // Atarimax MyIDE-II, 512 KB flash ROM + 512 KB RAM + CompactFlash i/f, requires DIY MyBIOS ROM installation into main system
+// device.option_add( "myideii", A800_MYIDE_II);
+ // 512KB flash + CompactFlash, emulates a Sparta DOS X, has DS1305 RTC hooked up thru SPI bus, SIDE 2 is an upgraded variant with slightly different CCTL mapping
+// device.option_add( "side1", A800_SIDE1);
+// device.option_add( "side2", A800_SIDE2);
+ // Upgrades SIDE 2 with SD card instead of CF, MX29LV640ET NOR flash chip, 2MB RAM, DMA with various OPs, ROM bank emulation modes with relocatable CCTL ...
+// device.option_add( "side3", A800_SIDE3);
+ // STM32 coprocessor with SD card, cfr. https://github.com/robinhedwards/UnoCart
+// device.option_add( "unocart", A800_UNOCART);
+ // earlier variant of above running on FPGA, cfr. https://github.com/robinhedwards/UltimateCart
+// device.option_add( "ultimatecart", A800_ULTIMATECART);
+ // (#62 / #65) The!Cart, 32/64/128MB + 512KB RAM, emulation modes
+// device.option_add( "thecart", A800_THECART);
+
+ // non-ROM types
+ device.option_add( "rtime8", A800_RTIME8);
+ // adds extra 65C816 coprocessor. No firmware, runs on code uploaded by main CPU, also two rev variants (V1 and V2)
+ // NB: SDX documentation calls this Weronika, which just seems a Polish alias
+// device.option_add( "veronica", A800_VERONICA);
+ // 128 or 256 KB additional RAM, schematics available at atarimax
+// device.option_add( "ramcart", A800_RAM_CART);
+ // converts analog mono sound to digital by reading $d500 low 4 bitset
+// device.option_add( "ad_converter", A800_AD_CONVERTER);
+ device.option_add( "supercharger", A800_SUPER_CHARGER);
+ // The PILL! / Super PILL! / Super Cart with RD4/RD5 held high and that's about it (lolwut)
+// device.option_add( "pill", A800_PILL);
+ // Thompson Proburner, EPROM burner
+// device.option_add( "proburner", A800_PROBURNER);
+ // The Multiplexer! (MUX!), PBI bus between 1 master and 8 slaves
+ // cfr. https://sdx.atari8.info/sdx_files/muxsdx.txt & http://realdos.net/mux.html
+// device.option_add( "mux", A800_MUX);
+}
+
+void a800_right(device_slot_interface &device)
+{
+ device.option_add_internal("a800_8k_right", A800_ROM_RIGHT);
+}
+
+void a5200_carts(device_slot_interface &device)
+{
+ device.option_add_internal("a5200_rom", A5200_ROM);
+ device.option_add_internal("a5200_2chips", A5200_ROM_2CHIPS);
+ device.option_add_internal("a5200_bbsb", A5200_ROM_BBSB);
+ device.option_add_internal("a5200_supercart", A5200_ROM_SUPERCART);
+}
diff --git a/src/devices/bus/a800/a800_carts.h b/src/devices/bus/a800/a800_carts.h
index b3ccbbc6830..6bbe9691e8a 100644
--- a/src/devices/bus/a800/a800_carts.h
+++ b/src/devices/bus/a800/a800_carts.h
@@ -1,56 +1,28 @@
// license:BSD-3-Clause
-// copyright-holders:Fabio Priuli
+// copyright-holders:Fabio Priuli, Angelo Salese
#ifndef MAME_BUS_A800_A800_CARTS_H
#define MAME_BUS_A800_A800_CARTS_H
#pragma once
-
#include "rom.h"
-#include "rtime8.h"
+#include "a5200_supercart.h"
+#include "atrax.h"
+#include "bbsb.h"
+#include "corina.h"
+#include "maxflash.h"
#include "oss.h"
+#include "phoenix.h"
+#include "rtime8.h"
+#include "sic.h"
#include "sparta.h"
-
-static void a800_left(device_slot_interface &device)
-{
- device.option_add_internal("a800_8k", A800_ROM);
- device.option_add_internal("a800_8k_right", A800_ROM);
- device.option_add_internal("a800_16k", A800_ROM);
- device.option_add_internal("a800_phoenix", A800_ROM); // not really emulated at this stage
- device.option_add_internal("a800_bbsb", A800_ROM_BBSB);
- device.option_add_internal("a800_oss8k", A800_ROM_OSS8K);
- device.option_add_internal("a800_oss034m", A800_ROM_OSS34);
- device.option_add_internal("a800_oss043m", A800_ROM_OSS43);
- device.option_add_internal("a800_ossm091", A800_ROM_OSS91);
- device.option_add_internal("a800_williams", A800_ROM_WILLIAMS);
- device.option_add_internal("a800_diamond", A800_ROM_EXPRESS);
- device.option_add_internal("a800_express", A800_ROM_EXPRESS);
- device.option_add_internal("a800_sparta", A800_ROM_SPARTADOS); // this is a passthru cart with unemulated (atm) subslot
- device.option_add_internal("a800_blizzard", A800_ROM);
- device.option_add_internal("a800_turbo64", A800_ROM_TURBO);
- device.option_add_internal("a800_turbo128", A800_ROM_TURBO);
- device.option_add_internal("a800_tlink2", A800_ROM_TELELINK2);
- device.option_add_internal("a800_sitsa", A800_ROM_MICROCALC);
- device.option_add_internal("a800_corina", A800_ROM); // NOT SUPPORTED YET!
- device.option_add( "rtime8", A800_RTIME8); // not a ROM cartridge
- device.option_add_internal("xegs", XEGS_ROM);
-}
-
-static void a800_right(device_slot_interface &device)
-{
- device.option_add_internal("a800_8k_right", A800_ROM);
-}
-
-static void xegs_carts(device_slot_interface &device)
-{
- device.option_add_internal("xegs", XEGS_ROM);
-}
-
-static void a5200_carts(device_slot_interface &device)
-{
- device.option_add_internal("a5200", A800_ROM);
- device.option_add_internal("a5200_2chips", A5200_ROM_2CHIPS);
- device.option_add_internal("a5200_bbsb", A5200_ROM_BBSB);
-}
+#include "supercharger.h"
+#include "telelink2.h"
+#include "ultracart.h"
+#include "williams.h"
+
+void a800_left(device_slot_interface &device);
+void a800_right(device_slot_interface &device);
+void a5200_carts(device_slot_interface &device);
#endif // MAME_BUS_A800_A800_CARTS_H
diff --git a/src/devices/bus/a800/a800_slot.cpp b/src/devices/bus/a800/a800_slot.cpp
index 1e9013bb602..8045f0152d0 100644
--- a/src/devices/bus/a800/a800_slot.cpp
+++ b/src/devices/bus/a800/a800_slot.cpp
@@ -1,50 +1,53 @@
// license:BSD-3-Clause
-// copyright-holders:Fabio Priuli
-/***********************************************************************************************************
+// copyright-holders:Fabio Priuli, Angelo Salese
+/**************************************************************************************************
+Atari A800/A5200/XEGS cart slot emulation
- Atari 8 bit cart emulation
- (through slot devices)
+<fill me>
- Emulation of the cartslot(s) for Atari 8bit series of home computers
+References:
+- Altirra HW reference manual 2022-07-07 edition, chapter 8;
+- https://github.com/atari800/atari800/blob/master/DOC/cart.txt
+- https://www.atarimax.com/jindroush.atari.org/acarts.html
- Accessors to ROM are typically given in the area 0xa000-0xbfff, but some
- carts (and the right slot in A800) maps ROM to 0x8000-0x9fff too
- Bankswitch typically happens by accessing addresses in 0xd500-0xd5ff
-
- Accordingly, this device offers the following handlers
- - read_80xx/write_80xx
- - read_d5xx/write_d5xx
- Notice that these are installed in different ranges at machine start by
- the drivers, so that it might well be that offs=0 for read_80xx is 0xa000!
-
- ***********************************************************************************************************/
+**************************************************************************************************/
#include "emu.h"
#include "a800_slot.h"
#include "hashfile.h"
+#include "multibyte.h"
//**************************************************************************
// GLOBAL VARIABLES
//**************************************************************************
-DEFINE_DEVICE_TYPE(A800_CART_SLOT, a800_cart_slot_device, "a800_cart_slot", "Atari 8bit Cartridge Slot")
+DEFINE_DEVICE_TYPE(A800_CART_SLOT, a800_cart_slot_device, "a800_cart_slot", "Atari 8-bit Cartridge Slot")
DEFINE_DEVICE_TYPE(A5200_CART_SLOT, a5200_cart_slot_device, "a5200_cart_slot", "Atari 5200 Cartridge Slot")
-DEFINE_DEVICE_TYPE(XEGS_CART_SLOT, xegs_cart_slot_device, "xegs_cart_slot", "Atari XEGS Cartridge Slot")
//-------------------------------------------------
-// device_vcs_cart_interface - constructor
+// device_a800_cart_interface - constructor
//-------------------------------------------------
-device_a800_cart_interface::device_a800_cart_interface (const machine_config &mconfig, device_t &device) :
- device_interface(device, "a800cart"),
- m_rom(nullptr),
- m_rom_size(0),
- m_bank_mask(0)
+device_a800_cart_interface::device_a800_cart_interface (const machine_config &mconfig, device_t &device)
+ : device_interface(device, "a800cart")
+ , m_rom(nullptr)
+ , m_rom_size(0)
+ , m_bank_mask(0)
+{
+ m_slot = dynamic_cast<a800_cart_slot_device *>(device.owner());
+}
+
+device_a5200_cart_interface::device_a5200_cart_interface (const machine_config &mconfig, device_t &device)
+ : device_interface(device, "a5200cart")
+ , m_rom(nullptr)
+ , m_rom_size(0)
+ , m_bank_mask(0)
{
+ m_slot = dynamic_cast<a5200_cart_slot_device *>(device.owner());
}
@@ -56,74 +59,119 @@ device_a800_cart_interface::~device_a800_cart_interface ()
{
}
+device_a5200_cart_interface::~device_a5200_cart_interface ()
+{
+}
+
//-------------------------------------------------
// rom_alloc - alloc the space for the cart
//-------------------------------------------------
-void device_a800_cart_interface::rom_alloc(uint32_t size, const char *tag)
+void device_a800_cart_interface::rom_alloc(uint32_t size)
{
if (m_rom == nullptr)
{
- m_rom = device().machine().memory().region_alloc(std::string(tag).append(A800SLOT_ROM_REGION_TAG).c_str(), size, 1, ENDIANNESS_LITTLE)->base();
+ // TODO: shouldn't really load from fixed tag
+ // (particularly inconvenient for stuff like flash ROM hookups)
+ m_rom = device().machine().memory().region_alloc(device().subtag("^cart:rom"), size, 1, ENDIANNESS_LITTLE)->base();
m_rom_size = size;
// setup other helpers
+ // TODO: unusable for SIC! and any other mapping that maps over 0x4000 rather than 0x2000
m_bank_mask = (size / 0x2000) - 1; // code for XEGS carts makes use of this to simplify banking
}
}
-//-------------------------------------------------
-// ram_alloc - alloc the space for the on-cart RAM
-//-------------------------------------------------
-
-void device_a800_cart_interface::ram_alloc(uint32_t size)
+void device_a800_cart_interface::interface_pre_start()
{
- m_ram.resize(size);
- device().save_item(NAME(m_ram));
+ if (!m_slot->started())
+ throw device_missing_dependencies();
}
+void device_a800_cart_interface::interface_post_start()
+{
+ m_slot->m_space_mem->install_device(0x0000, 0x3fff, *this, &device_a800_cart_interface::cart_map);
+ m_slot->m_space_io->install_device(0x0000, 0x00ff, *this, &device_a800_cart_interface::cctl_map);
+}
-//-------------------------------------------------
-// ram_alloc - alloc the space for the on-cart RAM
-//-------------------------------------------------
+void device_a800_cart_interface::cart_map(address_map &map)
+{
+ map(0x0000, 0x3fff).unmaprw();
+}
-void device_a800_cart_interface::nvram_alloc(uint32_t size)
+void device_a800_cart_interface::cctl_map(address_map &map)
{
- m_nvram.resize(size);
- device().save_item(NAME(m_nvram));
+ map(0x0000, 0x00ff).unmaprw();
}
+void device_a800_cart_interface::rd4_w(int state) { m_slot->m_rd4_cb(state); }
+void device_a800_cart_interface::rd5_w(int state) { m_slot->m_rd5_cb(state); }
+// helper to call both lines at same time, for anything banking on the full range.
+void device_a800_cart_interface::rd_both_w(int state) { rd4_w(state); rd5_w(state); }
-//**************************************************************************
-// LIVE DEVICE
-//**************************************************************************
+// a5200
-//-------------------------------------------------
-// ****_cart_slot_device - constructor
-//-------------------------------------------------
-a800_cart_slot_device::a800_cart_slot_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, type, tag, owner, clock),
- device_cartrom_image_interface(mconfig, *this),
- device_single_card_slot_interface<device_a800_cart_interface>(mconfig, *this),
- m_cart(nullptr), m_type(0)
+void device_a5200_cart_interface::rom_alloc(uint32_t size)
{
+ if (m_rom == nullptr)
+ {
+ // TODO: shouldn't really load from fixed tag
+ // (particularly inconvenient for stuff like flash ROM hookups)
+ m_rom = device().machine().memory().region_alloc(device().subtag("^cart:rom"), size, 1, ENDIANNESS_LITTLE)->base();
+ m_rom_size = size;
+
+ // setup other helpers
+ // TODO: unusable for SIC! and any other mapping that maps over 0x4000 rather than 0x2000
+ m_bank_mask = (size / 0x2000) - 1; // code for XEGS carts makes use of this to simplify banking
+ }
}
-a800_cart_slot_device::a800_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- a800_cart_slot_device(mconfig, A800_CART_SLOT, tag, owner, clock)
+void device_a5200_cart_interface::cart_map(address_map &map)
{
+ map(0x0000, 0x7fff).unmaprw();
}
+void device_a5200_cart_interface::interface_pre_start()
+{
+ if (!m_slot->started())
+ throw device_missing_dependencies();
+}
-a5200_cart_slot_device::a5200_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- a800_cart_slot_device(mconfig, A5200_CART_SLOT, tag, owner, clock)
+void device_a5200_cart_interface::interface_post_start()
{
+ m_slot->m_space_mem->install_device(0x0000, 0x7fff, *this, &device_a5200_cart_interface::cart_map);
}
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// ****_cart_slot_device - constructor
+//-------------------------------------------------
+
+a800_cart_slot_device::a800_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, A800_CART_SLOT, tag, owner, clock)
+ , device_memory_interface(mconfig, *this)
+ , device_cartrom_image_interface(mconfig, *this)
+ , device_single_card_slot_interface<device_a800_cart_interface>(mconfig, *this)
+ , m_cart(nullptr)
+ , m_rd4_cb(*this)
+ , m_rd5_cb(*this)
+ , m_space_mem_config("cart_mem", ENDIANNESS_LITTLE, 8, 14, 0, address_map_constructor())
+ , m_space_io_config("cart_io", ENDIANNESS_LITTLE, 8, 8, 0, address_map_constructor())
+ , m_is_xegs(false)
+{
+}
-xegs_cart_slot_device::xegs_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- a800_cart_slot_device(mconfig, XEGS_CART_SLOT, tag, owner, clock)
+a5200_cart_slot_device::a5200_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, A5200_CART_SLOT, tag, owner, clock)
+ , device_memory_interface(mconfig, *this)
+ , device_cartrom_image_interface(mconfig, *this)
+ , device_single_card_slot_interface<device_a5200_cart_interface>(mconfig, *this)
+ , m_cart(nullptr)
+ , m_space_mem_config("cart_mem", ENDIANNESS_LITTLE, 8, 15, 0, address_map_constructor())
{
}
@@ -140,10 +188,6 @@ a5200_cart_slot_device::~a5200_cart_slot_device()
{
}
-xegs_cart_slot_device::~xegs_cart_slot_device()
-{
-}
-
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
@@ -151,9 +195,15 @@ xegs_cart_slot_device::~xegs_cart_slot_device()
void a800_cart_slot_device::device_start()
{
m_cart = get_card_device();
+ m_space_io = &space(AS_IO);
+ m_space_mem = &space(AS_PROGRAM);
}
-
+void a5200_cart_slot_device::device_start()
+{
+ m_cart = get_card_device();
+ m_space_mem = &space(AS_PROGRAM);
+}
/*-------------------------------------------------
call load
@@ -179,25 +229,33 @@ static const a800_slot slot_list[] =
{ A800_OSSM091, "a800_ossm091" },
{ A800_OSS8K, "a800_oss8k" },
{ A800_PHOENIX, "a800_phoenix" },
+ { A800_BLIZZARD, "a800_blizzard" },
{ A800_XEGS, "xegs" },
{ A800_BBSB, "a800_bbsb" },
{ A800_DIAMOND, "a800_diamond" },
{ A800_WILLIAMS, "a800_williams" },
{ A800_EXPRESS, "a800_express" },
{ A800_SPARTADOS, "a800_sparta" },
- { A800_TURBO64, "a800_turbo64" },
- { A800_TURBO128, "a800_turbo128" },
+ { A800_SPARTADOS_128KB, "a800_sparta_128kb" },
+ { A800_TURBO, "a800_turbo" },
{ A800_BLIZZARD, "a800_blizzard" },
{ A800_TELELINK2, "a800_tlink2" },
- { A800_MICROCALC, "a800_sitsa" },
+ { A800_ULTRACART, "a800_ultracart" },
+ { A800_ATRAX, "a800_atrax" },
{ A800_CORINA, "a800_corina" },
+ { A800_CORINA_SRAM, "a800_corina_sram" },
+ { SIC_128KB, "sic_128kb" },
+ { SIC_256KB, "sic_256kb" },
+ { SIC_512KB, "sic_512kb" },
+ { ATARIMAX_MAXFLASH_128KB, "maxflash_128kb" },
+ { ATARIMAX_MAXFLASH_1MB, "maxflash_1mb" },
+ { A800_ADAWLIAH, "a800_adawliah" },
{ A800_8K_RIGHT, "a800_8k_right" },
- { A5200_4K, "a5200" },
- { A5200_8K, "a5200" },
- { A5200_16K, "a5200" },
- { A5200_32K, "a5200" },
+ { A5200_4K, "a5200_rom" },
+ { A5200_8K, "a5200_rom" },
+ { A5200_16K, "a5200_rom" },
+ { A5200_32K, "a5200_rom" },
{ A5200_16K_2CHIPS, "a5200_2chips" },
- { A5200_32K, "a5200" },
{ A5200_BBSB, "a5200_bbsb" }
};
@@ -224,7 +282,7 @@ static const char *a800_get_slot(int type)
return "a800_8k";
}
-image_init_result a800_cart_slot_device::call_load()
+std::pair<std::error_condition, std::string> a800_cart_slot_device::call_load()
{
if (m_cart)
{
@@ -235,7 +293,7 @@ image_init_result a800_cart_slot_device::call_load()
const char *pcb_name;
len = get_software_region_length("rom");
- m_cart->rom_alloc(len, tag());
+ m_cart->rom_alloc(len);
memcpy(m_cart->get_rom_base(), get_software_region("rom"), len);
if ((pcb_name = get_feature("slot")) != nullptr)
@@ -271,26 +329,80 @@ image_init_result a800_cart_slot_device::call_load()
m_type = A5200_16K_2CHIPS;
}
- m_cart->rom_alloc(len, tag());
+ m_cart->rom_alloc(len);
fread(m_cart->get_rom_base(), len);
}
- if (m_type == A800_TELELINK2)
- m_cart->nvram_alloc(0x100);
logerror("%s loaded cartridge '%s' size %dK\n", machine().system().name, filename(), len/1024);
}
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
+std::pair<std::error_condition, std::string> a5200_cart_slot_device::call_load()
+{
+ if (m_cart)
+ {
+ uint32_t len;
-/*-------------------------------------------------
- call_unload
- -------------------------------------------------*/
+ if (loaded_through_softlist())
+ {
+ const char *pcb_name;
+ len = get_software_region_length("rom");
+
+ m_cart->rom_alloc(len);
+ memcpy(m_cart->get_rom_base(), get_software_region("rom"), len);
+
+ if ((pcb_name = get_feature("slot")) != nullptr)
+ m_type = a800_get_pcb_id(pcb_name);
+ else
+ m_type = A800_8K;
+ }
+ else
+ {
+ len = length();
+
+ // check whether there is an header, to identify the cart type
+ if ((len % 0x1000) == 0x10)
+ {
+ uint8_t header[16];
+ fread(header, 0x10);
+ m_type = identify_cart_type(header);
+ len -= 0x10; // in identify_cart_type the first 0x10 bytes are read, so we need to adjust here
+ }
+ else // otherwise try to guess based on size
+ {
+ if (len == 0x8000)
+ m_type = A5200_32K;
+ if (len == 0x4000)
+ m_type = A800_16K;
+ if (len == 0x2000)
+ m_type = A800_8K;
+ if (len == 0x1000)
+ m_type = A5200_4K;
+ // also make a try with .hsi file (for .a52 files)
+ std::string info;
+ if (hashfile_extrainfo(*this, info) && info.compare("A13MIRRORING")==0)
+ m_type = A5200_16K_2CHIPS;
+ }
+
+ m_cart->rom_alloc(len);
+ fread(m_cart->get_rom_base(), len);
+ }
+
+ logerror("%s loaded cartridge '%s' size %dK\n", machine().system().name, filename(), len/1024);
+ }
+ return std::make_pair(std::error_condition(), std::string());
+}
void a800_cart_slot_device::call_unload()
{
}
+void a5200_cart_slot_device::call_unload()
+{
+}
+
+
/*-------------------------------------------------
identify_cart_type - code to detect cart type from
fullpath
@@ -300,11 +412,13 @@ int a800_cart_slot_device::identify_cart_type(const uint8_t *header) const
{
int type = A800_8K;
+ // TODO: canonically applies to .car extension only, have 10 bytes extra header on top
+
// check CART format
if (strncmp((const char *)header, "CART", 4))
fatalerror("Invalid header detected!\n");
- switch ((header[4] << 24) + (header[5] << 16) + (header[6] << 8) + (header[7] << 0))
+ switch (get_u32be(&header[4]))
{
case 1:
type = A800_8K;
@@ -333,6 +447,9 @@ int a800_cart_slot_device::identify_cart_type(const uint8_t *header) const
case 15:
type = A800_OSSM091;
break;
+ case 17:
+ type = A800_ATRAX;
+ break;
case 18:
type = A800_BBSB;
break;
@@ -345,19 +462,40 @@ int a800_cart_slot_device::identify_cart_type(const uint8_t *header) const
case 40:
type = A800_BLIZZARD;
break;
+ case 41:
+ type = ATARIMAX_MAXFLASH_128KB;
+ break;
+ case 42:
+ type = ATARIMAX_MAXFLASH_1MB;
+ break;
+ case 43:
+ type = A800_SPARTADOS_128KB;
+ break;
case 44:
type = A800_OSS8K;
break;
case 50:
- type = A800_TURBO64;
+ type = A800_TURBO;
break;
case 51:
- type = A800_TURBO128;
+ type = A800_TURBO;
break;
case 52:
- type = A800_MICROCALC;
+ type = A800_ULTRACART;
+ break;
+ case 54:
+ type = SIC_128KB;
+ break;
+ case 55:
+ type = SIC_256KB;
break;
- // Atari 5200 CART files
+ case 56:
+ type = SIC_512KB;
+ break;
+ case 69:
+ type = A800_ADAWLIAH;
+ break;
+ // Atari 5200 CART files
case 4:
type = A5200_32K;
break;
@@ -377,7 +515,121 @@ int a800_cart_slot_device::identify_cart_type(const uint8_t *header) const
type = A5200_BBSB;
break;
default:
- osd_printf_info("Cart type \"%d\" is currently unsupported.\n", (header[4] << 24) + (header[5] << 16) + (header[6] << 8) + (header[7] << 0));
+ osd_printf_info("Cart type \"%d\" is currently unsupported.\n", get_u32be(&header[4]));
+ break;
+ }
+
+ return type;
+}
+
+int a5200_cart_slot_device::identify_cart_type(const uint8_t *header) const
+{
+ int type = A800_8K;
+
+ // TODO: canonically applies to .car extension only, have 10 bytes extra header on top
+
+ // check CART format
+ if (strncmp((const char *)header, "CART", 4))
+ fatalerror("Invalid header detected!\n");
+
+ switch (get_u32be(&header[4]))
+ {
+ case 1:
+ type = A800_8K;
+ break;
+ case 2:
+ type = A800_16K;
+ break;
+ case 3:
+ type = A800_OSS034M;
+ break;
+ case 8:
+ type = A800_WILLIAMS;
+ break;
+ case 9:
+ type = A800_DIAMOND;
+ break;
+ case 10:
+ type = A800_EXPRESS;
+ break;
+ case 11:
+ type = A800_SPARTADOS;
+ break;
+ case 12:
+ type = A800_XEGS;
+ break;
+ case 15:
+ type = A800_OSSM091;
+ break;
+ case 17:
+ type = A800_ATRAX;
+ break;
+ case 18:
+ type = A800_BBSB;
+ break;
+ case 21:
+ type = A800_8K_RIGHT;
+ break;
+ case 39:
+ type = A800_PHOENIX;
+ break;
+ case 40:
+ type = A800_BLIZZARD;
+ break;
+ case 41:
+ type = ATARIMAX_MAXFLASH_128KB;
+ break;
+ case 42:
+ type = ATARIMAX_MAXFLASH_1MB;
+ break;
+ case 43:
+ type = A800_SPARTADOS_128KB;
+ break;
+ case 44:
+ type = A800_OSS8K;
+ break;
+ case 50:
+ type = A800_TURBO;
+ break;
+ case 51:
+ type = A800_TURBO;
+ break;
+ case 52:
+ type = A800_ULTRACART;
+ break;
+ case 54:
+ type = SIC_128KB;
+ break;
+ case 55:
+ type = SIC_256KB;
+ break;
+ case 56:
+ type = SIC_512KB;
+ break;
+ case 69:
+ type = A800_ADAWLIAH;
+ break;
+ // Atari 5200 CART files
+ case 4:
+ type = A5200_32K;
+ break;
+ case 16:
+ type = A5200_16K;
+ break;
+ case 19:
+ type = A5200_8K;
+ break;
+ case 20:
+ type = A5200_4K;
+ break;
+ case 6:
+ type = A5200_16K_2CHIPS;
+ break;
+ case 7:
+ type = A5200_BBSB;
+ break;
+ default:
+ osd_printf_info("Cart type \"%d\" is currently unsupported.\n", get_u32be(&header[4]));
break;
}
@@ -390,29 +642,42 @@ int a800_cart_slot_device::identify_cart_type(const uint8_t *header) const
std::string a800_cart_slot_device::get_default_card_software(get_default_card_software_hook &hook) const
{
+ // Nope, will crash when mounting the SDX subslot
+// std::string slot_default_option = default_option();
+ const bool is_xegs = m_is_xegs;
+
if (hook.image_file())
{
uint64_t len;
hook.image_file()->length(len); // FIXME: check error return
+ int type = is_xegs ? A800_XEGS : A800_8K;
// check whether there is an header, to identify the cart type
- int type = A800_8K;
if ((len % 0x1000) == 0x10)
{
- size_t actual;
uint8_t head[0x10];
- hook.image_file()->read(&head[0], 0x10, actual); // FIXME: check error return or read returning short
+ /*auto const [err, actual] =*/ read(*hook.image_file(), &head[0], 0x10); // FIXME: check error return or read returning short
type = identify_cart_type(&head[0]);
}
else // otherwise try to guess based on size
{
+ if (is_xegs)
+ return std::string("xegs");
+ // TODO: very incomplete, is it also worth it?
+ // Altirra sports a very complex scoring analysis (including code binary patterns),
+ // and it still grants to the user multiple options
if (len == 0x4000)
type = A800_16K;
if (len == 0x2000)
type = A800_8K;
}
- if (type >= A5200_4K)
+ if (is_xegs && type != A800_XEGS)
+ {
+ osd_printf_info("This game is not designed for XEGS.\n");
+ osd_printf_info("You might want to run it in %s.\n", type >= A5200_4K ? "A5200" : "A800");
+ }
+ else if (type >= A5200_4K)
osd_printf_info("This game is not designed for A800. You might want to run it in A5200.\n");
char const *const slot_string = a800_get_slot(type);
@@ -420,7 +685,7 @@ std::string a800_cart_slot_device::get_default_card_software(get_default_card_so
return std::string(slot_string);
}
- return software_get_default_slot("a800_8k");
+ return software_get_default_slot(is_xegs ? "xegs" : "a800_8k");
}
@@ -435,9 +700,8 @@ std::string a5200_cart_slot_device::get_default_card_software(get_default_card_s
int type = A5200_8K;
if ((len % 0x1000) == 0x10)
{
- size_t actual;
uint8_t head[0x10];
- hook.image_file()->read(&head[0], 0x10, actual); // FIXME: check error return or read returning short
+ /*auto const [err, actual] =*/ read(*hook.image_file(), &head[0], 0x10); // FIXME: check error return or read returning short
type = identify_cart_type(&head[0]);
}
else
@@ -454,77 +718,61 @@ std::string a5200_cart_slot_device::get_default_card_software(get_default_card_s
return std::string(slot_string);
}
- return software_get_default_slot("a5200");
+ return software_get_default_slot("a5200_rom");
}
-std::string xegs_cart_slot_device::get_default_card_software(get_default_card_software_hook &hook) const
-{
- if (hook.image_file())
- {
- uint64_t len;
- hook.image_file()->length(len); // FIXME: check error return
-
- // check whether there is an header, to identify the cart type
- int type = A800_8K;
- if ((len % 0x1000) == 0x10)
- {
- size_t actual;
- uint8_t head[0x10];
- hook.image_file()->read(&head[0], 0x10, actual); // FIXME: check error return or read returning short
- type = identify_cart_type(&head[0]);
- }
- if (type != A800_XEGS)
- {
- osd_printf_info("This game is not designed for XEGS. ");
- if (type >= A5200_4K)
- osd_printf_info("You might want to run it in A5200.\n");
- else
- osd_printf_info("You might want to run it in A800 or A800XL.\n");
- }
-
- char const *const slot_string = a800_get_slot(type);
+/*-------------------------------------------------
+ read
+ -------------------------------------------------*/
- return std::string(slot_string);
- }
+device_memory_interface::space_config_vector a800_cart_slot_device::memory_space_config() const
+{
+ return space_config_vector{
+ std::make_pair(AS_PROGRAM, &m_space_mem_config),
+ std::make_pair(AS_IO, &m_space_io_config)
+ };
+}
- return software_get_default_slot("xegs");
+template <unsigned Bank> uint8_t a800_cart_slot_device::read_cart(offs_t offset)
+{
+ return m_space_mem->read_byte(offset | Bank << 13);
}
+template <unsigned Bank> void a800_cart_slot_device::write_cart(offs_t offset, uint8_t data)
+{
+ return m_space_mem->write_byte(offset | Bank << 13, data);
+}
-/*-------------------------------------------------
- read
- -------------------------------------------------*/
+// Instantiate maps
+template uint8_t a800_cart_slot_device::read_cart<0>(offs_t offset);
+template uint8_t a800_cart_slot_device::read_cart<1>(offs_t offset);
+template void a800_cart_slot_device::write_cart<0>(offs_t offset, uint8_t data);
+template void a800_cart_slot_device::write_cart<1>(offs_t offset, uint8_t data);
-uint8_t a800_cart_slot_device::read_80xx(offs_t offset)
+uint8_t a800_cart_slot_device::read_cctl(offs_t offset)
{
- if (m_cart)
- return m_cart->read_80xx(offset);
- else
- return 0xff;
+ return m_space_io->read_byte(offset);
}
-uint8_t a800_cart_slot_device::read_d5xx(offs_t offset)
+void a800_cart_slot_device::write_cctl(offs_t offset, uint8_t data)
{
- if (m_cart)
- return m_cart->read_d5xx(offset);
- else
- return 0xff;
+ m_space_io->write_byte(offset, data);
}
+device_memory_interface::space_config_vector a5200_cart_slot_device::memory_space_config() const
+{
+ return space_config_vector{
+ std::make_pair(AS_PROGRAM, &m_space_mem_config)
+ };
+}
-/*-------------------------------------------------
- write
- -------------------------------------------------*/
-
-void a800_cart_slot_device::write_80xx(offs_t offset, uint8_t data)
+uint8_t a5200_cart_slot_device::read_cart(offs_t offset)
{
- if (m_cart)
- m_cart->write_80xx(offset, data);
+ return m_space_mem->read_byte(offset);
}
-void a800_cart_slot_device::write_d5xx(offs_t offset, uint8_t data)
+void a5200_cart_slot_device::write_cart(offs_t offset, uint8_t data)
{
- if (m_cart)
- m_cart->write_d5xx(offset, data);
+ return m_space_mem->write_byte(offset, data);
}
diff --git a/src/devices/bus/a800/a800_slot.h b/src/devices/bus/a800/a800_slot.h
index 233fa922583..476a54a4f4d 100644
--- a/src/devices/bus/a800/a800_slot.h
+++ b/src/devices/bus/a800/a800_slot.h
@@ -1,5 +1,5 @@
// license:BSD-3-Clause
-// copyright-holders:Fabio Priuli
+// copyright-holders:Fabio Priuli, Angelo Salese
#ifndef MAME_BUS_A800_A800_SLOT_H
#define MAME_BUS_A800_A800_SLOT_H
@@ -12,9 +12,8 @@
TYPE DEFINITIONS
***************************************************************************/
-#define A800SLOT_ROM_REGION_TAG ":cart:rom"
-
/* PCB */
+// TODO: make this enum to actually follow up the .car specs, not the other way around
enum
{
A800_8K = 0,
@@ -25,18 +24,26 @@ enum
A800_OSSM091,
A800_OSS8K,
A800_PHOENIX,
+ A800_BLIZZARD,
A800_XEGS,
A800_BBSB,
A800_DIAMOND,
A800_WILLIAMS,
A800_EXPRESS,
A800_SPARTADOS,
- A800_BLIZZARD,
- A800_TURBO64,
- A800_TURBO128,
+ A800_SPARTADOS_128KB,
+ A800_TURBO,
A800_TELELINK2,
- A800_MICROCALC,
+ A800_ULTRACART,
+ A800_ADAWLIAH,
+ A800_ATRAX,
A800_CORINA,
+ A800_CORINA_SRAM,
+ ATARIMAX_MAXFLASH_128KB,
+ ATARIMAX_MAXFLASH_1MB,
+ SIC_128KB,
+ SIC_256KB,
+ SIC_512KB,
A5200_4K,
A5200_8K,
A5200_16K,
@@ -45,8 +52,7 @@ enum
A5200_BBSB
};
-
-// ======================> device_a800_cart_interface
+class a800_cart_slot_device;
class device_a800_cart_interface : public device_interface
{
@@ -54,41 +60,49 @@ public:
// construction/destruction
virtual ~device_a800_cart_interface();
- // memory accessor
- virtual uint8_t read_80xx(offs_t offset) { return 0xff; }
- virtual uint8_t read_d5xx(offs_t offset) { return 0xff; }
- virtual void write_80xx(offs_t offset, uint8_t data) {}
- virtual void write_d5xx(offs_t offset, uint8_t data) {}
+ virtual void cart_map(address_map &map);
+ virtual void cctl_map(address_map &map);
- void rom_alloc(uint32_t size, const char *tag);
- void ram_alloc(uint32_t size);
- void nvram_alloc(uint32_t size);
+ // TODO: remove all of this
+ void rom_alloc(uint32_t size);
uint8_t* get_rom_base() { return m_rom; }
- uint8_t* get_ram_base() { return &m_ram[0]; }
- uint8_t* get_nvram_base() { return &m_nvram[0]; }
uint32_t get_rom_size() { return m_rom_size; }
- uint32_t get_ram_size() { return m_ram.size(); }
- uint32_t get_nvram_size() { return m_nvram.size(); }
+
+ ///
+ /// Carts can either init RD4/RD5 at startup or not, depending on if they have
+ /// reset circuitry or not. Future expansion of this getter will return a third value,
+ /// giving back the timing value where the initialization should happen.
+ ///
+ /// \return RD4, RD5 initial state
+ virtual std::tuple<int, int> get_initial_rd_state() { return std::make_tuple(0, 0); }
protected:
device_a800_cart_interface(const machine_config &mconfig, device_t &device);
+ virtual void interface_pre_start() override;
+ virtual void interface_post_start() override;
+ a800_cart_slot_device *m_slot;
+
// internal state
uint8_t *m_rom;
uint32_t m_rom_size;
- std::vector<uint8_t> m_ram;
- std::vector<uint8_t> m_nvram; // HiScore cart can save scores!
// helpers
int m_bank_mask;
+
+ void rd4_w( int state );
+ void rd5_w( int state );
+ void rd_both_w ( int state );
};
// ======================> a800_cart_slot_device
class a800_cart_slot_device : public device_t,
+ public device_memory_interface,
public device_cartrom_image_interface,
public device_single_card_slot_interface<device_a800_cart_interface>
{
+ friend class device_a800_cart_interface;
public:
// construction/destruction
template <typename T>
@@ -103,46 +117,86 @@ public:
a800_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
virtual ~a800_cart_slot_device();
- // image-level overrides
- virtual image_init_result call_load() override;
- virtual void call_unload() override;
-
virtual bool is_reset_on_load() const noexcept override { return true; }
virtual const char *image_interface() const noexcept override { return "a8bit_cart"; }
virtual const char *file_extensions() const noexcept override { return "bin,rom,car"; }
// slot interface overrides
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
-
- int get_cart_type() { return m_type; }
int identify_cart_type(const uint8_t *header) const;
+ virtual std::pair<std::error_condition, std::string> call_load() override;
+ virtual void call_unload() override;
+
bool has_cart() { return m_cart != nullptr; }
+ auto rd4_callback() { return m_rd4_cb.bind(); }
+ auto rd5_callback() { return m_rd5_cb.bind(); }
+ void set_is_xegs(bool is_xegs) { m_is_xegs = is_xegs; }
- // reading and writing
- uint8_t read_80xx(offs_t offset);
- uint8_t read_d5xx(offs_t offset);
- void write_80xx(offs_t offset, uint8_t data);
- void write_d5xx(offs_t offset, uint8_t data);
+ template <unsigned Bank> uint8_t read_cart(offs_t offset);
+ template <unsigned Bank> void write_cart(offs_t offset, uint8_t data);
+ uint8_t read_cctl(offs_t offset);
+ void write_cctl(offs_t offset, uint8_t data);
+ auto get_initial_rd_state() { return m_cart->get_initial_rd_state(); }
protected:
- a800_cart_slot_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+ //a800_cart_slot_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
+ virtual space_config_vector memory_space_config() const override;
private:
device_a800_cart_interface* m_cart;
- int m_type;
+
+ devcb_write_line m_rd4_cb;
+ devcb_write_line m_rd5_cb;
+
+ address_space_config m_space_mem_config;
+ address_space_config m_space_io_config;
+
+ address_space *m_space_mem;
+ address_space *m_space_io;
+
+ int m_type = 0;
+ bool m_is_xegs = false;
};
+class a5200_cart_slot_device;
+
+class device_a5200_cart_interface : public device_interface
+{
+public:
+ // construction/destruction
+ virtual ~device_a5200_cart_interface();
+
+ virtual void cart_map(address_map &map);
-// The variants below are added to handle the additional formats for a5200, and to give more
-// clear error messages if you try to load an A5200 game into an A800 or a XEGS, etc.
+ // TODO: remove all of this
+ void rom_alloc(uint32_t size);
+ uint8_t* get_rom_base() { return m_rom; }
+ uint32_t get_rom_size() { return m_rom_size; }
+
+protected:
+ device_a5200_cart_interface(const machine_config &mconfig, device_t &device);
-// ======================> a5200_cart_slot_device
+ virtual void interface_pre_start() override;
+ virtual void interface_post_start() override;
+ a5200_cart_slot_device *m_slot;
-class a5200_cart_slot_device : public a800_cart_slot_device
+ // internal state
+ uint8_t *m_rom;
+ uint32_t m_rom_size;
+ // helpers
+ int m_bank_mask;
+};
+
+
+class a5200_cart_slot_device : public device_t,
+ public device_memory_interface,
+ public device_cartrom_image_interface,
+ public device_single_card_slot_interface<device_a5200_cart_interface>
{
+ friend class device_a5200_cart_interface;
public:
// construction/destruction
template <typename T>
@@ -157,39 +211,33 @@ public:
a5200_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual ~a5200_cart_slot_device();
+ virtual bool is_reset_on_load() const noexcept override { return true; }
+ virtual const char *image_interface() const noexcept override { return "a8bit_cart"; }
virtual const char *file_extensions() const noexcept override { return "bin,rom,car,a52"; }
// slot interface overrides
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
-};
+ int identify_cart_type(const uint8_t *header) const;
+ virtual std::pair<std::error_condition, std::string> call_load() override;
+ virtual void call_unload() override;
-// ======================> xegs_cart_slot_device
+ u8 read_cart(offs_t offset);
+ void write_cart(offs_t offset, u8 data);
-class xegs_cart_slot_device : public a800_cart_slot_device
-{
-public:
- // construction/destruction
- template <typename T>
- xegs_cart_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts, char const *dflt)
- : xegs_cart_slot_device(mconfig, tag, owner, (uint32_t)0)
- {
- option_reset();
- opts(*this);
- set_default_option(dflt);
- set_fixed(false);
- }
- xegs_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual ~xegs_cart_slot_device();
+protected:
+ virtual void device_start() override;
+ virtual space_config_vector memory_space_config() const override;
- virtual const char *file_extensions() const noexcept override { return "bin,rom,car"; }
+private:
+ device_a5200_cart_interface* m_cart;
+ address_space_config m_space_mem_config;
- // slot interface overrides
- virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
+ address_space *m_space_mem;
+ int m_type;
};
// device type definition
DECLARE_DEVICE_TYPE(A800_CART_SLOT, a800_cart_slot_device)
DECLARE_DEVICE_TYPE(A5200_CART_SLOT, a5200_cart_slot_device)
-DECLARE_DEVICE_TYPE(XEGS_CART_SLOT, xegs_cart_slot_device)
#endif // MAME_BUS_A800_A800_SLOT_H
diff --git a/src/devices/bus/a800/a8sio.cpp b/src/devices/bus/a800/a8sio.cpp
index 41fb3f863e5..c7e134a4e46 100644
--- a/src/devices/bus/a800/a8sio.cpp
+++ b/src/devices/bus/a800/a8sio.cpp
@@ -41,7 +41,7 @@
// GLOBAL VARIABLES
//**************************************************************************
-DEFINE_DEVICE_TYPE(A8SIO, a8sio_device, "a8sio", "Atari 8 bit SIO Slot")
+DEFINE_DEVICE_TYPE(A8SIO, a8sio_device, "a8sio", "Atari 8-bit SIO Slot")
//**************************************************************************
// LIVE DEVICE
@@ -74,13 +74,6 @@ void a8sio_device::device_resolve_objects()
m_device = get_card_device();
if (m_device)
m_device->set_a8sio_device(this);
-
- // resolve callbacks
- m_out_clock_in_cb.resolve_safe();
- m_out_data_in_cb.resolve_safe();
- m_out_proceed_cb.resolve_safe();
- m_out_audio_in_cb.resolve_safe();
- m_out_interrupt_cb.resolve_safe();
}
//-------------------------------------------------
@@ -104,41 +97,41 @@ device_a8sio_card_interface *a8sio_device::get_a8sio_card()
return m_device;
}
-WRITE_LINE_MEMBER( a8sio_device::clock_in_w )
+void a8sio_device::clock_in_w(int state)
{
m_out_clock_in_cb(state);
}
-WRITE_LINE_MEMBER( a8sio_device::clock_out_w )
+void a8sio_device::clock_out_w(int state)
{
if (m_device)
m_device->clock_out_w(state);
}
-WRITE_LINE_MEMBER( a8sio_device::data_in_w )
+void a8sio_device::data_in_w(int state)
{
m_out_data_in_cb(state);
}
-WRITE_LINE_MEMBER( a8sio_device::data_out_w )
+void a8sio_device::data_out_w(int state)
{
if (m_device)
m_device->data_out_w(state);
}
-WRITE_LINE_MEMBER( a8sio_device::command_w )
+void a8sio_device::command_w(int state)
{
if (m_device)
m_device->command_w(state);
}
-WRITE_LINE_MEMBER( a8sio_device::motor_w )
+void a8sio_device::motor_w(int state)
{
if (m_device)
m_device->motor_w(state);
}
-WRITE_LINE_MEMBER( a8sio_device::proceed_w )
+void a8sio_device::proceed_w(int state)
{
m_out_proceed_cb(state);
}
@@ -148,7 +141,7 @@ void a8sio_device::audio_in_w(uint8_t data)
m_out_audio_in_cb(data);
}
-WRITE_LINE_MEMBER( a8sio_device::interrupt_w )
+void a8sio_device::interrupt_w(int state)
{
m_out_interrupt_cb(state);
}
@@ -182,24 +175,24 @@ void device_a8sio_card_interface::set_a8sio_device(a8sio_device *sio)
m_a8sio = sio;
}
-WRITE_LINE_MEMBER( device_a8sio_card_interface::clock_out_w )
+void device_a8sio_card_interface::clock_out_w(int state)
{
}
-WRITE_LINE_MEMBER( device_a8sio_card_interface::data_out_w )
+void device_a8sio_card_interface::data_out_w(int state)
{
}
-WRITE_LINE_MEMBER( device_a8sio_card_interface::command_w )
+void device_a8sio_card_interface::command_w(int state)
{
}
-WRITE_LINE_MEMBER( device_a8sio_card_interface::motor_w )
+void device_a8sio_card_interface::motor_w(int state)
{
//printf("device_a8sio_card_interface::motor_w %d\n", state);
}
-WRITE_LINE_MEMBER( device_a8sio_card_interface::ready_w )
+void device_a8sio_card_interface::ready_w(int state)
{
}
diff --git a/src/devices/bus/a800/a8sio.h b/src/devices/bus/a800/a8sio.h
index 643dffe19a5..dfc04577466 100644
--- a/src/devices/bus/a800/a8sio.h
+++ b/src/devices/bus/a800/a8sio.h
@@ -62,15 +62,15 @@ public:
device_a8sio_card_interface *get_a8sio_card();
- DECLARE_WRITE_LINE_MEMBER( clock_in_w ); // pin 1
- DECLARE_WRITE_LINE_MEMBER( clock_out_w ); // pin 2
- DECLARE_WRITE_LINE_MEMBER( data_in_w ); // pin 3
- DECLARE_WRITE_LINE_MEMBER( data_out_w ); // pin 5
- DECLARE_WRITE_LINE_MEMBER( command_w ); // pin 7
- DECLARE_WRITE_LINE_MEMBER( motor_w ); // pin 8
- DECLARE_WRITE_LINE_MEMBER( proceed_w ); // pin 9
- void audio_in_w(uint8_t data); // pin 11
- DECLARE_WRITE_LINE_MEMBER( interrupt_w ); // pin 13
+ void clock_in_w(int state); // pin 1
+ void clock_out_w(int state); // pin 2
+ void data_in_w(int state); // pin 3
+ void data_out_w(int state); // pin 5
+ void command_w(int state); // pin 7
+ void motor_w(int state); // pin 8
+ void proceed_w(int state); // pin 9
+ void audio_in_w(uint8_t data); // pin 11
+ void interrupt_w(int state); // pin 13
protected:
a8sio_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
@@ -102,11 +102,11 @@ public:
void set_a8sio_device(a8sio_device *sio);
- virtual DECLARE_WRITE_LINE_MEMBER( clock_out_w );
- virtual DECLARE_WRITE_LINE_MEMBER( data_out_w );
- virtual DECLARE_WRITE_LINE_MEMBER( command_w );
- virtual DECLARE_WRITE_LINE_MEMBER( motor_w );
- virtual DECLARE_WRITE_LINE_MEMBER( ready_w );
+ virtual void clock_out_w(int state);
+ virtual void data_out_w(int state);
+ virtual void command_w(int state);
+ virtual void motor_w(int state);
+ virtual void ready_w(int state);
public:
device_a8sio_card_interface(const machine_config &mconfig, device_t &device);
diff --git a/src/devices/bus/a800/atari1050.cpp b/src/devices/bus/a800/atari1050.cpp
index 12191d4cc72..dec666b0b6b 100644
--- a/src/devices/bus/a800/atari1050.cpp
+++ b/src/devices/bus/a800/atari1050.cpp
@@ -45,26 +45,26 @@ void atari1050_device::step_w(u8 data)
void atari1050_device::mem_map(address_map &map)
{
map(0x0000, 0x007f).mirror(0x0900).ram(); // MCM6810
- map(0x0080, 0x00ff).mirror(0x0900).m(m_pia, FUNC(mos6532_new_device::ram_map));
- map(0x0280, 0x029f).mirror(0x0960).m(m_pia, FUNC(mos6532_new_device::io_map));
+ map(0x0080, 0x00ff).mirror(0x0900).m(m_pia, FUNC(mos6532_device::ram_map));
+ map(0x0280, 0x029f).mirror(0x0960).m(m_pia, FUNC(mos6532_device::io_map));
map(0x0400, 0x0403).mirror(0x0bfc).rw(m_fdc, FUNC(wd2793_device::read), FUNC(wd2793_device::write));
map(0x1000, 0x1fff).rom().region("rom", 0);
}
-WRITE_LINE_MEMBER(atari1050_device::data_out_w)
+void atari1050_device::data_out_w(int state)
{
- m_pia->pb6_w(state);
+ m_pia->pb_bit_w<6>(state);
}
-WRITE_LINE_MEMBER(atari1050_device::command_w)
+void atari1050_device::command_w(int state)
{
- m_pia->pb7_w(state);
+ m_pia->pb_bit_w<7>(state);
}
-WRITE_LINE_MEMBER(atari1050_device::ready_w)
+void atari1050_device::ready_w(int state)
{
- m_pia->pb1_w(state);
+ m_pia->pb_bit_w<1>(state);
}
@@ -88,17 +88,17 @@ void atari1050_device::device_add_mconfig(machine_config &config)
m6507_device &fdcpu(M6507(config, "fdcpu", 4_MHz_XTAL / 4));
fdcpu.set_addrmap(AS_PROGRAM, &atari1050_device::mem_map);
- MOS6532_NEW(config, m_pia, 4_MHz_XTAL / 4);
+ MOS6532(config, m_pia, 4_MHz_XTAL / 4);
m_pia->pa_rd_callback().set_ioport("SELECT");
m_pia->pa_wr_callback().set(m_fdc, FUNC(wd2793_device::dden_w)).bit(3);
//m_pia->pa_wr_callback().append(atari1050_device::motor_control_w)).bit(1);
m_pia->pb_wr_callback().set(FUNC(atari1050_device::step_w));
- m_pia->irq_wr_callback().set(m_pia, FUNC(mos6532_new_device::pa6_w)).invert();
+ m_pia->irq_wr_callback().set(m_pia, FUNC(mos6532_device::pa_bit_w<6>)).invert();
//m_pia->irq_wr_callback().append(m_fdc, FUNC(wd2793_device::ip_w));
WD2793(config, m_fdc, 4_MHz_XTAL / 4);
- m_fdc->drq_wr_callback().set(m_pia, FUNC(mos6532_new_device::pa7_w));
- m_fdc->enp_wr_callback().set(m_pia, FUNC(mos6532_new_device::pa4_w));
+ m_fdc->drq_wr_callback().set(m_pia, FUNC(mos6532_device::pa_bit_w<7>));
+ m_fdc->enp_wr_callback().set(m_pia, FUNC(mos6532_device::pa_bit_w<4>));
}
diff --git a/src/devices/bus/a800/atari1050.h b/src/devices/bus/a800/atari1050.h
index 48e32b86430..5c2c1243b7b 100644
--- a/src/devices/bus/a800/atari1050.h
+++ b/src/devices/bus/a800/atari1050.h
@@ -12,7 +12,7 @@
#pragma once
#include "a8sio.h"
-#include "machine/mos6530n.h"
+#include "machine/mos6530.h"
#include "machine/wd_fdc.h"
@@ -29,20 +29,19 @@ protected:
virtual void device_add_mconfig(machine_config &config) override;
virtual const tiny_rom_entry *device_rom_region() const override;
- virtual DECLARE_WRITE_LINE_MEMBER(data_out_w) override;
- virtual DECLARE_WRITE_LINE_MEMBER(command_w) override;
- virtual DECLARE_WRITE_LINE_MEMBER(ready_w) override;
+ virtual void data_out_w(int state) override;
+ virtual void command_w(int state) override;
+ virtual void ready_w(int state) override;
private:
void step_w(u8 data);
void mem_map(address_map &map);
- required_device<mos6532_new_device> m_pia;
+ required_device<mos6532_device> m_pia;
required_device<wd2793_device> m_fdc;
};
-// device type declaration
DECLARE_DEVICE_TYPE(ATARI1050, atari1050_device)
#endif // MAME_BUS_A800_ATARI1050
diff --git a/src/devices/bus/a800/atari810.cpp b/src/devices/bus/a800/atari810.cpp
index 69b5bd09d2f..62118335376 100644
--- a/src/devices/bus/a800/atari810.cpp
+++ b/src/devices/bus/a800/atari810.cpp
@@ -44,25 +44,25 @@ void atari810_device::mem_map(address_map &map)
{
map(0x0000, 0x0003).mirror(0x167c).rw(m_fdc, FUNC(fd1771_device::read), FUNC(fd1771_device::write));
map(0x0080, 0x00ff).mirror(0x1400).ram(); // MCM6810
- map(0x0100, 0x017f).mirror(0x1480).m(m_pia, FUNC(mos6532_new_device::ram_map));
- map(0x0300, 0x031f).mirror(0x14e0).m(m_pia, FUNC(mos6532_new_device::io_map));
+ map(0x0100, 0x017f).mirror(0x1480).m(m_pia, FUNC(mos6532_device::ram_map));
+ map(0x0300, 0x031f).mirror(0x14e0).m(m_pia, FUNC(mos6532_device::io_map));
map(0x0800, 0x0fff).mirror(0x1000).rom().region("rom", 0);
}
-WRITE_LINE_MEMBER(atari810_device::data_out_w)
+void atari810_device::data_out_w(int state)
{
- m_pia->pb7_w(state);
+ m_pia->pb_bit_w<7>(state);
}
-WRITE_LINE_MEMBER(atari810_device::command_w)
+void atari810_device::command_w(int state)
{
- m_pia->pb6_w(state);
+ m_pia->pb_bit_w<6>(state);
}
-WRITE_LINE_MEMBER(atari810_device::ready_w)
+void atari810_device::ready_w(int state)
{
- m_pia->pb1_w(state);
+ m_pia->pb_bit_w<1>(state);
}
@@ -86,14 +86,14 @@ void atari810_device::device_add_mconfig(machine_config &config)
m6507_device &fdcpu(M6507(config, "fdcpu", 1_MHz_XTAL / 2));
fdcpu.set_addrmap(AS_PROGRAM, &atari810_device::mem_map);
- MOS6532_NEW(config, m_pia, 1_MHz_XTAL / 2);
+ MOS6532(config, m_pia, 1_MHz_XTAL / 2);
m_pia->pa_rd_callback().set_ioport("SELECT");
m_pia->pb_wr_callback().set(FUNC(atari810_device::step_w));
//m_pia->irq_wr_callback().set(m_fdc, FUNC(fd1771_device::ip_w));
FD1771(config, m_fdc, 1_MHz_XTAL);
- m_fdc->drq_wr_callback().set(m_pia, FUNC(mos6532_new_device::pa7_w));
- m_fdc->intrq_wr_callback().set(m_pia, FUNC(mos6532_new_device::pa6_w));
+ m_fdc->drq_wr_callback().set(m_pia, FUNC(mos6532_device::pa_bit_w<7>));
+ m_fdc->intrq_wr_callback().set(m_pia, FUNC(mos6532_device::pa_bit_w<6>));
}
diff --git a/src/devices/bus/a800/atari810.h b/src/devices/bus/a800/atari810.h
index 1bbe8db0f8c..3406c14fdf0 100644
--- a/src/devices/bus/a800/atari810.h
+++ b/src/devices/bus/a800/atari810.h
@@ -12,7 +12,7 @@
#pragma once
#include "a8sio.h"
-#include "machine/mos6530n.h"
+#include "machine/mos6530.h"
#include "machine/wd_fdc.h"
@@ -29,20 +29,19 @@ protected:
virtual void device_add_mconfig(machine_config &config) override;
virtual const tiny_rom_entry *device_rom_region() const override;
- virtual DECLARE_WRITE_LINE_MEMBER(data_out_w) override;
- virtual DECLARE_WRITE_LINE_MEMBER(command_w) override;
- virtual DECLARE_WRITE_LINE_MEMBER(ready_w) override;
+ virtual void data_out_w(int state) override;
+ virtual void command_w(int state) override;
+ virtual void ready_w(int state) override;
private:
void step_w(u8 data);
void mem_map(address_map &map);
- required_device<mos6532_new_device> m_pia;
+ required_device<mos6532_device> m_pia;
required_device<fd1771_device> m_fdc;
};
-// device type declaration
DECLARE_DEVICE_TYPE(ATARI810, atari810_device)
#endif // MAME_BUS_A800_ATARI810
diff --git a/src/devices/bus/a800/atrax.cpp b/src/devices/bus/a800/atrax.cpp
new file mode 100644
index 00000000000..bdf815c8074
--- /dev/null
+++ b/src/devices/bus/a800/atrax.cpp
@@ -0,0 +1,54 @@
+// license: BSD-3-Clause
+// copyright-holders: Angelo Salese
+/**************************************************************************************************
+
+Atrax 128KB cart ROM
+
+Not to be confused with the Sparta DOS X variants, this one is just a standalone cart with
+single CCTL register that covers RD5 and bank.
+
+**************************************************************************************************/
+
+#include "emu.h"
+#include "atrax.h"
+
+DEFINE_DEVICE_TYPE(A800_ROM_ATRAX, a800_rom_atrax_device, "a800_atrax", "Atari 8-bit Atrax 128KB cart")
+
+
+a800_rom_atrax_device::a800_rom_atrax_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : a800_rom_device(mconfig, A800_ROM_ATRAX, tag, owner, clock)
+ , m_bank(0)
+{
+}
+
+void a800_rom_atrax_device::device_start()
+{
+ save_item(NAME(m_bank));
+}
+
+void a800_rom_atrax_device::device_reset()
+{
+ m_bank = 0;
+}
+
+void a800_rom_atrax_device::cart_map(address_map &map)
+{
+ map(0x2000, 0x3fff).lr8(
+ NAME([this](offs_t offset) { return m_rom[(offset & 0x1fff) + (m_bank * 0x2000)]; })
+ );
+}
+
+void a800_rom_atrax_device::cctl_map(address_map &map)
+{
+ map(0x00, 0xff).w(FUNC(a800_rom_atrax_device::config_bank_w));
+}
+
+/*
+ * x--- ---- RD5 disabled (1) enabled (0)
+ * ---- xxxx bank number
+ */
+void a800_rom_atrax_device::config_bank_w(offs_t offset, u8 data)
+{
+ rd5_w(!BIT(data, 7));
+ m_bank = data & 0xf;
+}
diff --git a/src/devices/bus/a800/atrax.h b/src/devices/bus/a800/atrax.h
new file mode 100644
index 00000000000..943d4587452
--- /dev/null
+++ b/src/devices/bus/a800/atrax.h
@@ -0,0 +1,34 @@
+// license: BSD-3-Clause
+// copyright-holders: Angelo Salese
+
+#ifndef MAME_BUS_A800_ATRAX_H
+#define MAME_BUS_A800_ATRAX_H
+
+#pragma once
+
+#include "rom.h"
+
+
+class a800_rom_atrax_device : public a800_rom_device
+{
+public:
+ a800_rom_atrax_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void cart_map(address_map &map) override;
+ virtual void cctl_map(address_map &map) override;
+ virtual std::tuple<int, int> get_initial_rd_state() override { return std::make_tuple(0, 1); }
+
+protected:
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ void config_bank_w(offs_t offset, u8 data);
+
+private:
+ int m_bank;
+};
+
+
+DECLARE_DEVICE_TYPE(A800_ROM_ATRAX, a800_rom_atrax_device)
+
+#endif // MAME_BUS_A800_ATRAX_H
diff --git a/src/devices/bus/a800/bbsb.cpp b/src/devices/bus/a800/bbsb.cpp
new file mode 100644
index 00000000000..bd57367bca3
--- /dev/null
+++ b/src/devices/bus/a800/bbsb.cpp
@@ -0,0 +1,136 @@
+// license: BSD-3-Clause
+// copyright-holders: Fabio Priuli, Angelo Salese
+/**************************************************************************************************
+
+A800/A5200 Bounty Bob Strikes Back ROM schemes
+
+Dual banking overlay access mapped in cart_map rd4 space at $xff6-$xff9,
+A12 select bank window, bank bases are different.
+rd5 just points to the last bank.
+
+A5200 BBSB is mostly similar to the A800 version but with shuffled around data banks
+i.e. fixed bank is actually the first one, and the overlay banks comes afterwards in the ROM space.
+
+TODO:
+- It's unknown if rd4 and rd5 can even be disabled from software (probably not);
+
+**************************************************************************************************/
+
+#include "emu.h"
+#include "bbsb.h"
+
+DEFINE_DEVICE_TYPE(A800_ROM_BBSB, a800_rom_bbsb_device, "a800_bbsb", "Atari 8-bit Bounty Bob Strikes Back cart")
+DEFINE_DEVICE_TYPE(A5200_ROM_BBSB, a5200_rom_bbsb_device, "a5200_bbsb", "Atari 5200 ROM Bounty Bob Strikes Back cart")
+
+
+a800_rom_bbsb_device::a800_rom_bbsb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : a800_rom_device(mconfig, A800_ROM_BBSB, tag, owner, clock)
+{
+}
+
+
+void a800_rom_bbsb_device::device_start()
+{
+ // TODO: m_banks should be an extra interface for a5200
+ save_item(NAME(m_banks));
+}
+
+void a800_rom_bbsb_device::device_reset()
+{
+ m_banks[0] = 0;
+ m_banks[1] = 0;
+}
+
+template <unsigned BankNum> u8 a800_rom_bbsb_device::read_bank(offs_t offset)
+{
+ return m_rom[(offset & 0xfff) + (m_banks[BankNum] * 0x1000) + (BankNum * 0x4000)];
+}
+
+void a800_rom_bbsb_device::cart_map(address_map &map)
+{
+ map(0x0000, 0x0fff).r(FUNC(a800_rom_bbsb_device::read_bank<0>));
+ map(0x1000, 0x1fff).r(FUNC(a800_rom_bbsb_device::read_bank<1>));
+ map(0x0ff6, 0x0ff9).select(0x1000).rw(FUNC(a800_rom_bbsb_device::bank_r), FUNC(a800_rom_bbsb_device::bank_w));
+
+ map(0x2000, 0x3fff).lr8(
+ NAME([this](offs_t offset) { return m_rom[(offset & 0x1fff) + 0x8000]; } )
+ );
+}
+
+uint8_t a800_rom_bbsb_device::bank_r(offs_t offset)
+{
+ const u8 bank_window = (offset & ~3) != 0;
+ const u8 bank_num = offset & 3;
+ if (!machine().side_effects_disabled())
+ m_banks[bank_window] = bank_num;
+
+ // TODO: unconfirmed, all $xff6-$xff9 just points to 0xff values
+ // Real cart overlay may return floating bus or the contents of the previous bank instead,
+ // needs to be tested by trying to execute code from there.
+ return 0xff;
+}
+
+void a800_rom_bbsb_device::bank_w(offs_t offset, uint8_t data)
+{
+ const u8 bank_window = (offset & ~3) != 0;
+ const u8 bank_num = offset & 3;
+ m_banks[bank_window] = bank_num;
+}
+
+/*-------------------------------------------------
+
+ A5200 Bounty Bob Strikes Back! cart
+
+ -------------------------------------------------*/
+
+a5200_rom_bbsb_device::a5200_rom_bbsb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : a5200_rom_device(mconfig, A5200_ROM_BBSB, tag, owner, clock)
+{
+}
+
+void a5200_rom_bbsb_device::device_start()
+{
+ save_item(NAME(m_banks));
+}
+
+void a5200_rom_bbsb_device::device_reset()
+{
+ m_banks[0] = 0;
+ m_banks[1] = 0;
+}
+
+template <unsigned BankNum> u8 a5200_rom_bbsb_device::read_bank(offs_t offset)
+{
+ return m_rom[(offset & 0xfff) + (m_banks[BankNum] * 0x1000) + (BankNum ? 0x6000 : 0x2000)];
+}
+
+void a5200_rom_bbsb_device::cart_map(address_map &map)
+{
+ map(0x0000, 0x0fff).r(FUNC(a5200_rom_bbsb_device::read_bank<0>));
+ map(0x1000, 0x1fff).r(FUNC(a5200_rom_bbsb_device::read_bank<1>));
+ map(0x0ff6, 0x0ff9).select(0x1000).rw(FUNC(a5200_rom_bbsb_device::bank_r), FUNC(a5200_rom_bbsb_device::bank_w));
+
+ map(0x4000, 0x7fff).lr8(
+ NAME([this](offs_t offset) { return m_rom[offset & 0x1fff]; } )
+ );
+}
+
+uint8_t a5200_rom_bbsb_device::bank_r(offs_t offset)
+{
+ const u8 bank_window = (offset & ~3) != 0;
+ const u8 bank_num = offset & 3;
+ if (!machine().side_effects_disabled())
+ m_banks[bank_window] = bank_num;
+
+ // TODO: unconfirmed, all $xff6-$xff9 just points to 0xff values
+ // Real cart overlay may return floating bus or the contents of the previous bank instead,
+ // needs to be tested by trying to execute code from there.
+ return 0xff;
+}
+
+void a5200_rom_bbsb_device::bank_w(offs_t offset, uint8_t data)
+{
+ const u8 bank_window = (offset & ~3) != 0;
+ const u8 bank_num = offset & 3;
+ m_banks[bank_window] = bank_num;
+}
diff --git a/src/devices/bus/a800/bbsb.h b/src/devices/bus/a800/bbsb.h
new file mode 100644
index 00000000000..c96a1a70420
--- /dev/null
+++ b/src/devices/bus/a800/bbsb.h
@@ -0,0 +1,52 @@
+// license: BSD-3-Clause
+// copyright-holders: Fabio Priuli, Angelo Salese
+
+#ifndef MAME_BUS_A800_BBSB_H
+#define MAME_BUS_A800_BBSB_H
+
+#pragma once
+
+#include "rom.h"
+
+
+class a800_rom_bbsb_device : public a800_rom_device
+{
+public:
+ a800_rom_bbsb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void cart_map(address_map &map) override;
+ virtual std::tuple<int, int> get_initial_rd_state() override { return std::make_tuple(1, 1); }
+
+protected:
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ int m_banks[2];
+
+ template <unsigned BankNum> u8 read_bank(offs_t offset);
+ u8 bank_r(offs_t offset);
+ void bank_w(offs_t offset, u8 data);
+};
+
+class a5200_rom_bbsb_device : public a5200_rom_device
+{
+public:
+ a5200_rom_bbsb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void cart_map(address_map &map) override;
+
+protected:
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ int m_banks[2];
+
+ template <unsigned BankNum> u8 read_bank(offs_t offset);
+ u8 bank_r(offs_t offset);
+ void bank_w(offs_t offset, u8 data);
+};
+
+DECLARE_DEVICE_TYPE(A800_ROM_BBSB, a800_rom_bbsb_device)
+DECLARE_DEVICE_TYPE(A5200_ROM_BBSB, a5200_rom_bbsb_device)
+
+#endif // MAME_BUS_A800_BBSB_H
diff --git a/src/devices/bus/a800/cassette.cpp b/src/devices/bus/a800/cassette.cpp
index 32d9fe0b390..50feed49c5c 100644
--- a/src/devices/bus/a800/cassette.cpp
+++ b/src/devices/bus/a800/cassette.cpp
@@ -25,7 +25,7 @@ TODO:
// GLOBAL VARIABLES
//**************************************************************************
-DEFINE_DEVICE_TYPE(A8SIO_CASSETTE, a8sio_cassette_device, "a8sio_cass", "Atari 8 bit cassette")
+DEFINE_DEVICE_TYPE(A8SIO_CASSETTE, a8sio_cassette_device, "a8sio_cass", "Atari 8-bit cassette")
void a8sio_cassette_device::device_add_mconfig(machine_config &config)
{
@@ -66,7 +66,7 @@ void a8sio_cassette_device::device_reset()
{
}
-WRITE_LINE_MEMBER( a8sio_cassette_device::motor_w )
+void a8sio_cassette_device::motor_w(int state)
{
//printf("a8sio_cassette::motor_w %d\n", state);
if (!state)
diff --git a/src/devices/bus/a800/cassette.h b/src/devices/bus/a800/cassette.h
index d1c91c5a2fa..c2436946b66 100644
--- a/src/devices/bus/a800/cassette.h
+++ b/src/devices/bus/a800/cassette.h
@@ -29,7 +29,7 @@ public:
// construction/destruction
a8sio_cassette_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual DECLARE_WRITE_LINE_MEMBER( motor_w ) override;
+ virtual void motor_w(int state) override;
protected:
a8sio_cassette_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
diff --git a/src/devices/bus/a800/corina.cpp b/src/devices/bus/a800/corina.cpp
new file mode 100644
index 00000000000..451e6e31462
--- /dev/null
+++ b/src/devices/bus/a800/corina.cpp
@@ -0,0 +1,135 @@
+// license: BSD-3-Clause
+// copyright-holders: Angelo Salese
+/**************************************************************************************************
+
+Corina
+
+Known configs:
+- 1MB Flash ROM (yakungfu)
+- 512KB Flash ROM + 512KB SRAM (bombjake)
+
+Both contains 8KB NVRAM
+
+TODO:
+- Pinpoint and convert to flash interface;
+- Unknown behaviour when accessing the "reserved" view;
+
+**************************************************************************************************/
+
+#include "emu.h"
+#include "corina.h"
+
+DEFINE_DEVICE_TYPE(A800_ROM_CORINA, a800_rom_corina_device, "a800_corina", "Atari 8-bit Corina 1MB flash ROM cart")
+DEFINE_DEVICE_TYPE(A800_ROM_CORINA_SRAM, a800_rom_corina_sram_device, "a800_corina_sram", "Atari 8-bit Corina 512KB flash ROM + 512KB RAM cart")
+
+a800_rom_corina_device::a800_rom_corina_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : a800_rom_device(mconfig, type, tag, owner, clock)
+ , m_nvram(*this, "nvram")
+ , m_view(*this, "corina_view")
+ , m_rom_bank(0)
+{
+}
+
+a800_rom_corina_device::a800_rom_corina_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : a800_rom_corina_device(mconfig, A800_ROM_CORINA, tag, owner, clock)
+{
+}
+
+void a800_rom_corina_device::device_add_mconfig(machine_config &config)
+{
+ NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_1);
+}
+
+void a800_rom_corina_device::device_start()
+{
+ const u32 nvram_size = 0x2000;
+ m_nvram_ptr = std::make_unique<uint8_t[]>(nvram_size);
+ m_nvram->set_base(m_nvram_ptr.get(), nvram_size);
+
+ save_pointer(NAME(m_nvram_ptr), nvram_size);
+ save_item(NAME(m_rom_bank));
+}
+
+void a800_rom_corina_device::device_reset()
+{
+ m_rom_bank = 0;
+ m_view.select(0);
+}
+
+void a800_rom_corina_device::cart_map(address_map &map)
+{
+ map.unmap_value_high();
+ map(0x0000, 0x3fff).view(m_view);
+ // TODO: spam writes during loading, flash commands?
+ m_view[0](0x0000, 0x3fff).lr8(
+ NAME([this](offs_t offset) { return m_rom[(offset & 0x3fff) + (m_rom_bank * 0x4000)]; })
+ );
+ m_view[1](0x0000, 0x3fff).rw(FUNC(a800_rom_corina_device::read_view_1), FUNC(a800_rom_corina_device::write_view_1));
+ m_view[2](0x0000, 0x3fff).lrw8(
+ NAME([this](offs_t offset) { return m_nvram_ptr[offset & 0x1fff]; }),
+ NAME([this](offs_t offset, uint8_t data) { m_nvram_ptr[offset & 0x1fff] = data; })
+ );
+ m_view[3](0x0000, 0x3fff).unmaprw();
+}
+
+void a800_rom_corina_device::cctl_map(address_map &map)
+{
+ map(0x00, 0x00).w(FUNC(a800_rom_corina_device::ctrl_w));
+}
+
+uint8_t a800_rom_corina_device::read_view_1(offs_t offset)
+{
+ return m_rom[(offset & 0x3fff) + (m_rom_bank * 0x4000) + 0x80000];
+}
+
+void a800_rom_corina_device::write_view_1(offs_t offset, u8 data)
+{
+}
+
+/*
+ * 0--- ---- enable Corina window
+ * 1--- ---- disable Corina and select main unit 8000-bfff window instead
+ * -xx- ---- view select
+ * -00- ---- first half of ROM
+ * -01- ---- second half of ROM or RAM (^ depending on PCB config)
+ * -10- ---- NVRAM
+ * -11- ---- <reserved>
+ * ---x xxxx ROM/RAM lower bank value,
+ * ignored if view select is not in ROM/RAM mode
+ * or Corina window is disabled
+ */
+void a800_rom_corina_device::ctrl_w(offs_t offset, uint8_t data)
+{
+ m_rom_bank = data & 0x1f;
+ m_view.select((data & 0x60) >> 5);
+ rd_both_w(!BIT(data, 7));
+}
+
+/*-------------------------------------------------
+
+ SRAM variant overrides
+
+ -------------------------------------------------*/
+
+a800_rom_corina_sram_device::a800_rom_corina_sram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : a800_rom_corina_device(mconfig, A800_ROM_CORINA_SRAM, tag, owner, clock)
+{
+}
+
+void a800_rom_corina_sram_device::device_start()
+{
+ a800_rom_corina_device::device_start();
+
+ m_ram.resize(0x80000);
+ save_item(NAME(m_ram));
+}
+
+uint8_t a800_rom_corina_sram_device::read_view_1(offs_t offset)
+{
+ return m_ram[(offset & 0x3fff) + (m_rom_bank * 0x4000)];
+}
+
+void a800_rom_corina_sram_device::write_view_1(offs_t offset, u8 data)
+{
+ m_ram[(offset & 0x3fff) + (m_rom_bank * 0x4000)] = data;
+}
diff --git a/src/devices/bus/a800/corina.h b/src/devices/bus/a800/corina.h
new file mode 100644
index 00000000000..1bd4fae2ba8
--- /dev/null
+++ b/src/devices/bus/a800/corina.h
@@ -0,0 +1,59 @@
+// license: BSD-3-Clause
+// copyright-holders: Angelo Salese
+
+#ifndef MAME_BUS_A800_CORINA_H
+#define MAME_BUS_A800_CORINA_H
+
+#pragma once
+
+#include "rom.h"
+//#include "machine/intelfsh.h"
+
+class a800_rom_corina_device : public a800_rom_device
+{
+public:
+ a800_rom_corina_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+ a800_rom_corina_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void cart_map(address_map &map) override;
+ virtual void cctl_map(address_map &map) override;
+ virtual std::tuple<int, int> get_initial_rd_state() override { return std::make_tuple(1, 1); }
+
+protected:
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+
+ std::unique_ptr<uint8_t[]> m_nvram_ptr;
+
+ virtual uint8_t read_view_1(offs_t offset);
+ virtual void write_view_1(offs_t offset, u8 data);
+
+ void ctrl_w(offs_t offset, u8 data);
+
+ required_device<nvram_device> m_nvram;
+ memory_view m_view;
+ u8 m_rom_bank;
+};
+
+class a800_rom_corina_sram_device : public a800_rom_corina_device
+{
+public:
+ // construction/destruction
+ a800_rom_corina_sram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+
+protected:
+ virtual void device_start() override;
+
+ virtual uint8_t read_view_1(offs_t offset) override;
+ virtual void write_view_1(offs_t offset, u8 data) override;
+
+private:
+ std::vector<uint8_t> m_ram;
+};
+
+DECLARE_DEVICE_TYPE(A800_ROM_CORINA, a800_rom_corina_device)
+DECLARE_DEVICE_TYPE(A800_ROM_CORINA_SRAM, a800_rom_corina_sram_device)
+
+#endif // MAME_BUS_A800_CORINA_H
diff --git a/src/devices/bus/a800/maxflash.cpp b/src/devices/bus/a800/maxflash.cpp
new file mode 100644
index 00000000000..583f2991570
--- /dev/null
+++ b/src/devices/bus/a800/maxflash.cpp
@@ -0,0 +1,123 @@
+// license: BSD-3-Clause
+// copyright-holders: Angelo Salese
+/**************************************************************************************************
+
+Maxflash
+
+TODO:
+- alt flash configs;
+- alt buggy revision of 1MB version, with m_bank starting at 0x7f;
+
+**************************************************************************************************/
+
+#include "emu.h"
+#include "maxflash.h"
+
+// device type definition
+DEFINE_DEVICE_TYPE(A800_MAXFLASH_128KB, a800_maxflash_128kb_device, "maxflash_128kb", "Atari 8-bit Atarimax Maxflash 128K flash ROM cart")
+DEFINE_DEVICE_TYPE(A800_MAXFLASH_1MB, a800_maxflash_1mb_device, "maxflash_1mb", "Atari 8-bit Atarimax Maxflash 1MB flash ROM cart")
+
+a800_maxflash_128kb_device::a800_maxflash_128kb_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : a800_rom_device(mconfig, type, tag, owner, clock)
+ , m_flash(*this, "flash")
+ , m_bank(0)
+{
+}
+
+a800_maxflash_128kb_device::a800_maxflash_128kb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : a800_maxflash_128kb_device(mconfig, A800_MAXFLASH_128KB, tag, owner, clock)
+{
+}
+
+void a800_maxflash_128kb_device::device_add_mconfig(machine_config &config)
+{
+ AMD_29F010(config, m_flash);
+
+ // TODO: alt config with Micron M29F010B ($20/$20)
+}
+
+void a800_maxflash_128kb_device::device_start()
+{
+ save_item(NAME(m_bank));
+}
+
+void a800_maxflash_128kb_device::device_reset()
+{
+ // TODO: ugly assignment, and shouldn't happen in device_reset
+ // TODO: assert against intended size for slot
+ memcpy(m_flash->base(), m_rom, get_rom_size());
+
+ // NB: this starts with 0x7f in the older Atarimax 1MB version
+ m_bank = 0;
+}
+
+void a800_maxflash_128kb_device::cart_map(address_map &map)
+{
+ map(0x2000, 0x3fff).lrw8(
+ NAME([this](offs_t offset) {
+ return m_flash->read((offset & 0x1fff) + (m_bank * 0x2000));
+ }),
+ NAME([this](offs_t offset, u8 data) {
+ m_flash->write((offset & 0x1fff) + (m_bank * 0x2000), data);
+ })
+ );
+}
+
+void a800_maxflash_128kb_device::cctl_map(address_map &map)
+{
+ map(0x00, 0x0f).rw(FUNC(a800_maxflash_128kb_device::rom_bank_r), FUNC(a800_maxflash_128kb_device::rom_bank_w));
+ map(0x10, 0x1f).rw(FUNC(a800_maxflash_128kb_device::disable_rom_r), FUNC(a800_maxflash_128kb_device::disable_rom_w));
+}
+
+uint8_t a800_maxflash_128kb_device::disable_rom_r(offs_t offset)
+{
+ if(!machine().side_effects_disabled())
+ rd5_w(0);
+
+ return 0xff;
+}
+
+void a800_maxflash_128kb_device::disable_rom_w(offs_t offset, uint8_t data)
+{
+ rd5_w(0);
+}
+
+uint8_t a800_maxflash_128kb_device::rom_bank_r(offs_t offset)
+{
+ if(!machine().side_effects_disabled())
+ {
+ rd5_w(1);
+ m_bank = (offset & m_bank_mask);
+ }
+ return 0xff;
+}
+
+void a800_maxflash_128kb_device::rom_bank_w(offs_t offset, uint8_t data)
+{
+ rd5_w(1);
+ m_bank = (offset & m_bank_mask);
+}
+
+// 8MB overrides
+
+a800_maxflash_1mb_device::a800_maxflash_1mb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : a800_maxflash_128kb_device(mconfig, A800_MAXFLASH_1MB, tag, owner, clock)
+{
+}
+
+void a800_maxflash_1mb_device::device_add_mconfig(machine_config &config)
+{
+ // TODO: AMD_29F040B according to Altirra?
+ // AMD_29F040 doesn't match 0x100000 size requirement, 'B is still 4 megabits?
+ // replace it with a suitable flash device for now
+ INTEL_E28F008SA(config, m_flash);
+
+ // TODO: alt config with Bright BM29F040 ($ad/$40)
+}
+
+
+void a800_maxflash_1mb_device::cctl_map(address_map &map)
+{
+ map(0x00, 0x7f).rw(FUNC(a800_maxflash_1mb_device::rom_bank_r), FUNC(a800_maxflash_1mb_device::rom_bank_w));
+ map(0x80, 0xff).rw(FUNC(a800_maxflash_1mb_device::disable_rom_r), FUNC(a800_maxflash_1mb_device::disable_rom_w));
+}
diff --git a/src/devices/bus/a800/maxflash.h b/src/devices/bus/a800/maxflash.h
new file mode 100644
index 00000000000..63c4843d913
--- /dev/null
+++ b/src/devices/bus/a800/maxflash.h
@@ -0,0 +1,53 @@
+// license: BSD-3-Clause
+// copyright-holders: Angelo Salese
+
+#ifndef MAME_BUS_A800_MAXFLASH_H
+#define MAME_BUS_A800_MAXFLASH_H
+
+#pragma once
+
+#include "rom.h"
+#include "machine/intelfsh.h"
+
+class a800_maxflash_128kb_device : public a800_rom_device
+{
+public:
+ a800_maxflash_128kb_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+ a800_maxflash_128kb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void cart_map(address_map &map) override;
+ virtual void cctl_map(address_map &map) override;
+ virtual std::tuple<int, int> get_initial_rd_state() override { return std::make_tuple(0, 1); }
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override;
+
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ required_device<intelfsh8_device> m_flash;
+
+ uint8_t disable_rom_r(offs_t offset);
+ void disable_rom_w(offs_t offset, uint8_t data);
+ uint8_t rom_bank_r(offs_t offset);
+ void rom_bank_w(offs_t offset, uint8_t data);
+
+private:
+ int m_bank;
+};
+
+class a800_maxflash_1mb_device : public a800_maxflash_128kb_device
+{
+public:
+ a800_maxflash_1mb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void cctl_map(address_map &map) override;
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override;
+};
+
+DECLARE_DEVICE_TYPE(A800_MAXFLASH_128KB, a800_maxflash_128kb_device)
+DECLARE_DEVICE_TYPE(A800_MAXFLASH_1MB, a800_maxflash_1mb_device)
+
+#endif // MAME_BUS_A800_MAXFLASH_H
diff --git a/src/devices/bus/a800/oss.cpp b/src/devices/bus/a800/oss.cpp
index f25dfcce130..bd1cf4025a6 100644
--- a/src/devices/bus/a800/oss.cpp
+++ b/src/devices/bus/a800/oss.cpp
@@ -1,10 +1,17 @@
// license:BSD-3-Clause
-// copyright-holders:Fabio Priuli
-/***********************************************************************************************************
+// copyright-holders:Fabio Priuli, Angelo Salese
+/**************************************************************************************************
- A800 ROM cart emulation
+ "Optimized System Software" OSS ROM cart emulation
-***********************************************************************************************************/
+https://en.wikipedia.org/wiki/Optimized_Systems_Software
+
+Running on similar non-linear but incompatible banking schemes.
+
+TODO:
+- OSS034M doesn't really exist, it's an OSS043M with wrong ROM contents.
+
+**************************************************************************************************/
#include "emu.h"
@@ -15,37 +22,30 @@
// constructor
//-------------------------------------------------
-DEFINE_DEVICE_TYPE(A800_ROM_OSS8K, a800_rom_oss8k_device, "a800_oss8k", "Atari 800 ROM Carts OSS 8K")
-DEFINE_DEVICE_TYPE(A800_ROM_OSS34, a800_rom_oss34_device, "a800_034m", "Atari 800 ROM Carts OSS-034M")
-DEFINE_DEVICE_TYPE(A800_ROM_OSS43, a800_rom_oss43_device, "a800_043m", "Atari 800 ROM Carts OSS-043M")
-DEFINE_DEVICE_TYPE(A800_ROM_OSS91, a800_rom_oss91_device, "a800_m091", "Atari 800 ROM Carts OSS-M091")
+DEFINE_DEVICE_TYPE(A800_ROM_OSS8K, a800_rom_oss8k_device, "a800_oss8k", "Atari 8-bit OSS 8K cart")
+DEFINE_DEVICE_TYPE(A800_ROM_OSS34, a800_rom_oss034m_device, "a800_034m", "Atari 8-bit OSS-034M cart")
+DEFINE_DEVICE_TYPE(A800_ROM_OSS43, a800_rom_oss043m_device, "a800_043m", "Atari 8-bit OSS-043M cart")
+DEFINE_DEVICE_TYPE(A800_ROM_OSS91, a800_rom_oss091m_device, "a800_m091", "Atari 8-bit OSS-M091 cart")
+/*-------------------------------------------------
-a800_rom_oss8k_device::a800_rom_oss8k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : a800_rom_device(mconfig, A800_ROM_OSS8K, tag, owner, clock), m_bank(0)
-{
-}
-
+ OSS 8K
-a800_rom_oss34_device::a800_rom_oss34_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : a800_rom_device(mconfig, A800_ROM_OSS34, tag, owner, clock), m_bank(0)
-{
-}
+ This is used by The Writer's Tool only.
+ -------------------------------------------------*/
-a800_rom_oss43_device::a800_rom_oss43_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : a800_rom_device(mconfig, A800_ROM_OSS43, tag, owner, clock), m_bank(0)
+a800_rom_oss8k_device::a800_rom_oss8k_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : a800_rom_device(mconfig, type, tag, owner, clock)
+ , m_bank(0)
{
}
-
-a800_rom_oss91_device::a800_rom_oss91_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : a800_rom_device(mconfig, A800_ROM_OSS91, tag, owner, clock), m_bank(0)
+a800_rom_oss8k_device::a800_rom_oss8k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : a800_rom_oss8k_device(mconfig, A800_ROM_OSS8K, tag, owner, clock)
{
}
-
-
void a800_rom_oss8k_device::device_start()
{
save_item(NAME(m_bank));
@@ -56,197 +56,200 @@ void a800_rom_oss8k_device::device_reset()
m_bank = 0;
}
-
-void a800_rom_oss34_device::device_start()
-{
- save_item(NAME(m_bank));
-}
-
-void a800_rom_oss34_device::device_reset()
+void a800_rom_oss8k_device::cart_map(address_map &map)
{
- m_bank = 1;
+ map(0x2000, 0x2fff).lr8(
+ NAME([this](offs_t offset) { return m_rom[(offset & 0x0fff) | m_bank * 0x1000]; })
+ );
+ map(0x3000, 0x3fff).lr8(
+ NAME([this](offs_t offset) { return m_rom[offset & 0x0fff]; })
+ );
}
-
-void a800_rom_oss43_device::device_start()
+/*
+ * ---- 0--x selects bank 1
+ * ---- 1--0 RD5 clear
+ * ---- 1--1 selects bank 0
+ */
+inline void a800_rom_oss8k_device::bank_config_access(offs_t offset)
{
- save_item(NAME(m_bank));
+ if (!(BIT(offset, 3)))
+ {
+ rd5_w(1);
+ m_bank = 1;
+ }
+ else
+ {
+ rd5_w(BIT(offset, 0));
+ m_bank = 0;
+ }
}
-void a800_rom_oss43_device::device_reset()
+u8 a800_rom_oss8k_device::rom_bank_r(offs_t offset)
{
- m_bank = 0;
+ if (!machine().side_effects_disabled())
+ bank_config_access(offset);
+ return 0xff;
}
-
-void a800_rom_oss91_device::device_start()
+void a800_rom_oss8k_device::rom_bank_w(offs_t offset, u8 data)
{
- save_item(NAME(m_bank));
+ bank_config_access(offset);
}
-void a800_rom_oss91_device::device_reset()
+void a800_rom_oss8k_device::cctl_map(address_map &map)
{
- m_bank = 0;
+ map(0x00, 0xff).rw(FUNC(a800_rom_oss8k_device::rom_bank_r), FUNC(a800_rom_oss8k_device::rom_bank_w));
}
-
/*-------------------------------------------------
- mapper specific handlers
- -------------------------------------------------*/
-/*-------------------------------------------------
+ OSS 091M
- OSS 8K
-
- This is used by The Writer's Tool only.
+ Later variant of OSS 8k
-------------------------------------------------*/
-uint8_t a800_rom_oss8k_device::read_80xx(offs_t offset)
+a800_rom_oss091m_device::a800_rom_oss091m_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : a800_rom_oss8k_device(mconfig, A800_ROM_OSS91, tag, owner, clock)
{
- if (offset >= 0x1000)
- return m_rom[offset & 0xfff];
- else
- return m_rom[(offset & 0xfff) + (m_bank * 0x1000)];
}
-void a800_rom_oss8k_device::write_d5xx(offs_t offset, uint8_t data)
+/*
+ * ---- 0--0 bank 1
+ * ---- 0--1 bank 3
+ * ---- 1--0 RD5 clear
+ * ---- 1--1 bank 2
+ */
+inline void a800_rom_oss091m_device::bank_config_access(offs_t offset)
{
- switch (offset & 0x09)
+ const u8 a0 = BIT(offset, 0);
+ if (!(BIT(offset, 3)))
+ {
+ rd5_w(1);
+ m_bank = 1 | (a0 << 1);
+ }
+ else
{
- case 0:
- case 1:
- m_bank = 1;
- break;
- case 9:
- m_bank = 0;
- break;
- default:
- break;
+ rd5_w(a0);
+ m_bank = 2;
}
}
-
/*-------------------------------------------------
- OSS 034M
-
- This apparently comes from a dump with the wrong bank order...
- investigate whether we should remove it!
+ OSS 043M
-------------------------------------------------*/
-uint8_t a800_rom_oss34_device::read_80xx(offs_t offset)
+a800_rom_oss043m_device::a800_rom_oss043m_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : a800_rom_device(mconfig, type, tag, owner, clock)
+ , m_bankdev(*this, "bankdev")
+ , m_bank_base1(0)
+ , m_bank_base2(0)
{
- if (offset >= 0x1000)
- return m_rom[(offset & 0xfff) + 0x3000];
- else if (m_bank == 3)
- return 0xff;
- else
- return m_rom[(offset & 0xfff) + (m_bank * 0x1000)];
}
-void a800_rom_oss34_device::write_d5xx(offs_t offset, uint8_t data)
+a800_rom_oss043m_device::a800_rom_oss043m_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : a800_rom_oss043m_device(mconfig, A800_ROM_OSS43, tag, owner, clock)
{
- switch (offset & 0x0f)
- {
- case 0:
- case 1:
- m_bank = 0;
- break;
- case 2:
- case 6:
- m_bank = 3; // in this case the ROM gets disabled and 0xff is returned in 0xa000-0xafff
- break;
- case 3:
- case 7:
- m_bank = 1;
- break;
- case 4:
- case 5:
- m_bank = 2;
- break;
- default:
- break;
- }
}
+void a800_rom_oss043m_device::device_add_mconfig(machine_config &config)
+{
+ ADDRESS_MAP_BANK(config, m_bankdev).set_map(&a800_rom_oss043m_device::bankdev_map).set_options(ENDIANNESS_LITTLE, 8, 12 + 3, 0x1000);
+}
-/*-------------------------------------------------
+void a800_rom_oss043m_device::device_start()
+{
+ m_bank_base1 = 0x2000;
+ m_bank_base2 = 0x1000;
+}
- OSS 043M
+void a800_rom_oss043m_device::device_reset()
+{
+ m_bankdev->set_bank(0);
- Same as above but with correct bank order
+ rd4_w(0);
+ rd5_w(1);
+}
- -------------------------------------------------*/
+void a800_rom_oss043m_device::bankdev_map(address_map &map)
+{
+ map(0x0000, 0x0fff).lr8(
+ NAME([this](offs_t offset) { return m_rom[offset & 0x0fff]; })
+ );
+ map(0x1000, 0x1fff).lr8(
+ NAME([this](offs_t offset) { return m_rom[offset & 0x0fff] & m_rom[(offset & 0x0fff) | m_bank_base1]; })
+ );
+ map(0x2000, 0x2fff).mirror(0x4000).lr8(
+ NAME([]() { return 0xff; })
+ );
+ map(0x3000, 0x3fff).mirror(0x4000).lr8(
+ NAME([this](offs_t offset) { return m_rom[(offset & 0x0fff) | m_bank_base1]; })
+ );
+ map(0x4000, 0x4fff).lr8(
+ NAME([this](offs_t offset) { return m_rom[(offset & 0x0fff) | m_bank_base2]; })
+ );
+ map(0x5000, 0x5fff).lr8(
+ NAME([this](offs_t offset) { return m_rom[(offset & 0x0fff) | m_bank_base1] & m_rom[(offset & 0x0fff) | m_bank_base2]; })
+ );
+}
-uint8_t a800_rom_oss43_device::read_80xx(offs_t offset)
+void a800_rom_oss043m_device::cart_map(address_map &map)
{
- if (offset >= 0x1000)
- return m_rom[(offset & 0xfff) + 0x3000];
- else if (m_bank == 3)
- return 0xff;
- else
- return m_rom[(offset & 0xfff) + (m_bank * 0x1000)];
+ map(0x2000, 0x2fff).m(m_bankdev, FUNC(address_map_bank_device::amap8));
+ map(0x3000, 0x3fff).lr8(
+ NAME([this](offs_t offset) { return m_rom[(offset & 0x0fff) | 0x3000]; })
+ );
}
-void a800_rom_oss43_device::write_d5xx(offs_t offset, uint8_t data)
+void a800_rom_oss043m_device::cctl_map(address_map &map)
{
- switch (offset & 0x0f)
- {
- case 0:
- case 1:
- m_bank = 0;
- break;
- case 2:
- case 6:
- m_bank = 3; // in this case the ROM gets disabled and 0xff is returned in 0xa000-0xafff
- break;
- case 3:
- case 7:
- m_bank = 2;
- break;
- case 4:
- case 5:
- m_bank = 1;
- break;
- default:
- break;
- }
+ map(0x00, 0xff).rw(FUNC(a800_rom_oss043m_device::rom_bank_r), FUNC(a800_rom_oss043m_device::rom_bank_w));
}
+/*
+ * 0000 bank 0
+ * 0001 returns AND-ed contents of banks 0 & 2
+ * 0x10 returns 0xff to window (i.e. RD5 is still asserted)
+ * 0x11 bank 2
+ * 0100 bank 1
+ * 0101 returns AND-ed contents of banks 1 & 2
+ * 1000 RD5 clear
+ */
+inline void a800_rom_oss043m_device::bank_config_access(offs_t offset)
+{
+ rd5_w(!(BIT(offset, 3)));
+ m_bankdev->set_bank(offset & 7);
+}
-/*-------------------------------------------------
+u8 a800_rom_oss043m_device::rom_bank_r(offs_t offset)
+{
+ if (!machine().side_effects_disabled())
+ bank_config_access(offset);
+ return 0xff;
+}
- OSS M091
+void a800_rom_oss043m_device::rom_bank_w(offs_t offset, u8 data)
+{
+ bank_config_access(offset);
+}
- Simplified banking system which only uses two
- address lines (A0 & A3)
+/*-------------------------------------------------
+
+ OSS 034M (fake)
-------------------------------------------------*/
-uint8_t a800_rom_oss91_device::read_80xx(offs_t offset)
+a800_rom_oss034m_device::a800_rom_oss034m_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : a800_rom_oss043m_device(mconfig, A800_ROM_OSS34, tag, owner, clock)
{
- if (offset >= 0x1000)
- return m_rom[offset & 0xfff];
- else
- return m_rom[(offset & 0xfff) + (m_bank * 0x1000)];
}
-void a800_rom_oss91_device::write_d5xx(offs_t offset, uint8_t data)
+void a800_rom_oss034m_device::device_start()
{
- switch (offset & 0x09)
- {
- case 0:
- m_bank = 1;
- break;
- case 1:
- m_bank = 3;
- break;
- case 9:
- m_bank = 2;
- break;
- default:
- break;
- }
+ a800_rom_oss043m_device::device_start();
+ m_bank_base1 = 0x1000;
+ m_bank_base2 = 0x2000;
}
diff --git a/src/devices/bus/a800/oss.h b/src/devices/bus/a800/oss.h
index 65527039825..c8511d62abc 100644
--- a/src/devices/bus/a800/oss.h
+++ b/src/devices/bus/a800/oss.h
@@ -1,99 +1,86 @@
// license:BSD-3-Clause
-// copyright-holders:Fabio Priuli
+// copyright-holders:Fabio Priuli, Angelo Salese
#ifndef MAME_BUS_A800_OSS_H
#define MAME_BUS_A800_OSS_H
#pragma once
#include "rom.h"
+#include "machine/bankdev.h"
-// ======================> a800_rom_oss8k_device
-
class a800_rom_oss8k_device : public a800_rom_device
{
public:
- // construction/destruction
a800_rom_oss8k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ a800_rom_oss8k_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
- virtual uint8_t read_80xx(offs_t offset) override;
- virtual void write_d5xx(offs_t offset, uint8_t data) override;
+ virtual void cart_map(address_map &map) override;
+ virtual void cctl_map(address_map &map) override;
+ virtual std::tuple<int, int> get_initial_rd_state() override { return std::make_tuple(0, 1); }
protected:
- // device-level overrides
virtual void device_start() override;
virtual void device_reset() override;
int m_bank;
+ virtual void bank_config_access(offs_t offset);
+ u8 rom_bank_r(offs_t offset);
+ void rom_bank_w(offs_t offset, u8 data);
};
-// ======================> a800_rom_oss34_device
-
-class a800_rom_oss34_device : public a800_rom_device
+class a800_rom_oss043m_device : public a800_rom_device
{
public:
- // construction/destruction
- a800_rom_oss34_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ a800_rom_oss043m_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ a800_rom_oss043m_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
- virtual uint8_t read_80xx(offs_t offset) override;
- virtual void write_d5xx(offs_t offset, uint8_t data) override;
+ virtual void cart_map(address_map &map) override;
+ virtual void cctl_map(address_map &map) override;
+ virtual std::tuple<int, int> get_initial_rd_state() override { return std::make_tuple(0, 1); }
protected:
- // device-level overrides
virtual void device_start() override;
virtual void device_reset() override;
+ virtual void device_add_mconfig(machine_config &config) override;
- int m_bank;
-};
+ void bankdev_map(address_map &map);
+ void bank_config_access(offs_t offset);
+ u8 rom_bank_r(offs_t offset);
+ void rom_bank_w(offs_t offset, u8 data);
+ required_device<address_map_bank_device> m_bankdev;
+
+ u16 m_bank_base1, m_bank_base2;
+};
-// ======================> a800_rom_oss43_device
-class a800_rom_oss43_device : public a800_rom_device
+class a800_rom_oss034m_device : public a800_rom_oss043m_device
{
public:
- // construction/destruction
- a800_rom_oss43_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual uint8_t read_80xx(offs_t offset) override;
- virtual void write_d5xx(offs_t offset, uint8_t data) override;
+ a800_rom_oss034m_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
- // device-level overrides
virtual void device_start() override;
- virtual void device_reset() override;
-
- int m_bank;
};
-// ======================> a800_rom_oss91_device
-
-class a800_rom_oss91_device : public a800_rom_device
+class a800_rom_oss091m_device : public a800_rom_oss8k_device
{
public:
- // construction/destruction
- a800_rom_oss91_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual uint8_t read_80xx(offs_t offset) override;
- virtual void write_d5xx(offs_t offset, uint8_t data) override;
+ a800_rom_oss091m_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
-
- int m_bank;
+ virtual void bank_config_access(offs_t offset) override;
};
-// device type definition
DECLARE_DEVICE_TYPE(A800_ROM_OSS8K, a800_rom_oss8k_device)
-DECLARE_DEVICE_TYPE(A800_ROM_OSS34, a800_rom_oss34_device)
-DECLARE_DEVICE_TYPE(A800_ROM_OSS43, a800_rom_oss43_device)
-DECLARE_DEVICE_TYPE(A800_ROM_OSS91, a800_rom_oss91_device)
+DECLARE_DEVICE_TYPE(A800_ROM_OSS34, a800_rom_oss034m_device)
+DECLARE_DEVICE_TYPE(A800_ROM_OSS43, a800_rom_oss043m_device)
+DECLARE_DEVICE_TYPE(A800_ROM_OSS91, a800_rom_oss091m_device)
#endif // MAME_BUS_A800_OSS_H
diff --git a/src/devices/bus/a800/phoenix.cpp b/src/devices/bus/a800/phoenix.cpp
new file mode 100644
index 00000000000..5f8e734e88f
--- /dev/null
+++ b/src/devices/bus/a800/phoenix.cpp
@@ -0,0 +1,176 @@
+// license: BSD-3-Clause
+// copyright-holders: Angelo Salese
+/**************************************************************************************************
+
+Phoenix/Blizzard cart schemes
+
+RD5 is special here: once disarmed it cannot be armed again from software.
+
+TODO:
+- Reset button optionally located on cart allows RD5 to be rearmed;
+
+Notes:
+- "Blizzard 4KB" note from .car specs suggests being a Phoenix in disguise,
+ they are definitely a better suit to use the a800_phoenix def rather than blizzard_device
+ given the RD4 access of latter.
+- For "Blizzard 32KB" cfr. ultracart.cpp
+- "Phoenix AST2K" is an oddity, according to Kr0tki on AtariAge forums:
+ "AST 2000 was two cartridges in one - it contained an AST Utility cartridge,
+ and a cartridge for Turbo 2000 (another turbo system popular in Poland).
+ The "AST 2000" contained a 16KB ROM and a two-position switch, which allowed to choose between
+ one of two 8KB banks. [...] the second half (Turbo 2000) [...] contained a capacitor that
+ automatically switched off the cartridge from memory after a certain time [...]"
+ https://forums.atariage.com/topic/169199-mess-a800-cartridge-software-list/#comment-2136371
+
+
+
+**************************************************************************************************/
+
+#include "emu.h"
+#include "phoenix.h"
+
+DEFINE_DEVICE_TYPE(A800_ROM_PHOENIX, a800_rom_phoenix_device, "a800_phoenix", "Atari 8-bit Phoenix cart")
+DEFINE_DEVICE_TYPE(A800_ROM_BLIZZARD_16KB, a800_rom_blizzard_16kb_device, "a800_blizzard", "Atari 8-bit Blizzard 16KB ROM cart")
+DEFINE_DEVICE_TYPE(A800_ROM_PHOENIX_AST2K, a800_rom_phoenix_ast2k_device, "a800_phoenix_ast2k", "Atari 8-bit Phoenix AST2K 2-in-1 cart")
+
+a800_rom_phoenix_device::a800_rom_phoenix_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : a800_rom_device(mconfig, type, tag, owner, clock)
+{
+}
+
+a800_rom_phoenix_device::a800_rom_phoenix_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : a800_rom_phoenix_device(mconfig, A800_ROM_PHOENIX, tag, owner, clock)
+{
+}
+
+void a800_rom_phoenix_device::device_start()
+{
+ m_rom_mask = get_rom_size() - 1;
+}
+
+void a800_rom_phoenix_device::device_reset()
+{
+
+}
+
+void a800_rom_phoenix_device::cart_map(address_map &map)
+{
+ map(0x2000, 0x3fff).lr8(
+ NAME([this](offs_t offset) { return m_rom[(offset & m_rom_mask)]; })
+ );
+}
+
+u8 a800_rom_phoenix_device::disable_rom_r(offs_t offset)
+{
+ if(!machine().side_effects_disabled())
+ rd5_w(0);
+
+ return 0xff;
+}
+
+void a800_rom_phoenix_device::disable_rom_w(offs_t offset, u8 data)
+{
+ rd5_w(0);
+}
+
+void a800_rom_phoenix_device::cctl_map(address_map &map)
+{
+ map(0x00, 0xff).rw(FUNC(a800_rom_phoenix_device::disable_rom_r), FUNC(a800_rom_phoenix_device::disable_rom_w));
+}
+
+/*-------------------------------------------------
+
+ Blizzard 16KB carts
+
+ -------------------------------------------------*/
+
+a800_rom_blizzard_16kb_device::a800_rom_blizzard_16kb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : a800_rom_phoenix_device(mconfig, A800_ROM_BLIZZARD_16KB, tag, owner, clock)
+{
+}
+
+void a800_rom_blizzard_16kb_device::device_reset()
+{
+}
+
+void a800_rom_blizzard_16kb_device::cart_map(address_map &map)
+{
+ map(0x0000, 0x3fff).lr8(
+ NAME([this](offs_t offset) { return m_rom[(offset & m_rom_mask)]; })
+ );
+}
+
+u8 a800_rom_blizzard_16kb_device::disable_rom_r(offs_t offset)
+{
+ if(!machine().side_effects_disabled())
+ rd_both_w(0);
+
+ return 0xff;
+}
+
+void a800_rom_blizzard_16kb_device::disable_rom_w(offs_t offset, u8 data)
+{
+ rd_both_w(0);
+}
+
+/*-------------------------------------------------
+
+ Phoenix AST2K variant
+
+ -------------------------------------------------*/
+
+a800_rom_phoenix_ast2k_device::a800_rom_phoenix_ast2k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : a800_rom_phoenix_device(mconfig, A800_ROM_PHOENIX_AST2K, tag, owner, clock)
+ , m_dsw(*this, "DSW")
+ , m_rom_select(0)
+{
+}
+
+static INPUT_PORTS_START(ast2k)
+ PORT_START("DSW")
+ // two position switch located on cart
+ // we default to Turbo 2000 mode since it's a bit more worth in regtest scenarios
+ PORT_DIPNAME(0x01, 0x01, "Boot mode" )
+ PORT_DIPSETTING(0x00, "AST Utility" )
+ PORT_DIPSETTING(0x01, "Turbo 2000" )
+INPUT_PORTS_END
+
+ioport_constructor a800_rom_phoenix_ast2k_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(ast2k);
+}
+
+void a800_rom_phoenix_ast2k_device::device_start()
+{
+// a800_rom_phoenix_device::device_start();
+ // FIXME: not initing this properly, needs memory_region
+ m_rom_mask = 0x1fff;
+ m_rd5_disarm_timer = timer_alloc(FUNC(a800_rom_phoenix_ast2k_device::rd5_disarm_cb), this);
+ save_item(NAME(m_rom_select));
+}
+
+void a800_rom_phoenix_ast2k_device::device_reset()
+{
+ a800_rom_phoenix_device::device_reset();
+
+ m_rom_select = BIT(m_dsw->read(), 0) << 13;
+
+ // TODO: unknown RD5 disarm time details
+ // - frame 137 is the first attempt of Turbo 2k software that tries to write to RD5 space;
+ // - is the disarm mechanic really disabled in AST Utility mode?
+ // - 4 seconds is a very lax time so that it doesn't backfire in case of atari400 driver timing changes;
+ m_rd5_disarm_timer->adjust((m_rom_select) ? attotime::from_seconds(4) : attotime::never);
+}
+
+TIMER_CALLBACK_MEMBER(a800_rom_phoenix_ast2k_device::rd5_disarm_cb)
+{
+ logerror("RD5 disarmed thru timer\n");
+ rd5_w(0);
+}
+
+void a800_rom_phoenix_ast2k_device::cart_map(address_map &map)
+{
+ map(0x2000, 0x3fff).lr8(
+ NAME([this](offs_t offset) { return m_rom[(offset & m_rom_mask) | m_rom_select]; })
+ );
+}
diff --git a/src/devices/bus/a800/phoenix.h b/src/devices/bus/a800/phoenix.h
new file mode 100644
index 00000000000..56f790d9061
--- /dev/null
+++ b/src/devices/bus/a800/phoenix.h
@@ -0,0 +1,70 @@
+// license: BSD-3-Clause
+// copyright-holders: Angelo Salese
+
+#ifndef MAME_BUS_A800_PHOENIX_H
+#define MAME_BUS_A800_PHOENIX_H
+
+#pragma once
+
+#include "rom.h"
+
+class a800_rom_phoenix_device : public a800_rom_device
+{
+public:
+ a800_rom_phoenix_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+ a800_rom_phoenix_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void cart_map(address_map &map) override;
+ virtual void cctl_map(address_map &map) override;
+ virtual std::tuple<int, int> get_initial_rd_state() override { return std::make_tuple(0, 1); }
+
+protected:
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ u32 m_rom_mask;
+ virtual u8 disable_rom_r(offs_t offset);
+ virtual void disable_rom_w(offs_t offset, u8 data);
+};
+
+class a800_rom_blizzard_16kb_device : public a800_rom_phoenix_device
+{
+public:
+ a800_rom_blizzard_16kb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void cart_map(address_map &map) override;
+ virtual std::tuple<int, int> get_initial_rd_state() override { return std::make_tuple(1, 1); }
+
+protected:
+ virtual void device_reset() override;
+
+ virtual u8 disable_rom_r(offs_t offset) override;
+ virtual void disable_rom_w(offs_t offset, u8 data) override;
+};
+
+class a800_rom_phoenix_ast2k_device : public a800_rom_phoenix_device
+{
+ public:
+ a800_rom_phoenix_ast2k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void cart_map(address_map &map) override;
+
+protected:
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual ioport_constructor device_input_ports() const override;
+
+private:
+ required_ioport m_dsw;
+ u32 m_rom_select;
+
+ emu_timer *m_rd5_disarm_timer;
+
+ TIMER_CALLBACK_MEMBER(rd5_disarm_cb);
+};
+
+DECLARE_DEVICE_TYPE(A800_ROM_PHOENIX, a800_rom_phoenix_device)
+DECLARE_DEVICE_TYPE(A800_ROM_BLIZZARD_16KB, a800_rom_blizzard_16kb_device)
+DECLARE_DEVICE_TYPE(A800_ROM_PHOENIX_AST2K, a800_rom_phoenix_ast2k_device)
+
+#endif // MAME_BUS_A800_PHOENIX_H
diff --git a/src/devices/bus/a800/rom.cpp b/src/devices/bus/a800/rom.cpp
index f6db2cb1cf1..c8a3131f206 100644
--- a/src/devices/bus/a800/rom.cpp
+++ b/src/devices/bus/a800/rom.cpp
@@ -1,33 +1,25 @@
// license:BSD-3-Clause
-// copyright-holders:Fabio Priuli
-/***********************************************************************************************************
+// copyright-holders:Fabio Priuli, Angelo Salese
+/**************************************************************************************************
- A800/A5200/XEGS ROM cart emulation
-
- Basic carts work the same (in addition of being mostly compatible) for all these systems
- and thus we deal with them in a single file
-
-***********************************************************************************************************/
+ A800/A5200/XEGS ROM base cart emulation
+**************************************************************************************************/
#include "emu.h"
#include "rom.h"
-
//-------------------------------------------------
// constructor
//-------------------------------------------------
-DEFINE_DEVICE_TYPE(A800_ROM, a800_rom_device, "a800_rom", "Atari 800 ROM Carts")
-DEFINE_DEVICE_TYPE(A800_ROM_BBSB, a800_rom_bbsb_device, "a800_bbsb", "Atari 800 ROM Carts BBSB")
-DEFINE_DEVICE_TYPE(A800_ROM_WILLIAMS, a800_rom_williams_device, "a800_williams", "Atari 800 64K ROM Carts Williams")
-DEFINE_DEVICE_TYPE(A800_ROM_EXPRESS, a800_rom_express_device, "a800_express", "Atari 800 64K ROM Carts Express/Diamond")
-DEFINE_DEVICE_TYPE(A800_ROM_TURBO, a800_rom_turbo_device, "a800_turbo", "Atari 800 64K ROM Carts Turbosoft")
-DEFINE_DEVICE_TYPE(A800_ROM_TELELINK2, a800_rom_telelink2_device, "a800_tlink2", "Atari 800 64K ROM Cart Telelink II")
-DEFINE_DEVICE_TYPE(A800_ROM_MICROCALC, a800_rom_microcalc_device, "a800_sitsa", "Atari 800 64K ROM Carts SITSA MicroCalc")
-DEFINE_DEVICE_TYPE(XEGS_ROM, xegs_rom_device, "a800_xegs", "Atari XEGS 64K ROM Carts")
-DEFINE_DEVICE_TYPE(A5200_ROM_2CHIPS, a5200_rom_2chips_device, "a5200_16k2c", "Atari 5200 ROM Cart 16K in 2 Chips")
-DEFINE_DEVICE_TYPE(A5200_ROM_BBSB, a5200_rom_bbsb_device, "a5200_bbsb", "Atari 5200 ROM Cart BBSB")
+DEFINE_DEVICE_TYPE(A800_ROM, a800_rom_device, "a800_rom", "Atari 8-bit ROM cart")
+DEFINE_DEVICE_TYPE(A800_ROM_16KB, a800_rom_16kb_device, "a800_rom_16kb", "Atari 8-bit ROM 16kb cart")
+DEFINE_DEVICE_TYPE(A800_ROM_RIGHT, a800_rom_right_device, "a800_rom_right","Atari 8-bit ROM Right cart")
+DEFINE_DEVICE_TYPE(XEGS_ROM, xegs_rom_device, "a800_xegs", "Atari XEGS 64K cart")
+
+DEFINE_DEVICE_TYPE(A5200_ROM, a5200_rom_device, "a5200_rom", "Atari 5200 ROM cart")
+DEFINE_DEVICE_TYPE(A5200_ROM_2CHIPS, a5200_rom_2chips_device, "a5200_16k2c", "Atari 5200 ROM cart 16K in 2 Chips")
a800_rom_device::a800_rom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
@@ -36,74 +28,17 @@ a800_rom_device::a800_rom_device(const machine_config &mconfig, device_type type
{
}
-a800_rom_device::a800_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : a800_rom_device(mconfig, A800_ROM, tag, owner, clock)
-{
-}
-
-
-a800_rom_bbsb_device::a800_rom_bbsb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : a800_rom_device(mconfig, A800_ROM_BBSB, tag, owner, clock)
-{
-}
-
-
-
-xegs_rom_device::xegs_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : a800_rom_device(mconfig, XEGS_ROM, tag, owner, clock)
- , m_bank(0)
-{
-}
-
-
-a800_rom_williams_device::a800_rom_williams_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : a800_rom_device(mconfig, A800_ROM_WILLIAMS, tag, owner, clock)
- , m_bank(0)
-{
-}
-
-
-a800_rom_express_device::a800_rom_express_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : a800_rom_device(mconfig, A800_ROM_EXPRESS, tag, owner, clock)
- , m_bank(0)
-{
-}
-
-
-a800_rom_turbo_device::a800_rom_turbo_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : a800_rom_device(mconfig, A800_ROM_TURBO, tag, owner, clock)
- , m_bank(0)
-{
-}
-
-
-a800_rom_telelink2_device::a800_rom_telelink2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : a800_rom_device(mconfig, A800_ROM_TELELINK2, tag, owner, clock)
-{
-}
-
-
-a800_rom_microcalc_device::a800_rom_microcalc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : a800_rom_device(mconfig, A800_ROM_MICROCALC, tag, owner, clock)
- , m_bank(0)
-{
-}
-
+/*-------------------------------------------------
-a5200_rom_2chips_device::a5200_rom_2chips_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : a800_rom_device(mconfig, A5200_ROM_2CHIPS, tag, owner, clock)
-{
-}
+ Generic left cart 8kb
+ -------------------------------------------------*/
-a5200_rom_bbsb_device::a5200_rom_bbsb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : a800_rom_device(mconfig, A5200_ROM_BBSB, tag, owner, clock)
+a800_rom_device::a800_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : a800_rom_device(mconfig, A800_ROM, tag, owner, clock)
{
}
-
-
-
void a800_rom_device::device_start()
{
}
@@ -112,291 +47,143 @@ void a800_rom_device::device_reset()
{
}
-
-void a800_rom_bbsb_device::device_start()
-{
- save_item(NAME(m_banks));
-}
-
-void a800_rom_bbsb_device::device_reset()
-{
- m_banks[0] = 0;
- m_banks[1] = 0;
-}
-
-
-void xegs_rom_device::device_start()
-{
- save_item(NAME(m_bank));
-}
-
-void xegs_rom_device::device_reset()
-{
- m_bank = 0;
-}
-
-
-void a800_rom_williams_device::device_start()
-{
- save_item(NAME(m_bank));
-}
-
-void a800_rom_williams_device::device_reset()
-{
- m_bank = 0;
-}
-
-
-void a800_rom_express_device::device_start()
-{
- save_item(NAME(m_bank));
-}
-
-void a800_rom_express_device::device_reset()
-{
- m_bank = 0;
-}
-
-
-void a800_rom_turbo_device::device_start()
+void a800_rom_device::cart_map(address_map &map)
{
- save_item(NAME(m_bank));
+ map(0x2000, 0x3fff).lr8(
+ NAME([this](offs_t offset) { return m_rom[offset & (m_rom_size - 1)]; })
+ );
}
-void a800_rom_turbo_device::device_reset()
-{
- m_bank = 0;
-}
+/*-------------------------------------------------
+ Generic right cart 8kb
-void a800_rom_microcalc_device::device_start()
-{
- save_item(NAME(m_bank));
-}
+ -------------------------------------------------*/
-void a800_rom_microcalc_device::device_reset()
+a800_rom_right_device::a800_rom_right_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : a800_rom_device(mconfig, A800_ROM_RIGHT, tag, owner, clock)
{
- m_bank = 0;
}
-
-void a5200_rom_bbsb_device::device_start()
+void a800_rom_right_device::device_start()
{
- save_item(NAME(m_banks));
}
-void a5200_rom_bbsb_device::device_reset()
+void a800_rom_right_device::device_reset()
{
- m_banks[0] = 0;
- m_banks[1] = 0;
+ rd4_w(1);
+ rd5_w(0);
}
-
-
-/*-------------------------------------------------
- mapper specific handlers
- -------------------------------------------------*/
-
-/*-------------------------------------------------
-
- Carts with no bankswitch (8K, 16K)
-
- The cart accessors are mapped in the correct
- range at driver start
-
- -------------------------------------------------*/
-
-uint8_t a800_rom_device::read_80xx(offs_t offset)
+void a800_rom_right_device::cart_map(address_map &map)
{
- return m_rom[offset & (m_rom_size - 1)];
+ map(0x0000, 0x1fff).lr8(
+ NAME([this](offs_t offset) { return m_rom[offset & (m_rom_size - 1)]; })
+ );
}
-
-
/*-------------------------------------------------
- Bounty Bob Strikes Back! cart (40K)
-
- Area 0xa000-0xbfff always point to last 8K bank
- Areas 0x8000-0x8fff and 0x9000-0x9fff are
- separate banks of 4K mapped either in the first
- 16K chunk or in the second 16K chunk
- Bankswitch is controlled by data written in
- 0x8000-0x8fff and 0x9000-0x9fff respectively
+ Generic 16kb RD4 + RD5 cart
-------------------------------------------------*/
-uint8_t a800_rom_bbsb_device::read_80xx(offs_t offset)
+a800_rom_16kb_device::a800_rom_16kb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : a800_rom_device(mconfig, A800_ROM_16KB, tag, owner, clock)
{
- if (offset < 0x1000)
- return m_rom[(offset & 0xfff) + (m_banks[0] * 0x1000) + 0];
- else if (offset < 0x2000)
- return m_rom[(offset & 0xfff) + (m_banks[1] * 0x1000) + 0x4000];
- else
- return m_rom[(offset & 0x1fff) + 0x8000];
}
-void a800_rom_bbsb_device::write_80xx(offs_t offset, uint8_t data)
+void a800_rom_16kb_device::device_start()
{
- uint16_t addr = offset & 0xfff;
- if (addr >= 0xff6 && addr <= 0xff9)
- m_banks[BIT(offset, 12)] = (addr - 0xff6);
}
-/*-------------------------------------------------
-
- XEGS carts (32K, 64K or 128K)
-
- Bankswitch is controlled by data written in
- 0xd500-0xd5ff
-
- -------------------------------------------------*/
-
-uint8_t xegs_rom_device::read_80xx(offs_t offset)
+void a800_rom_16kb_device::device_reset()
{
- if (offset < 0x2000)
- return m_rom[(offset & 0x1fff) + (m_bank * 0x2000)];
- else
- return m_rom[(offset & 0x1fff) + (m_bank_mask * 0x2000)]; // always last 8K bank
-
+ rd_both_w(1);
}
-void xegs_rom_device::write_d5xx(offs_t offset, uint8_t data)
+void a800_rom_16kb_device::cart_map(address_map &map)
{
- m_bank = data & m_bank_mask;
+ map(0x0000, 0x3fff).lr8(
+ NAME([this](offs_t offset) { return m_rom[offset & (m_rom_size - 1)]; })
+ );
}
-
/*-------------------------------------------------
- Williams 64K
-
- The rom is accessed in 8K chunks at 0xa000-0xbfff
- Bankswitch is controlled by writing to 7 diff
- offsets (their location varies with the cart type):
- offs 0 points to bank 0, offs 1 points to bank 1,
- and so on... the rom can be disabled by writing to
- the offsets 0x8-0xf of the same range as the bankswitch
+ XEGS carts (32K, 64K or 128K)
-------------------------------------------------*/
-uint8_t a800_rom_williams_device::read_80xx(offs_t offset)
+xegs_rom_device::xegs_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : a800_rom_device(mconfig, XEGS_ROM, tag, owner, clock)
+ , m_bank(0)
{
- return m_rom[(offset & 0x1fff) + (m_bank * 0x2000)];
}
-void a800_rom_williams_device::write_d5xx(offs_t offset, uint8_t data)
+void xegs_rom_device::device_start()
{
- m_bank = (offset & 0x07);
+ save_item(NAME(m_bank));
}
-/*-------------------------------------------------
-
- Express 64K / Diamond 64K carts
-
- The rom is accessed in 8K chunks at 0xa000-0xbfff
- Bankswitch is the same as above, but writes trigger
- banks in reverse order: offs 7 points to bank 0, offs 6
- points to bank 1, and so on... the rom can be disabled
- by writing to the offsets 0x8-0xf of the same range
- as the bankswitch
-
- -------------------------------------------------*/
-
-uint8_t a800_rom_express_device::read_80xx(offs_t offset)
+void xegs_rom_device::device_reset()
{
- return m_rom[(offset & 0x1fff) + (m_bank * 0x2000)];
+ // TODO: random
+ m_bank = 0;
}
-void a800_rom_express_device::write_d5xx(offs_t offset, uint8_t data)
+// RD5 always maps to the last bank
+void xegs_rom_device::cart_map(address_map &map)
{
- m_bank = (offset ^ 0x07) & 0x0f;
+ map(0x0000, 0x1fff).lr8(
+ NAME([this](offs_t offset) { return m_rom[(offset & 0x1fff) + (m_bank * 0x2000)]; })
+ );
+ map(0x2000, 0x3fff).lr8(
+ NAME([this](offs_t offset) { return m_rom[(offset & 0x1fff) + (m_bank_mask * 0x2000)]; })
+ );
}
-
-/*-------------------------------------------------
-
- Turbosoft 64K / 128K
-
-
- -------------------------------------------------*/
-
-uint8_t a800_rom_turbo_device::read_80xx(offs_t offset)
+void xegs_rom_device::cctl_map(address_map &map)
{
- return m_rom[(offset & 0x1fff) + (m_bank * 0x2000)];
+ map(0x00, 0xff).lw8(
+ NAME([this](offs_t offset, u8 data) { m_bank = data & m_bank_mask; })
+ );
}
-void a800_rom_turbo_device::write_d5xx(offs_t offset, uint8_t data)
-{
- m_bank = offset & m_bank_mask;
-}
+
+// Atari 5200
/*-------------------------------------------------
- Telelink II
+ Carts with no bankswitch (4K, 8K, 16K, 32K)
+ Same as base carts above
-------------------------------------------------*/
-uint8_t a800_rom_telelink2_device::read_80xx(offs_t offset)
-{
- if (offset >= 0x2000)
- return m_rom[offset & 0x1fff];
- if (offset >= 0x1000 && offset < 0x1100)
- return m_nvram[offset & 0xff];
-
- return 0xff;
-}
-
-void a800_rom_telelink2_device::write_80xx(offs_t offset, uint8_t data)
-{
- m_nvram[offset & 0xff] = data | 0xf0; // low 4bits only
-}
-
-uint8_t a800_rom_telelink2_device::read_d5xx(offs_t offset)
+a5200_rom_device::a5200_rom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, type, tag, owner, clock)
+ , device_a5200_cart_interface( mconfig, *this )
{
- // this should affect NVRAM enable / save
- return 0xff;
}
-void a800_rom_telelink2_device::write_d5xx(offs_t offset, uint8_t data)
+a5200_rom_device::a5200_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : a5200_rom_device(mconfig, A5200_ROM, tag, owner, clock)
{
- // this should affect NVRAM enable / save
}
-
-
-/*-------------------------------------------------
-
- SITSA Microcalc
-
-
- -------------------------------------------------*/
-
-uint8_t a800_rom_microcalc_device::read_80xx(offs_t offset)
+void a5200_rom_device::cart_map(address_map &map)
{
- return m_rom[(offset & 0x1fff) + (m_bank * 0x2000)];
+ map(0x0000, 0x7fff).lr8(
+ NAME([this](offs_t offset) { return m_rom[(offset & (m_rom_size - 1))]; })
+ );
}
-void a800_rom_microcalc_device::write_d5xx(offs_t offset, uint8_t data)
+void a5200_rom_device::device_start()
{
- m_bank = data;
}
-
-
-// Atari 5200
-
-
-/*-------------------------------------------------
-
- Carts with no bankswitch (4K, 8K, 16K, 32K)
-
- Same as base carts above
-
- -------------------------------------------------*/
-
/*-------------------------------------------------
Carts with 2x8K (16K) with A13 line not connected
@@ -407,45 +194,17 @@ void a800_rom_microcalc_device::write_d5xx(offs_t offset, uint8_t data)
-------------------------------------------------*/
-uint8_t a5200_rom_2chips_device::read_80xx(offs_t offset)
-{
- if (offset < 0x4000)
- return m_rom[offset & 0x1fff];
- else
- return m_rom[(offset & 0x1fff) + 0x2000];
-}
-
-
-/*-------------------------------------------------
-
- Bounty Bob Strikes Back! cart (40K)
-
- Similar to the A800 version, but:
- Area 0x8000-0xbfff always point to last 8K bank
- (repeated twice)
- Areas 0x4000-0x4fff and 0x5000-0x5fff are
- separate banks of 4K mapped either in the first
- 16K chunk or in the second 16K chunk
- Bankswitch is controlled by data written in
- 0x4000-0x4fff and 0x5000-0x5fff respectively
-
- -------------------------------------------------*/
-
-uint8_t a5200_rom_bbsb_device::read_80xx(offs_t offset)
+a5200_rom_2chips_device::a5200_rom_2chips_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : a5200_rom_device(mconfig, A5200_ROM_2CHIPS, tag, owner, clock)
{
- if (offset < 0x1000)
- return m_rom[(offset & 0xfff) + (m_banks[0] * 0x1000) + 0];
- else if (offset < 0x2000)
- return m_rom[(offset & 0xfff) + (m_banks[1] * 0x1000) + 0x4000];
- else if (offset >= 0x4000)
- return m_rom[(offset & 0x1fff) + 0x8000];
- else
- return 0;
}
-void a5200_rom_bbsb_device::write_80xx(offs_t offset, uint8_t data)
+void a5200_rom_2chips_device::cart_map(address_map &map)
{
- uint16_t addr = offset & 0xfff;
- if (addr >= 0xff6 && addr <= 0xff9)
- m_banks[BIT(offset, 12)] = (addr - 0xff6);
+ map(0x0000, 0x3fff).lr8(
+ NAME([this](offs_t offset) { return m_rom[offset & 0x1fff]; })
+ );
+ map(0x4000, 0x7fff).lr8(
+ NAME([this](offs_t offset) { return m_rom[(offset & 0x1fff) + 0x2000]; })
+ );
}
diff --git a/src/devices/bus/a800/rom.h b/src/devices/bus/a800/rom.h
index e48b4a4ed7c..8d6b551519a 100644
--- a/src/devices/bus/a800/rom.h
+++ b/src/devices/bus/a800/rom.h
@@ -1,229 +1,102 @@
// license:BSD-3-Clause
-// copyright-holders:Fabio Priuli
+// copyright-holders:Fabio Priuli, Angelo Salese
+
#ifndef MAME_BUS_A800_ROM_H
#define MAME_BUS_A800_ROM_H
#pragma once
#include "a800_slot.h"
+#include "machine/nvram.h"
-// ======================> a800_rom_device
-
class a800_rom_device : public device_t,
public device_a800_cart_interface
{
public:
- // construction/destruction
a800_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual uint8_t read_80xx(offs_t offset) override;
+ virtual void cart_map(address_map &map) override;
+ virtual std::tuple<int, int> get_initial_rd_state() override { return std::make_tuple(0, 1); }
protected:
a800_rom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
- // device-level overrides
virtual void device_start() override;
virtual void device_reset() override;
};
-
-// ======================> a800_rom_bbsb_device
-
-class a800_rom_bbsb_device : public a800_rom_device
+class a800_rom_right_device : public a800_rom_device
{
public:
- // construction/destruction
- a800_rom_bbsb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ a800_rom_right_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual uint8_t read_80xx(offs_t offset) override;
- virtual void write_80xx(offs_t offset, uint8_t data) override;
+ virtual void cart_map(address_map &map) override;
+ virtual std::tuple<int, int> get_initial_rd_state() override { return std::make_tuple(1, 0); }
protected:
- // device-level overrides
virtual void device_start() override;
virtual void device_reset() override;
-
- int m_banks[2];
};
-
-// ======================> a800_rom_williams_device
-
-class a800_rom_williams_device : public a800_rom_device
+class a800_rom_16kb_device : public a800_rom_device
{
public:
- // construction/destruction
- a800_rom_williams_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ a800_rom_16kb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual uint8_t read_80xx(offs_t offset) override;
- virtual void write_d5xx(offs_t offset, uint8_t data) override;
+ virtual void cart_map(address_map &map) override;
+ virtual std::tuple<int, int> get_initial_rd_state() override { return std::make_tuple(1, 1); }
protected:
- // device-level overrides
virtual void device_start() override;
virtual void device_reset() override;
-
- int m_bank;
};
-// ======================> a800_rom_express_device
-
-class a800_rom_express_device : public a800_rom_device
-{
-public:
- // construction/destruction
- a800_rom_express_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual uint8_t read_80xx(offs_t offset) override;
- virtual void write_d5xx(offs_t offset, uint8_t data) override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
-
- int m_bank;
-};
-
-
-// ======================> a800_rom_blizzard_device
-
-class a800_rom_blizzard_device : public a800_rom_device
-{
-public:
- // construction/destruction
- a800_rom_blizzard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual uint8_t read_80xx(offs_t offset) override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
-};
-
-
-// ======================> a800_rom_turbo_device
-
-class a800_rom_turbo_device : public a800_rom_device
+class xegs_rom_device : public a800_rom_device
{
public:
- // construction/destruction
- a800_rom_turbo_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ xegs_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual uint8_t read_80xx(offs_t offset) override;
- virtual void write_d5xx(offs_t offset, uint8_t data) override;
+ virtual void cart_map(address_map &map) override;
+ virtual void cctl_map(address_map &map) override;
+ virtual std::tuple<int, int> get_initial_rd_state() override { return std::make_tuple(1, 1); }
protected:
- // device-level overrides
virtual void device_start() override;
virtual void device_reset() override;
int m_bank;
};
-
-// ======================> a800_rom_telelink2_device
-
-class a800_rom_telelink2_device : public a800_rom_device
-{
-public:
- // construction/destruction
- a800_rom_telelink2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual uint8_t read_80xx(offs_t offset) override;
- virtual void write_80xx(offs_t offset, uint8_t data) override;
- virtual uint8_t read_d5xx(offs_t offset) override;
- virtual void write_d5xx(offs_t offset, uint8_t data) override;
-};
-
-
-// ======================> a800_rom_microcalc_device
-
-class a800_rom_microcalc_device : public a800_rom_device
+class a5200_rom_device : public device_t,
+ public device_a5200_cart_interface
{
public:
- // construction/destruction
- a800_rom_microcalc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ a5200_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual uint8_t read_80xx(offs_t offset) override;
- virtual void write_d5xx(offs_t offset, uint8_t data) override;
+ virtual void cart_map(address_map &map) override;
protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
-
- int m_bank;
-};
-
-
-// ======================> xegs_rom_device
-
-class xegs_rom_device : public a800_rom_device
-{
-public:
- // construction/destruction
- xegs_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ a5200_rom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
- // device-level overrides
virtual void device_start() override;
- virtual void device_reset() override;
-
- virtual uint8_t read_80xx(offs_t offset) override;
- virtual void write_d5xx(offs_t offset, uint8_t data) override;
-
-protected:
- int m_bank;
};
-
-// ======================> a5200_rom_2chips_device
-
-class a5200_rom_2chips_device : public a800_rom_device
+class a5200_rom_2chips_device : public a5200_rom_device
{
public:
- // construction/destruction
a5200_rom_2chips_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual uint8_t read_80xx(offs_t offset) override;
+ virtual void cart_map(address_map &map) override;
};
-
-// ======================> a5200_rom_bbsb_device
-
-class a5200_rom_bbsb_device : public a800_rom_device
-{
-public:
- // construction/destruction
- a5200_rom_bbsb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual uint8_t read_80xx(offs_t offset) override;
- virtual void write_80xx(offs_t offset, uint8_t data) override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
-
- int m_banks[2];
-};
-
-
-
-// device type definition
-DECLARE_DEVICE_TYPE(A800_ROM, a800_rom_device)
-DECLARE_DEVICE_TYPE(A800_ROM_BBSB, a800_rom_bbsb_device)
-DECLARE_DEVICE_TYPE(A800_ROM_WILLIAMS, a800_rom_williams_device)
-DECLARE_DEVICE_TYPE(A800_ROM_EXPRESS, a800_rom_express_device)
-DECLARE_DEVICE_TYPE(A800_ROM_TURBO, a800_rom_turbo_device)
-DECLARE_DEVICE_TYPE(A800_ROM_TELELINK2, a800_rom_telelink2_device)
-DECLARE_DEVICE_TYPE(A800_ROM_MICROCALC, a800_rom_microcalc_device)
-DECLARE_DEVICE_TYPE(XEGS_ROM, xegs_rom_device)
-DECLARE_DEVICE_TYPE(A5200_ROM_2CHIPS, a5200_rom_2chips_device)
-DECLARE_DEVICE_TYPE(A5200_ROM_BBSB, a5200_rom_bbsb_device)
+DECLARE_DEVICE_TYPE(A800_ROM, a800_rom_device)
+DECLARE_DEVICE_TYPE(A800_ROM_RIGHT, a800_rom_right_device)
+DECLARE_DEVICE_TYPE(A800_ROM_16KB, a800_rom_16kb_device)
+DECLARE_DEVICE_TYPE(XEGS_ROM, xegs_rom_device)
+DECLARE_DEVICE_TYPE(A5200_ROM, a5200_rom_device)
+DECLARE_DEVICE_TYPE(A5200_ROM_2CHIPS, a5200_rom_2chips_device)
#endif // MAME_BUS_A800_ROM_H
diff --git a/src/devices/bus/a800/rtime8.cpp b/src/devices/bus/a800/rtime8.cpp
index ec59036bc4b..88f133941b6 100644
--- a/src/devices/bus/a800/rtime8.cpp
+++ b/src/devices/bus/a800/rtime8.cpp
@@ -6,8 +6,7 @@
The circuitry in this clock cartridge is very simple, containing the RTC itself, oscillator and
battery, and a 74HCT138 to decode the $D5B8-$D5BF address range from the /CCTL and A7-A3 pins. No ROM
- is included; however, the cartridge can be placed in the (currently unemulated) passthrough slot of the
- SpartaDOS X cartridge.
+ is included; the cartridge can be placed in the passthrough slot of the SpartaDOS X cartridge.
***********************************************************************************************************/
@@ -24,7 +23,7 @@ DEFINE_DEVICE_TYPE(A800_RTIME8, a800_rtime8_device, "a800_rtime8", "ICD R-Time 8
a800_rtime8_device::a800_rtime8_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: device_t(mconfig, A800_RTIME8, tag, owner, clock)
- , device_a800_cart_interface(mconfig, *this)
+ , device_a800_cart_interface(mconfig, *this)
, m_rtc(*this, "rtc")
{
}
@@ -51,20 +50,11 @@ void a800_rtime8_device::device_start()
// read_d5xx - handle reads from $D500-$D5FF
//-------------------------------------------------
-u8 a800_rtime8_device::read_d5xx(offs_t offset)
+// TODO: 4-bit access, D7-D4 returns open bus
+void a800_rtime8_device::cctl_map(address_map &map)
{
- if ((offset & 0xf8) == 0xb8)
- return m_rtc->read(); // TODO: D7-D4 is open bus, in case this matters
- else
- return 0xff;
-}
-
-//-------------------------------------------------
-// write_d5xx - handle writes to $D500-$D5FF
-//-------------------------------------------------
-
-void a800_rtime8_device::write_d5xx(offs_t offset, u8 data)
-{
- if ((offset & 0xf8) == 0xb8)
- m_rtc->write(data & 0x0f);
+ map(0xb8, 0xbf).lrw8(
+ NAME([this](offs_t offset) { return m_rtc->read() | 0xf0; }),
+ NAME([this](offs_t offset, u8 data) { m_rtc->write(data & 0x0f); })
+ );
}
diff --git a/src/devices/bus/a800/rtime8.h b/src/devices/bus/a800/rtime8.h
index 713c3c9ef72..ba37059c705 100644
--- a/src/devices/bus/a800/rtime8.h
+++ b/src/devices/bus/a800/rtime8.h
@@ -15,23 +15,18 @@
class a800_rtime8_device : public device_t, public device_a800_cart_interface
{
public:
- // construction/destruction
a800_rtime8_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+ virtual void cctl_map(address_map &map) override;
+
protected:
- // device-level overrides
virtual void device_add_mconfig(machine_config &config) override;
virtual void device_start() override;
- // device_a800_cart_interface overrides
- virtual u8 read_d5xx(offs_t offset) override;
- virtual void write_d5xx(offs_t offset, u8 data) override;
-
private:
required_device<m3002_device> m_rtc;
};
-// device type declaration
DECLARE_DEVICE_TYPE(A800_RTIME8, a800_rtime8_device)
#endif // MAME_BUS_A800_RTIME8_H
diff --git a/src/devices/bus/a800/sic.cpp b/src/devices/bus/a800/sic.cpp
new file mode 100644
index 00000000000..fa5aaadb802
--- /dev/null
+++ b/src/devices/bus/a800/sic.cpp
@@ -0,0 +1,114 @@
+// license: BSD-3-Clause
+// copyright-holders: Angelo Salese
+/**************************************************************************************************
+
+SIC! "Super Inexpensive Cartridge!"
+
+TODO:
+- Unknown flash types used, Altirra just observed a Winbond 29C020;
+- Customizable Jumper/switch handling for pin signals;
+
+**************************************************************************************************/
+
+#include "emu.h"
+#include "sic.h"
+
+// device type definition
+DEFINE_DEVICE_TYPE(A800_SIC_128KB, a800_sic_128kb_device, "a800_siccart_128kb", "Atari 8-bit SIC! 128KB flash ROM cart")
+DEFINE_DEVICE_TYPE(A800_SIC_256KB, a800_sic_256kb_device, "a800_siccart_256kb", "Atari 8-bit SIC! 256KB flash ROM cart")
+DEFINE_DEVICE_TYPE(A800_SIC_512KB, a800_sic_512kb_device, "a800_siccart_512kb", "Atari 8-bit SIC! 512KB flash ROM cart")
+
+a800_sic_128kb_device::a800_sic_128kb_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : a800_rom_device(mconfig, type, tag, owner, clock)
+ , m_flash(*this, "flash")
+ , m_bank(0)
+ , m_write_protect(true)
+{
+}
+
+a800_sic_128kb_device::a800_sic_128kb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : a800_sic_128kb_device(mconfig, A800_SIC_128KB, tag, owner, clock)
+{
+}
+
+void a800_sic_128kb_device::device_add_mconfig(machine_config &config)
+{
+ AMD_29F010(config, m_flash);
+}
+
+void a800_sic_128kb_device::device_start()
+{
+ save_item(NAME(m_bank));
+ save_item(NAME(m_write_protect));
+}
+
+void a800_sic_128kb_device::device_reset()
+{
+ // TODO: ugly assignment, and shouldn't happen in device_reset
+ // TODO: assert against intended size for slot
+ memcpy(m_flash->base(), m_rom, get_rom_size());
+ m_bank_mask = (get_rom_size() / 0x4000) - 1;
+
+ // value of 0 for config_bank_w confirmed
+ m_bank = 0;
+ m_write_protect = true;
+}
+
+// SIC! maps rd4 and rd5 linearly
+// so that 0x8000 maps to 0 and 0xa000 to 0x2000
+u8 a800_sic_128kb_device::read(offs_t offset)
+{
+ return m_flash->read((offset & 0x3fff) | (m_bank * 0x4000));
+}
+
+void a800_sic_128kb_device::write(offs_t offset, u8 data)
+{
+ if (!m_write_protect)
+ m_flash->write((offset & 0x3fff) | (m_bank * 0x4000), data);
+}
+
+void a800_sic_128kb_device::cart_map(address_map &map)
+{
+ map(0x0000, 0x3fff).rw(FUNC(a800_sic_128kb_device::read), FUNC(a800_sic_128kb_device::write));
+}
+
+/*
+ * 1--- ---- enable flash write
+ * -1-- ---- RD4 enable
+ * --0- ---- RD5 enable
+ * ---x xxxx ROM bank, where upper bits are unused for 128KB and 256KB versions
+ */
+void a800_sic_128kb_device::config_bank_w(offs_t offset, u8 data)
+{
+ m_bank = (data & m_bank_mask);
+ rd4_w(BIT(data, 5));
+ rd5_w(!(BIT(data, 6)));
+ m_write_protect = !(BIT(data, 7));
+}
+
+void a800_sic_128kb_device::cctl_map(address_map &map)
+{
+ map(0x00, 0x1f).w(FUNC(a800_sic_128kb_device::config_bank_w));
+}
+
+// 256/512KB variants
+
+a800_sic_256kb_device::a800_sic_256kb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : a800_sic_128kb_device(mconfig, A800_SIC_256KB, tag, owner, clock)
+{
+}
+
+void a800_sic_256kb_device::device_add_mconfig(machine_config &config)
+{
+ AMD_29LV200T(config, m_flash);
+}
+
+a800_sic_512kb_device::a800_sic_512kb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : a800_sic_128kb_device(mconfig, A800_SIC_512KB, tag, owner, clock)
+{
+}
+
+void a800_sic_512kb_device::device_add_mconfig(machine_config &config)
+{
+ AMD_29F040(config, m_flash);
+}
diff --git a/src/devices/bus/a800/sic.h b/src/devices/bus/a800/sic.h
new file mode 100644
index 00000000000..52dba880bae
--- /dev/null
+++ b/src/devices/bus/a800/sic.h
@@ -0,0 +1,64 @@
+// license: BSD-3-Clause
+// copyright-holders: Angelo Salese
+
+#ifndef MAME_BUS_A800_SIC_H
+#define MAME_BUS_A800_SIC_H
+
+#pragma once
+
+#include "rom.h"
+#include "machine/intelfsh.h"
+
+class a800_sic_128kb_device : public a800_rom_device
+{
+public:
+ a800_sic_128kb_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+ a800_sic_128kb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void cart_map(address_map &map) override;
+ virtual void cctl_map(address_map &map) override;
+ virtual std::tuple<int, int> get_initial_rd_state() override { return std::make_tuple(0, 1); }
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override;
+
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ required_device<intelfsh8_device> m_flash;
+
+private:
+ int m_bank;
+ bool m_write_protect;
+ int m_bank_mask;
+
+ u8 read(offs_t offset);
+ void write(offs_t offset, u8 data);
+
+ u8 config_bank_r(offs_t offset);
+ void config_bank_w(offs_t offset, u8 data);
+};
+
+class a800_sic_256kb_device : public a800_sic_128kb_device
+{
+public:
+ a800_sic_256kb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override;
+};
+
+class a800_sic_512kb_device : public a800_sic_128kb_device
+{
+public:
+ a800_sic_512kb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override;
+};
+
+DECLARE_DEVICE_TYPE(A800_SIC_128KB, a800_sic_128kb_device)
+DECLARE_DEVICE_TYPE(A800_SIC_256KB, a800_sic_256kb_device)
+DECLARE_DEVICE_TYPE(A800_SIC_512KB, a800_sic_512kb_device)
+
+#endif // MAME_BUS_A800_SIC_H
diff --git a/src/devices/bus/a800/sparta.cpp b/src/devices/bus/a800/sparta.cpp
index 8b8242d8dad..f4e6e69e25f 100644
--- a/src/devices/bus/a800/sparta.cpp
+++ b/src/devices/bus/a800/sparta.cpp
@@ -1,73 +1,189 @@
// license:BSD-3-Clause
-// copyright-holders:Fabio Priuli
-/***********************************************************************************************************
+// copyright-holders:Fabio Priuli, Angelo Salese
+/**************************************************************************************************
- A800 SpartaDOS cart emulation
+SpartaDOS X (SDX) cart emulation
-***********************************************************************************************************/
+https://sdx.atari8.info/index.php?show=en_introduction
+SDX 128KB a newer format used by the 200x releases: adds an extra bank access to $d5f0-$d5f7.
+Should mirror $e8-$ef to $fx by logic.
+
+**************************************************************************************************/
#include "emu.h"
#include "sparta.h"
-
+#include "a800_carts.h"
//-------------------------------------------------
// constructor
//-------------------------------------------------
-DEFINE_DEVICE_TYPE(A800_ROM_SPARTADOS, a800_rom_spartados_device, "a800_sparta", "Atari 800 SpartaDOS ROM Carts")
+DEFINE_DEVICE_TYPE(A800_ROM_SPARTADOS, a800_rom_spartados_device, "a800_sparta", "Atari 8-bit SpartaDOS X cart")
+DEFINE_DEVICE_TYPE(A800_ROM_SPARTADOS_128KB, a800_rom_spartados_128kb_device, "a800_sparta_128kb", "Atari 8-bit SpartaDOS X 128KB cart")
+a800_rom_spartados_device::a800_rom_spartados_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : a800_rom_device(mconfig, type, tag, owner, clock)
+ , m_bank(0)
+ , m_subcart(*this, "subcart")
+ , m_cart_view(*this, "cart_view")
+{
+
+}
a800_rom_spartados_device::a800_rom_spartados_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : a800_rom_device(mconfig, A800_ROM_SPARTADOS, tag, owner, clock)
- , m_bank(0)
- , m_subslot_enabled(0)
+ : a800_rom_spartados_device(mconfig, A800_ROM_SPARTADOS, tag, owner, clock)
{
}
+static void spartados_carts(device_slot_interface &device)
+{
+ // NB: game carts will usually override SDX boot, meaning that they aren't all that useful to hook up here.
+ // also a SDX attached to another SDX just produces a black screen.
+ // we just hook them all up for the sake of completeness.
+ a800_left(device);
+}
+void a800_rom_spartados_device::subcart_rd4_w(int state)
+{
+ m_subcart_rd4_enabled = state;
+ if (m_subcart_enabled)
+ {
+ rd4_w(m_subcart_rd4_enabled);
+ rd5_w(m_subcart_rd5_enabled);
+ }
+}
+
+void a800_rom_spartados_device::subcart_rd5_w(int state)
+{
+ m_subcart_rd5_enabled = state;
+ if (m_subcart_enabled)
+ {
+ rd4_w(m_subcart_rd4_enabled);
+ rd5_w(m_subcart_rd5_enabled);
+ }
+}
+
+void a800_rom_spartados_device::device_add_mconfig(machine_config &config)
+{
+ A800_CART_SLOT(config, m_subcart, spartados_carts, nullptr);
+ m_subcart->rd4_callback().set(FUNC(a800_rom_spartados_device::subcart_rd4_w));
+ m_subcart->rd5_callback().set(FUNC(a800_rom_spartados_device::subcart_rd5_w));
+}
void a800_rom_spartados_device::device_start()
{
save_item(NAME(m_bank));
- save_item(NAME(m_subslot_enabled));
+ save_item(NAME(m_subcart_enabled));
}
void a800_rom_spartados_device::device_reset()
{
- m_bank = 0;
- m_subslot_enabled = 0;
+ m_bank = 7;
+ m_subcart_enabled = false;
+ if (!m_subcart->exists())
+ m_subcart_rd4_enabled = m_subcart_rd5_enabled = 0;
+ else
+ std::tie(m_subcart_rd4_enabled, m_subcart_rd5_enabled) = m_subcart->get_initial_rd_state();
+
+ m_cart_view.select(0);
}
-/*-------------------------------------------------
- mapper specific handlers
- -------------------------------------------------*/
+void a800_rom_spartados_device::cart_map(address_map &map)
+{
+ map(0x0000, 0x3fff).view(m_cart_view);
+ m_cart_view[0](0x2000, 0x3fff).lr8(
+ NAME([this](offs_t offset) { return m_rom[(offset & 0x1fff) + (m_bank * 0x2000)]; })
+ );
+ m_cart_view[1](0x0000, 0x1fff).rw(m_subcart, FUNC(a800_cart_slot_device::read_cart<0>), FUNC(a800_cart_slot_device::write_cart<0>));
+ m_cart_view[1](0x2000, 0x3fff).rw(m_subcart, FUNC(a800_cart_slot_device::read_cart<1>), FUNC(a800_cart_slot_device::write_cart<1>));
+}
-/*-------------------------------------------------
+void a800_rom_spartados_device::cctl_map(address_map &map)
+{
+ map(0x00, 0xff).rw(m_subcart, FUNC(a800_cart_slot_device::read_cctl), FUNC(a800_cart_slot_device::write_cctl));
+ map(0xe0, 0xe7).rw(FUNC(a800_rom_spartados_device::rom_bank_r), FUNC(a800_rom_spartados_device::rom_bank_w));
+ map(0xe8, 0xef).rw(FUNC(a800_rom_spartados_device::subslot_r), FUNC(a800_rom_spartados_device::subslot_w));
+}
- SpartaDOS 64K carts
+inline void a800_rom_spartados_device::bank_config_access(offs_t offset)
+{
+ rd4_w(0);
+ rd5_w(1);
+ m_cart_view.select(0);
+ m_bank = ((offset ^ m_bank_mask) & m_bank_mask);
+ m_subcart_enabled = false;
+}
- Similar to Express / Diamond carts, because
- bankswitch is controlled by writing to 7 diff
- offsets in reverse order, but writes to offsets
- 0x8-0xf also enable/disable subslot
+uint8_t a800_rom_spartados_device::rom_bank_r(offs_t offset)
+{
+ if(!machine().side_effects_disabled())
+ bank_config_access(offset);
- -------------------------------------------------*/
+ return m_subcart->read_cctl(offset | 0xe0);
+}
-uint8_t a800_rom_spartados_device::read_80xx(offs_t offset)
+void a800_rom_spartados_device::rom_bank_w(offs_t offset, uint8_t data)
{
- if (!m_subslot_enabled)
- return m_rom[(offset & 0x1fff) + (m_bank * 0x2000)];
- else
- return 0xff; // subslot, currently not implemented
+ bank_config_access(offset);
+ m_subcart->write_cctl(offset | 0xe0, data);
}
-void a800_rom_spartados_device::write_d5xx(offs_t offset, uint8_t data)
+inline void a800_rom_spartados_device::subslot_config_access(offs_t offset)
{
- if (offset & 0x08)
- m_subslot_enabled = !BIT(offset, 2);
+ if (!BIT(offset, 2))
+ {
+ m_subcart_enabled = true;
+ rd4_w(m_subcart_rd4_enabled);
+ rd5_w(m_subcart_rd5_enabled);
+ m_cart_view.select(1);
+ }
else
- m_bank = (offset ^ 0x07) & 0x0f;
+ {
+ m_subcart_enabled = false;
+ rd4_w(0);
+ rd5_w(0);
+ }
+}
+
+u8 a800_rom_spartados_device::subslot_r(offs_t offset)
+{
+ if(!machine().side_effects_disabled())
+ subslot_config_access(offset);
+
+ return m_subcart->read_cctl(offset | 0xe8);
+}
+
+void a800_rom_spartados_device::subslot_w(offs_t offset, u8 data)
+{
+ subslot_config_access(offset);
+
+ return m_subcart->write_cctl(offset | 0xe8, data);
+}
+
+/*-------------------------------------------------
+
+ SpartaDOS 128KB variant
+ -------------------------------------------------*/
+
+a800_rom_spartados_128kb_device::a800_rom_spartados_128kb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : a800_rom_spartados_device(mconfig, A800_ROM_SPARTADOS_128KB, tag, owner, clock)
+{
+}
+
+// NB: .select not .mirror, we need the offset to propagate to sub cart cctl
+void a800_rom_spartados_128kb_device::cctl_map(address_map &map)
+{
+ a800_rom_spartados_device::cctl_map(map);
+ map(0xe0, 0xe7).select(0x10).rw(FUNC(a800_rom_spartados_128kb_device::rom_bank_r), FUNC(a800_rom_spartados_128kb_device::rom_bank_w));
+ map(0xe8, 0xef).select(0x10).rw(FUNC(a800_rom_spartados_128kb_device::subslot_r), FUNC(a800_rom_spartados_128kb_device::subslot_w));
+}
+
+inline void a800_rom_spartados_128kb_device::bank_config_access(offs_t offset)
+{
+ a800_rom_spartados_device::bank_config_access(offset);
+ const u8 upper_bank = !BIT(offset, 4);
+ m_bank = ((offset ^ 7) & 7) | (upper_bank << 3);
}
diff --git a/src/devices/bus/a800/sparta.h b/src/devices/bus/a800/sparta.h
index ea211472f31..31c4c439a28 100644
--- a/src/devices/bus/a800/sparta.h
+++ b/src/devices/bus/a800/sparta.h
@@ -1,36 +1,63 @@
// license:BSD-3-Clause
-// copyright-holders:Fabio Priuli
+// copyright-holders:Fabio Priuli, Angelo Salese
#ifndef MAME_BUS_A800_SPARTA_H
#define MAME_BUS_A800_SPARTA_H
#pragma once
#include "rom.h"
-
-
-// ======================> a800_rom_spartados_device
+#include "a800_slot.h"
class a800_rom_spartados_device : public a800_rom_device
{
public:
- // construction/destruction
+ a800_rom_spartados_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
a800_rom_spartados_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual uint8_t read_80xx(offs_t offset) override;
- virtual void write_d5xx(offs_t offset, uint8_t data) override;
+ virtual void cart_map(address_map &map) override;
+ virtual void cctl_map(address_map &map) override;
+ virtual std::tuple<int, int> get_initial_rd_state() override { return std::make_tuple(0, 1); }
protected:
- // device-level overrides
virtual void device_start() override;
virtual void device_reset() override;
- int m_bank, m_subslot_enabled;
+ virtual void device_add_mconfig(machine_config &config) override;
+
+ virtual void bank_config_access(offs_t offset);
+
+ int m_bank;
+
+ u8 rom_bank_r(offs_t offset);
+ void rom_bank_w(offs_t offset, u8 data);
+
+ u8 subslot_r(offs_t offset);
+ void subslot_w(offs_t offset, u8 data);
+private:
+ required_device<a800_cart_slot_device> m_subcart;
+ memory_view m_cart_view;
+
+ void subslot_config_access(offs_t offset);
+ void subcart_rd4_w( int state );
+ void subcart_rd5_w( int state );
+
+ bool m_subcart_enabled;
+ int m_subcart_rd4_enabled = 0, m_subcart_rd5_enabled = 0;
};
+class a800_rom_spartados_128kb_device : public a800_rom_spartados_device
+{
+public:
+ a800_rom_spartados_128kb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void cctl_map(address_map &map) override;
+protected:
+ virtual void bank_config_access(offs_t offset) override;
+};
-// device type definition
-DECLARE_DEVICE_TYPE(A800_ROM_SPARTADOS, a800_rom_spartados_device)
+DECLARE_DEVICE_TYPE(A800_ROM_SPARTADOS, a800_rom_spartados_device)
+DECLARE_DEVICE_TYPE(A800_ROM_SPARTADOS_128KB, a800_rom_spartados_128kb_device)
#endif // MAME_BUS_A800_SPARTA_H
diff --git a/src/devices/bus/a800/supercharger.cpp b/src/devices/bus/a800/supercharger.cpp
new file mode 100644
index 00000000000..88f721dd35f
--- /dev/null
+++ b/src/devices/bus/a800/supercharger.cpp
@@ -0,0 +1,94 @@
+// license: BSD-3-Clause
+// copyright-holders: Angelo Salese
+// thanks-to: Jindroush, HiassofT
+/**************************************************************************************************
+
+"SuperCharger"
+
+multiply/divide math unit (unknown 18-pins chip type, scratched on PCB)
+used by "Assault Force" floppy disk.
+Not to be confused with Starpath SuperCharger, which is for Atari VCS.
+
+**************************************************************************************************/
+
+#include "emu.h"
+#include "supercharger.h"
+
+// device type definition
+DEFINE_DEVICE_TYPE(A800_SUPER_CHARGER, a800_supercharger_device, "a800_supercharger", "Atari 8-bit SuperCharger 3D math unit cart")
+
+a800_supercharger_device::a800_supercharger_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, A800_SUPER_CHARGER, tag, owner, clock)
+ , device_a800_cart_interface(mconfig, *this)
+ , m_status(0)
+{
+}
+
+void a800_supercharger_device::device_start()
+{
+ save_pointer(NAME(m_data), 3);
+ save_item(NAME(m_status));
+}
+
+void a800_supercharger_device::device_reset()
+{
+ std::fill(std::begin(m_data), std::end(m_data), 0);
+ m_status = 1;
+}
+
+void a800_supercharger_device::cctl_map(address_map &map)
+{
+ map(0x00, 0x02).mirror(0xfc).lrw8(
+ NAME([this](offs_t offset) { return m_data[offset]; }),
+ NAME([this](offs_t offset, u8 data) { m_data[offset] = data; })
+ );
+ map(0x03, 0x03).mirror(0xfc).rw(FUNC(a800_supercharger_device::status_r), FUNC(a800_supercharger_device::command_w));
+}
+
+/*
+ * ---- ---x last command status
+ * (0) valid
+ * (1) error (division by zero, result == 0 or unsupported command)
+ */
+u8 a800_supercharger_device::status_r(offs_t offset)
+{
+ return m_status;
+}
+
+// TODO: not instant
+// (program sets four NOPs after each call)
+void a800_supercharger_device::command_w(offs_t offset, u8 data)
+{
+ switch (data)
+ {
+ // division
+ case 1:
+ {
+ const u32 numerator = (m_data[1] << 8) | (m_data[2] & 0xff);
+ const u32 denominator = m_data[0];
+
+ if (m_data[0] < m_data[1] || denominator == 0)
+ m_status = 1;
+ else
+ {
+ m_data[1] = (u8)(numerator % denominator);
+ m_data[2] = (u8)(numerator / denominator);
+ m_status = 0;
+ }
+ break;
+ }
+ // multiplication
+ case 2:
+ {
+ const u32 result = m_data[0] * m_data[2];
+
+ m_data[1] = (u8)(result >> 8);
+ m_data[2] = (u8)(result & 0xff);
+ m_status = 0;
+ break;
+ }
+ default:
+ m_status = 1;
+ break;
+ }
+}
diff --git a/src/devices/bus/a800/supercharger.h b/src/devices/bus/a800/supercharger.h
new file mode 100644
index 00000000000..cca2ea30236
--- /dev/null
+++ b/src/devices/bus/a800/supercharger.h
@@ -0,0 +1,35 @@
+// license: BSD-3-Clause
+// copyright-holders: Angelo Salese
+
+#ifndef MAME_BUS_A800_SUPERCHARGER_H
+#define MAME_BUS_A800_SUPERCHARGER_H
+
+#pragma once
+
+#include "a800_slot.h"
+
+
+// ======================> a800_rtime8_device
+
+class a800_supercharger_device : public device_t,
+ public device_a800_cart_interface
+{
+public:
+ a800_supercharger_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void cctl_map(address_map &map) override;
+
+protected:
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ u8 m_data[3]{};
+ u8 m_status;
+
+ u8 status_r(offs_t offset);
+ void command_w(offs_t offset, u8 data);
+};
+
+DECLARE_DEVICE_TYPE(A800_SUPER_CHARGER, a800_supercharger_device)
+
+#endif // MAME_BUS_A800_SUPERCHARGER_H
diff --git a/src/devices/bus/a800/telelink2.cpp b/src/devices/bus/a800/telelink2.cpp
new file mode 100644
index 00000000000..eb4238258f2
--- /dev/null
+++ b/src/devices/bus/a800/telelink2.cpp
@@ -0,0 +1,64 @@
+// license: BSD-3-Clause
+// copyright-holders: Fabio Priuli, Angelo Salese
+/**************************************************************************************************
+
+Telelink II
+
+4-bit X2212 NVRAM and other stuff not known at current stage.
+RD4 hardwired to +5V
+
+TODO:
+- CCTL mapping details are unknown;
+- Requires modem i/f to work;
+
+**************************************************************************************************/
+
+#include "emu.h"
+#include "telelink2.h"
+
+DEFINE_DEVICE_TYPE(A800_ROM_TELELINK2, a800_rom_telelink2_device, "a800_tlink2", "Atari 8-bit Telelink II cart")
+
+
+a800_rom_telelink2_device::a800_rom_telelink2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : a800_rom_device(mconfig, A800_ROM_TELELINK2, tag, owner, clock)
+ , m_nvram(*this, "nvram")
+{
+}
+
+void a800_rom_telelink2_device::device_add_mconfig(machine_config &config)
+{
+ NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_1);
+}
+
+void a800_rom_telelink2_device::device_start()
+{
+ const u32 nvram_size = 0x100;
+
+ m_nvram_ptr = std::make_unique<uint8_t[]>(nvram_size);
+ m_nvram->set_base(m_nvram_ptr.get(), nvram_size);
+
+ save_pointer(NAME(m_nvram_ptr), nvram_size);
+}
+
+void a800_rom_telelink2_device::device_reset()
+{
+}
+
+
+void a800_rom_telelink2_device::cart_map(address_map &map)
+{
+ // 4-bit NVRAM
+ map(0x1000, 0x10ff).lrw8(
+ NAME([this](offs_t offset) { return m_nvram_ptr[offset & 0xff]; }),
+ NAME([this](offs_t offset, u8 data) { m_nvram_ptr[offset & 0xff] = data | 0xf0; })
+ );
+ map(0x2000, 0x3fff).lr8(
+ NAME([this](offs_t offset) { return m_rom[offset & 0x1fff]; })
+ );
+}
+
+void a800_rom_telelink2_device::cctl_map(address_map &map)
+{
+// map(0x01, 0x01) read before reading NVRAM, value discarded
+// map(0x02, 0x02) written before writing NVRAM when changing stored information
+}
diff --git a/src/devices/bus/a800/telelink2.h b/src/devices/bus/a800/telelink2.h
new file mode 100644
index 00000000000..a3b30da0a87
--- /dev/null
+++ b/src/devices/bus/a800/telelink2.h
@@ -0,0 +1,34 @@
+// license: BSD-3-Clause
+// copyright-holders: Fabio Priuli, Angelo Salese
+
+#ifndef MAME_BUS_A800_TELELINK2_H
+#define MAME_BUS_A800_TELELINK2_H
+
+#pragma once
+
+#include "rom.h"
+
+class a800_rom_telelink2_device : public a800_rom_device
+{
+public:
+ // construction/destruction
+ a800_rom_telelink2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void cart_map(address_map &map) override;
+ virtual void cctl_map(address_map &map) override;
+
+ // RD4 tied to +5V, assume always enabled
+ virtual std::tuple<int, int> get_initial_rd_state() override { return std::make_tuple(1, 1); }
+
+private:
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+
+ required_device<nvram_device> m_nvram;
+ std::unique_ptr<uint8_t[]> m_nvram_ptr;
+};
+
+DECLARE_DEVICE_TYPE(A800_ROM_TELELINK2, a800_rom_telelink2_device)
+
+#endif // MAME_BUS_A800_TELELINK2_H
diff --git a/src/devices/bus/a800/ultracart.cpp b/src/devices/bus/a800/ultracart.cpp
new file mode 100644
index 00000000000..fa8c4cd2d4c
--- /dev/null
+++ b/src/devices/bus/a800/ultracart.cpp
@@ -0,0 +1,130 @@
+// license: BSD-3-Clause
+// copyright-holders: Fabio Priuli, Angelo Salese
+/**************************************************************************************************
+
+Ultracart ROM scheme
+
+Observed in SITSA MicroCalc SW (Altirra calls it this way),
+PCB label pic has clear "ULTRACART" with an unreadable sub-title from available pic
+("PIGNY MEXICO"?)
+Sports extra SN74LS169BN (synchronous 4-bit up/down binary counter), any access to CCTL
+bankswitch to the next index, disarms RD5 after bank 3, re-enables from bank 0 if accessed again.
+
+"Blizzard 32KB" looks a derived design of Ultracart, it joins a binary counter with RD5 disarm
+once it goes past 3rd bank index.
+
+"aDawliah" scheme is again very similar but without any RD5 disarm (just loops back to index 0)
+PCB marking "A-NA0002"
+
+TODO:
+- exact interface with SN74LS169;
+
+**************************************************************************************************/
+
+#include "emu.h"
+#include "ultracart.h"
+
+DEFINE_DEVICE_TYPE(A800_ROM_ULTRACART, a800_rom_ultracart_device, "a800_ultracart", "Atari 8-bit Ultracart \"MicroCalc\" cart")
+DEFINE_DEVICE_TYPE(A800_ROM_BLIZZARD_32KB, a800_rom_blizzard_32kb_device, "a800_blizzard_32kb", "Atari 8-bit Blizzard 32KB cart")
+DEFINE_DEVICE_TYPE(A800_ROM_ADAWLIAH, a800_rom_adawliah_device, "a800_adawliah", "Atari 8-bit aDawliah 32KB cart")
+
+
+a800_rom_ultracart_device::a800_rom_ultracart_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : a800_rom_device(mconfig, type, tag, owner, clock)
+ , m_bank(0)
+{
+}
+
+a800_rom_ultracart_device::a800_rom_ultracart_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : a800_rom_ultracart_device(mconfig, A800_ROM_ULTRACART, tag, owner, clock)
+{
+}
+
+void a800_rom_ultracart_device::device_start()
+{
+ save_item(NAME(m_bank));
+}
+
+void a800_rom_ultracart_device::device_reset()
+{
+ m_bank = 0;
+}
+
+void a800_rom_ultracart_device::cart_map(address_map &map)
+{
+ map(0x2000, 0x3fff).lr8(
+ NAME([this](offs_t offset) { return m_rom[(offset & 0x1fff) + (m_bank * 0x2000)]; })
+ );
+}
+
+void a800_rom_ultracart_device::cctl_map(address_map &map)
+{
+ map(0x00, 0xff).rw(FUNC(a800_rom_ultracart_device::config_bank_r), FUNC(a800_rom_ultracart_device::config_bank_w));
+}
+
+inline void a800_rom_ultracart_device::binary_counter_access()
+{
+ // TODO: simplification, the real counter has several config options
+ m_bank = (m_bank + 1) & 0xf;
+
+ if (m_bank & 0xc)
+ {
+ rd5_w(0);
+ m_bank = 0xf;
+ }
+ else
+ rd5_w(1);
+}
+
+u8 a800_rom_ultracart_device::config_bank_r(offs_t offset)
+{
+ if (!machine().side_effects_disabled())
+ binary_counter_access();
+
+ return 0xff;
+}
+
+void a800_rom_ultracart_device::config_bank_w(offs_t offset, u8 data)
+{
+ binary_counter_access();
+}
+
+
+/*-------------------------------------------------
+
+ Blizzard 32KB carts
+
+ -------------------------------------------------*/
+
+a800_rom_blizzard_32kb_device::a800_rom_blizzard_32kb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : a800_rom_ultracart_device(mconfig, A800_ROM_BLIZZARD_32KB, tag, owner, clock)
+{
+}
+
+inline void a800_rom_blizzard_32kb_device::binary_counter_access()
+{
+ // TODO: simplification, the real counter has several config options
+ m_bank = (m_bank + 1) & 0xf;
+
+ // as per phoenix carts RD5 can only be re-enabled by restarting the machine
+ // it's unknown about how the binary counter behaves once this event occurs
+ if (m_bank & 0xc)
+ rd5_w(0);
+}
+
+/*-------------------------------------------------
+
+ aDawliah 32KB carts
+
+ -------------------------------------------------*/
+
+a800_rom_adawliah_device::a800_rom_adawliah_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : a800_rom_ultracart_device(mconfig, A800_ROM_ADAWLIAH, tag, owner, clock)
+{
+}
+
+inline void a800_rom_adawliah_device::binary_counter_access()
+{
+ // TODO: simplification, the real counter has several config options
+ m_bank = (m_bank + 1) & 0x3;
+}
diff --git a/src/devices/bus/a800/ultracart.h b/src/devices/bus/a800/ultracart.h
new file mode 100644
index 00000000000..2e5b45d8d4d
--- /dev/null
+++ b/src/devices/bus/a800/ultracart.h
@@ -0,0 +1,55 @@
+// license: BSD-3-Clause
+// copyright-holders: Fabio Priuli, Angelo Salese
+
+#ifndef MAME_BUS_A800_ULTRACART_H
+#define MAME_BUS_A800_ULTRACART_H
+
+#pragma once
+
+#include "rom.h"
+
+class a800_rom_ultracart_device : public a800_rom_device
+{
+public:
+ a800_rom_ultracart_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+ a800_rom_ultracart_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void cart_map(address_map &map) override;
+ virtual void cctl_map(address_map &map) override;
+ virtual std::tuple<int, int> get_initial_rd_state() override { return std::make_tuple(0, 1); }
+
+protected:
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ int m_bank;
+
+ virtual void binary_counter_access();
+ u8 config_bank_r(offs_t offset);
+ void config_bank_w(offs_t offset, u8 data);
+};
+
+class a800_rom_blizzard_32kb_device : public a800_rom_ultracart_device
+{
+public:
+ a800_rom_blizzard_32kb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual void binary_counter_access() override;
+};
+
+class a800_rom_adawliah_device : public a800_rom_ultracart_device
+{
+public:
+ a800_rom_adawliah_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual void binary_counter_access() override;
+};
+
+DECLARE_DEVICE_TYPE(A800_ROM_ULTRACART, a800_rom_ultracart_device)
+DECLARE_DEVICE_TYPE(A800_ROM_BLIZZARD_32KB, a800_rom_blizzard_32kb_device)
+DECLARE_DEVICE_TYPE(A800_ROM_ADAWLIAH, a800_rom_adawliah_device)
+
+
+#endif // MAME_BUS_A800_ULTRACART_H
diff --git a/src/devices/bus/a800/williams.cpp b/src/devices/bus/a800/williams.cpp
new file mode 100644
index 00000000000..83d8edb66a1
--- /dev/null
+++ b/src/devices/bus/a800/williams.cpp
@@ -0,0 +1,160 @@
+// license: BSD-3-Clause
+// copyright-holders: Fabio Priuli, Angelo Salese
+/**************************************************************************************************
+
+Williams cart scheme and variants
+
+- Regular Williams cart maps ROM bankswitch to $x0 - $x7, RD5 disables with A3. x is mirrored.
+- Express carts maps x = $7x, bank map is xor-ed
+- Diamond carts maps x = $dx, bank map is xor-ed
+- Turbosoft carts raises number of banks to 16, moves RD5 disable to A4 instead of A3
+- All CCTL accesses works both on reading and writing.
+
+**************************************************************************************************/
+
+#include "emu.h"
+#include "williams.h"
+
+DEFINE_DEVICE_TYPE(A800_ROM_WILLIAMS, a800_rom_williams_device, "a800_williams", "Atari 8-bit Williams cart")
+DEFINE_DEVICE_TYPE(A800_ROM_EXPRESS, a800_rom_express_device, "a800_express", "Atari 8-bit Express cart")
+DEFINE_DEVICE_TYPE(A800_ROM_DIAMOND, a800_rom_diamond_device, "a800_diamond", "Atari 8-bit Diamond cart")
+DEFINE_DEVICE_TYPE(A800_ROM_TURBO, a800_rom_turbo_device, "a800_turbo", "Atari 8-bit Turbosoft 64KB/128KB cart")
+
+a800_rom_williams_device::a800_rom_williams_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : a800_rom_device(mconfig, type, tag, owner, clock)
+ , m_bank(0)
+{
+}
+
+a800_rom_williams_device::a800_rom_williams_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : a800_rom_williams_device(mconfig, A800_ROM_WILLIAMS, tag, owner, clock)
+{
+}
+
+void a800_rom_williams_device::device_start()
+{
+ save_item(NAME(m_bank));
+}
+
+void a800_rom_williams_device::device_reset()
+{
+ // turboc1 (at least) reads ROM window without setting bank first,
+ // any non-zero value will make it to punt
+ m_bank = 0;
+}
+
+void a800_rom_williams_device::cart_map(address_map &map)
+{
+ map(0x2000, 0x3fff).lr8(
+ NAME([this](offs_t offset) { return m_rom[(offset & 0x1fff) + (m_bank * 0x2000)]; })
+ );
+}
+
+void a800_rom_williams_device::cctl_map(address_map &map)
+{
+ map(0x00, 0x07).mirror(0xf0).rw(FUNC(a800_rom_williams_device::rom_bank_r), FUNC(a800_rom_williams_device::rom_bank_w));
+ map(0x08, 0x0f).mirror(0xf0).rw(FUNC(a800_rom_williams_device::disable_rom_r), FUNC(a800_rom_williams_device::disable_rom_w));
+}
+
+uint8_t a800_rom_williams_device::disable_rom_r(offs_t offset)
+{
+ if(!machine().side_effects_disabled())
+ rd5_w(0);
+
+ return 0xff;
+}
+
+void a800_rom_williams_device::disable_rom_w(offs_t offset, uint8_t data)
+{
+ rd5_w(0);
+}
+
+// m_bank_mask necessary for turbo128 carts
+uint8_t a800_rom_williams_device::rom_bank_r(offs_t offset)
+{
+ if(!machine().side_effects_disabled())
+ {
+ rd5_w(1);
+ m_bank = (offset & m_bank_mask);
+ }
+ return 0xff;
+}
+
+void a800_rom_williams_device::rom_bank_w(offs_t offset, uint8_t data)
+{
+ rd5_w(1);
+ m_bank = (offset & m_bank_mask);
+}
+
+/*-------------------------------------------------
+
+ Express 64K carts
+
+ -------------------------------------------------*/
+
+a800_rom_express_device::a800_rom_express_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : a800_rom_williams_device(mconfig, type, tag, owner, clock)
+{
+}
+
+a800_rom_express_device::a800_rom_express_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : a800_rom_williams_device(mconfig, A800_ROM_EXPRESS, tag, owner, clock)
+{
+}
+
+void a800_rom_express_device::cctl_map(address_map &map)
+{
+ map(0x70, 0x77).rw(FUNC(a800_rom_express_device::rom_bank_r), FUNC(a800_rom_express_device::rom_bank_w));
+ map(0x78, 0x7f).rw(FUNC(a800_rom_express_device::disable_rom_r), FUNC(a800_rom_express_device::disable_rom_w));
+}
+
+uint8_t a800_rom_express_device::rom_bank_r(offs_t offset)
+{
+ if(!machine().side_effects_disabled())
+ {
+ rd5_w(1);
+ m_bank = ((offset ^ m_bank_mask) & m_bank_mask);
+ }
+ return 0xff;
+}
+
+void a800_rom_express_device::rom_bank_w(offs_t offset, uint8_t data)
+{
+ rd5_w(1);
+ m_bank = ((offset ^ m_bank_mask) & m_bank_mask);
+}
+
+/*-------------------------------------------------
+
+ Diamond 64K carts
+
+ -------------------------------------------------*/
+
+
+a800_rom_diamond_device::a800_rom_diamond_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : a800_rom_express_device(mconfig, A800_ROM_DIAMOND, tag, owner, clock)
+{
+}
+
+void a800_rom_diamond_device::cctl_map(address_map &map)
+{
+ map(0xd0, 0xd7).rw(FUNC(a800_rom_diamond_device::rom_bank_r), FUNC(a800_rom_diamond_device::rom_bank_w));
+ map(0xd8, 0xdf).rw(FUNC(a800_rom_diamond_device::disable_rom_r), FUNC(a800_rom_diamond_device::disable_rom_w));
+}
+
+/*-------------------------------------------------
+
+ Turbosoft 64K / 128K
+
+ -------------------------------------------------*/
+
+a800_rom_turbo_device::a800_rom_turbo_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : a800_rom_williams_device(mconfig, A800_ROM_TURBO, tag, owner, clock)
+{
+}
+
+void a800_rom_turbo_device::cctl_map(address_map &map)
+{
+ map(0x00, 0x0f).mirror(0xe0).rw(FUNC(a800_rom_turbo_device::rom_bank_r), FUNC(a800_rom_turbo_device::rom_bank_w));
+ map(0x10, 0x1f).mirror(0xe0).rw(FUNC(a800_rom_turbo_device::disable_rom_r), FUNC(a800_rom_turbo_device::disable_rom_w));
+}
diff --git a/src/devices/bus/a800/williams.h b/src/devices/bus/a800/williams.h
new file mode 100644
index 00000000000..24d8542eb26
--- /dev/null
+++ b/src/devices/bus/a800/williams.h
@@ -0,0 +1,69 @@
+// license: BSD-3-Clause
+// copyright-holders: Fabio Priuli, Angelo Salese
+
+#ifndef MAME_BUS_A800_WILLIAMS_H
+#define MAME_BUS_A800_WILLIAMS_H
+
+#pragma once
+
+#include "rom.h"
+
+class a800_rom_williams_device : public a800_rom_device
+{
+public:
+ a800_rom_williams_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+ a800_rom_williams_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void cart_map(address_map &map) override;
+ virtual void cctl_map(address_map &map) override;
+ virtual std::tuple<int, int> get_initial_rd_state() override { return std::make_tuple(0, 1); };
+
+protected:
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ int m_bank;
+
+ uint8_t disable_rom_r(offs_t offset);
+ void disable_rom_w(offs_t offset, uint8_t data);
+ virtual uint8_t rom_bank_r(offs_t offset);
+ virtual void rom_bank_w(offs_t offset, uint8_t data);
+};
+
+
+class a800_rom_express_device : public a800_rom_williams_device
+{
+public:
+ a800_rom_express_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+ a800_rom_express_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual void cctl_map(address_map &map) override;
+
+ virtual uint8_t rom_bank_r(offs_t offset) override;
+ virtual void rom_bank_w(offs_t offset, uint8_t data) override;
+};
+
+class a800_rom_diamond_device : public a800_rom_express_device
+{
+public:
+ a800_rom_diamond_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+private:
+ virtual void cctl_map(address_map &map) override;
+};
+
+class a800_rom_turbo_device : public a800_rom_williams_device
+{
+public:
+ a800_rom_turbo_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void cctl_map(address_map &map) override;
+};
+
+DECLARE_DEVICE_TYPE(A800_ROM_WILLIAMS, a800_rom_williams_device)
+DECLARE_DEVICE_TYPE(A800_ROM_EXPRESS, a800_rom_express_device)
+DECLARE_DEVICE_TYPE(A800_ROM_DIAMOND, a800_rom_diamond_device)
+DECLARE_DEVICE_TYPE(A800_ROM_TURBO, a800_rom_turbo_device)
+
+#endif // MAME_BUS_A800_WILLIAMS_H
diff --git a/src/devices/bus/abcbus/abcbus.cpp b/src/devices/bus/abcbus/abcbus.cpp
index 5e0adb49c3f..d02042720b7 100644
--- a/src/devices/bus/abcbus/abcbus.cpp
+++ b/src/devices/bus/abcbus/abcbus.cpp
@@ -71,18 +71,6 @@ abcbus_slot_device::abcbus_slot_device(const machine_config &mconfig, const char
void abcbus_slot_device::device_start()
{
m_card = get_card_device();
-
- // resolve callbacks
- m_write_irq.resolve_safe();
- m_write_nmi.resolve_safe();
- m_write_rdy.resolve_safe();
- m_write_resin.resolve_safe();
- m_write_pren.resolve_safe();
- m_write_trrq.resolve_safe();
- m_write_xint2.resolve_safe();
- m_write_xint3.resolve_safe();
- m_write_xint4.resolve_safe();
- m_write_xint5.resolve_safe();
}
diff --git a/src/devices/bus/abcbus/abcbus.h b/src/devices/bus/abcbus/abcbus.h
index e8ce92a2d9b..638d460efa3 100644
--- a/src/devices/bus/abcbus/abcbus.h
+++ b/src/devices/bus/abcbus/abcbus.h
@@ -192,16 +192,16 @@ public:
void write_c4(uint8_t data) { if (m_card) m_card->abcbus_c4(data); }
uint8_t xmemfl_r(offs_t offset) { return m_card ? m_card->abcbus_xmemfl(offset) : 0xff; }
void xmemw_w(offs_t offset, uint8_t data) { if (m_card) m_card->abcbus_xmemw(offset, data); }
- DECLARE_READ_LINE_MEMBER( csb_r ) { return m_card ? m_card->abcbus_csb() : 1; }
+ int csb_r() { return m_card ? m_card->abcbus_csb() : 1; }
uint8_t ops_r() { return m_card ? m_card->abcbus_ops() : 0xff; }
uint8_t exp_r() { return m_card ? m_card->abcbus_exp() : 0xff; }
- DECLARE_READ_LINE_MEMBER( xcsb2_r ) { return m_card ? m_card->abcbus_xcsb2() : 1; }
- DECLARE_READ_LINE_MEMBER( xcsb3_r ) { return m_card ? m_card->abcbus_xcsb3() : 1; }
- DECLARE_READ_LINE_MEMBER( xcsb4_r ) { return m_card ? m_card->abcbus_xcsb4() : 1; }
- DECLARE_READ_LINE_MEMBER( xcsb5_r ) { return m_card ? m_card->abcbus_xcsb5() : 1; }
+ int xcsb2_r() { return m_card ? m_card->abcbus_xcsb2() : 1; }
+ int xcsb3_r() { return m_card ? m_card->abcbus_xcsb3() : 1; }
+ int xcsb4_r() { return m_card ? m_card->abcbus_xcsb4() : 1; }
+ int xcsb5_r() { return m_card ? m_card->abcbus_xcsb5() : 1; }
uint8_t read_tren() { return m_card ? m_card->abcbus_tren() : 0xff; }
void write_tren(uint8_t data) { if (m_card) m_card->abcbus_tren(data); }
- DECLARE_WRITE_LINE_MEMBER( prac_w ) { if (m_card) m_card->abcbus_prac(state); }
+ void prac_w(int state) { if (m_card) m_card->abcbus_prac(state); }
void cs_w(uint8_t data) { write_cs(data); }
uint8_t rst_r() { return read_rst(); }
@@ -213,26 +213,26 @@ public:
void c3_w(uint8_t data) { write_c3(data); }
void c4_w(uint8_t data) { write_c4(data); }
- DECLARE_READ_LINE_MEMBER( irq_r ) { return m_irq; }
- DECLARE_READ_LINE_MEMBER( nmi_r ) { return m_nmi; }
- DECLARE_READ_LINE_MEMBER( pren_r ) { return m_pren; }
- DECLARE_READ_LINE_MEMBER( trrq_r ) { return m_trrq; }
- DECLARE_READ_LINE_MEMBER( xint2_r ) { return m_xint2; }
- DECLARE_READ_LINE_MEMBER( xint3_r ) { return m_xint3; }
- DECLARE_READ_LINE_MEMBER( xint4_r ) { return m_xint4; }
- DECLARE_READ_LINE_MEMBER( xint5_r ) { return m_xint5; }
+ int irq_r() { return m_irq; }
+ int nmi_r() { return m_nmi; }
+ int pren_r() { return m_pren; }
+ int trrq_r() { return m_trrq; }
+ int xint2_r() { return m_xint2; }
+ int xint3_r() { return m_xint3; }
+ int xint4_r() { return m_xint4; }
+ int xint5_r() { return m_xint5; }
// card interface
- DECLARE_WRITE_LINE_MEMBER( irq_w ) { if (m_irq != state) { m_irq = state; m_write_irq(state); } }
- DECLARE_WRITE_LINE_MEMBER( nmi_w ) { m_nmi = state; m_write_nmi(state); }
- DECLARE_WRITE_LINE_MEMBER( rdy_w ) { m_write_rdy(state); }
- DECLARE_WRITE_LINE_MEMBER( resin_w ) { m_write_resin(state); }
- DECLARE_WRITE_LINE_MEMBER( pren_w ) { if (m_pren != state) { m_pren = state; m_write_pren(state); } }
- DECLARE_WRITE_LINE_MEMBER( trrq_w ) { if (m_trrq != state) { m_trrq = state; m_write_trrq(state); } }
- DECLARE_WRITE_LINE_MEMBER( xint2_w ) { m_xint2 = state; m_write_xint2(state); }
- DECLARE_WRITE_LINE_MEMBER( xint3_w ) { m_xint3 = state; m_write_xint3(state); }
- DECLARE_WRITE_LINE_MEMBER( xint4_w ) { m_xint4 = state; m_write_xint4(state); }
- DECLARE_WRITE_LINE_MEMBER( xint5_w ) { m_xint5 = state; m_write_xint5(state); }
+ void irq_w(int state) { if (m_irq != state) { m_irq = state; m_write_irq(state); } }
+ void nmi_w(int state) { m_nmi = state; m_write_nmi(state); }
+ void rdy_w(int state) { m_write_rdy(state); }
+ void resin_w(int state) { m_write_resin(state); }
+ void pren_w(int state) { if (m_pren != state) { m_pren = state; m_write_pren(state); } }
+ void trrq_w(int state) { if (m_trrq != state) { m_trrq = state; m_write_trrq(state); } }
+ void xint2_w(int state) { m_xint2 = state; m_write_xint2(state); }
+ void xint3_w(int state) { m_xint3 = state; m_write_xint3(state); }
+ void xint4_w(int state) { m_xint4 = state; m_write_xint4(state); }
+ void xint5_w(int state) { m_xint5 = state; m_write_xint5(state); }
protected:
// device-level overrides
diff --git a/src/devices/bus/abcbus/fd2.cpp b/src/devices/bus/abcbus/fd2.cpp
index b23daa8ebd7..4a245b3fee8 100644
--- a/src/devices/bus/abcbus/fd2.cpp
+++ b/src/devices/bus/abcbus/fd2.cpp
@@ -39,6 +39,8 @@ Notes:
#include "emu.h"
#include "fd2.h"
+#include "formats/abcfd2_dsk.h"
+
//**************************************************************************
@@ -193,8 +195,8 @@ void abc_fd2_device::pio_pb_w(uint8_t data)
floppy_image_device *floppy = nullptr;
- if (BIT(data, 0)) floppy = m_floppy0->get_device();
- if (BIT(data, 1)) floppy = m_floppy1->get_device();
+ if (BIT(data, 0)) floppy = m_floppy[0]->get_device();
+ if (BIT(data, 1)) floppy = m_floppy[1]->get_device();
m_fdc->set_floppy(floppy);
@@ -258,8 +260,8 @@ void abc_fd2_device::device_add_mconfig(machine_config &config)
m_fdc->drq_wr_callback().set(m_pio, FUNC(z80pio_device::pb5_w));
m_fdc->hld_wr_callback().set(m_pio, FUNC(z80pio_device::pb6_w));
- FLOPPY_CONNECTOR(config, m_floppy0, abc_fd2_floppies, "525sssd", abc_fd2_device::floppy_formats).enable_sound(true);
- FLOPPY_CONNECTOR(config, m_floppy1, abc_fd2_floppies, "525sssd", abc_fd2_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[0], abc_fd2_floppies, "525sssd", abc_fd2_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[1], abc_fd2_floppies, "525sssd", abc_fd2_device::floppy_formats).enable_sound(true);
}
@@ -277,8 +279,7 @@ abc_fd2_device::abc_fd2_device(const machine_config &mconfig, const char *tag, d
m_maincpu(*this, Z80_TAG),
m_pio(*this, Z80PIO_TAG),
m_fdc(*this, FD1771_TAG),
- m_floppy0(*this, FD1771_TAG ":0"),
- m_floppy1(*this, FD1771_TAG ":1"),
+ m_floppy(*this, FD1771_TAG ":%u", 0U),
m_dos_rom(*this, "dos"),
m_cs(false), m_status(0), m_data(0)
{
diff --git a/src/devices/bus/abcbus/fd2.h b/src/devices/bus/abcbus/fd2.h
index a476b66c821..140a1368154 100644
--- a/src/devices/bus/abcbus/fd2.h
+++ b/src/devices/bus/abcbus/fd2.h
@@ -14,7 +14,6 @@
#include "abcbus.h"
#include "cpu/z80/z80.h"
#include "machine/z80daisy.h"
-#include "formats/abcfd2_dsk.h"
#include "imagedev/floppy.h"
#include "machine/wd_fdc.h"
#include "machine/z80pio.h"
@@ -68,8 +67,7 @@ private:
required_device<z80_device> m_maincpu;
required_device<z80pio_device> m_pio;
required_device<fd1771_device> m_fdc;
- required_device<floppy_connector> m_floppy0;
- required_device<floppy_connector> m_floppy1;
+ required_device_array<floppy_connector, 2> m_floppy;
required_memory_region m_dos_rom;
bool m_cs;
diff --git a/src/devices/bus/abcbus/lux10828.cpp b/src/devices/bus/abcbus/lux10828.cpp
index e349cd76bb5..2516229d941 100644
--- a/src/devices/bus/abcbus/lux10828.cpp
+++ b/src/devices/bus/abcbus/lux10828.cpp
@@ -114,6 +114,9 @@ Notes:
#include "emu.h"
#include "lux10828.h"
+#include "formats/abc800_dsk.h"
+#include "formats/abc800i_dsk.h"
+
//**************************************************************************
@@ -231,13 +234,13 @@ uint8_t luxor_55_10828_device::pio_pb_r()
// single/double sided drive
uint8_t sw1 = m_sw1->read() & 0x0f;
- bool ds0 = m_sel0 ? BIT(sw1, 0) : 1;
- bool ds1 = m_sel1 ? BIT(sw1, 1) : 1;
+ bool ds0 = BIT(m_sel, 0) ? BIT(sw1, 0) : 1;
+ bool ds1 = BIT(m_sel, 1) ? BIT(sw1, 1) : 1;
data |= !(ds0 && ds1);
// single/double density drive
- bool dd0 = m_sel0 ? BIT(sw1, 2) : 1;
- bool dd1 = m_sel1 ? BIT(sw1, 3) : 1;
+ bool dd0 = BIT(m_sel, 0) ? BIT(sw1, 2) : 1;
+ bool dd1 = BIT(m_sel, 1) ? BIT(sw1, 3) : 1;
data |= !(dd0 && dd1) << 1;
// TODO ULA output
@@ -302,10 +305,11 @@ static void abc_floppies(device_slot_interface &device)
void luxor_55_10828_device::floppy_formats(format_registration &fr)
{
fr.add_mfm_containers();
+ fr.add(FLOPPY_ABC800I_FORMAT);
fr.add(FLOPPY_ABC800_FORMAT);
}
-WRITE_LINE_MEMBER( luxor_55_10828_device::fdc_intrq_w )
+void luxor_55_10828_device::fdc_intrq_w(int state)
{
m_fdc_irq = state;
m_pio->port_b_write(state << 7);
@@ -313,7 +317,7 @@ WRITE_LINE_MEMBER( luxor_55_10828_device::fdc_intrq_w )
//if (state) m_maincpu->wait_w(CLEAR_LINE);
}
-WRITE_LINE_MEMBER( luxor_55_10828_device::fdc_drq_w )
+void luxor_55_10828_device::fdc_drq_w(int state)
{
m_fdc_drq = state;
@@ -343,8 +347,8 @@ void luxor_55_10828_device::device_add_mconfig(machine_config &config)
m_fdc->intrq_wr_callback().set(FUNC(luxor_55_10828_device::fdc_intrq_w));
m_fdc->drq_wr_callback().set(FUNC(luxor_55_10828_device::fdc_drq_w));
- FLOPPY_CONNECTOR(config, m_floppy0, abc_floppies, "525ssdd", luxor_55_10828_device::floppy_formats).enable_sound(true);
- FLOPPY_CONNECTOR(config, m_floppy1, abc_floppies, "525ssdd", luxor_55_10828_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[0], abc_floppies, "525ssdd", luxor_55_10828_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[1], abc_floppies, "525ssdd", luxor_55_10828_device::floppy_formats).enable_sound(true);
}
@@ -409,8 +413,7 @@ luxor_55_10828_device::luxor_55_10828_device(const machine_config &mconfig, cons
m_maincpu(*this, Z80_TAG),
m_pio(*this, Z80PIO_TAG),
m_fdc(*this, MB8876_TAG),
- m_floppy0(*this, MB8876_TAG":0"),
- m_floppy1(*this, MB8876_TAG":1"),
+ m_floppy(*this, MB8876_TAG":%u", 0U),
m_sw1(*this, "SW1"),
m_s1(*this, "S1"),
m_cs(false),
@@ -419,8 +422,7 @@ luxor_55_10828_device::luxor_55_10828_device(const machine_config &mconfig, cons
m_fdc_irq(0),
m_fdc_drq(0),
m_wait_enable(0),
- m_sel0(0),
- m_sel1(0)
+ m_sel(0)
{
}
@@ -438,8 +440,7 @@ void luxor_55_10828_device::device_start()
save_item(NAME(m_fdc_irq));
save_item(NAME(m_fdc_drq));
save_item(NAME(m_wait_enable));
- save_item(NAME(m_sel0));
- save_item(NAME(m_sel1));
+ save_item(NAME(m_sel));
// patch out protection checks (bioses basf6106/mpi02)
uint8_t *rom = memregion(Z80_TAG)->base();
@@ -599,13 +600,12 @@ void luxor_55_10828_device::ctrl_w(uint8_t data)
return;
// drive selection
- m_sel0 = BIT(data, 0);
- m_sel1 = BIT(data, 1);
+ m_sel = data & 0x03;
floppy_image_device *floppy = nullptr;
- if (m_sel0) floppy = m_floppy0->get_device();
- if (m_sel1) floppy = m_floppy1->get_device();
+ if (BIT(m_sel, 0)) floppy = m_floppy[0]->get_device();
+ if (BIT(m_sel, 1)) floppy = m_floppy[1]->get_device();
m_fdc->set_floppy(floppy);
diff --git a/src/devices/bus/abcbus/lux10828.h b/src/devices/bus/abcbus/lux10828.h
index c5bf46a8c89..6a65fe2d695 100644
--- a/src/devices/bus/abcbus/lux10828.h
+++ b/src/devices/bus/abcbus/lux10828.h
@@ -14,7 +14,6 @@
#include "abcbus.h"
#include "cpu/z80/z80.h"
#include "machine/z80daisy.h"
-#include "formats/abc800_dsk.h"
#include "imagedev/floppy.h"
#include "machine/wd_fdc.h"
#include "machine/z80pio.h"
@@ -80,8 +79,8 @@ private:
uint8_t pio_pb_r();
void pio_pb_w(uint8_t data);
- DECLARE_WRITE_LINE_MEMBER( fdc_intrq_w );
- DECLARE_WRITE_LINE_MEMBER( fdc_drq_w );
+ void fdc_intrq_w(int state);
+ void fdc_drq_w(int state);
void ctrl_w(uint8_t data);
void status_w(uint8_t data);
@@ -96,19 +95,17 @@ private:
required_device<z80_device> m_maincpu;
required_device<z80pio_device> m_pio;
required_device<mb8876_device> m_fdc;
- required_device<floppy_connector> m_floppy0;
- required_device<floppy_connector> m_floppy1;
+ required_device_array<floppy_connector, 2> m_floppy;
required_ioport m_sw1;
required_ioport m_s1;
bool m_cs; // card selected
- uint8_t m_status; // ABC BUS status
- uint8_t m_data; // ABC BUS data
+ uint8_t m_status; // ABC BUS status
+ uint8_t m_data; // ABC BUS data
bool m_fdc_irq; // floppy interrupt
bool m_fdc_drq; // floppy data request
int m_wait_enable; // wait enable
- int m_sel0; // drive select 0
- int m_sel1; // drive select 1
+ uint8_t m_sel; // drive select
};
diff --git a/src/devices/bus/abcbus/lux21046.cpp b/src/devices/bus/abcbus/lux21046.cpp
index 7dd4ebfb791..facfeb83c7d 100644
--- a/src/devices/bus/abcbus/lux21046.cpp
+++ b/src/devices/bus/abcbus/lux21046.cpp
@@ -77,6 +77,9 @@ Notes:
#include "emu.h"
#include "lux21046.h"
+#include "formats/abc800_dsk.h"
+#include "formats/abc800i_dsk.h"
+
//**************************************************************************
@@ -226,7 +229,7 @@ void luxor_55_21046_device::luxor_55_21046_io(address_map &map)
*/
-WRITE_LINE_MEMBER( luxor_55_21046_device::dma_int_w )
+void luxor_55_21046_device::dma_int_w(int state)
{
m_dma_irq = state;
@@ -257,6 +260,7 @@ void luxor_55_21046_device::io_write_byte(offs_t offset, uint8_t data)
void luxor_55_21046_device::floppy_formats(format_registration &fr)
{
fr.add_mfm_containers();
+ fr.add(FLOPPY_ABC800I_FORMAT);
fr.add(FLOPPY_ABC800_FORMAT);
}
@@ -270,7 +274,7 @@ static void abc_floppies(device_slot_interface &device)
device.option_add("8dsdd", FLOPPY_8_DSDD);
}
-WRITE_LINE_MEMBER( luxor_55_21046_device::fdc_intrq_w )
+void luxor_55_21046_device::fdc_intrq_w(int state)
{
m_fdc_irq = state;
@@ -317,36 +321,36 @@ void luxor_55_21046_device::device_add_mconfig(machine_config & config)
void abc830_device::device_add_mconfig(machine_config &config)
{
luxor_55_21046_device::device_add_mconfig(config);
- FLOPPY_CONNECTOR(config, m_floppy0, abc_floppies, "525ssdd", luxor_55_21046_device::floppy_formats).enable_sound(true);
- FLOPPY_CONNECTOR(config, m_floppy1, abc_floppies, "525ssdd", luxor_55_21046_device::floppy_formats).enable_sound(true);
+ for (auto &floppy : m_floppy)
+ FLOPPY_CONNECTOR(config, floppy, abc_floppies, "525ssdd", luxor_55_21046_device::floppy_formats).enable_sound(true);
}
void abc832_device::device_add_mconfig(machine_config &config)
{
luxor_55_21046_device::device_add_mconfig(config);
- FLOPPY_CONNECTOR(config, m_floppy0, abc_floppies, "525qd", luxor_55_21046_device::floppy_formats).enable_sound(true);
- FLOPPY_CONNECTOR(config, m_floppy1, abc_floppies, "525qd", luxor_55_21046_device::floppy_formats).enable_sound(true);
+ for (auto &floppy : m_floppy)
+ FLOPPY_CONNECTOR(config, floppy, abc_floppies, "525qd", luxor_55_21046_device::floppy_formats).enable_sound(true);
}
void abc834_device::device_add_mconfig(machine_config &config)
{
luxor_55_21046_device::device_add_mconfig(config);
- FLOPPY_CONNECTOR(config, m_floppy0, abc_floppies, "525qd", luxor_55_21046_device::floppy_formats).enable_sound(true);
- FLOPPY_CONNECTOR(config, m_floppy1, abc_floppies, "525qd", luxor_55_21046_device::floppy_formats).enable_sound(true);
+ for (auto &floppy : m_floppy)
+ FLOPPY_CONNECTOR(config, floppy, abc_floppies, "525qd", luxor_55_21046_device::floppy_formats).enable_sound(true);
}
void abc838_device::device_add_mconfig(machine_config &config)
{
luxor_55_21046_device::device_add_mconfig(config);
- FLOPPY_CONNECTOR(config, m_floppy0, abc_floppies, "8dsdd", luxor_55_21046_device::floppy_formats).enable_sound(true);
- FLOPPY_CONNECTOR(config, m_floppy1, abc_floppies, "8dsdd", luxor_55_21046_device::floppy_formats).enable_sound(true);
+ for (auto &floppy : m_floppy)
+ FLOPPY_CONNECTOR(config, floppy, abc_floppies, "8dsdd", luxor_55_21046_device::floppy_formats).enable_sound(true);
}
void abc850_floppy_device::device_add_mconfig(machine_config &config)
{
luxor_55_21046_device::device_add_mconfig(config);
- FLOPPY_CONNECTOR(config, m_floppy0, abc_floppies, "525qd", luxor_55_21046_device::floppy_formats).enable_sound(true);
- FLOPPY_CONNECTOR(config, m_floppy1, abc_floppies, nullptr, luxor_55_21046_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[0], abc_floppies, "525qd", luxor_55_21046_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[1], abc_floppies, nullptr, luxor_55_21046_device::floppy_formats).enable_sound(true);
}
@@ -718,12 +722,11 @@ luxor_55_21046_device::luxor_55_21046_device(const machine_config &mconfig, cons
luxor_55_21046_device::luxor_55_21046_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, type, tag, owner, clock),
device_abcbus_card_interface(mconfig, *this),
- m_floppy0(*this, SAB1793_TAG":0"),
- m_floppy1(*this, SAB1793_TAG":1"),
+ m_floppy(*this, SAB1793_TAG":%u", 0U),
m_maincpu(*this, Z80_TAG),
m_dma(*this, Z80DMA_TAG),
m_fdc(*this, SAB1793_TAG),
- m_floppy(nullptr),
+ m_selected_floppy(nullptr),
m_sw1(*this, "SW1"),
m_sw2(*this, "SW2"),
m_sw3(*this, "SW3"),
@@ -1014,20 +1017,23 @@ void luxor_55_21046_device::_9b_w(uint8_t data)
*/
// drive select
- m_floppy = nullptr;
+ m_selected_floppy = nullptr;
- if (BIT(data, 0)) m_floppy = m_floppy0->get_device();
- if (BIT(data, 1)) m_floppy = m_floppy1->get_device();
+ for (int n = 0; n < 2; n++)
+ {
+ if (BIT(data, n))
+ m_selected_floppy = m_floppy[n]->get_device();
+ }
- m_fdc->set_floppy(m_floppy);
+ m_fdc->set_floppy(m_selected_floppy);
- if (m_floppy)
+ if (m_selected_floppy)
{
// motor enable
- m_floppy->mon_w(!BIT(data, 3));
+ m_selected_floppy->mon_w(!BIT(data, 3));
// side select
- m_floppy->ss_w(BIT(data, 5));
+ m_selected_floppy->ss_w(BIT(data, 5));
}
}
@@ -1092,8 +1098,8 @@ uint8_t luxor_55_21046_device::_9a_r(offs_t offset)
data |= m_busy;
// floppy
- data |= (m_floppy ? m_floppy->twosid_r() : 1) << 1;
- //data |= (m_floppy ? m_floppy->dskchg_r() : 1) << 4;
+ data |= (m_selected_floppy ? m_selected_floppy->twosid_r() : 1) << 1;
+ //data |= (m_selected_floppy ? m_selected_floppy->dskchg_r() : 1) << 4;
// SW2
uint8_t sw2 = m_sw2->read() & 0x0f;
diff --git a/src/devices/bus/abcbus/lux21046.h b/src/devices/bus/abcbus/lux21046.h
index 735de99641c..3f83864b476 100644
--- a/src/devices/bus/abcbus/lux21046.h
+++ b/src/devices/bus/abcbus/lux21046.h
@@ -14,7 +14,6 @@
#include "abcbus.h"
#include "cpu/z80/z80.h"
#include "machine/z80daisy.h"
-#include "formats/abc800_dsk.h"
#include "imagedev/floppy.h"
#include "machine/wd_fdc.h"
#include "machine/z80dma.h"
@@ -79,18 +78,17 @@ protected:
static void floppy_formats(format_registration &fr);
- required_device<floppy_connector> m_floppy0;
- required_device<floppy_connector> m_floppy1;
+ required_device_array<floppy_connector, 2> m_floppy;
private:
- DECLARE_WRITE_LINE_MEMBER( dma_int_w );
+ void dma_int_w(int state);
uint8_t memory_read_byte(offs_t offset);
void memory_write_byte(offs_t offset, uint8_t data);
uint8_t io_read_byte(offs_t offset);
void io_write_byte(offs_t offset, uint8_t data);
- DECLARE_WRITE_LINE_MEMBER( fdc_intrq_w );
+ void fdc_intrq_w(int state);
uint8_t out_r();
void inp_w(uint8_t data);
@@ -105,15 +103,15 @@ private:
required_device<z80_device> m_maincpu;
required_device<z80dma_device> m_dma;
required_device<fd1793_device> m_fdc;
- floppy_image_device *m_floppy;
+ floppy_image_device *m_selected_floppy;
required_ioport m_sw1;
required_ioport m_sw2;
required_ioport m_sw3;
bool m_cs; // card selected
- uint8_t m_status; // ABC BUS status
- uint8_t m_out; // ABC BUS data in
- uint8_t m_inp; // ABC BUS data out
+ uint8_t m_status; // ABC BUS status
+ uint8_t m_out; // ABC BUS data in
+ uint8_t m_inp; // ABC BUS data out
bool m_fdc_irq; // FDC interrupt
int m_dma_irq; // DMA interrupt
int m_busy; // busy bit
diff --git a/src/devices/bus/abcbus/lux21056.cpp b/src/devices/bus/abcbus/lux21056.cpp
index f14ea5a0f68..f1f4ca536b0 100644
--- a/src/devices/bus/abcbus/lux21056.cpp
+++ b/src/devices/bus/abcbus/lux21056.cpp
@@ -198,7 +198,7 @@ void luxor_55_21056_device::io_write_byte(offs_t offset, uint8_t data)
}
-WRITE_LINE_MEMBER( luxor_55_21056_device::write_sasi_bsy )
+void luxor_55_21056_device::write_sasi_bsy(int state)
{
m_sasi_bsy = state;
@@ -208,7 +208,7 @@ WRITE_LINE_MEMBER( luxor_55_21056_device::write_sasi_bsy )
}
}
-WRITE_LINE_MEMBER( luxor_55_21056_device::write_sasi_io )
+void luxor_55_21056_device::write_sasi_io(int state)
{
m_sasi_io = state;
@@ -222,7 +222,7 @@ WRITE_LINE_MEMBER( luxor_55_21056_device::write_sasi_io )
}
}
-WRITE_LINE_MEMBER( luxor_55_21056_device::write_sasi_req )
+void luxor_55_21056_device::write_sasi_req(int state)
{
m_sasi_req = state;
@@ -233,12 +233,12 @@ WRITE_LINE_MEMBER( luxor_55_21056_device::write_sasi_req )
}
}
-WRITE_LINE_MEMBER( luxor_55_21056_device::write_sasi_cd )
+void luxor_55_21056_device::write_sasi_cd(int state)
{
m_sasi_cd = state;
}
-WRITE_LINE_MEMBER( luxor_55_21056_device::write_sasi_msg )
+void luxor_55_21056_device::write_sasi_msg(int state)
{
m_sasi_msg = state;
}
diff --git a/src/devices/bus/abcbus/lux21056.h b/src/devices/bus/abcbus/lux21056.h
index 812bb8325a3..bf70c79bae1 100644
--- a/src/devices/bus/abcbus/lux21056.h
+++ b/src/devices/bus/abcbus/lux21056.h
@@ -58,11 +58,11 @@ private:
uint8_t io_read_byte(offs_t offset);
void io_write_byte(offs_t offset, uint8_t data);
- DECLARE_WRITE_LINE_MEMBER( write_sasi_req );
- DECLARE_WRITE_LINE_MEMBER( write_sasi_io );
- DECLARE_WRITE_LINE_MEMBER( write_sasi_cd );
- DECLARE_WRITE_LINE_MEMBER( write_sasi_msg );
- DECLARE_WRITE_LINE_MEMBER( write_sasi_bsy );
+ void write_sasi_req(int state);
+ void write_sasi_io(int state);
+ void write_sasi_cd(int state);
+ void write_sasi_msg(int state);
+ void write_sasi_bsy(int state);
uint8_t sasi_status_r();
void stat_w(uint8_t data);
diff --git a/src/devices/bus/abcbus/lux4105.cpp b/src/devices/bus/abcbus/lux4105.cpp
index 324fd542ac7..1db5d0d3869 100644
--- a/src/devices/bus/abcbus/lux4105.cpp
+++ b/src/devices/bus/abcbus/lux4105.cpp
@@ -94,7 +94,7 @@ INPUT_PORTS_START( luxor_4105 )
PORT_DIPSETTING( 0x01, "Half (Seagate/Texas)" )
PORT_DIPSETTING( 0x02, "Half (Tandon)" )
PORT_DIPSETTING( 0x03, "Buffered" )
- PORT_DIPNAME( 0x0c, 0x0c, "Heads" ) PORT_DIPLOCATION("1E:3,4")
+ PORT_DIPNAME( 0x0c, 0x04, "Heads" ) PORT_DIPLOCATION("1E:3,4")
PORT_DIPSETTING( 0x00, "2" )
PORT_DIPSETTING( 0x04, "4" )
PORT_DIPSETTING( 0x08, "6" )
@@ -106,7 +106,7 @@ INPUT_PORTS_START( luxor_4105 )
PORT_DIPSETTING( 0x30, "Seagate ST412" )
PORT_START("5E")
- PORT_DIPNAME( 0x7f, 0x25, "Card Address" ) PORT_DIPLOCATION("5E:1,2,3,4,5,6,7")
+ PORT_DIPNAME( 0x3f, 0x25, "Card Address" ) PORT_DIPLOCATION("5E:1,2,3,4,5,6")
PORT_DIPSETTING( 0x25, "37" )
PORT_DIPSETTING( 0x2d, "45" )
@@ -286,7 +286,7 @@ void luxor_4105_device::write_sasi_data(uint8_t data)
}
-WRITE_LINE_MEMBER( luxor_4105_device::write_sasi_bsy )
+void luxor_4105_device::write_sasi_bsy(int state)
{
if (state)
{
@@ -295,13 +295,13 @@ WRITE_LINE_MEMBER( luxor_4105_device::write_sasi_bsy )
}
-WRITE_LINE_MEMBER( luxor_4105_device::write_sasi_cd )
+void luxor_4105_device::write_sasi_cd(int state)
{
update_dma();
}
-WRITE_LINE_MEMBER( luxor_4105_device::write_sasi_req )
+void luxor_4105_device::write_sasi_req(int state)
{
if (LOG) logerror("%s REQ %u\n", machine().describe_context(), state);
@@ -316,13 +316,13 @@ WRITE_LINE_MEMBER( luxor_4105_device::write_sasi_req )
}
-WRITE_LINE_MEMBER( luxor_4105_device::write_sasi_msg )
+void luxor_4105_device::write_sasi_msg(int state)
{
update_ack();
}
-WRITE_LINE_MEMBER( luxor_4105_device::write_sasi_io )
+void luxor_4105_device::write_sasi_io(int state)
{
if (state)
{
diff --git a/src/devices/bus/abcbus/lux4105.h b/src/devices/bus/abcbus/lux4105.h
index dde20ad3075..75003907c65 100644
--- a/src/devices/bus/abcbus/lux4105.h
+++ b/src/devices/bus/abcbus/lux4105.h
@@ -61,11 +61,11 @@ private:
void write_dma_register(uint8_t data);
void write_sasi_data(uint8_t data);
- DECLARE_WRITE_LINE_MEMBER( write_sasi_bsy );
- DECLARE_WRITE_LINE_MEMBER( write_sasi_cd );
- DECLARE_WRITE_LINE_MEMBER( write_sasi_req );
- DECLARE_WRITE_LINE_MEMBER( write_sasi_msg );
- DECLARE_WRITE_LINE_MEMBER( write_sasi_io );
+ void write_sasi_bsy(int state);
+ void write_sasi_cd(int state);
+ void write_sasi_req(int state);
+ void write_sasi_msg(int state);
+ void write_sasi_io(int state);
required_device<nscsi_callback_device> m_sasi;
required_ioport m_1e;
diff --git a/src/devices/bus/abcbus/memcard.cpp b/src/devices/bus/abcbus/memcard.cpp
index e8cd5464ae7..8ace715f696 100644
--- a/src/devices/bus/abcbus/memcard.cpp
+++ b/src/devices/bus/abcbus/memcard.cpp
@@ -67,37 +67,15 @@ DEFINE_DEVICE_TYPE(ABC_MEMORY_CARD, abc_memory_card_device, "abc_memcard", "ABC
//-------------------------------------------------
-// ROM( abc_dos )
+// device_add_mconfig - add device configuration
//-------------------------------------------------
-ROM_START( abc_dos )
- ROM_REGION( 0x1000, "dos", 0 )
- ROM_DEFAULT_BIOS("ufd20")
- ROM_SYSTEM_BIOS( 0, "abcdos", "ABC-DOS" ) // Scandia Metric FD2
- ROMX_LOAD( "abcdos.3d", 0x0000, 0x1000, CRC(2cb2192f) SHA1(a6b3a9587714f8db807c05bee6c71c0684363744), ROM_BIOS(0) )
- ROM_SYSTEM_BIOS( 1, "dosdd80", "ABC-DOS DD" ) // ABC 830
- ROMX_LOAD( "dosdd80.3d", 0x0000, 0x1000, CRC(36db4c15) SHA1(ae462633f3a9c142bb029beb14749a84681377fa), ROM_BIOS(1) )
- ROM_SYSTEM_BIOS( 2, "ufd20", "UFD-DOS v.20" ) // ABC 830
- ROMX_LOAD( "ufddos20.3d", 0x0000, 0x1000, CRC(69b09c0b) SHA1(403997a06cf6495b8fa13dc74eff6a64ef7aa53e), ROM_BIOS(2) )
-
- ROM_REGION( 0x400, "iec", 0 )
- ROM_LOAD( "iec.4b", 0x000, 0x400, NO_DUMP )
-
- ROM_REGION( 0x400, "opt", 0 )
- ROM_LOAD( "spare.4a", 0x000, 0x400, NO_DUMP )
-
- ROM_REGION( 0x400, "prn", 0 )
- ROM_LOAD( "printer.3b", 0x000, 0x400, NO_DUMP )
-ROM_END
-
-
-//-------------------------------------------------
-// rom_region - device-specific ROM region
-//-------------------------------------------------
-
-const tiny_rom_entry *abc_memory_card_device::device_rom_region() const
+void abc_memory_card_device::device_add_mconfig(machine_config & config)
{
- return ROM_NAME( abc_dos );
+ GENERIC_SOCKET(config, m_dos_rom, generic_plain_slot, "abc80_dos", "bin");
+ GENERIC_SOCKET(config, m_iec_rom, generic_plain_slot, "abc80_iec", "bin");
+ GENERIC_SOCKET(config, m_opt_rom, generic_plain_slot, "abc80_opt", "bin");
+ GENERIC_SOCKET(config, m_prn_rom, generic_plain_slot, "abc80_prn", "bin");
}
@@ -145,19 +123,19 @@ uint8_t abc_memory_card_device::abcbus_xmemfl(offs_t offset)
if (offset >= 0x6000 && offset < 0x7000)
{
- data = m_dos_rom->base()[offset & 0xfff];
+ data = m_dos_rom->read_rom(offset & 0xfff);
}
if (offset >= 0x7000 && offset < 0x7400)
{
- data = m_iec_rom->base()[offset & 0x3ff];
+ data = m_iec_rom->read_rom(offset & 0x3ff);
}
if (offset >= 0x7400 && offset < 0x7800)
{
- data = m_opt_rom->base()[offset & 0x3ff];
+ data = m_opt_rom->read_rom(offset & 0x3ff);
}
if (offset >= 0x7800 && offset < 0x7c00)
{
- data = m_prn_rom->base()[offset & 0x3ff];
+ data = m_prn_rom->read_rom(offset & 0x3ff);
}
return data;
diff --git a/src/devices/bus/abcbus/memcard.h b/src/devices/bus/abcbus/memcard.h
index dae0a14fd50..f2f47cabb9e 100644
--- a/src/devices/bus/abcbus/memcard.h
+++ b/src/devices/bus/abcbus/memcard.h
@@ -12,6 +12,8 @@
#pragma once
#include "abcbus.h"
+#include "bus/generic/carts.h"
+#include "bus/generic/slot.h"
@@ -28,7 +30,7 @@ public:
abc_memory_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override;
protected:
// device-level overrides
@@ -39,10 +41,10 @@ protected:
virtual uint8_t abcbus_xmemfl(offs_t offset) override;
private:
- required_memory_region m_dos_rom;
- required_memory_region m_iec_rom;
- required_memory_region m_opt_rom;
- required_memory_region m_prn_rom;
+ required_device<generic_slot_device> m_dos_rom;
+ required_device<generic_slot_device> m_iec_rom;
+ required_device<generic_slot_device> m_opt_rom;
+ required_device<generic_slot_device> m_prn_rom;
};
diff --git a/src/devices/bus/abcbus/ssa.cpp b/src/devices/bus/abcbus/ssa.cpp
index c17c2e2a826..5a190fc0fbb 100644
--- a/src/devices/bus/abcbus/ssa.cpp
+++ b/src/devices/bus/abcbus/ssa.cpp
@@ -161,6 +161,23 @@ void abc_super_smartaid_device::device_reset()
}
+void abc_super_smartaid_device::nvram_default()
+{
+}
+
+bool abc_super_smartaid_device::nvram_read(util::read_stream &file)
+{
+ auto const [err, actual] = read(file, m_nvram, m_nvram.bytes());
+ return !err && (actual == m_nvram.bytes());
+}
+
+bool abc_super_smartaid_device::nvram_write(util::write_stream &file)
+{
+ auto const [err, actual] = write(file, m_nvram, m_nvram.bytes());
+ return !err;
+}
+
+
//**************************************************************************
// ABC BUS INTERFACE
diff --git a/src/devices/bus/abcbus/ssa.h b/src/devices/bus/abcbus/ssa.h
index f8f94bd2f93..d19f0ce9100 100644
--- a/src/devices/bus/abcbus/ssa.h
+++ b/src/devices/bus/abcbus/ssa.h
@@ -30,20 +30,20 @@ public:
abc_super_smartaid_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
protected:
- // device-level overrides
+ // device_t implementation
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
virtual void device_start() override;
virtual void device_reset() override;
- // device_nvram_interface overrides
- virtual void nvram_default() override { }
- virtual bool nvram_read(util::read_stream &file) override { size_t actual; return !file.read(m_nvram, m_nvram.bytes(), actual) && actual == m_nvram.bytes(); }
- virtual bool nvram_write(util::write_stream &file) override { size_t actual; return !file.write(m_nvram, m_nvram.bytes(), actual) && actual == m_nvram.bytes(); }
+ // device_nvram_interface implementation
+ virtual void nvram_default() override;
+ virtual bool nvram_read(util::read_stream &file) override;
+ virtual bool nvram_write(util::write_stream &file) override;
- // device_abcbus_interface overrides
+ // device_abcbus_interface implementation
virtual void abcbus_cs(uint8_t data) override { m_bus->write_cs(data); }
virtual uint8_t abcbus_inp() override { return m_bus->read_inp(); }
virtual void abcbus_out(uint8_t data) override { m_bus->write_out(data); }
diff --git a/src/devices/bus/abckb/abc77.cpp b/src/devices/bus/abckb/abc77.cpp
index 442ff553e2f..81a0cc44cc7 100644
--- a/src/devices/bus/abckb/abc77.cpp
+++ b/src/devices/bus/abckb/abc77.cpp
@@ -41,6 +41,14 @@ Notes:
*/
+/*
+
+ TODO:
+
+ - serial input is not working, fails systest1600 keyboard test
+
+*/
+
#include "emu.h"
#include "abc77.h"
#include "speaker.h"
@@ -166,7 +174,7 @@ INPUT_CHANGED_MEMBER( abc77_device::keyboard_reset )
// INPUT_PORTS( abc55 )
//-------------------------------------------------
-INPUT_PORTS_START( abc55 )
+static INPUT_PORTS_START( abc55 )
PORT_START("X0")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED )
@@ -192,17 +200,17 @@ INPUT_PORTS_START( abc55 )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_BACKSLASH2) PORT_CHAR('<') PORT_CHAR('>')
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("RETURN") PORT_CODE(KEYCODE_ENTER) PORT_CHAR('\r')
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )
- PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("\xE2\x86\x90") PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8)
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"\u2190") PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8) // U+2190 = ←
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED )
- PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("\xE2\x86\x92") PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT))
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"\u2192") PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT)) // U+2192 = →
PORT_START("X3")
- PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR(0x00E9) PORT_CHAR(0x00C9)
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR(U'é') PORT_CHAR(U'É')
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('+') PORT_CHAR('?')
- PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR(0x00E5) PORT_CHAR(0x00C5)
- PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(0x00FC) PORT_CHAR(0x00DC)
- PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(0x00E4) PORT_CHAR(0x00C4)
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR(U'å') PORT_CHAR(U'Å')
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(U'ü') PORT_CHAR(U'Ü')
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(U'ä') PORT_CHAR(U'Ä')
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('\'') PORT_CHAR('*')
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("SPACE") PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ')
@@ -213,7 +221,7 @@ INPUT_PORTS_START( abc55 )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O')
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P')
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L')
- PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_COLON) PORT_CHAR(0x00F6) PORT_CHAR(0x00D6)
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_COLON) PORT_CHAR(U'ö') PORT_CHAR(U'Ö')
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR(':')
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('-') PORT_CHAR('_')
@@ -238,7 +246,7 @@ INPUT_PORTS_START( abc55 )
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N')
PORT_START("X7")
- PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("4 \xC2\xA4") PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR(0x00A4)
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR(U'¤')
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#')
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E')
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R')
@@ -323,7 +331,7 @@ ioport_constructor abc55_device::device_input_ports() const
// INPUT_PORTS( abc77 )
//-------------------------------------------------
-INPUT_PORTS_START( abc77 )
+static INPUT_PORTS_START( abc77 )
PORT_INCLUDE( abc55 )
PORT_MODIFY("X9")
@@ -364,21 +372,6 @@ ioport_constructor abc77_device::device_input_ports() const
//**************************************************************************
//-------------------------------------------------
-// serial_output -
-//-------------------------------------------------
-
-inline void abc77_device::serial_output(int state)
-{
- if (m_txd != state)
- {
- m_txd = state;
-
- m_slot->write_rx(m_txd);
- }
-}
-
-
-//-------------------------------------------------
// serial_clock -
//-------------------------------------------------
@@ -390,20 +383,6 @@ TIMER_CALLBACK_MEMBER(abc77_device::serial_clock)
}
-//-------------------------------------------------
-// keydown -
-//-------------------------------------------------
-
-inline void abc77_device::key_down(int state)
-{
- if (m_keydown != state)
- {
- m_slot->keydown_w(state);
- m_keydown = state;
- }
-}
-
-
//**************************************************************************
// LIVE DEVICE
@@ -421,10 +400,12 @@ abc77_device::abc77_device(const machine_config &mconfig, device_type type, cons
m_discrete(*this, DISCRETE_TAG),
m_x(*this, "X%u", 0),
m_dsw(*this, "DSW"),
- m_txd(1), m_keylatch(0),
- m_keydown(1),
- m_clock(0), m_hys(0),
- m_stb(1), m_j3(0), m_serial_timer(nullptr), m_reset_timer(nullptr)
+ m_keylatch(0),
+ m_clock(0),
+ m_stb(1),
+ m_j3(0),
+ m_serial_timer(nullptr),
+ m_reset_timer(nullptr)
{
}
@@ -443,7 +424,8 @@ void abc77_device::device_start()
{
// allocate timers
m_serial_timer = timer_alloc(FUNC(abc77_device::serial_clock), this);
- m_serial_timer->adjust(attotime::from_hz(19200), 0, attotime::from_hz(19200)); // ALE/32
+ attotime serial_clock = attotime::from_hz((m_maincpu->get_ale_clock()/32)*2); // 600 bps
+ m_serial_timer->adjust(serial_clock, 0, serial_clock);
m_reset_timer = timer_alloc(FUNC(abc77_device::reset_tick), this);
}
@@ -489,6 +471,16 @@ void abc77_device::txd_w(int state)
//-------------------------------------------------
+// reset_w -
+//-------------------------------------------------
+
+void abc77_device::reset_w(int state)
+{
+ // connected to NE556 pin 8
+}
+
+
+//-------------------------------------------------
// p1_r -
//-------------------------------------------------
@@ -558,41 +550,8 @@ void abc77_device::p2_w(uint8_t data)
m_discrete->write(NODE_01, BIT(data, 4));
// transmit data
- serial_output(BIT(data, 5));
+ m_slot->write_rx(BIT(data, 5));
// key down
- key_down(BIT(data, 6));
-
- // hysteresis
- m_hys = BIT(data, 7);
-}
-
-
-//-------------------------------------------------
-// t1_r -
-//-------------------------------------------------
-
-READ_LINE_MEMBER( abc77_device::t1_r )
-{
- return m_clock;
-}
-
-
-//-------------------------------------------------
-// prog_w -
-//-------------------------------------------------
-
-WRITE_LINE_MEMBER( abc77_device::prog_w )
-{
- m_stb = state;
-}
-
-
-//-------------------------------------------------
-// j3_w -
-//-------------------------------------------------
-
-void abc77_device::j3_w(uint8_t data)
-{
- m_j3 = data;
+ m_slot->keydown_w(BIT(data, 6));
}
diff --git a/src/devices/bus/abckb/abc77.h b/src/devices/bus/abckb/abc77.h
index 4982c746570..304f8c3329f 100644
--- a/src/devices/bus/abckb/abc77.h
+++ b/src/devices/bus/abckb/abc77.h
@@ -26,7 +26,8 @@
// ======================> abc77_device
-class abc77_device : public device_t, public abc_keyboard_interface
+class abc77_device : public device_t,
+ public abc_keyboard_interface
{
public:
// construction/destruction
@@ -48,11 +49,9 @@ protected:
// abc_keyboard_interface overrides
virtual void txd_w(int state) override;
+ virtual void reset_w(int state) override;
private:
- void serial_output(int state);
- void key_down(int state);
-
TIMER_CALLBACK_MEMBER(serial_clock);
TIMER_CALLBACK_MEMBER(reset_tick);
@@ -62,11 +61,8 @@ private:
required_ioport_array<12> m_x;
required_ioport m_dsw;
- int m_txd; // transmit data
int m_keylatch; // keyboard row latch
- int m_keydown; // key down
int m_clock; // transmit clock
- int m_hys; // hysteresis
int m_stb; // strobe
uint8_t m_j3;
@@ -76,16 +72,16 @@ private:
uint8_t p1_r();
void p2_w(uint8_t data);
- DECLARE_READ_LINE_MEMBER( t1_r );
- DECLARE_WRITE_LINE_MEMBER( prog_w );
- void j3_w(uint8_t data);
+ int t1_r() { return m_clock; }
+ void prog_w(int state) { m_stb = state; }
+ void j3_w(uint8_t data) { m_j3 = data; }
void abc77_io(address_map &map);
void abc77_map(address_map &map);
};
-class abc55_device : public abc77_device
+class abc55_device : public abc77_device
{
public:
// construction/destruction
diff --git a/src/devices/bus/abckb/abc800kb.cpp b/src/devices/bus/abckb/abc800kb.cpp
index 571a62d5a6e..a7fdeea7351 100644
--- a/src/devices/bus/abckb/abc800kb.cpp
+++ b/src/devices/bus/abckb/abc800kb.cpp
@@ -158,7 +158,7 @@ INPUT_PORTS_START( abc800_keyboard )
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED ) // 86
PORT_START("X3")
- PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("4 \xC2\xA4") PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR(0x00A4)
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR(U'¤')
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E')
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D')
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C')
@@ -204,7 +204,7 @@ INPUT_PORTS_START( abc800_keyboard )
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M')
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("PF1") PORT_CODE(KEYCODE_F1) PORT_CHAR(UCHAR_MAMEKEY(F1))
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("RETURN") PORT_CODE(KEYCODE_ENTER) PORT_CHAR('\r')
- PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(UTF8_LEFT) PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8)
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"\u2190") PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8) // U+2190 = ←
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("PF7") PORT_CODE(KEYCODE_F7) PORT_CHAR(UCHAR_MAMEKEY(F7))
PORT_START("X8")
@@ -213,24 +213,24 @@ INPUT_PORTS_START( abc800_keyboard )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K')
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR(';')
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('<') PORT_CHAR('>')
- PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u_UMLAUT " " U_UMLAUT) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(0x00FC) PORT_CHAR(0x00DC)
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(U'ü') PORT_CHAR(U'Ü')
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_BACKSLASH2) PORT_CHAR('\'') PORT_CHAR('*')
- PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(UTF8_RIGHT) PORT_CODE(KEYCODE_TAB) PORT_CHAR(UCHAR_MAMEKEY(TAB))
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"\u2192") PORT_CODE(KEYCODE_TAB) PORT_CHAR(UCHAR_MAMEKEY(TAB)) // U+2192 = →
PORT_START("X9")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR('=')
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O')
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L')
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR(':')
- PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(e_ACUTE " " E_ACUTE) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR(0x00E9) PORT_CHAR(0x00C9)
- PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(a_RING " " A_RING) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR(0x00E5) PORT_CHAR(0x00C5)
- PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(a_UMLAUT " " A_UMLAUT) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(0x00E4) PORT_CHAR(0x00C4)
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR(U'é') PORT_CHAR(U'É')
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR(U'å') PORT_CHAR(U'Å')
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(U'ä') PORT_CHAR(U'Ä')
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Right SHIFT") PORT_CODE(KEYCODE_RSHIFT)
PORT_START("X10")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('+') PORT_CHAR('?')
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P')
- PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(o_UMLAUT " " O_UMLAUT) PORT_CODE(KEYCODE_COLON) PORT_CHAR(0x00F6) PORT_CHAR(0x00D6)
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_COLON) PORT_CHAR(U'ö') PORT_CHAR(U'Ö')
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('-') PORT_CHAR('_')
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED ) // 87
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED ) // 88
@@ -454,7 +454,7 @@ void abc800_keyboard_device::kb_p2_w(uint8_t data)
// kb_t1_r - keyboard T1 timer read
//-------------------------------------------------
-READ_LINE_MEMBER( abc800_keyboard_device::kb_t1_r )
+int abc800_keyboard_device::kb_t1_r()
{
return m_clk;
}
diff --git a/src/devices/bus/abckb/abc800kb.h b/src/devices/bus/abckb/abc800kb.h
index 39f54e2f854..1f780444e97 100644
--- a/src/devices/bus/abckb/abc800kb.h
+++ b/src/devices/bus/abckb/abc800kb.h
@@ -52,7 +52,7 @@ private:
uint8_t kb_p1_r();
void kb_p1_w(uint8_t data);
void kb_p2_w(uint8_t data);
- DECLARE_READ_LINE_MEMBER( kb_t1_r );
+ int kb_t1_r();
required_device<i8048_device> m_maincpu;
required_ioport_array<12> m_x;
diff --git a/src/devices/bus/abckb/abc99.cpp b/src/devices/bus/abckb/abc99.cpp
index 3273e625a4b..a515ce5c8b0 100644
--- a/src/devices/bus/abckb/abc99.cpp
+++ b/src/devices/bus/abckb/abc99.cpp
@@ -2,7 +2,7 @@
// copyright-holders:Curt Coder
/**********************************************************************
- Luxor ABC-99 keyboard and mouse emulation
+ Luxor ABC-99 keyboard emulation
*********************************************************************/
@@ -43,17 +43,14 @@ Notes:
TODO:
- - verify cursor keys
- - language DIP
- - mouse
- - MCS-48 PC:01DC - Unimplemented opcode = 75
- - 75 = ENT0 CLK : enable CLK (unscaled_clock/3) output on T0
- - halt Z2 when Z5 is reset, resume Z2 when Z5 executes ENT0 CLK instruction
+ - watchdog clock
+ - output leds
*/
#include "emu.h"
#include "abc99.h"
+
#include "speaker.h"
@@ -62,8 +59,9 @@ Notes:
// MACROS / CONSTANTS
//**************************************************************************
-#define I8035_Z2_TAG "z2"
-#define I8035_Z5_TAG "z5"
+#define I8035_Z2_TAG "z2"
+#define I8035_Z5_TAG "z5"
+#define R8_TAG "r8"
@@ -81,10 +79,10 @@ DEFINE_DEVICE_TYPE(ABC99, abc99_device, "abc99", "Luxor ABC 99")
ROM_START( abc99 )
ROM_SYSTEM_BIOS( 0, "107268", "107268-17" )
ROM_SYSTEM_BIOS( 1, "106819", "106819-09" )
- ROM_DEFAULT_BIOS("107268")
+ ROM_DEFAULT_BIOS("106819")
ROM_REGION( 0x1000, I8035_Z2_TAG, 0 )
- ROMX_LOAD( "107268-17.z3", 0x0000, 0x0800, CRC(2f60cc35) SHA1(ebc6af9cd0a49a0d01698589370e628eebb6221c), ROM_BIOS(0) )
+ ROMX_LOAD( "107268-17.z3", 0x0000, 0x0800, CRC(2f60cc35) SHA1(ebc6af9cd0a49a0d01698589370e628eebb6221c), ROM_BIOS(0) ) // UP/DOWN mode is broken
ROMX_LOAD( "106819-09.z3", 0x0000, 0x1000, CRC(ffe32a71) SHA1(fa2ce8e0216a433f9bbad0bdd6e3dc0b540f03b7), ROM_BIOS(1) ) // ABC 99 6490423-01
ROM_REGION( 0x800, I8035_Z5_TAG, 0 )
@@ -104,46 +102,31 @@ const tiny_rom_entry *abc99_device::device_rom_region() const
//-------------------------------------------------
-// ADDRESS_MAP( abc99_z2_mem )
+// ADDRESS_MAP( keyboard_mem )
//-------------------------------------------------
-void abc99_device::abc99_z2_mem(address_map &map)
+void abc99_device::keyboard_mem(address_map &map)
{
map(0x0000, 0x0fff).rom().region(I8035_Z2_TAG, 0);
}
//-------------------------------------------------
-// ADDRESS_MAP( abc99_z2_io )
+// ADDRESS_MAP( keyboard_io )
//-------------------------------------------------
-void abc99_device::abc99_z2_io(address_map &map)
+void abc99_device::keyboard_io(address_map &map)
{
- map(0x21, 0x21).w(FUNC(abc99_device::z2_led_w));
- map(0x30, 0x30).portr("X0").nopw();
- map(0x31, 0x31).portr("X1").nopw();
- map(0x32, 0x32).portr("X2").nopw();
- map(0x33, 0x33).portr("X3").nopw();
- map(0x34, 0x34).portr("X4").nopw();
- map(0x35, 0x35).portr("X5").nopw();
- map(0x36, 0x36).portr("X6").nopw();
- map(0x37, 0x37).portr("X7").nopw();
- map(0x38, 0x38).portr("X8").nopw();
- map(0x39, 0x39).portr("X9").nopw();
- map(0x3a, 0x3a).portr("X10").nopw();
- map(0x3b, 0x3b).portr("X11").nopw();
- map(0x3c, 0x3c).portr("X12").nopw();
- map(0x3d, 0x3d).portr("X13").nopw();
- map(0x3e, 0x3e).portr("X14").nopw();
- map(0x3f, 0x3f).portr("X15").nopw();
+ map(0x21, 0x21).w(FUNC(abc99_device::led_w));
+ map(0x30, 0x3f).rw(FUNC(abc99_device::key_y_r), FUNC(abc99_device::key_x_w));
}
//-------------------------------------------------
-// ADDRESS_MAP( abc99_z5_mem )
+// ADDRESS_MAP( mouse_mem )
//-------------------------------------------------
-void abc99_device::abc99_z5_mem(address_map &map)
+void abc99_device::mouse_mem(address_map &map)
{
map(0x0000, 0x07ff).rom().region(I8035_Z5_TAG, 0);
}
@@ -156,22 +139,27 @@ void abc99_device::abc99_z5_mem(address_map &map)
void abc99_device::device_add_mconfig(machine_config &config)
{
// keyboard CPU
- I8035(config, m_maincpu, XTAL(6'000'000)/3); // from Z5 T0 output
- m_maincpu->set_addrmap(AS_PROGRAM, &abc99_device::abc99_z2_mem);
- m_maincpu->set_addrmap(AS_IO, &abc99_device::abc99_z2_io);
+ I8035(config, m_maincpu, 0); // from Z5 T0 output
+ m_maincpu->set_addrmap(AS_PROGRAM, &abc99_device::keyboard_mem);
+ m_maincpu->set_addrmap(AS_IO, &abc99_device::keyboard_io);
m_maincpu->p1_out_cb().set(FUNC(abc99_device::z2_p1_w));
m_maincpu->p2_in_cb().set(FUNC(abc99_device::z2_p2_r));
- m_maincpu->t0_in_cb().set(FUNC(abc99_device::z2_t0_r));
+ m_maincpu->t0_in_cb().set_constant(0); // mouse connected
m_maincpu->t1_in_cb().set(FUNC(abc99_device::z2_t1_r));
// mouse CPU
I8035(config, m_mousecpu, XTAL(6'000'000));
- m_mousecpu->set_addrmap(AS_PROGRAM, &abc99_device::abc99_z5_mem);
- //m_mousecpu->p1_in_cb().set(FUNC(abc99_device::z5_p1_r));
- //m_mousecpu->p2_out_cb().set(FUNC(abc99_device::z5_p2_w));
- //m_mousecpu->set_t0_clk_cb(); // Z2 CLK
- //m_mousecpu->t1_in_cb().set(FUNC(abc99_device::z5_t1_r));
- m_mousecpu->set_disable(); // HACK fix for broken serial I/O
+ m_mousecpu->set_addrmap(AS_PROGRAM, &abc99_device::mouse_mem);
+ m_mousecpu->p1_in_cb().set(FUNC(abc99_device::z5_p1_r));
+ m_mousecpu->p2_out_cb().set(FUNC(abc99_device::z5_p2_w));
+ m_mousecpu->set_t0_clk_cb(I8035_Z2_TAG, FUNC(device_t::set_unscaled_clock_int));
+ m_mousecpu->t1_in_cb().set(FUNC(abc99_device::z5_t1_r));
+
+ // watchdog
+ WATCHDOG_TIMER(config, m_watchdog).set_time(attotime::from_hz(0));
+
+ // mouse
+ LUXOR_R8(config, m_mouse, 0);
// sound hardware
SPEAKER(config, "mono").front_center();
@@ -196,11 +184,53 @@ INPUT_CHANGED_MEMBER( abc99_device::keyboard_reset )
// INPUT_PORTS( abc99 )
//-------------------------------------------------
-INPUT_PORTS_START( abc99 )
+CUSTOM_INPUT_MEMBER( abc99_device::cursor_x4_r )
+{
+ u8 cursor = m_cursor->read();
+ u8 data = 0;
+ switch (cursor & 0xf)
+ {
+ case 0x1: // up
+ case 0x9: // up-right
+ data = 0x1;
+ break;
+ case 0x2: // down
+ case 0xa: // down-right
+ data = 0x2;
+ break;
+ case 0x8: // right
+ data = 0x3;
+ break;
+ }
+ return data;
+}
+
+CUSTOM_INPUT_MEMBER( abc99_device::cursor_x6_r )
+{
+ u8 cursor = m_cursor->read();
+ u8 data = 0;
+ switch (cursor & 0xf)
+ {
+ case 0x1: // up
+ case 0x5: // up-left
+ data = 0x1;
+ break;
+ case 0x2: // down
+ case 0x6: // down-left
+ data = 0x2;
+ break;
+ case 0x4: // left
+ data = 0x3;
+ break;
+ }
+ return data;
+}
+
+static INPUT_PORTS_START( abc99 )
PORT_START("X0")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("PF13") PORT_CODE(KEYCODE_PRTSCR)
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME(UTF8_RIGHT"|") PORT_CODE(KEYCODE_TAB) PORT_CHAR('\t')
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME(u8"\u2192|") PORT_CODE(KEYCODE_TAB) PORT_CHAR('\t') // U+2192 = →
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("RETURN") PORT_CODE(KEYCODE_ENTER) PORT_CHAR('\r')
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("LF") PORT_CODE(KEYCODE_RCONTROL) PORT_CHAR(UCHAR_MAMEKEY(RCONTROL))
@@ -242,8 +272,7 @@ INPUT_PORTS_START( abc99 )
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("PF15") PORT_CODE(KEYCODE_PAUSE)
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("DEL") PORT_CODE(KEYCODE_DEL) PORT_CHAR(UCHAR_MAMEKEY(DEL))
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_UNUSED )
- PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME(UTF8_RIGHT) PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT)) // cursor B
- PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME(UTF8_LEFT) PORT_CODE(KEYCODE_LEFT) PORT_CHAR(UCHAR_MAMEKEY(LEFT)) // cursor D
+ PORT_BIT( 0x30, IP_ACTIVE_HIGH, IPT_CUSTOM) PORT_CUSTOM_MEMBER(abc99_device, cursor_x4_r)
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X')
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNUSED )
@@ -251,7 +280,7 @@ INPUT_PORTS_START( abc99 )
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("PF12") PORT_CODE(KEYCODE_F12) PORT_CHAR(UCHAR_MAMEKEY(F12))
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("BS") PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8)
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(0x00FC) PORT_CHAR(0x00DC)
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(U'ü') PORT_CHAR(U'Ü')
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('\'') PORT_CHAR('*')
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Right SHIFT") PORT_CODE(KEYCODE_RSHIFT)
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q')
@@ -262,17 +291,16 @@ INPUT_PORTS_START( abc99 )
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("PF14") PORT_CODE(KEYCODE_SCRLOCK)
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("INS") PORT_CODE(KEYCODE_INSERT) PORT_CHAR(UCHAR_MAMEKEY(INSERT))
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_UNUSED )
- PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME(UTF8_UP) PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP)) // cursor A
- PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME(UTF8_DOWN) PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN)) // cursor C
+ PORT_BIT( 0x30, IP_ACTIVE_HIGH, IPT_CUSTOM) PORT_CUSTOM_MEMBER(abc99_device, cursor_x6_r)
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("CTRL") PORT_CODE(KEYCODE_LCONTROL) PORT_CHAR(UCHAR_MAMEKEY(LCONTROL))
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("CAPS LOCK") PORT_CODE(KEYCODE_CAPSLOCK) PORT_CHAR(UCHAR_MAMEKEY(CAPSLOCK))
PORT_START("X7")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("PF11") PORT_CODE(KEYCODE_F11) PORT_CHAR(UCHAR_MAMEKEY(F11))
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR(0x00E9) PORT_CHAR(0x00C9)
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR(0x00E5) PORT_CHAR(0x00C5)
- PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(0x00E4) PORT_CHAR(0x00C4)
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR(U'é') PORT_CHAR(U'É')
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR(U'å') PORT_CHAR(U'Å')
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(U'ä') PORT_CHAR(U'Ä')
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('-') PORT_CHAR('_')
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W')
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S')
@@ -285,14 +313,14 @@ INPUT_PORTS_START( abc99 )
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Keypad 2") PORT_CODE(KEYCODE_2_PAD) PORT_CHAR(UCHAR_MAMEKEY(2_PAD))
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_UNUSED )
- PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("|" UTF8_LEFT) PORT_CODE(KEYCODE_RALT) PORT_CHAR(UCHAR_MAMEKEY(RALT))
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME(u8"|\u2190") PORT_CODE(KEYCODE_RALT) PORT_CHAR(UCHAR_MAMEKEY(RALT)) // U+2190 = ←
PORT_START("X9")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('+') PORT_CHAR('?')
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P')
- PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_COLON) PORT_CHAR(0x00F6) PORT_CHAR(0x00D6)
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_COLON) PORT_CHAR(U'ö') PORT_CHAR(U'Ö')
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR(':')
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E')
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D')
@@ -335,7 +363,7 @@ INPUT_PORTS_START( abc99 )
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G')
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V')
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("PF5") PORT_CODE(KEYCODE_F5) PORT_CHAR(UCHAR_MAMEKEY(F5))
- PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("4 \xC2\xA4") PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR(0x00A4)
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR(U'¤')
PORT_START("X14")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED )
@@ -359,28 +387,23 @@ INPUT_PORTS_START( abc99 )
PORT_START("Z14")
PORT_DIPNAME( 0x07, 0x00, DEF_STR( Language ) ) PORT_DIPLOCATION("Z14:1,2,3")
- PORT_DIPSETTING( 0x00, DEF_STR( Unknown ) )
- PORT_DIPSETTING( 0x01, DEF_STR( Unknown ) )
- PORT_DIPSETTING( 0x02, DEF_STR( Unknown ) )
- PORT_DIPSETTING( 0x03, DEF_STR( Unknown ) )
- PORT_DIPSETTING( 0x04, DEF_STR( Unknown ) )
- PORT_DIPSETTING( 0x05, DEF_STR( Unknown ) )
- PORT_DIPSETTING( 0x06, DEF_STR( Unknown ) )
- PORT_DIPSETTING( 0x07, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x00, "Swedish" )
+ PORT_DIPSETTING( 0x01, "US English" )
+ PORT_DIPSETTING( 0x02, "Spanish" )
+ PORT_DIPSETTING( 0x03, "Danish" )
+ PORT_DIPSETTING( 0x04, "Norwegian" )
+ PORT_DIPSETTING( 0x05, DEF_STR( Unused ) )
+ PORT_DIPSETTING( 0x06, DEF_STR( Unused ) )
+ PORT_DIPSETTING( 0x07, DEF_STR( Unused ) )
PORT_DIPNAME( 0x08, 0x08, "Keyboard Program" ) PORT_DIPLOCATION("Z14:4")
PORT_DIPSETTING( 0x00, "Internal (8048)" )
PORT_DIPSETTING( 0x08, "External PROM" )
- PORT_START("MOUSEB")
- PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("Left Mouse Button") PORT_CODE(MOUSECODE_BUTTON1)
- PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("Middle Mouse Button") PORT_CODE(MOUSECODE_BUTTON3)
- PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("Right Mouse Button") PORT_CODE(MOUSECODE_BUTTON2)
-
- PORT_START("MOUSEX")
- PORT_BIT( 0xff, 0x00, IPT_MOUSE_X ) PORT_SENSITIVITY(100) PORT_KEYDELTA(5) PORT_MINMAX(0, 255) PORT_PLAYER(1)
-
- PORT_START("MOUSEY")
- PORT_BIT( 0xff, 0x00, IPT_MOUSE_Y ) PORT_SENSITIVITY(100) PORT_KEYDELTA(5) PORT_MINMAX(0, 255) PORT_PLAYER(1)
+ PORT_START("CURSOR")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME(u8"\u2191") PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP)) // U+2191 = ↑
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME(u8"\u2193") PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN)) // U+2193 = ↓
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME(u8"\u2190") PORT_CODE(KEYCODE_LEFT) PORT_CHAR(UCHAR_MAMEKEY(LEFT)) // U+2190 = ←
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME(u8"\u2192") PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT)) // U+2192 = →
PORT_START("J4")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("Keyboard Reset") PORT_CHANGED_MEMBER(DEVICE_SELF, abc99_device, keyboard_reset, 0)
@@ -410,21 +433,6 @@ void abc99_device::serial_input()
//-------------------------------------------------
-// serial_output -
-//-------------------------------------------------
-
-void abc99_device::serial_output(int state)
-{
- if (m_txd != state)
- {
- m_txd = state;
-
- m_slot->write_rx(m_txd);
- }
-}
-
-
-//-------------------------------------------------
// serial_clock -
//-------------------------------------------------
@@ -435,30 +443,6 @@ TIMER_CALLBACK_MEMBER(abc99_device::serial_clock)
}
-//-------------------------------------------------
-// scan_mouse -
-//-------------------------------------------------
-
-TIMER_CALLBACK_MEMBER(abc99_device::scan_mouse)
-{
-}
-
-
-//-------------------------------------------------
-// keydown -
-//-------------------------------------------------
-
-void abc99_device::key_down(int state)
-{
- if (m_keydown != state)
- {
- m_slot->keydown_w(state);
- m_keydown = state;
- }
-}
-
-
-
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
@@ -469,23 +453,26 @@ void abc99_device::key_down(int state)
abc99_device::abc99_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, ABC99, tag, owner, clock),
- abc_keyboard_interface(mconfig, *this), m_serial_timer(nullptr), m_mouse_timer(nullptr),
+ abc_keyboard_interface(mconfig, *this),
+ m_serial_timer(nullptr),
m_maincpu(*this, I8035_Z2_TAG),
m_mousecpu(*this, I8035_Z5_TAG),
+ m_watchdog(*this, "watchdog"),
m_speaker(*this, "speaker"),
+ m_mouse(*this, R8_TAG),
+ m_x(*this, "X%u", 0),
m_z14(*this, "Z14"),
- m_mouseb(*this, "MOUSEB"),
+ m_cursor(*this, "CURSOR"),
m_leds(*this, "led%u", 0U),
+ m_keylatch(0),
m_si(1),
m_si_en(1),
m_so_z2(1),
m_so_z5(1),
- m_keydown(0),
m_t1_z2(0),
m_t1_z5(0),
- m_led_en(0),
- m_reset(1),
- m_txd(1)
+ m_led_en(1),
+ m_reset(1)
{
}
@@ -497,23 +484,22 @@ abc99_device::abc99_device(const machine_config &mconfig, const char *tag, devic
void abc99_device::device_start()
{
m_leds.resolve();
+
// allocate timers
m_serial_timer = timer_alloc(FUNC(abc99_device::serial_clock), this);
- m_serial_timer->adjust(MCS48_ALE_CLOCK(XTAL(6'000'000)/3), 0, MCS48_ALE_CLOCK(XTAL(6'000'000)/3));
-
- m_mouse_timer = timer_alloc(FUNC(abc99_device::scan_mouse), this);
+ attotime serial_clock = MCS48_ALE_CLOCK(m_mousecpu->get_t0_clock()); // 8333 bps
+ m_serial_timer->adjust(serial_clock, 0, serial_clock);
// state saving
+ save_item(NAME(m_keylatch));
save_item(NAME(m_si));
save_item(NAME(m_si_en));
save_item(NAME(m_so_z2));
save_item(NAME(m_so_z5));
- save_item(NAME(m_keydown));
save_item(NAME(m_t1_z2));
save_item(NAME(m_t1_z5));
save_item(NAME(m_led_en));
save_item(NAME(m_reset));
- save_item(NAME(m_txd));
}
@@ -523,7 +509,7 @@ void abc99_device::device_start()
void abc99_device::device_reset()
{
- // set EA lines
+ // external access
m_maincpu->set_input_line(MCS48_INPUT_EA, ASSERT_LINE);
m_mousecpu->set_input_line(MCS48_INPUT_EA, ASSERT_LINE);
@@ -546,10 +532,20 @@ void abc99_device::txd_w(int state)
//-------------------------------------------------
-// z2_bus_w -
+// reset_w -
//-------------------------------------------------
-void abc99_device::z2_led_w(uint8_t data)
+void abc99_device::reset_w(int state)
+{
+ m_mousecpu->set_input_line(INPUT_LINE_RESET, state);
+}
+
+
+//-------------------------------------------------
+// key_x_w -
+//-------------------------------------------------
+
+void abc99_device::led_w(uint8_t data)
{
if (m_led_en) return;
@@ -565,6 +561,31 @@ void abc99_device::z2_led_w(uint8_t data)
//-------------------------------------------------
+// key_y_r -
+//-------------------------------------------------
+
+uint8_t abc99_device::key_y_r()
+{
+ return m_x[m_keylatch]->read();
+}
+
+
+//-------------------------------------------------
+// key_x_w -
+//-------------------------------------------------
+
+void abc99_device::key_x_w(offs_t offset, uint8_t data)
+{
+ m_keylatch = offset & 0x0f;
+
+ if (m_keylatch == 14)
+ {
+ m_watchdog->watchdog_reset();
+ }
+}
+
+
+//-------------------------------------------------
// z2_p1_w -
//-------------------------------------------------
@@ -587,18 +608,18 @@ void abc99_device::z2_p1_w(uint8_t data)
// serial output
m_so_z2 = BIT(data, 0);
- serial_output(m_so_z2 && m_so_z5);
+ m_slot->write_rx(m_so_z2 && m_so_z5);
// key down
- key_down(!BIT(data, 1));
+ m_slot->keydown_w(!BIT(data, 1));
// master T1
m_t1_z5 = BIT(data, 2);
// key LEDs
- m_leds[LED_INS] = BIT(data, 3);
- m_leds[LED_ALT] = BIT(data, 4);
- m_leds[LED_CAPS_LOCK] = BIT(data, 5);
+ m_leds[LED_INS] = !BIT(data, 3);
+ m_leds[LED_ALT] = !BIT(data, 4);
+ m_leds[LED_CAPS_LOCK] = !BIT(data, 5);
// speaker output
m_speaker->level_w(!BIT(data, 6));
@@ -636,26 +657,6 @@ uint8_t abc99_device::z2_p2_r()
//-------------------------------------------------
-// z2_t0_r -
-//-------------------------------------------------
-
-READ_LINE_MEMBER( abc99_device::z2_t0_r )
-{
- return 1; // 0=mouse connected, 1=no mouse
-}
-
-
-//-------------------------------------------------
-// z2_t1_r -
-//-------------------------------------------------
-
-READ_LINE_MEMBER( abc99_device::z2_t1_r )
-{
- return m_t1_z2;
-}
-
-
-//-------------------------------------------------
// z5_p1_r -
//-------------------------------------------------
@@ -678,8 +679,8 @@ uint8_t abc99_device::z5_p1_r()
uint8_t data = 0;
- // mouse buttons
- data |= (m_mouseb->read() & 0x07) << 4;
+ // mouse
+ data |= m_mouse->read() & 0x7f;
// serial input
data |= m_si << 7;
@@ -721,27 +722,17 @@ void abc99_device::z5_p2_w(uint8_t data)
// Z2 reset
int reset = BIT(data, 5);
- if (!m_reset && reset)
+ if (m_reset != reset)
{
- m_maincpu->reset();
+ m_maincpu->set_input_line(INPUT_LINE_RESET, reset ? CLEAR_LINE : ASSERT_LINE);
}
m_reset = reset;
// serial output
m_so_z5 = BIT(data, 6);
- serial_output(m_so_z2 && m_so_z5);
+ m_slot->write_rx(m_so_z2 && m_so_z5);
// keyboard CPU T1
m_t1_z2 = BIT(data, 7);
}
-
-
-//-------------------------------------------------
-// z5_t1_r -
-//-------------------------------------------------
-
-uint8_t abc99_device::z5_t1_r()
-{
- return m_t1_z5;
-}
diff --git a/src/devices/bus/abckb/abc99.h b/src/devices/bus/abckb/abc99.h
index d2c30db1f4f..8f47aa1c6e7 100644
--- a/src/devices/bus/abckb/abc99.h
+++ b/src/devices/bus/abckb/abc99.h
@@ -2,7 +2,7 @@
// copyright-holders:Curt Coder
/**********************************************************************
- Luxor ABC-99 keyboard and mouse emulation
+ Luxor ABC-99 keyboard emulation
*********************************************************************/
@@ -13,7 +13,9 @@
#include "abckb.h"
+#include "bus/abckb/r8.h"
#include "cpu/mcs48/mcs48.h"
+#include "machine/watchdog.h"
#include "sound/spkrdev.h"
@@ -25,12 +27,15 @@
// ======================> abc99_device
class abc99_device : public device_t,
- public abc_keyboard_interface
+ public abc_keyboard_interface
{
public:
// construction/destruction
abc99_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ DECLARE_CUSTOM_INPUT_MEMBER( cursor_x4_r );
+ DECLARE_CUSTOM_INPUT_MEMBER( cursor_x6_r );
+
DECLARE_INPUT_CHANGED_MEMBER( keyboard_reset );
protected:
@@ -45,6 +50,7 @@ protected:
// abc_keyboard_interface overrides
virtual void txd_w(int state) override;
+ virtual void reset_w(int state) override;
private:
enum
@@ -63,45 +69,44 @@ private:
};
void serial_input();
- void serial_output(int state);
TIMER_CALLBACK_MEMBER(serial_clock);
- TIMER_CALLBACK_MEMBER(scan_mouse);
- void key_down(int state);
+ uint8_t key_y_r();
+ void key_x_w(offs_t offset, uint8_t data);
void z2_p1_w(uint8_t data);
uint8_t z2_p2_r();
- DECLARE_READ_LINE_MEMBER( z2_t0_r );
- DECLARE_READ_LINE_MEMBER( z2_t1_r );
+ int z2_t1_r() { return m_t1_z2; }
- void z2_led_w(uint8_t data);
+ void led_w(uint8_t data);
uint8_t z5_p1_r();
void z5_p2_w(uint8_t data);
- uint8_t z5_t1_r();
+ int z5_t1_r() { return m_t1_z5; }
- void abc99_z2_io(address_map &map);
- void abc99_z2_mem(address_map &map);
- void abc99_z5_mem(address_map &map);
+ void keyboard_io(address_map &map);
+ void keyboard_mem(address_map &map);
+ void mouse_mem(address_map &map);
emu_timer *m_serial_timer;
- emu_timer *m_mouse_timer;
required_device<i8035_device> m_maincpu;
required_device<i8035_device> m_mousecpu;
+ required_device<watchdog_timer_device> m_watchdog;
required_device<speaker_sound_device> m_speaker;
+ required_device<luxor_r8_device> m_mouse;
+ required_ioport_array<16> m_x;
required_ioport m_z14;
- required_ioport m_mouseb;
+ required_ioport m_cursor;
output_finder<11> m_leds;
+ int m_keylatch;
int m_si;
int m_si_en;
int m_so_z2;
int m_so_z5;
- int m_keydown;
int m_t1_z2;
int m_t1_z5;
int m_led_en;
int m_reset;
- int m_txd;
};
diff --git a/src/devices/bus/abckb/abckb.cpp b/src/devices/bus/abckb/abckb.cpp
index 32af6f47178..efe3ef757e3 100644
--- a/src/devices/bus/abckb/abckb.cpp
+++ b/src/devices/bus/abckb/abckb.cpp
@@ -48,7 +48,8 @@ abc_keyboard_port_device::abc_keyboard_port_device(const machine_config &mconfig
device_single_card_slot_interface<abc_keyboard_interface>(mconfig, *this),
m_out_rx_handler(*this),
m_out_trxc_handler(*this),
- m_out_keydown_handler(*this), m_card(nullptr)
+ m_out_keydown_handler(*this),
+ m_card(nullptr)
{
}
@@ -60,11 +61,20 @@ abc_keyboard_port_device::abc_keyboard_port_device(const machine_config &mconfig
void abc_keyboard_port_device::device_start()
{
m_card = get_card_device();
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
- // resolve callbacks
- m_out_rx_handler.resolve_safe();
- m_out_trxc_handler.resolve_safe();
- m_out_keydown_handler.resolve_safe();
+void abc_keyboard_port_device::device_reset()
+{
+ if (m_card)
+ {
+ m_card->reset_w(ASSERT_LINE);
+ m_card->reset_w(CLEAR_LINE);
+ }
}
@@ -72,7 +82,7 @@ void abc_keyboard_port_device::device_start()
// write_rx -
//-------------------------------------------------
-WRITE_LINE_MEMBER( abc_keyboard_port_device::write_rx )
+void abc_keyboard_port_device::write_rx(int state)
{
m_out_rx_handler(state);
}
@@ -82,7 +92,7 @@ WRITE_LINE_MEMBER( abc_keyboard_port_device::write_rx )
// txd_w -
//-------------------------------------------------
-WRITE_LINE_MEMBER( abc_keyboard_port_device::txd_w )
+void abc_keyboard_port_device::txd_w(int state)
{
if (m_card)
m_card->txd_w(state);
@@ -93,7 +103,7 @@ WRITE_LINE_MEMBER( abc_keyboard_port_device::txd_w )
// trxc_w -
//-------------------------------------------------
-WRITE_LINE_MEMBER( abc_keyboard_port_device::trxc_w )
+void abc_keyboard_port_device::trxc_w(int state)
{
m_out_trxc_handler(state);
}
@@ -103,7 +113,7 @@ WRITE_LINE_MEMBER( abc_keyboard_port_device::trxc_w )
// keydown_w -
//-------------------------------------------------
-WRITE_LINE_MEMBER( abc_keyboard_port_device::keydown_w )
+void abc_keyboard_port_device::keydown_w(int state)
{
m_out_keydown_handler(state);
}
@@ -118,9 +128,13 @@ WRITE_LINE_MEMBER( abc_keyboard_port_device::keydown_w )
#include "abc77.h"
#include "abc99.h"
+void abc800_keyboard_devices(device_slot_interface &device)
+{
+ device.option_add_internal("abc800", ABC800_KEYBOARD);
+}
+
void abc_keyboard_devices(device_slot_interface &device)
{
- device.option_add("abc800", ABC800_KEYBOARD);
device.option_add("abc55", ABC55);
device.option_add("abc77", ABC77);
device.option_add("abc99", ABC99);
diff --git a/src/devices/bus/abckb/abckb.h b/src/devices/bus/abckb/abckb.h
index 63b8b2c799e..af1a8ca83ac 100644
--- a/src/devices/bus/abckb/abckb.h
+++ b/src/devices/bus/abckb/abckb.h
@@ -39,16 +39,17 @@ public:
auto out_keydown_handler() { return m_out_keydown_handler.bind(); }
// computer interface
- DECLARE_WRITE_LINE_MEMBER( txd_w );
+ void txd_w(int state);
// peripheral interface
- DECLARE_WRITE_LINE_MEMBER( write_rx );
- DECLARE_WRITE_LINE_MEMBER( trxc_w );
- DECLARE_WRITE_LINE_MEMBER( keydown_w );
+ void write_rx(int state);
+ void trxc_w(int state);
+ void keydown_w(int state);
protected:
// device-level overrides
virtual void device_start() override;
+ virtual void device_reset() override;
devcb_write_line m_out_rx_handler;
devcb_write_line m_out_trxc_handler;
@@ -62,6 +63,7 @@ class abc_keyboard_interface : public device_interface
{
public:
virtual void txd_w(int state) { }
+ virtual void reset_w(int state) { }
protected:
// construction/destruction
@@ -76,6 +78,7 @@ DECLARE_DEVICE_TYPE(ABC_KEYBOARD_PORT, abc_keyboard_port_device)
// supported devices
+void abc800_keyboard_devices(device_slot_interface &device);
void abc_keyboard_devices(device_slot_interface &device);
#endif // MAME_BUS_ABCKB_ABCKB_H
diff --git a/src/devices/bus/abckb/r8.cpp b/src/devices/bus/abckb/r8.cpp
new file mode 100644
index 00000000000..8372bbdedbc
--- /dev/null
+++ b/src/devices/bus/abckb/r8.cpp
@@ -0,0 +1,160 @@
+// copyright-holders:Curt Coder
+/**********************************************************************
+
+ Luxor R8 mouse emulation
+
+*********************************************************************/
+
+#include "emu.h"
+#include "r8.h"
+
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(LUXOR_R8, luxor_r8_device, "luxor_r8", "Luxor R8")
+
+
+//-------------------------------------------------
+// INPUT_PORTS( r8 )
+//-------------------------------------------------
+
+static INPUT_PORTS_START( r8 )
+ PORT_START("MOUSEB")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("Left Mouse Button") PORT_CODE(MOUSECODE_BUTTON1)
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("Middle Mouse Button") PORT_CODE(MOUSECODE_BUTTON3)
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("Right Mouse Button") PORT_CODE(MOUSECODE_BUTTON2)
+
+ PORT_START("MOUSEX")
+ PORT_BIT( 0xfff, 0x000, IPT_MOUSE_X ) PORT_SENSITIVITY(50)
+
+ PORT_START("MOUSEY")
+ PORT_BIT( 0xfff, 0x000, IPT_MOUSE_Y ) PORT_SENSITIVITY(50)
+INPUT_PORTS_END
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor luxor_r8_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( r8 );
+}
+
+
+//-------------------------------------------------
+// scan_mouse -
+//-------------------------------------------------
+
+TIMER_CALLBACK_MEMBER(luxor_r8_device::scan_mouse)
+{
+ switch(m_phase)
+ {
+ case 0:
+ m_xa = m_x > m_prev_x ? CLEAR_LINE : ASSERT_LINE;
+ m_xb = m_x < m_prev_x ? CLEAR_LINE : ASSERT_LINE;
+ m_ya = m_y > m_prev_y ? CLEAR_LINE : ASSERT_LINE;
+ m_yb = m_y < m_prev_y ? CLEAR_LINE : ASSERT_LINE;
+ break;
+ case 1:
+ m_xa = m_xb = m_x != m_prev_x ? CLEAR_LINE : ASSERT_LINE;
+ m_ya = m_yb = m_y != m_prev_y ? CLEAR_LINE : ASSERT_LINE;
+ break;
+ case 2:
+ m_xa = m_x < m_prev_x ? CLEAR_LINE : ASSERT_LINE;
+ m_xb = m_x > m_prev_x ? CLEAR_LINE : ASSERT_LINE;
+ m_ya = m_y < m_prev_y ? CLEAR_LINE : ASSERT_LINE;
+ m_yb = m_y > m_prev_y ? CLEAR_LINE : ASSERT_LINE;
+ break;
+ case 3:
+ m_xa = m_xb = ASSERT_LINE;
+ m_ya = m_yb = ASSERT_LINE;
+ m_prev_x = m_x;
+ m_prev_y = m_y;
+ m_x = m_mouse_x->read();
+ m_y = m_mouse_y->read();
+ break;
+ }
+
+ m_phase = (m_phase + 1) & 3;
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// luxor_r8_device - constructor
+//-------------------------------------------------
+
+luxor_r8_device::luxor_r8_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, LUXOR_R8, tag, owner, clock),
+ m_mouse_timer(nullptr),
+ m_mouse_b(*this, "MOUSEB"),
+ m_mouse_x(*this, "MOUSEX"),
+ m_mouse_y(*this, "MOUSEY")
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void luxor_r8_device::device_start()
+{
+ // allocate timers
+ m_mouse_timer = timer_alloc(FUNC(luxor_r8_device::scan_mouse), this);
+ m_mouse_timer->adjust(attotime::from_hz(1000), 0, attotime::from_hz(1000));
+
+ // state saving
+ save_item(NAME(m_phase));
+ save_item(NAME(m_x));
+ save_item(NAME(m_y));
+ save_item(NAME(m_prev_x));
+ save_item(NAME(m_prev_y));
+ save_item(NAME(m_xa));
+ save_item(NAME(m_xb));
+ save_item(NAME(m_ya));
+ save_item(NAME(m_yb));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void luxor_r8_device::device_reset()
+{
+ m_phase = 0;
+ m_xa = m_xb = ASSERT_LINE;
+ m_ya = m_yb = ASSERT_LINE;
+ m_x = m_y = 0;
+ m_prev_x = m_prev_y = 0;
+}
+
+
+//-------------------------------------------------
+// read -
+//-------------------------------------------------
+
+u8 luxor_r8_device::read()
+{
+ u8 data = 0;
+
+ // mouse movement
+ data |= m_xa;
+ data |= m_xb << 1;
+ data |= m_ya << 2;
+ data |= m_yb << 3;
+
+ // mouse buttons
+ data |= (m_mouse_b->read() & 0x07) << 4;
+
+ return data;
+}
diff --git a/src/devices/bus/abckb/r8.h b/src/devices/bus/abckb/r8.h
new file mode 100644
index 00000000000..26c03fa64b2
--- /dev/null
+++ b/src/devices/bus/abckb/r8.h
@@ -0,0 +1,62 @@
+// license:BSD-3-Clause
+// copyright-holders:Curt Coder
+/**********************************************************************
+
+ Luxor R8 mouse emulation
+
+*********************************************************************/
+
+#ifndef MAME_BUS_ABCKB_R8_H
+#define MAME_BUS_ABCKB_R8_H
+
+#pragma once
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> luxor_r8_device
+
+class luxor_r8_device : public device_t
+{
+public:
+ // construction/destruction
+ luxor_r8_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ u8 read();
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ // optional information overrides
+ virtual ioport_constructor device_input_ports() const override;
+
+private:
+ TIMER_CALLBACK_MEMBER(scan_mouse);
+
+ emu_timer *m_mouse_timer;
+ required_ioport m_mouse_b;
+ required_ioport m_mouse_x;
+ required_ioport m_mouse_y;
+
+ int m_phase;
+ int m_x;
+ int m_y;
+ int m_prev_x;
+ int m_prev_y;
+ int m_xa;
+ int m_xb;
+ int m_ya;
+ int m_yb;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(LUXOR_R8, luxor_r8_device)
+
+
+#endif // MAME_BUS_ABCKB_R8_H
diff --git a/src/devices/bus/acorn/atom/discpack.cpp b/src/devices/bus/acorn/atom/discpack.cpp
index 2f2024b86b0..ec0505d2da8 100644
--- a/src/devices/bus/acorn/atom/discpack.cpp
+++ b/src/devices/bus/acorn/atom/discpack.cpp
@@ -6,10 +6,11 @@
**********************************************************************/
-
#include "emu.h"
#include "discpack.h"
+#include "formats/acorn_dsk.h"
+
//**************************************************************************
// DEVICE DEFINITIONS
@@ -99,20 +100,20 @@ void atom_discpack_device::device_start()
// IMPLEMENTATION
//**************************************************************************
-WRITE_LINE_MEMBER(atom_discpack_device::motor_w)
+void atom_discpack_device::motor_w(int state)
{
if (m_floppy[0]->get_device()) m_floppy[0]->get_device()->mon_w(!state);
if (m_floppy[1]->get_device()) m_floppy[1]->get_device()->mon_w(!state);
m_fdc->ready_w(!state);
}
-WRITE_LINE_MEMBER(atom_discpack_device::side_w)
+void atom_discpack_device::side_w(int state)
{
if (m_floppy[0]->get_device()) m_floppy[0]->get_device()->ss_w(state);
if (m_floppy[1]->get_device()) m_floppy[1]->get_device()->ss_w(state);
}
-WRITE_LINE_MEMBER(atom_discpack_device::fdc_intrq_w)
+void atom_discpack_device::fdc_intrq_w(int state)
{
m_bus->nmi_w(state);
}
diff --git a/src/devices/bus/acorn/atom/discpack.h b/src/devices/bus/acorn/atom/discpack.h
index cff8a09005d..ffe2fc5bb89 100644
--- a/src/devices/bus/acorn/atom/discpack.h
+++ b/src/devices/bus/acorn/atom/discpack.h
@@ -15,7 +15,6 @@
#include "bus/acorn/bus.h"
#include "imagedev/floppy.h"
#include "machine/i8271.h"
-#include "formats/acorn_dsk.h"
//**************************************************************************
// TYPE DEFINITIONS
@@ -40,9 +39,9 @@ protected:
virtual const tiny_rom_entry *device_rom_region() const override;
private:
- DECLARE_WRITE_LINE_MEMBER(fdc_intrq_w);
- DECLARE_WRITE_LINE_MEMBER(motor_w);
- DECLARE_WRITE_LINE_MEMBER(side_w);
+ void fdc_intrq_w(int state);
+ void motor_w(int state);
+ void side_w(int state);
required_memory_region m_dos_rom;
required_device<i8271_device> m_fdc;
diff --git a/src/devices/bus/acorn/atom/econet.cpp b/src/devices/bus/acorn/atom/econet.cpp
index 70c92ff3489..206f3435e7e 100644
--- a/src/devices/bus/acorn/atom/econet.cpp
+++ b/src/devices/bus/acorn/atom/econet.cpp
@@ -76,7 +76,7 @@ uint8_t atom_econet_device::statid_r()
return 0xfe;
}
-WRITE_LINE_MEMBER(atom_econet_device::bus_irq_w)
+void atom_econet_device::bus_irq_w(int state)
{
m_bus->irq_w(state);
}
diff --git a/src/devices/bus/acorn/atom/econet.h b/src/devices/bus/acorn/atom/econet.h
index 114dc76bbeb..204cbc5b1be 100644
--- a/src/devices/bus/acorn/atom/econet.h
+++ b/src/devices/bus/acorn/atom/econet.h
@@ -37,7 +37,7 @@ protected:
private:
uint8_t statid_r();
- DECLARE_WRITE_LINE_MEMBER(bus_irq_w);
+ void bus_irq_w(int state);
required_device<mc6854_device> m_adlc;
required_device<econet_device> m_econet;
diff --git a/src/devices/bus/acorn/bus.cpp b/src/devices/bus/acorn/bus.cpp
index 55f332e6581..8f3a5fcde07 100644
--- a/src/devices/bus/acorn/bus.cpp
+++ b/src/devices/bus/acorn/bus.cpp
@@ -83,9 +83,6 @@ void acorn_bus_device::add_slot(acorn_bus_slot_device &slot)
void acorn_bus_device::device_start()
{
- // resolve callbacks
- m_out_irq_cb.resolve_safe();
- m_out_nmi_cb.resolve_safe();
}
//-------------------------------------------------
@@ -97,8 +94,8 @@ void acorn_bus_device::device_reset()
}
// interrupt request from acorn_bus card
-WRITE_LINE_MEMBER(acorn_bus_device::irq_w) { m_out_irq_cb(state); }
-WRITE_LINE_MEMBER(acorn_bus_device::nmi_w) { m_out_nmi_cb(state); }
+void acorn_bus_device::irq_w(int state) { m_out_irq_cb(state); }
+void acorn_bus_device::nmi_w(int state) { m_out_nmi_cb(state); }
diff --git a/src/devices/bus/acorn/bus.h b/src/devices/bus/acorn/bus.h
index bfd9a980304..e32b3cae0c6 100644
--- a/src/devices/bus/acorn/bus.h
+++ b/src/devices/bus/acorn/bus.h
@@ -69,8 +69,8 @@ public:
address_space &memspace() const { return *m_space; }
- DECLARE_WRITE_LINE_MEMBER(irq_w);
- DECLARE_WRITE_LINE_MEMBER(nmi_w);
+ void irq_w(int state);
+ void nmi_w(int state);
void add_slot(acorn_bus_slot_device &slot);
diff --git a/src/devices/bus/acorn/cms/4080term.cpp b/src/devices/bus/acorn/cms/4080term.cpp
index 97946af1406..8d9d2eae40f 100644
--- a/src/devices/bus/acorn/cms/4080term.cpp
+++ b/src/devices/bus/acorn/cms/4080term.cpp
@@ -169,7 +169,7 @@ TIMER_DEVICE_CALLBACK_MEMBER(cms_4080term_device::update_scanline)
m_ef9345->update_scanline((uint16_t)param);
}
-WRITE_LINE_MEMBER(cms_4080term_device::bus_irq_w)
+void cms_4080term_device::bus_irq_w(int state)
{
m_bus->irq_w(state);
}
diff --git a/src/devices/bus/acorn/cms/4080term.h b/src/devices/bus/acorn/cms/4080term.h
index 14d1beacd43..10dbda116bb 100644
--- a/src/devices/bus/acorn/cms/4080term.h
+++ b/src/devices/bus/acorn/cms/4080term.h
@@ -43,7 +43,7 @@ protected:
virtual const tiny_rom_entry *device_rom_region() const override;
private:
- DECLARE_WRITE_LINE_MEMBER(bus_irq_w);
+ void bus_irq_w(int state);
required_device<via6522_device> m_via;
required_device<mos6551_device> m_acia;
diff --git a/src/devices/bus/acorn/cms/fdc.cpp b/src/devices/bus/acorn/cms/fdc.cpp
index f918309bb76..b476bf11912 100644
--- a/src/devices/bus/acorn/cms/fdc.cpp
+++ b/src/devices/bus/acorn/cms/fdc.cpp
@@ -8,10 +8,11 @@
**********************************************************************/
-
#include "emu.h"
#include "fdc.h"
+#include "formats/acorn_dsk.h"
+
//**************************************************************************
// DEVICE DEFINITIONS
diff --git a/src/devices/bus/acorn/cms/fdc.h b/src/devices/bus/acorn/cms/fdc.h
index 99a92c34dc7..d1cfcf72891 100644
--- a/src/devices/bus/acorn/cms/fdc.h
+++ b/src/devices/bus/acorn/cms/fdc.h
@@ -6,7 +6,6 @@
**********************************************************************/
-
#ifndef MAME_BUS_ACORN_CMS_FDC_H
#define MAME_BUS_ACORN_CMS_FDC_H
@@ -15,7 +14,6 @@
#include "bus/acorn/bus.h"
#include "imagedev/floppy.h"
#include "machine/wd_fdc.h"
-#include "formats/acorn_dsk.h"
//**************************************************************************
// TYPE DEFINITIONS
diff --git a/src/devices/bus/acorn/cms/ieee.cpp b/src/devices/bus/acorn/cms/ieee.cpp
index 06d9b47f0dd..001424aeb41 100644
--- a/src/devices/bus/acorn/cms/ieee.cpp
+++ b/src/devices/bus/acorn/cms/ieee.cpp
@@ -83,7 +83,7 @@ void cms_ieee_device::device_start()
// IMPLEMENTATION
//**************************************************************************
-WRITE_LINE_MEMBER(cms_ieee_device::bus_irq_w)
+void cms_ieee_device::bus_irq_w(int state)
{
m_bus->irq_w(state);
}
diff --git a/src/devices/bus/acorn/cms/ieee.h b/src/devices/bus/acorn/cms/ieee.h
index 48352d4a100..635acba8141 100644
--- a/src/devices/bus/acorn/cms/ieee.h
+++ b/src/devices/bus/acorn/cms/ieee.h
@@ -34,7 +34,7 @@ protected:
virtual void device_add_mconfig(machine_config &config) override;
private:
- DECLARE_WRITE_LINE_MEMBER(bus_irq_w);
+ void bus_irq_w(int state);
required_device<ieee488_device> m_ieee;
required_device<tms9914_device> m_tms9914;
diff --git a/src/devices/bus/acorn/system/8k.cpp b/src/devices/bus/acorn/system/8k.cpp
index b2e1c7bb3d2..b83544d3c8f 100644
--- a/src/devices/bus/acorn/system/8k.cpp
+++ b/src/devices/bus/acorn/system/8k.cpp
@@ -137,16 +137,13 @@ void acorn_8k_device::device_reset()
// IMPLEMENTATION
//**************************************************************************
-image_init_result acorn_8k_device::load_rom(device_image_interface &image, generic_slot_device *slot)
+std::pair<std::error_condition, std::string> acorn_8k_device::load_rom(device_image_interface &image, generic_slot_device *slot)
{
- uint32_t size = slot->common_get_size("rom");
+ uint32_t const size = slot->common_get_size("rom");
// socket accepts 2K and 4K ROM only
if (size != 0x0800 && size != 0x1000)
- {
- image.seterror(image_error::INVALIDIMAGE, "Invalid size: Only 2K/4K is supported");
- return image_init_result::FAIL;
- }
+ return std::make_pair(image_error::INVALIDLENGTH, "Invalid size: Only 2K/4K is supported");
slot->rom_alloc(0x1000, GENERIC_ROM8_WIDTH, ENDIANNESS_LITTLE);
slot->common_load_rom(slot->get_rom_base(), size, "rom");
@@ -155,5 +152,5 @@ image_init_result acorn_8k_device::load_rom(device_image_interface &image, gener
uint8_t *rom = slot->get_rom_base();
if (size <= 0x0800) memcpy(rom + 0x0800, rom, 0x0800);
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
diff --git a/src/devices/bus/acorn/system/8k.h b/src/devices/bus/acorn/system/8k.h
index 09f089c1563..496a078ab1e 100644
--- a/src/devices/bus/acorn/system/8k.h
+++ b/src/devices/bus/acorn/system/8k.h
@@ -32,7 +32,7 @@ public:
acorn_8k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
virtual void device_reset() override;
@@ -41,7 +41,7 @@ protected:
virtual ioport_constructor device_input_ports() const override;
private:
- image_init_result load_rom(device_image_interface &image, generic_slot_device *slot);
+ std::pair<std::error_condition, std::string> load_rom(device_image_interface &image, generic_slot_device *slot);
DECLARE_DEVICE_IMAGE_LOAD_MEMBER(rom0_load) { return load_rom(image, m_rom[0]); }
DECLARE_DEVICE_IMAGE_LOAD_MEMBER(rom1_load) { return load_rom(image, m_rom[1]); }
diff --git a/src/devices/bus/acorn/system/cass.cpp b/src/devices/bus/acorn/system/cass.cpp
index 6e5b8faf40c..8905d9d6a22 100644
--- a/src/devices/bus/acorn/system/cass.cpp
+++ b/src/devices/bus/acorn/system/cass.cpp
@@ -65,7 +65,7 @@ void acorn_cass_device::device_start()
// IMPLEMENTATION
//**************************************************************************
-WRITE_LINE_MEMBER(acorn_cass_device::cass_w)
+void acorn_cass_device::cass_w(int state)
{
m_cass_state = state;
}
diff --git a/src/devices/bus/acorn/system/cass.h b/src/devices/bus/acorn/system/cass.h
index 02a323bb994..11e1d96256f 100644
--- a/src/devices/bus/acorn/system/cass.h
+++ b/src/devices/bus/acorn/system/cass.h
@@ -38,7 +38,7 @@ protected:
virtual void device_add_mconfig(machine_config &config) override;
private:
- DECLARE_WRITE_LINE_MEMBER(cass_w);
+ void cass_w(int state);
TIMER_DEVICE_CALLBACK_MEMBER(cass_c);
TIMER_DEVICE_CALLBACK_MEMBER(cass_p);
diff --git a/src/devices/bus/acorn/system/econet.cpp b/src/devices/bus/acorn/system/econet.cpp
index f8a0737e456..55ffc5232cf 100644
--- a/src/devices/bus/acorn/system/econet.cpp
+++ b/src/devices/bus/acorn/system/econet.cpp
@@ -83,7 +83,7 @@ uint8_t acorn_econet_device::statid_r()
return 0xfe;
}
-WRITE_LINE_MEMBER(acorn_econet_device::bus_irq_w)
+void acorn_econet_device::bus_irq_w(int state)
{
m_bus->irq_w(state);
}
diff --git a/src/devices/bus/acorn/system/econet.h b/src/devices/bus/acorn/system/econet.h
index b5e470975c9..9b2981ab947 100644
--- a/src/devices/bus/acorn/system/econet.h
+++ b/src/devices/bus/acorn/system/econet.h
@@ -40,7 +40,7 @@ protected:
private:
uint8_t statid_r();
- DECLARE_WRITE_LINE_MEMBER(bus_irq_w);
+ void bus_irq_w(int state);
required_device<mc6854_device> m_adlc;
required_device<econet_device> m_econet;
diff --git a/src/devices/bus/acorn/system/fdc.cpp b/src/devices/bus/acorn/system/fdc.cpp
index 397fbb9ac50..489b645054e 100644
--- a/src/devices/bus/acorn/system/fdc.cpp
+++ b/src/devices/bus/acorn/system/fdc.cpp
@@ -10,10 +10,11 @@
**********************************************************************/
-
#include "emu.h"
#include "fdc.h"
+#include "formats/acorn_dsk.h"
+
//**************************************************************************
// DEVICE DEFINITIONS
@@ -95,20 +96,20 @@ void acorn_fdc_device::device_reset()
// IMPLEMENTATION
//**************************************************************************
-WRITE_LINE_MEMBER(acorn_fdc_device::motor_w)
+void acorn_fdc_device::motor_w(int state)
{
if (m_floppy[0]->get_device()) m_floppy[0]->get_device()->mon_w(!state);
if (m_floppy[1]->get_device()) m_floppy[1]->get_device()->mon_w(!state);
m_fdc->ready_w(!state);
}
-WRITE_LINE_MEMBER(acorn_fdc_device::side_w)
+void acorn_fdc_device::side_w(int state)
{
if (m_floppy[0]->get_device()) m_floppy[0]->get_device()->ss_w(state);
if (m_floppy[1]->get_device()) m_floppy[1]->get_device()->ss_w(state);
}
-WRITE_LINE_MEMBER(acorn_fdc_device::bus_nmi_w)
+void acorn_fdc_device::bus_nmi_w(int state)
{
m_bus->nmi_w(state);
}
diff --git a/src/devices/bus/acorn/system/fdc.h b/src/devices/bus/acorn/system/fdc.h
index f943b1f6767..c4008eaff27 100644
--- a/src/devices/bus/acorn/system/fdc.h
+++ b/src/devices/bus/acorn/system/fdc.h
@@ -8,7 +8,6 @@
**********************************************************************/
-
#ifndef MAME_BUS_ACORN_SYSTEM_FDC_H
#define MAME_BUS_ACORN_SYSTEM_FDC_H
@@ -17,7 +16,6 @@
#include "bus/acorn/bus.h"
#include "imagedev/floppy.h"
#include "machine/i8271.h"
-#include "formats/acorn_dsk.h"
//**************************************************************************
// TYPE DEFINITIONS
@@ -42,9 +40,9 @@ protected:
virtual void device_add_mconfig(machine_config &config) override;
private:
- DECLARE_WRITE_LINE_MEMBER(bus_nmi_w);
- DECLARE_WRITE_LINE_MEMBER(motor_w);
- DECLARE_WRITE_LINE_MEMBER(side_w);
+ void bus_nmi_w(int state);
+ void motor_w(int state);
+ void side_w(int state);
required_device<i8271_device> m_fdc;
required_device_array<floppy_connector, 2> m_floppy;
diff --git a/src/devices/bus/acorn/system/vdu40.cpp b/src/devices/bus/acorn/system/vdu40.cpp
index 7bc8629ac35..1916981dc73 100644
--- a/src/devices/bus/acorn/system/vdu40.cpp
+++ b/src/devices/bus/acorn/system/vdu40.cpp
@@ -121,7 +121,7 @@ MC6845_UPDATE_ROW(acorn_vdu40_device::crtc_update_row)
}
}
-WRITE_LINE_MEMBER(acorn_vdu40_device::vsync_changed)
+void acorn_vdu40_device::vsync_changed(int state)
{
m_trom->dew_w(state);
}
diff --git a/src/devices/bus/acorn/system/vdu40.h b/src/devices/bus/acorn/system/vdu40.h
index ff80a76d1ea..28c87cfb054 100644
--- a/src/devices/bus/acorn/system/vdu40.h
+++ b/src/devices/bus/acorn/system/vdu40.h
@@ -42,7 +42,7 @@ protected:
private:
MC6845_UPDATE_ROW(crtc_update_row);
- DECLARE_WRITE_LINE_MEMBER(vsync_changed);
+ void vsync_changed(int state);
required_device<screen_device> m_screen;
required_device<mc6845_device> m_crtc;
diff --git a/src/devices/bus/acorn/system/vib.cpp b/src/devices/bus/acorn/system/vib.cpp
index bf685daac95..cb44e02ce79 100644
--- a/src/devices/bus/acorn/system/vib.cpp
+++ b/src/devices/bus/acorn/system/vib.cpp
@@ -127,7 +127,7 @@ void acorn_vib_device::device_reset()
//**************************************************************************
template<mc14411_device::timer_id T>
-WRITE_LINE_MEMBER(acorn_vib_device::write_acia_clock)
+void acorn_vib_device::write_acia_clock(int state)
{
if (T == m_txc->read())
m_acia->write_txc(state);
@@ -135,7 +135,7 @@ WRITE_LINE_MEMBER(acorn_vib_device::write_acia_clock)
m_acia->write_rxc(state);
}
-WRITE_LINE_MEMBER(acorn_vib_device::irq_w)
+void acorn_vib_device::irq_w(int state)
{
m_bus->irq_w(state);
}
diff --git a/src/devices/bus/acorn/system/vib.h b/src/devices/bus/acorn/system/vib.h
index bd4d886e281..2a681808ccc 100644
--- a/src/devices/bus/acorn/system/vib.h
+++ b/src/devices/bus/acorn/system/vib.h
@@ -45,8 +45,8 @@ protected:
virtual void device_add_mconfig(machine_config &config) override;
private:
- template<mc14411_device::timer_id T> DECLARE_WRITE_LINE_MEMBER(write_acia_clock);
- DECLARE_WRITE_LINE_MEMBER(irq_w);
+ template<mc14411_device::timer_id T> void write_acia_clock(int state);
+ void irq_w(int state);
required_device<i8255_device> m_ppi8255;
required_device<via6522_device> m_via6522;
diff --git a/src/devices/bus/adam/exp.cpp b/src/devices/bus/adam/exp.cpp
index 5a2098b2cfe..33b950a1776 100644
--- a/src/devices/bus/adam/exp.cpp
+++ b/src/devices/bus/adam/exp.cpp
@@ -9,6 +9,8 @@
#include "emu.h"
#include "exp.h"
+#include <tuple>
+
//**************************************************************************
@@ -67,9 +69,6 @@ adam_expansion_slot_device::adam_expansion_slot_device(const machine_config &mco
void adam_expansion_slot_device::device_start()
{
m_card = get_card_device();
-
- // resolve callbacks
- m_write_irq.resolve_safe();
}
@@ -77,17 +76,20 @@ void adam_expansion_slot_device::device_start()
// call_load -
//-------------------------------------------------
-image_init_result adam_expansion_slot_device::call_load()
+std::pair<std::error_condition, std::string> adam_expansion_slot_device::call_load()
{
+ std::error_condition err;
+
if (m_card)
{
- size_t size;
-
if (!loaded_through_softlist())
{
- size = length();
+ size_t const size = length();
- fread(m_card->m_rom, size);
+ std::size_t actual;
+ std::tie(err, m_card->m_rom, actual) = read(image_core_file(), size);
+ if (!err && (actual != size))
+ err = std::errc::io_error;
}
else
{
@@ -95,7 +97,7 @@ image_init_result adam_expansion_slot_device::call_load()
}
}
- return image_init_result::PASS;
+ return std::make_pair(err, std::string());
}
diff --git a/src/devices/bus/adam/exp.h b/src/devices/bus/adam/exp.h
index 01d73774bdb..f8e45daee56 100644
--- a/src/devices/bus/adam/exp.h
+++ b/src/devices/bus/adam/exp.h
@@ -47,20 +47,20 @@ public:
void bd_w(offs_t offset, uint8_t data, int bmreq, int biorq, int aux_rom_cs, int cas1, int cas2);
// cartridge interface
- DECLARE_WRITE_LINE_MEMBER( irq_w ) { m_write_irq(state); }
+ void irq_w(int state) { m_write_irq(state); }
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
- // image-level overrides
- virtual image_init_result call_load() override;
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
virtual bool is_reset_on_load() const noexcept override { return true; }
virtual const char *image_interface() const noexcept override { return "adam_rom"; }
virtual const char *file_extensions() const noexcept override { return "bin,rom"; }
- // slot interface overrides
+ // device_slot_interface implementation
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
devcb_write_line m_write_irq;
diff --git a/src/devices/bus/adamnet/adamnet.cpp b/src/devices/bus/adamnet/adamnet.cpp
index 18b91c4fb8c..c2886c61248 100644
--- a/src/devices/bus/adamnet/adamnet.cpp
+++ b/src/devices/bus/adamnet/adamnet.cpp
@@ -139,7 +139,7 @@ adamnet_device::daisy_entry::daisy_entry(device_t *device)
// rxd_r - receive data
//-------------------------------------------------
-READ_LINE_MEMBER( adamnet_device::rxd_r )
+int adamnet_device::rxd_r()
{
int state = m_txd;//1;
@@ -184,7 +184,7 @@ int adamnet_device::rxd_r(device_t *device)
// txd_w - transmit data
//-------------------------------------------------
-WRITE_LINE_MEMBER( adamnet_device::txd_w )
+void adamnet_device::txd_w(int state)
{
if (m_txd != state)
{
@@ -221,7 +221,7 @@ void adamnet_device::txd_w(device_t *device, int state)
// reset_r - bus reset
//-------------------------------------------------
-READ_LINE_MEMBER( adamnet_device::reset_r )
+int adamnet_device::reset_r()
{
return m_reset;
}
@@ -231,7 +231,7 @@ READ_LINE_MEMBER( adamnet_device::reset_r )
// reset_w - bus reset
//-------------------------------------------------
-WRITE_LINE_MEMBER( adamnet_device::reset_w )
+void adamnet_device::reset_w(int state)
{
m_reset = state;
diff --git a/src/devices/bus/adamnet/adamnet.h b/src/devices/bus/adamnet/adamnet.h
index a064ce24f2f..6db165e854b 100644
--- a/src/devices/bus/adamnet/adamnet.h
+++ b/src/devices/bus/adamnet/adamnet.h
@@ -30,13 +30,13 @@ public:
void add_device(device_t *target);
- DECLARE_READ_LINE_MEMBER( rxd_r );
+ int rxd_r();
int rxd_r(device_t *device);
- DECLARE_WRITE_LINE_MEMBER( txd_w );
+ void txd_w(int state);
void txd_w(device_t *device, int state);
- DECLARE_READ_LINE_MEMBER( reset_r );
- DECLARE_WRITE_LINE_MEMBER( reset_w );
+ int reset_r();
+ void reset_w(int state);
protected:
// device-level overrides
diff --git a/src/devices/bus/adamnet/ddp.cpp b/src/devices/bus/adamnet/ddp.cpp
index b4a17e909cd..f4d08232d4e 100644
--- a/src/devices/bus/adamnet/ddp.cpp
+++ b/src/devices/bus/adamnet/ddp.cpp
@@ -9,6 +9,8 @@
#include "emu.h"
#include "ddp.h"
+#include "formats/adam_cas.h"
+
//**************************************************************************
@@ -52,10 +54,7 @@ const tiny_rom_entry *adam_digital_data_pack_device::device_rom_region() const
void adam_digital_data_pack_device::adam_ddp_mem(address_map &map)
{
- map(0x0000, 0x001f).m(M6801_TAG, FUNC(m6801_cpu_device::m6801_io));
- map(0x0080, 0x00ff).ram();
map(0x0400, 0x07ff).ram();
- map(0xf800, 0xffff).rom().region(M6801_TAG, 0);
}
static const cassette_image::Options adam_cassette_options =
@@ -80,17 +79,14 @@ void adam_digital_data_pack_device::device_add_mconfig(machine_config &config)
// Port 3 = Multiplexed Address/Data
m_maincpu->in_p4_cb().set(FUNC(adam_digital_data_pack_device::p4_r));
- CASSETTE(config, m_ddp0);
- m_ddp0->set_formats(coleco_adam_cassette_formats);
- m_ddp0->set_create_opts(&adam_cassette_options);
- m_ddp0->set_default_state(CASSETTE_PLAY | CASSETTE_MOTOR_DISABLED | CASSETTE_SPEAKER_MUTED);
- m_ddp0->set_interface("adam_cass");
-
- CASSETTE(config, m_ddp1);
- m_ddp1->set_formats(coleco_adam_cassette_formats);
- m_ddp1->set_create_opts(&adam_cassette_options);
- m_ddp1->set_default_state(CASSETTE_PLAY | CASSETTE_MOTOR_DISABLED | CASSETTE_SPEAKER_MUTED);
- m_ddp1->set_interface("adam_cass");
+ for (auto &ddp : m_ddp)
+ {
+ CASSETTE(config, ddp);
+ ddp->set_formats(coleco_adam_cassette_formats);
+ ddp->set_create_opts(&adam_cassette_options);
+ ddp->set_default_state(CASSETTE_PLAY | CASSETTE_MOTOR_DISABLED | CASSETTE_SPEAKER_MUTED);
+ ddp->set_interface("adam_cass");
+ }
}
@@ -107,8 +103,8 @@ adam_digital_data_pack_device::adam_digital_data_pack_device(const machine_confi
: device_t(mconfig, ADAM_DDP, tag, owner, clock),
device_adamnet_card_interface(mconfig, *this),
m_maincpu(*this, M6801_TAG),
- m_ddp0(*this, "cassette"),
- m_ddp1(*this, "cassette2"), m_wr0(0), m_wr1(0), m_track(0)
+ m_ddp(*this, {"cassette", "cassette2"}),
+ m_wr(0), m_track(0)
{
}
@@ -120,8 +116,7 @@ adam_digital_data_pack_device::adam_digital_data_pack_device(const machine_confi
void adam_digital_data_pack_device::device_start()
{
// state saving
- save_item(NAME(m_wr0));
- save_item(NAME(m_wr1));
+ save_item(NAME(m_wr));
save_item(NAME(m_track));
}
@@ -157,27 +152,21 @@ void adam_digital_data_pack_device::p1_w(uint8_t data)
*/
- if (m_ddp0->exists())
+ for (int n = 0; n < 2; n++)
{
- m_ddp0->set_speed(BIT(data, 0) ? (double) 80/1.875 : 20/1.875); // speed select
- if(!(data & 0x08)) m_ddp0->go_forward();
- if(!(data & 0x10)) m_ddp0->go_reverse();
- m_ddp0->change_state(BIT(data, 1) ? CASSETTE_MOTOR_DISABLED : CASSETTE_MOTOR_ENABLED, CASSETTE_MASK_MOTOR); // motor control
+ if (m_ddp[n]->exists())
+ {
+ m_ddp[n]->set_speed(BIT(data, 0) ? (double) 80/1.875 : 20/1.875); // speed select
+ if (!BIT(data, 3))
+ m_ddp[n]->go_forward();
+ if (!BIT(data, 4))
+ m_ddp[n]->go_reverse();
+ m_ddp[n]->change_state(BIT(data, n + 1) ? CASSETTE_MOTOR_DISABLED : CASSETTE_MOTOR_ENABLED, CASSETTE_MASK_MOTOR); // motor control
+ }
}
- if (m_ddp1->exists())
- {
- m_ddp1->set_speed(BIT(data, 0) ? (double) 80/1.875 : 20/1.875); // speed select
- if(!(data & 0x08)) m_ddp1->go_forward();
- if(!(data & 0x10)) m_ddp1->go_reverse();
- m_ddp1->change_state(BIT(data, 2) ? CASSETTE_MOTOR_DISABLED : CASSETTE_MOTOR_ENABLED, CASSETTE_MASK_MOTOR); // motor control
- }
-
- // data write 0
- m_wr0 = BIT(data, 6);
-
- // data write 1
- m_wr1 = BIT(data, 7);
+ // data write 0/1
+ m_wr = BIT(data, 6, 2);
}
@@ -204,7 +193,7 @@ uint8_t adam_digital_data_pack_device::p2_r()
if (m_bus->reset_r())
data |= M6801_MODE_6;
else
- data |= m_ddp1->exists() << 1; // Cassette in place 1
+ data |= m_ddp[1]->exists() << 1; // Cassette in place 1
// NET RXD
data |= m_bus->rxd_r(this) << 3;
@@ -231,16 +220,14 @@ void adam_digital_data_pack_device::p2_w(uint8_t data)
*/
- if (m_ddp0->exists())
+ for (int n = 0; n < 2; n++)
{
- m_ddp0->set_channel(!BIT(data, 2)); // Track select
- if (!m_wr0) m_ddp0->output(BIT(data, 0) ? 1.0 : -1.0); // write data
- }
-
- if (m_ddp1->exists())
- {
- m_ddp1->set_channel(!BIT(data, 2));
- if (!m_wr1) m_ddp1->output(BIT(data, 0) ? 1.0 : -1.0);
+ if (m_ddp[n]->exists())
+ {
+ m_ddp[n]->set_channel(!BIT(data, 2)); // Track select
+ if (!BIT(m_wr, n))
+ m_ddp[n]->output(BIT(data, 0) ? 1.0 : -1.0); // write data
+ }
}
// NET TXD
@@ -271,19 +258,15 @@ uint8_t adam_digital_data_pack_device::p4_r()
uint8_t data = 0;
- // drive 0
- if (m_ddp0->exists())
- {
- data |= ((m_ddp0->get_state() & CASSETTE_MASK_UISTATE) != CASSETTE_STOPPED) << 3; // motion sense
- data |= 1 << 5; // cassette in place
- data |= (m_ddp0->input() < 0) << 7; // read data
- }
-
- // drive 1
- if (m_ddp1->exists())
+ for (int n = 0; n < 2; n++)
{
- data |= ((m_ddp1->get_state() & CASSETTE_MASK_UISTATE) != CASSETTE_STOPPED) << 4; // motion sense
- data |= (m_ddp1->input() < 0) << 7; // read data
+ if (m_ddp[n]->exists())
+ {
+ data |= ((m_ddp[n]->get_state() & CASSETTE_MASK_UISTATE) != CASSETTE_STOPPED) << (n + 3); // motion sense
+ if (n == 0)
+ data |= 1 << 5; // cassette in place (drive 0)
+ data |= (m_ddp[n]->input() < 0) << 7; // read data
+ }
}
// read data 0 (always 1)
diff --git a/src/devices/bus/adamnet/ddp.h b/src/devices/bus/adamnet/ddp.h
index c6fa66f98d3..9f28beebbd7 100644
--- a/src/devices/bus/adamnet/ddp.h
+++ b/src/devices/bus/adamnet/ddp.h
@@ -13,7 +13,6 @@
#include "adamnet.h"
#include "cpu/m6800/m6801.h"
-#include "formats/adam_cas.h"
#include "imagedev/cassette.h"
@@ -44,11 +43,9 @@ protected:
private:
required_device<m6801_cpu_device> m_maincpu;
- required_device<cassette_image_device> m_ddp0;
- required_device<cassette_image_device> m_ddp1;
+ required_device_array<cassette_image_device, 2> m_ddp;
- int m_wr0;
- int m_wr1;
+ uint8_t m_wr;
int m_track;
void p1_w(uint8_t data);
diff --git a/src/devices/bus/adamnet/fdc.cpp b/src/devices/bus/adamnet/fdc.cpp
index 1b7753cfe17..af249acbad9 100644
--- a/src/devices/bus/adamnet/fdc.cpp
+++ b/src/devices/bus/adamnet/fdc.cpp
@@ -19,6 +19,8 @@
#include "emu.h"
#include "fdc.h"
+#include "formats/adam_dsk.h"
+
//**************************************************************************
@@ -79,8 +81,6 @@ const tiny_rom_entry *adam_fdc_device::device_rom_region() const
void adam_fdc_device::adam_fdc_mem(address_map &map)
{
- map(0x0000, 0x001f).m(M6801_TAG, FUNC(m6801_cpu_device::m6801_io));
- map(0x0080, 0x00ff).ram();
map(0x0400, 0x07ff).ram().writeonly().share("ram");
map(0x0800, 0x0800).mirror(0x3ff).r(WD2793_TAG, FUNC(wd2793_device::status_r));
map(0x1400, 0x17ff).ram().readonly().share("ram");
@@ -118,7 +118,7 @@ static void adam_fdc_floppies(device_slot_interface &device)
void adam_fdc_device::device_add_mconfig(machine_config &config)
{
- M6801(config, m_maincpu, 4_MHz_XTAL),
+ M6803(config, m_maincpu, 4_MHz_XTAL),
m_maincpu->set_addrmap(AS_PROGRAM, &adam_fdc_device::adam_fdc_mem);
m_maincpu->in_p1_cb().set(FUNC(adam_fdc_device::p1_r));
m_maincpu->out_p1_cb().set(FUNC(adam_fdc_device::p1_w));
diff --git a/src/devices/bus/adamnet/fdc.h b/src/devices/bus/adamnet/fdc.h
index d4d1cc33a01..3324f84fce5 100644
--- a/src/devices/bus/adamnet/fdc.h
+++ b/src/devices/bus/adamnet/fdc.h
@@ -13,7 +13,6 @@
#include "adamnet.h"
#include "cpu/m6800/m6801.h"
-#include "formats/adam_dsk.h"
#include "imagedev/floppy.h"
#include "machine/wd_fdc.h"
diff --git a/src/devices/bus/adamnet/kb.cpp b/src/devices/bus/adamnet/kb.cpp
index 046ceba61f4..06626f8dc13 100644
--- a/src/devices/bus/adamnet/kb.cpp
+++ b/src/devices/bus/adamnet/kb.cpp
@@ -47,25 +47,12 @@ const tiny_rom_entry *adam_keyboard_device::device_rom_region() const
//-------------------------------------------------
-// ADDRESS_MAP( adam_kb_mem )
-//-------------------------------------------------
-
-void adam_keyboard_device::adam_kb_mem(address_map &map)
-{
- map(0x0000, 0x001f).m(M6801_TAG, FUNC(m6801_cpu_device::m6801_io));
- map(0x0080, 0x00ff).ram();
- map(0xf800, 0xffff).rom().region(M6801_TAG, 0);
-}
-
-
-//-------------------------------------------------
// device_add_mconfig - add device configuration
//-------------------------------------------------
void adam_keyboard_device::device_add_mconfig(machine_config &config)
{
M6801(config, m_maincpu, XTAL(4'000'000));
- m_maincpu->set_addrmap(AS_PROGRAM, &adam_keyboard_device::adam_kb_mem);
m_maincpu->in_p1_cb().set(FUNC(adam_keyboard_device::p1_r));
m_maincpu->in_p2_cb().set(FUNC(adam_keyboard_device::p2_r));
m_maincpu->out_p2_cb().set(FUNC(adam_keyboard_device::p2_w));
@@ -162,10 +149,10 @@ static INPUT_PORTS_START( adam_kb )
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("CLEAR") PORT_CODE(KEYCODE_PGUP) PORT_CHAR(UCHAR_MAMEKEY(PGUP))
PORT_START("Y8")
- PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(UTF8_UP) PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP))
- PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(UTF8_RIGHT) PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT))
- PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(UTF8_DOWN) PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN))
- PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(UTF8_LEFT) PORT_CODE(KEYCODE_LEFT) PORT_CHAR(UCHAR_MAMEKEY(LEFT))
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"\u2191") PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP)) // U+2191 = ↑
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"\u2192") PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT)) // U+2192 = →
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"\u2193") PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN)) // U+2193 = ↓
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"\u2190") PORT_CODE(KEYCODE_LEFT) PORT_CHAR(UCHAR_MAMEKEY(LEFT)) // U+2190 = ←
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("BACKSPACE") PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8)
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("INSERT") PORT_CODE(KEYCODE_DEL) PORT_CHAR(UCHAR_MAMEKEY(DEL))
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("PRINT") PORT_CODE(KEYCODE_END) PORT_CHAR(UCHAR_MAMEKEY(END))
diff --git a/src/devices/bus/adamnet/kb.h b/src/devices/bus/adamnet/kb.h
index 167ff1fc46d..bd506cf4647 100644
--- a/src/devices/bus/adamnet/kb.h
+++ b/src/devices/bus/adamnet/kb.h
@@ -54,8 +54,6 @@ private:
void p3_w(uint8_t data);
uint8_t p4_r();
void p4_w(uint8_t data);
-
- void adam_kb_mem(address_map &map);
};
diff --git a/src/devices/bus/adamnet/printer.cpp b/src/devices/bus/adamnet/printer.cpp
index 841fa76b138..0e8c5fcd8b4 100644
--- a/src/devices/bus/adamnet/printer.cpp
+++ b/src/devices/bus/adamnet/printer.cpp
@@ -47,32 +47,18 @@ const tiny_rom_entry *adam_printer_device::device_rom_region() const
//-------------------------------------------------
-// ADDRESS_MAP( adam_prn_mem )
-//-------------------------------------------------
-
-void adam_printer_device::adam_prn_mem(address_map &map)
-{
- map(0x0000, 0x001f).m(M6801_TAG, FUNC(m6801_cpu_device::m6801_io));
- map(0x0080, 0x00ff).ram();
- map(0xf800, 0xffff).rom().region(M6801_TAG, 0);
-}
-
-
-//-------------------------------------------------
// device_add_mconfig - add device configuration
//-------------------------------------------------
void adam_printer_device::device_add_mconfig(machine_config &config)
{
M6801(config, m_maincpu, XTAL(4'000'000));
- m_maincpu->set_addrmap(AS_PROGRAM, &adam_printer_device::adam_prn_mem);
m_maincpu->out_p1_cb().set(FUNC(adam_printer_device::p1_w));
m_maincpu->in_p2_cb().set(FUNC(adam_printer_device::p2_r));
m_maincpu->out_p2_cb().set(FUNC(adam_printer_device::p2_w));
m_maincpu->in_p3_cb().set(FUNC(adam_printer_device::p3_r));
m_maincpu->in_p4_cb().set(FUNC(adam_printer_device::p4_r));
m_maincpu->out_p4_cb().set(FUNC(adam_printer_device::p4_w));
- m_maincpu->set_disable(); // TODO
}
diff --git a/src/devices/bus/adamnet/printer.h b/src/devices/bus/adamnet/printer.h
index 376db4a9a99..80e3c62ad4c 100644
--- a/src/devices/bus/adamnet/printer.h
+++ b/src/devices/bus/adamnet/printer.h
@@ -49,8 +49,6 @@ private:
uint8_t p3_r();
uint8_t p4_r();
void p4_w(uint8_t data);
-
- void adam_prn_mem(address_map &map);
};
diff --git a/src/devices/bus/adamnet/spi.cpp b/src/devices/bus/adamnet/spi.cpp
index 008a99a2bfa..34cbcb7f5ab 100644
--- a/src/devices/bus/adamnet/spi.cpp
+++ b/src/devices/bus/adamnet/spi.cpp
@@ -44,9 +44,8 @@ const tiny_rom_entry *adam_spi_device::device_rom_region() const
void adam_spi_device::adam_spi_mem(address_map &map)
{
- map(0x0000, 0x001f).m(m_maincpu, FUNC(m6801_cpu_device::m6801_io));
- map(0x0080, 0x00ff).ram();
- map(0xf800, 0xffff).rom().region("m6801", 0);
+ map(0x0100, 0x0103).rw("epci", FUNC(scn2661a_device::read), FUNC(scn2661a_device::write));
+ map(0x0104, 0x01ff).ram();
}
@@ -60,11 +59,17 @@ void adam_spi_device::device_add_mconfig(machine_config &config)
m_maincpu->set_addrmap(AS_PROGRAM, &adam_spi_device::adam_spi_mem);
m_maincpu->in_p2_cb().set(FUNC(adam_spi_device::p2_r));
m_maincpu->out_p2_cb().set(FUNC(adam_spi_device::p2_w));
- m_maincpu->set_disable();
- SCN2661A(config, "epci", XTAL(4'915'200));
+ scn2661a_device &epci(SCN2661A(config, "epci", XTAL(4'915'200)));
+ epci.txd_handler().set("rs232", FUNC(rs232_port_device::write_txd));
+ epci.rts_handler().set("rs232", FUNC(rs232_port_device::write_rts));
+ epci.dtr_handler().set("rs232", FUNC(rs232_port_device::write_dtr));
- RS232_PORT(config, "rs232", default_rs232_devices, nullptr);
+ rs232_port_device &rs232(RS232_PORT(config, "rs232", default_rs232_devices, nullptr));
+ rs232.rxd_handler().set("epci", FUNC(scn2661a_device::rxd_w));
+ rs232.cts_handler().set("epci", FUNC(scn2661a_device::cts_w));
+ rs232.dsr_handler().set("epci", FUNC(scn2661a_device::dsr_w));
+ rs232.dcd_handler().set("epci", FUNC(scn2661a_device::dcd_w));
centronics_device &centronics(CENTRONICS(config, "centronics", centronics_devices, "printer"));
centronics.set_data_input_buffer("cent_data_in");
diff --git a/src/devices/bus/adb/a9m0330.cpp b/src/devices/bus/adb/a9m0330.cpp
index 8d3f9226299..e4e96d45a90 100644
--- a/src/devices/bus/adb/a9m0330.cpp
+++ b/src/devices/bus/adb/a9m0330.cpp
@@ -256,13 +256,13 @@ void a9m0330_device::p2_w(u8 data)
}
}
-DECLARE_READ_LINE_MEMBER(a9m0330_device::t0_r)
+int a9m0330_device::t0_r()
{
// appears to be a config jumper of some sort
return 0;
}
-DECLARE_READ_LINE_MEMBER(a9m0330_device::t1_r)
+int a9m0330_device::t1_r()
{
return m_adb_state & 1;
}
diff --git a/src/devices/bus/adb/a9m0330.h b/src/devices/bus/adb/a9m0330.h
index 1d44a28bba8..c74a13feb38 100644
--- a/src/devices/bus/adb/a9m0330.h
+++ b/src/devices/bus/adb/a9m0330.h
@@ -35,8 +35,8 @@ private:
u8 bus_r();
void p1_w(u8 data);
void p2_w(u8 data);
- DECLARE_READ_LINE_MEMBER(t0_r);
- DECLARE_READ_LINE_MEMBER(t1_r);
+ int t0_r();
+ int t1_r();
int m_adb_state;
int m_kbd_row;
diff --git a/src/devices/bus/adb/adb.cpp b/src/devices/bus/adb/adb.cpp
index cdf0810369a..28d836ec3ff 100644
--- a/src/devices/bus/adb/adb.cpp
+++ b/src/devices/bus/adb/adb.cpp
@@ -52,8 +52,6 @@ adb_device::adb_device(const machine_config &mconfig, device_type type, const ch
void adb_device::device_start()
{
- m_adb_cb.resolve_safe();
- m_poweron_cb.resolve_safe();
}
void adb_device::device_reset()
diff --git a/src/devices/bus/amiga/keyboard/a1200.cpp b/src/devices/bus/amiga/keyboard/a1200.cpp
index 4877903d73a..d375bb07917 100644
--- a/src/devices/bus/amiga/keyboard/a1200.cpp
+++ b/src/devices/bus/amiga/keyboard/a1200.cpp
@@ -114,7 +114,7 @@ a1200_kbd_device::a1200_kbd_device(machine_config const &mconfig, char const *ta
{
}
-WRITE_LINE_MEMBER(a1200_kbd_device::kdat_w)
+void a1200_kbd_device::kdat_w(int state)
{
if (bool(state) != m_host_kdat)
{
@@ -167,7 +167,7 @@ void a1200_kbd_device::mpu_portc_w(offs_t offset, u8 data, u8 mem_mask)
m_led_kbd_caps = BIT(~data, 7);
}
-WRITE_LINE_MEMBER(a1200_kbd_device::mpu_tcmp)
+void a1200_kbd_device::mpu_tcmp(int state)
{
m_host->krst_w(state);
}
diff --git a/src/devices/bus/amiga/keyboard/a1200.h b/src/devices/bus/amiga/keyboard/a1200.h
index 4cbba0616db..65b38560e32 100644
--- a/src/devices/bus/amiga/keyboard/a1200.h
+++ b/src/devices/bus/amiga/keyboard/a1200.h
@@ -27,7 +27,7 @@ public:
a1200_kbd_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock);
// from host
- virtual DECLARE_WRITE_LINE_MEMBER(kdat_w) override;
+ virtual void kdat_w(int state) override;
DECLARE_INPUT_CHANGED_MEMBER(layout_changed);
@@ -37,7 +37,7 @@ protected:
void mpu_porta_w(offs_t offset, u8 data, u8 mem_mask = ~0);
void mpu_portb_w(offs_t offset, u8 data, u8 mem_mask = ~0);
void mpu_portc_w(offs_t offset, u8 data, u8 mem_mask = ~0);
- DECLARE_WRITE_LINE_MEMBER(mpu_tcmp);
+ void mpu_tcmp(int state);
virtual tiny_rom_entry const *device_rom_region() const override;
virtual void device_add_mconfig(machine_config &config) override;
diff --git a/src/devices/bus/amiga/keyboard/a2000.cpp b/src/devices/bus/amiga/keyboard/a2000.cpp
index 59aac50b652..75c078f128e 100644
--- a/src/devices/bus/amiga/keyboard/a2000.cpp
+++ b/src/devices/bus/amiga/keyboard/a2000.cpp
@@ -59,7 +59,6 @@
#include "cpu/mcs48/mcs48.h"
-#define LOG_GENERAL (1U << 0)
#define LOG_COMM (1U << 1)
#define LOG_SCAN (1U << 2)
@@ -90,7 +89,7 @@ class a2000_kbd_g80_device : public device_t, public device_amiga_keyboard_inter
{
public:
// from host
- virtual DECLARE_WRITE_LINE_MEMBER(kdat_w) override
+ virtual void kdat_w(int state) override
{
if (bool(state) != m_host_kdat)
{
@@ -304,37 +303,37 @@ INPUT_PORTS_START(a2000_us_keyboard)
PORT_INCLUDE(a2000_common_keyboard)
PORT_MODIFY("ROW0")
- PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR(')') PORT_CHAR(0x00bb) // »
- PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('^') PORT_CHAR(0x00bd) // ½
- PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N') PORT_CHAR(0x00ad) PORT_CHAR(0x00af) // soft hyphen ¯
- PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H') PORT_CHAR(0x02c6) // ˆ
- PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P') PORT_CHAR(0x00b6) // ¶
- PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y') PORT_CHAR(0x00a4) PORT_CHAR(0x00a5) // ¤ ¥
+ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR(')') PORT_CHAR(U'»')
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('^') PORT_CHAR(U'½')
+ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N') PORT_CHAR(0xad) PORT_CHAR(U'¯') // soft hyphen
+ PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H') PORT_CHAR(U'ˆ')
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P') PORT_CHAR(U'¶')
+ PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y') PORT_CHAR(U'¤') PORT_CHAR(U'¥')
PORT_MODIFY("ROW1")
- PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%') PORT_CHAR(0x00bc) // ¼
- PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B') PORT_CHAR(0x00ba) // º
- PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G') PORT_CHAR(0x02cb) // ˋ
- PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T') PORT_CHAR(0x00fe) PORT_CHAR(0x00de) // þ Þ
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%') PORT_CHAR(U'¼')
+ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B') PORT_CHAR(U'º')
+ PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G') PORT_CHAR(U'ˋ')
+ PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T') PORT_CHAR(U'þ') PORT_CHAR(U'Þ')
PORT_MODIFY("ROW2")
- PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('@') PORT_CHAR(0x00b2) // ²
- PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X') PORT_CHAR(0x00d7) PORT_CHAR(0x00f7) // × ÷
- PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S') PORT_CHAR(0x00df) PORT_CHAR(0x00a7) // ß §
- PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W') PORT_CHAR(0x00b0) // °
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('@') PORT_CHAR(U'²')
+ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X') PORT_CHAR(U'×') PORT_CHAR(U'÷')
+ PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S') PORT_CHAR(U'ß') PORT_CHAR(U'§')
+ PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W') PORT_CHAR(U'°')
PORT_MODIFY("ROW3")
PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_UNUSED)
- PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!') PORT_CHAR(0x00b9) // ¹
- PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z') PORT_CHAR(0x00b1) PORT_CHAR(0x00ac) // ± ¬
- PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A') PORT_CHAR(0x00e6) PORT_CHAR(0x00c6) // æ Æ
- PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q') PORT_CHAR(0x00e5) PORT_CHAR(0x00c5) // å Å
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!') PORT_CHAR(U'¹')
+ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z') PORT_CHAR(U'±') PORT_CHAR(U'¬')
+ PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A') PORT_CHAR(U'æ') PORT_CHAR(U'Æ')
+ PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q') PORT_CHAR(U'å') PORT_CHAR(U'Å')
PORT_MODIFY("ROW4")
- PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#') PORT_CHAR(0x00b3) // ³
- PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C') PORT_CHAR(0x00e7) PORT_CHAR(0x00c7) // ç Ç
- PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D') PORT_CHAR(0x00f0) PORT_CHAR(0x00d0) // ð Ð
- PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E') PORT_CHAR(0x00a9) // ©
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#') PORT_CHAR(U'³')
+ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C') PORT_CHAR(U'ç') PORT_CHAR(U'Ç')
+ PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D') PORT_CHAR(U'ð') PORT_CHAR(U'Ð')
+ PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E') PORT_CHAR(U'©')
PORT_MODIFY("ROW6")
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_NUMLOCK) PORT_CHAR(UCHAR_MAMEKEY(NUMLOCK)) PORT_NAME("Keypad (")
@@ -342,268 +341,268 @@ INPUT_PORTS_START(a2000_us_keyboard)
PORT_MODIFY("ROW8")
PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('\\') PORT_CHAR('|')
- PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$') PORT_CHAR(0x00a2) // ¢
- PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V') PORT_CHAR(0x00aa) // ª
- PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F') PORT_CHAR(0x00b4) // ´
- PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R') PORT_CHAR(0x00ae) // ®
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$') PORT_CHAR(U'¢')
+ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V') PORT_CHAR(U'ª')
+ PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F') PORT_CHAR(U'´')
+ PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R') PORT_CHAR(U'®')
PORT_MODIFY("ROW9")
- PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=') PORT_CHAR('+')
- PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(']') PORT_CHAR('}')
- PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('*') PORT_CHAR(0x00b7) // ·
- PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<')
- PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K') PORT_CHAR(0x00a8) // ¨
+ PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=') PORT_CHAR('+')
+ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(']') PORT_CHAR('}')
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('*') PORT_CHAR(U'·')
+ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<')
+ PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K') PORT_CHAR(U'¨')
PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_UNUSED)
- PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I') PORT_CHAR(0x00a1) PORT_CHAR(0x00a6) // ¡ ¦
+ PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I') PORT_CHAR(U'¡') PORT_CHAR(U'¦')
PORT_MODIFY("ROW10")
PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHAR('_')
PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('[') PORT_CHAR('{')
- PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR('(') PORT_CHAR(0x00ab) // «
- PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>')
- PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L') PORT_CHAR(0x00a3) // £
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR('(') PORT_CHAR(U'«')
+ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>')
+ PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L') PORT_CHAR(U'£')
PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR('\'') PORT_CHAR('"')
- PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O') PORT_CHAR(0x00f8) PORT_CHAR(0x00d8) // ø Ø
+ PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O') PORT_CHAR(U'ø') PORT_CHAR(U'Ø')
PORT_MODIFY("ROW11")
- PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?')
- PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('&') PORT_CHAR(0x00be) // ¾
- PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M') PORT_CHAR(0x00b8) PORT_CHAR(0x00bf) // ¸ ¿
- PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J') PORT_CHAR(0x02dc) // ˜
- PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR(':')
- PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U') PORT_CHAR(0x00b5) // µ
+ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?')
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('&') PORT_CHAR(U'¾')
+ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M') PORT_CHAR(U'¸') PORT_CHAR(U'¿')
+ PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J') PORT_CHAR(U'˜')
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR(':')
+ PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U') PORT_CHAR(U'µ')
INPUT_PORTS_END
INPUT_PORTS_START(a2000_de_keyboard)
PORT_INCLUDE(a2000_common_keyboard)
PORT_MODIFY("ROW0")
- PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR('=') PORT_CHAR(0x00bb) // »
- PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('&') PORT_CHAR(0x00bd) // ½
- PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N') PORT_CHAR(0x00ad) PORT_CHAR(0x00af) // soft hyphen ¯
- PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H') PORT_CHAR(0x02c6) // ˆ
- PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P') PORT_CHAR(0x00b6) // ¶
- PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_Y) PORT_CHAR('z') PORT_CHAR('Z') PORT_CHAR(0x00a4) PORT_CHAR(0x00a5) // ¤ ¥
+ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR('=') PORT_CHAR(U'»')
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('&') PORT_CHAR(U'½')
+ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N') PORT_CHAR(0xad) PORT_CHAR(U'¯') // soft hyphen
+ PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H') PORT_CHAR(U'ˆ')
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P') PORT_CHAR(U'¶')
+ PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_Y) PORT_CHAR('z') PORT_CHAR('Z') PORT_CHAR(U'¤') PORT_CHAR(U'¥')
PORT_MODIFY("ROW1")
- PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%') PORT_CHAR(0x00bc) // ¼
- PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B') PORT_CHAR(0x00ba) // º
- PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G') PORT_CHAR(0x02cb) // ˋ
- PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T') PORT_CHAR(0x00fe) PORT_CHAR(0x00de) // þ Þ
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%') PORT_CHAR(U'¼')
+ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B') PORT_CHAR(U'º')
+ PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G') PORT_CHAR(U'ˋ')
+ PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T') PORT_CHAR(U'þ') PORT_CHAR(U'Þ')
PORT_MODIFY("ROW2")
- PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('"') PORT_CHAR('@') PORT_CHAR(0x00b2) // ²
- PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X') PORT_CHAR(0x00d7) PORT_CHAR(0x00f7) // × ÷
- PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S') PORT_CHAR(0x00df) PORT_CHAR(0x00a7) // ß §
- PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W') PORT_CHAR(0x00b0) // °
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('"') PORT_CHAR('@') PORT_CHAR(U'²')
+ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X') PORT_CHAR(U'×') PORT_CHAR(U'÷')
+ PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S') PORT_CHAR(U'ß') PORT_CHAR(U'§')
+ PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W') PORT_CHAR(U'°')
PORT_MODIFY("ROW3")
- PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH2) PORT_CHAR('<') PORT_CHAR('>')
- PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!') PORT_CHAR(0x00b9) // ¹
- PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('y') PORT_CHAR('Y') PORT_CHAR(0x00b1) PORT_CHAR(0x00ac) // ± ¬
- PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A') PORT_CHAR(0x00e6) PORT_CHAR(0x00c6) // æ Æ
- PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q') PORT_CHAR(0x00e5) PORT_CHAR(0x00c5) // å Å
+ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH2) PORT_CHAR('<') PORT_CHAR('>')
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!') PORT_CHAR(U'¹')
+ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('y') PORT_CHAR('Y') PORT_CHAR(U'±') PORT_CHAR(U'¬')
+ PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A') PORT_CHAR(U'æ') PORT_CHAR(U'Æ')
+ PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q') PORT_CHAR(U'å') PORT_CHAR(U'Å')
PORT_MODIFY("ROW4")
- PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR(0x00a7) PORT_CHAR(0x00b3) // § ³
- PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C') PORT_CHAR(0x00e7) PORT_CHAR(0x00c7) // ç Ç
- PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D') PORT_CHAR(0x00f0) PORT_CHAR(0x00d0) // ð Ð
- PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E') PORT_CHAR(0x00a9) // ©
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR(U'§') PORT_CHAR(U'³')
+ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C') PORT_CHAR(U'ç') PORT_CHAR(U'Ç')
+ PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D') PORT_CHAR(U'ð') PORT_CHAR(U'Ð')
+ PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E') PORT_CHAR(U'©')
PORT_MODIFY("ROW6")
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_NUMLOCK) PORT_CHAR(UCHAR_MAMEKEY(NUMLOCK)) PORT_NAME("Keypad [ {")
PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_SCRLOCK) PORT_CHAR(UCHAR_MAMEKEY(SCRLOCK)) PORT_NAME("Keypad ] }")
PORT_MODIFY("ROW8")
- PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$') PORT_CHAR(0x00b0) PORT_CHAR(0x00a2) // ° ¢
- PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V') PORT_CHAR(0x00aa) // ª
- PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F') PORT_CHAR(0x00b4) // ´
- PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R') PORT_CHAR(0x00ae) // ®
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$') PORT_CHAR(U'°') PORT_CHAR(U'¢')
+ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V') PORT_CHAR(U'ª')
+ PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F') PORT_CHAR(U'´')
+ PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R') PORT_CHAR(U'®')
PORT_MODIFY("ROW9")
- PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR(0x00b4) PORT_CHAR(0x02cb) // ´ ˋ
- PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR('+') PORT_CHAR('*') PORT_CHAR(']') PORT_CHAR('}')
- PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('(') PORT_CHAR(0x00b7) // ·
- PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR(';')
- PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K') PORT_CHAR(0x02dc) // ˜
- PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('#') PORT_CHAR('^')
- PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I') PORT_CHAR(0x00a1) PORT_CHAR(0x00a6) // ¡ ¦
+ PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR(U'´') PORT_CHAR(U'ˋ')
+ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR('+') PORT_CHAR('*') PORT_CHAR(']') PORT_CHAR('}')
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('(') PORT_CHAR(U'·')
+ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR(';')
+ PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K') PORT_CHAR(U'˜')
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('#') PORT_CHAR('^')
+ PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I') PORT_CHAR(U'¡') PORT_CHAR(U'¦')
PORT_MODIFY("ROW10")
- PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS) PORT_CHAR(0x00df) PORT_CHAR('?') // ß
- PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR(0x00fc) PORT_CHAR(0x00dc) PORT_CHAR('[') PORT_CHAR('{') // ü Ü
- PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR(')') PORT_CHAR(0x00ab) // «
- PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR(':')
- PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L') PORT_CHAR(0x00a3) // £
- PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(0x00e4) PORT_CHAR(0x00c4) PORT_CHAR('\'') // ä Ä
- PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O') PORT_CHAR(0x00f8) PORT_CHAR(0x00d8) // ø Ø
+ PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS) PORT_CHAR(U'ß') PORT_CHAR('?')
+ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR(U'ü') PORT_CHAR(U'Ü') PORT_CHAR('[') PORT_CHAR('{')
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR(')') PORT_CHAR(U'«')
+ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR(':')
+ PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L') PORT_CHAR(U'£')
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(U'ä') PORT_CHAR(U'Ä') PORT_CHAR('\'')
+ PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O') PORT_CHAR(U'ø') PORT_CHAR(U'Ø')
PORT_MODIFY("ROW11")
- PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('-') PORT_CHAR('_')
- PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('/') PORT_CHAR(0x00be) // ¾
- PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M') PORT_CHAR(0x00b8) PORT_CHAR(0x00bf) // ¸ ¿
- PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J') PORT_CHAR(0x02dc) // ˜
- PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(0x00f6) PORT_CHAR(0x00d6) // ö Ö
- PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U') PORT_CHAR(0x00b5) // µ
+ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('-') PORT_CHAR('_')
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('/') PORT_CHAR(U'¾')
+ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M') PORT_CHAR(U'¸') PORT_CHAR(U'¿')
+ PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J') PORT_CHAR(U'˜')
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(U'ö') PORT_CHAR(U'Ö')
+ PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U') PORT_CHAR(U'µ')
INPUT_PORTS_END
INPUT_PORTS_START(a2000_se_keyboard)
PORT_INCLUDE(a2000_common_keyboard)
PORT_MODIFY("ROW0")
- PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR('=') PORT_CHAR(0x00bb) // »
- PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('&') PORT_CHAR(0x00bd) PORT_CHAR('^') // ½
- PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N') PORT_CHAR(0x00ad) PORT_CHAR(0x00af) // soft hyphen ¯
- PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H') PORT_CHAR(0x02c6) // ˆ
- PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P') PORT_CHAR(0x00b6) // ¶
- PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y') PORT_CHAR(0x00a4) PORT_CHAR(0x00a5) // ¤ ¥
+ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR('=') PORT_CHAR(U'»')
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('&') PORT_CHAR(U'½') PORT_CHAR('^')
+ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N') PORT_CHAR(0xad) PORT_CHAR(U'¯') // soft hyphen
+ PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H') PORT_CHAR(U'ˆ')
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P') PORT_CHAR(U'¶')
+ PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y') PORT_CHAR(U'¤') PORT_CHAR(U'¥')
PORT_MODIFY("ROW1")
- PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%') PORT_CHAR(0x00bc) // ¼
- PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B') PORT_CHAR(0x00ba) // º
- PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G') PORT_CHAR(0x02cb) // ˋ
- PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T') PORT_CHAR(0x00fe) PORT_CHAR(0x00de) // þ Þ
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%') PORT_CHAR(U'¼')
+ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B') PORT_CHAR(U'º')
+ PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G') PORT_CHAR(U'ˋ')
+ PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T') PORT_CHAR(U'þ') PORT_CHAR(U'Þ')
PORT_MODIFY("ROW2")
- PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('"') PORT_CHAR(0x00b2) PORT_CHAR('@') // ²
- PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X') PORT_CHAR(0x00d7) PORT_CHAR(0x00f7) // × ÷
- PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S') PORT_CHAR(0x00df) PORT_CHAR(0x00a7) // ß §
- PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W') PORT_CHAR(0x00b0) // °
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('"') PORT_CHAR(U'²') PORT_CHAR('@')
+ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X') PORT_CHAR(U'×') PORT_CHAR(U'÷')
+ PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S') PORT_CHAR(U'ß') PORT_CHAR(U'§')
+ PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W') PORT_CHAR(U'°')
PORT_MODIFY("ROW3")
- PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH2) PORT_CHAR('<') PORT_CHAR('>')
- PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!') PORT_CHAR(0x00b9) // ¹
- PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z') PORT_CHAR(0x00b1) PORT_CHAR(0x00ac) // ± ¬
- PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A') PORT_CHAR(0x00e6) PORT_CHAR(0x00c6) // æ Æ
- PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q') PORT_CHAR(0x00e5) PORT_CHAR(0x00c5) // å Å
+ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH2) PORT_CHAR('<') PORT_CHAR('>')
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!') PORT_CHAR(U'¹')
+ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z') PORT_CHAR(U'±') PORT_CHAR(U'¬')
+ PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A') PORT_CHAR(U'æ') PORT_CHAR(U'Æ')
+ PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q') PORT_CHAR(U'å') PORT_CHAR(U'Å')
PORT_MODIFY("ROW4")
- PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR(0x00a3) PORT_CHAR(0x00b3) PORT_CHAR('#') // £ ³
- PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C') PORT_CHAR(0x00e7) PORT_CHAR(0x00c7) // ç Ç
- PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D') PORT_CHAR(0x00f0) PORT_CHAR(0x00d0) // ð Ð
- PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E') PORT_CHAR(0x00a9) // ©
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR(U'£') PORT_CHAR(U'³') PORT_CHAR('#')
+ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C') PORT_CHAR(U'ç') PORT_CHAR(U'Ç')
+ PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D') PORT_CHAR(U'ð') PORT_CHAR(U'Ð')
+ PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E') PORT_CHAR(U'©')
PORT_MODIFY("ROW6")
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_NUMLOCK) PORT_CHAR(UCHAR_MAMEKEY(NUMLOCK)) PORT_NAME("Keypad [ {")
PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_SCRLOCK) PORT_CHAR(UCHAR_MAMEKEY(SCRLOCK)) PORT_NAME("Keypad ] }")
PORT_MODIFY("ROW8")
- PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$') PORT_CHAR(0x00a2) // ¢
- PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V') PORT_CHAR(0x00aa) // ª
- PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F') PORT_CHAR(0x00b4) // ´
- PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R') PORT_CHAR(0x00ae) // ®
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$') PORT_CHAR(U'¢')
+ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V') PORT_CHAR(U'ª')
+ PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F') PORT_CHAR(U'´')
+ PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R') PORT_CHAR(U'®')
PORT_MODIFY("ROW9")
- PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR(0x00b4) PORT_CHAR(0x02cb) // ´ ˋ
- PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(0x00a8) PORT_CHAR(0x2c6) PORT_CHAR(']') PORT_CHAR('}') // ¨ ˆ
- PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('(') PORT_CHAR(0x00b7) // ·
- PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR(';')
- PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K')
- PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('\'') PORT_CHAR('*') PORT_CHAR(0x00fc) PORT_CHAR(0x00dc) // ü Ü
- PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I') PORT_CHAR(0x00a1) PORT_CHAR(0x00a6) // ¡ ¦
+ PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR(U'´') PORT_CHAR(U'ˋ')
+ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(U'¨') PORT_CHAR(U'ˆ') PORT_CHAR(']') PORT_CHAR('}')
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('(') PORT_CHAR(U'·')
+ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR(';')
+ PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K')
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('\'') PORT_CHAR('*') PORT_CHAR(U'ü') PORT_CHAR(U'Ü')
+ PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I') PORT_CHAR(U'¡') PORT_CHAR(U'¦')
PORT_MODIFY("ROW10")
- PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('+') PORT_CHAR('?')
- PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR(0x00e5) PORT_CHAR(0x00c5) PORT_CHAR('[') PORT_CHAR('{') // å Å
- PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR(')') PORT_CHAR(0x00ab) // «
- PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR(':')
- PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L') PORT_CHAR(0x00a3) // £
- PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(0x00e4) PORT_CHAR(0x00c4) // ä Ä
- PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O') PORT_CHAR(0x00f8) PORT_CHAR(0x00d8) // ø Ø
+ PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('+') PORT_CHAR('?')
+ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR(U'å') PORT_CHAR(U'Å') PORT_CHAR('[') PORT_CHAR('{')
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR(')') PORT_CHAR(U'«')
+ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR(':')
+ PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L') PORT_CHAR(U'£')
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(U'ä') PORT_CHAR(U'Ä')
+ PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O') PORT_CHAR(U'ø') PORT_CHAR(U'Ø')
PORT_MODIFY("ROW11")
- PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('-') PORT_CHAR('_')
- PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('/') PORT_CHAR(0x00be) // ¾
- PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M') PORT_CHAR(0x00b8) PORT_CHAR(0x00bf) // ¸ ¿
- PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J') PORT_CHAR(0x02dc) // ˜
- PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(0x00f6) PORT_CHAR(0x00d6) // ö Ö
- PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U') PORT_CHAR(0x00b5) // µ
+ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('-') PORT_CHAR('_')
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('/') PORT_CHAR(U'¾')
+ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M') PORT_CHAR(U'¸') PORT_CHAR(U'¿')
+ PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J') PORT_CHAR(U'˜')
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(U'ö') PORT_CHAR(U'Ö')
+ PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U') PORT_CHAR(U'µ')
INPUT_PORTS_END
INPUT_PORTS_START(a2000_dk_keyboard)
PORT_INCLUDE(a2000_common_keyboard)
PORT_MODIFY("ROW0")
- PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR('=')
- PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('&') PORT_CHAR(0x00bd) PORT_CHAR('^') // ½
- PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N') PORT_CHAR(0x00ad) PORT_CHAR(0x00af) // soft hyphen ¯
- PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H') PORT_CHAR(0x02c6) // ˆ
- PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P') PORT_CHAR(0x00b6) // ¶
- PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y') PORT_CHAR(0x00a4) PORT_CHAR(0x00a5) // ¤ ¥
+ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR('=')
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('&') PORT_CHAR(U'½') PORT_CHAR('^')
+ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N') PORT_CHAR(0xad) PORT_CHAR(U'¯') // soft hyphen
+ PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H') PORT_CHAR(U'ˆ')
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P') PORT_CHAR(U'¶')
+ PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y') PORT_CHAR(U'¤') PORT_CHAR(U'¥')
PORT_MODIFY("ROW1")
- PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%') PORT_CHAR(0x00bc) // ¼
- PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B') PORT_CHAR(0x00ba) // º
- PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G') PORT_CHAR(0x02cb) // ˋ
- PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T') PORT_CHAR(0x00fe) PORT_CHAR(0x00de) // þ Þ
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%') PORT_CHAR(U'¼')
+ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B') PORT_CHAR(U'º')
+ PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G') PORT_CHAR(U'ˋ')
+ PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T') PORT_CHAR(U'þ') PORT_CHAR(U'Þ')
PORT_MODIFY("ROW2")
- PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('"') PORT_CHAR(0x00b2) PORT_CHAR('@') // ²
- PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X') PORT_CHAR(0x00d7) PORT_CHAR(0x00f7) // × ÷
- PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S') PORT_CHAR(0x00df) PORT_CHAR(0x00a7) // ß §
- PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W') PORT_CHAR(0x00b0) // °
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('"') PORT_CHAR(U'²') PORT_CHAR('@')
+ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X') PORT_CHAR(U'×') PORT_CHAR(U'÷')
+ PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S') PORT_CHAR(U'ß') PORT_CHAR(U'§')
+ PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W') PORT_CHAR(U'°')
PORT_MODIFY("ROW3")
- PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH2) PORT_CHAR('<') PORT_CHAR('>') PORT_CHAR(0x00ab) PORT_CHAR(0x00bb) // « »
- PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!') PORT_CHAR(0x00b9) // ¹
- PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z') PORT_CHAR(0x00b1) PORT_CHAR(0x00ac) // ± ¬
- PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A') PORT_CHAR(0x00e6) PORT_CHAR(0x00c6) // æ Æ
- PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q') PORT_CHAR(0x00e5) PORT_CHAR(0x00c5) // å Å
+ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH2) PORT_CHAR('<') PORT_CHAR('>') PORT_CHAR(U'«') PORT_CHAR(U'»')
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!') PORT_CHAR(U'¹')
+ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z') PORT_CHAR(U'±') PORT_CHAR(U'¬')
+ PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A') PORT_CHAR(U'æ') PORT_CHAR(U'Æ')
+ PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q') PORT_CHAR(U'å') PORT_CHAR(U'Å')
PORT_MODIFY("ROW4")
- PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#') PORT_CHAR(0x00b3) // ³
- PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C') PORT_CHAR(0x00e7) PORT_CHAR(0x00c7) // ç Ç
- PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D') PORT_CHAR(0x00f0) PORT_CHAR(0x00d0) // ð Ð
- PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E') PORT_CHAR(0x00a9) // ©
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#') PORT_CHAR(U'³')
+ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C') PORT_CHAR(U'ç') PORT_CHAR(U'Ç')
+ PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D') PORT_CHAR(U'ð') PORT_CHAR(U'Ð')
+ PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E') PORT_CHAR(U'©')
PORT_MODIFY("ROW6")
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_NUMLOCK) PORT_CHAR(UCHAR_MAMEKEY(NUMLOCK)) PORT_NAME("Keypad [ {")
PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_SCRLOCK) PORT_CHAR(UCHAR_MAMEKEY(SCRLOCK)) PORT_NAME("Keypad ] }")
PORT_MODIFY("ROW8")
- PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR(0x00a4) PORT_CHAR(0x00a2) PORT_CHAR('$') // ¤ ¢
- PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V') PORT_CHAR(0x00aa) // ª
- PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F') PORT_CHAR(0x00b4) // ´
- PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R') PORT_CHAR(0x00ae) // ®
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR(U'¤') PORT_CHAR(U'¢') PORT_CHAR('$')
+ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V') PORT_CHAR(U'ª')
+ PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F') PORT_CHAR(U'´')
+ PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R') PORT_CHAR(U'®')
PORT_MODIFY("ROW9")
- PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR(0x00b4) PORT_CHAR(0x02cb) // ´ ˋ
- PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(0x00a8) PORT_CHAR(0x02c6) PORT_CHAR(']') PORT_CHAR('}') // ¨ ˆ
- PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('(') PORT_CHAR(0x00b7) // ·
- PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR(';')
- PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K') PORT_CHAR(0x00a8) // ¨
+ PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR(U'´') PORT_CHAR(U'ˋ')
+ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(U'¨') PORT_CHAR(U'ˆ') PORT_CHAR(']') PORT_CHAR('}')
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('(') PORT_CHAR(U'·')
+ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR(';')
+ PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K') PORT_CHAR(U'¨')
PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('\'') PORT_CHAR('*')
- PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I') PORT_CHAR(0x00a1) PORT_CHAR(0x00a6) // ¡ ¦
+ PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I') PORT_CHAR(U'¡') PORT_CHAR(U'¦')
PORT_MODIFY("ROW10")
PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('+') PORT_CHAR('?')
- PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR(0x00e5) PORT_CHAR(0x00c5) PORT_CHAR('[') PORT_CHAR('{') // å Å
- PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR(')')
- PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR(':')
- PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L') PORT_CHAR(0x00a3) // £
- PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(0x00f8) PORT_CHAR(0x00d8) PORT_CHAR('\'') PORT_CHAR('"') // ø Ø
- PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O') PORT_CHAR(0x00f8) PORT_CHAR(0x00d8) // ø Ø
+ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR(U'å') PORT_CHAR(U'Å') PORT_CHAR('[') PORT_CHAR('{')
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR(')')
+ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR(':')
+ PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L') PORT_CHAR(U'£')
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(U'ø') PORT_CHAR(U'Ø') PORT_CHAR('\'') PORT_CHAR('"')
+ PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O') PORT_CHAR(U'ø') PORT_CHAR(U'Ø')
PORT_MODIFY("ROW11")
- PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('-') PORT_CHAR('_') PORT_CHAR('/') PORT_CHAR('?')
- PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('/') PORT_CHAR(0x00be) // ¾
- PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M') PORT_CHAR(0x00b8) PORT_CHAR(0x00bf) // ¸ ¿
- PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J') PORT_CHAR(0x02dc) // ˜
- PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(0x00e6) PORT_CHAR(0x00c6) PORT_CHAR(';') PORT_CHAR(':') // æ Æ
- PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U') PORT_CHAR(0x00b5) // µ
+ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('-') PORT_CHAR('_') PORT_CHAR('/') PORT_CHAR('?')
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('/') PORT_CHAR(U'¾')
+ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M') PORT_CHAR(U'¸') PORT_CHAR(U'¿')
+ PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J') PORT_CHAR(U'˜')
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(U'æ') PORT_CHAR(U'Æ') PORT_CHAR(';') PORT_CHAR(':')
+ PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U') PORT_CHAR(U'µ')
INPUT_PORTS_END
INPUT_PORTS_START(a2000_gb_keyboard)
PORT_INCLUDE(a2000_us_keyboard)
PORT_MODIFY("ROW2")
- PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('"') PORT_CHAR(0x00b2) // ²
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('"') PORT_CHAR(U'²')
PORT_MODIFY("ROW4")
- PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR(0x00a3) PORT_CHAR(0x00b3) // £ ³
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR(U'£') PORT_CHAR(U'³')
PORT_MODIFY("ROW10")
- PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR('#') PORT_CHAR('@') PORT_CHAR('\'') PORT_CHAR('"')
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR('#') PORT_CHAR('@') PORT_CHAR('\'') PORT_CHAR('"')
INPUT_PORTS_END
diff --git a/src/devices/bus/amiga/keyboard/keyboard.cpp b/src/devices/bus/amiga/keyboard/keyboard.cpp
index 141998a15fa..a7c52973239 100644
--- a/src/devices/bus/amiga/keyboard/keyboard.cpp
+++ b/src/devices/bus/amiga/keyboard/keyboard.cpp
@@ -56,11 +56,6 @@ void amiga_keyboard_bus_device::device_start()
{
// get connected keyboard
m_kbd = get_card_device();
-
- // resolve callbacks
- m_kclk_handler.resolve_safe();
- m_kdat_handler.resolve_safe();
- m_krst_handler.resolve_safe();
}
//-------------------------------------------------
@@ -75,7 +70,7 @@ void amiga_keyboard_bus_device::device_reset()
// host to module interface
//-------------------------------------------------
-WRITE_LINE_MEMBER( amiga_keyboard_bus_device::kdat_in_w )
+void amiga_keyboard_bus_device::kdat_in_w(int state)
{
if (m_kbd)
m_kbd->kdat_w(state);
diff --git a/src/devices/bus/amiga/keyboard/keyboard.h b/src/devices/bus/amiga/keyboard/keyboard.h
index ce11d82ba32..aa57cb3da05 100644
--- a/src/devices/bus/amiga/keyboard/keyboard.h
+++ b/src/devices/bus/amiga/keyboard/keyboard.h
@@ -49,12 +49,12 @@ public:
auto krst_handler() { return m_krst_handler.bind(); }
// called from keyboard
- DECLARE_WRITE_LINE_MEMBER(kclk_w) { m_kclk_handler(state); }
- DECLARE_WRITE_LINE_MEMBER(kdat_w) { m_kdat_handler(state); }
- DECLARE_WRITE_LINE_MEMBER(krst_w) { m_krst_handler(state); }
+ void kclk_w(int state) { m_kclk_handler(state); }
+ void kdat_w(int state) { m_kdat_handler(state); }
+ void krst_w(int state) { m_krst_handler(state); }
// called from host
- DECLARE_WRITE_LINE_MEMBER(kdat_in_w);
+ void kdat_in_w(int state);
protected:
// device-level overrides
@@ -77,7 +77,7 @@ public:
// construction/destruction
virtual ~device_amiga_keyboard_interface();
- virtual DECLARE_WRITE_LINE_MEMBER(kdat_w) = 0;
+ virtual void kdat_w(int state) = 0;
protected:
device_amiga_keyboard_interface(const machine_config &mconfig, device_t &device);
diff --git a/src/devices/bus/amiga/keyboard/matrix.cpp b/src/devices/bus/amiga/keyboard/matrix.cpp
index 530d243f4b0..f550fe1aedc 100644
--- a/src/devices/bus/amiga/keyboard/matrix.cpp
+++ b/src/devices/bus/amiga/keyboard/matrix.cpp
@@ -111,66 +111,66 @@ INPUT_PORTS_START(matrix_us)
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED)
PORT_MODIFY("ROW1")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z') PORT_CHAR(0x00b1) PORT_CHAR(0x00ac) // ± ¬
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A') PORT_CHAR(0x00e6) PORT_CHAR(0x00c6) // æ Æ
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q') PORT_CHAR(0x00e5) PORT_CHAR(0x00c5) // å Å
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!') PORT_CHAR(0x00b9) // ¹
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z') PORT_CHAR(U'±') PORT_CHAR(U'¬')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A') PORT_CHAR(U'æ') PORT_CHAR(U'Æ')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q') PORT_CHAR(U'å') PORT_CHAR(U'Å')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!') PORT_CHAR(U'¹')
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_NUMLOCK) PORT_CHAR(UCHAR_MAMEKEY(NUMLOCK)) PORT_NAME("Keypad (")
PORT_MODIFY("ROW2")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X') PORT_CHAR(0x00d7) PORT_CHAR(0x00f7) // × ÷
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S') PORT_CHAR(0x00df) PORT_CHAR(0x00a7) // ß §
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W') PORT_CHAR(0x00b0) // °
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('@') PORT_CHAR(0x00b2) // ²
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X') PORT_CHAR(U'×') PORT_CHAR(U'÷')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S') PORT_CHAR(U'ß') PORT_CHAR(U'§')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W') PORT_CHAR(U'°')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('@') PORT_CHAR(U'²')
PORT_MODIFY("ROW3")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C') PORT_CHAR(0x00e7) PORT_CHAR(0x00c7) // ç Ç
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D') PORT_CHAR(0x00f0) PORT_CHAR(0x00d0) // ð Ð
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E') PORT_CHAR(0x00a9) // ©
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#') PORT_CHAR(0x00b3) // ³
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C') PORT_CHAR(U'ç') PORT_CHAR(U'Ç')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D') PORT_CHAR(U'ð') PORT_CHAR(U'Ð')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E') PORT_CHAR(U'©')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#') PORT_CHAR(U'³')
PORT_MODIFY("ROW4")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V') PORT_CHAR(0x00aa) // ª
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F') PORT_CHAR(0x00b4) // ´
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R') PORT_CHAR(0x00ae) // ®
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$') PORT_CHAR(0x00a2) // ¢
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V') PORT_CHAR(U'ª')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F') PORT_CHAR(U'´')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R') PORT_CHAR(U'®')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$') PORT_CHAR(U'¢')
PORT_MODIFY("ROW5")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B') PORT_CHAR(0x00ba) // º
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G') PORT_CHAR(0x02cb) // ˋ
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T') PORT_CHAR(0x00fe) PORT_CHAR(0x00de) // þ Þ
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%') PORT_CHAR(0x00bc) // ¼
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B') PORT_CHAR(U'º')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G') PORT_CHAR(U'ˋ')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T') PORT_CHAR(U'þ') PORT_CHAR(U'Þ')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%') PORT_CHAR(U'¼')
PORT_MODIFY("ROW6")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N') PORT_CHAR(0x00ad) PORT_CHAR(0x00af) // soft hyphen ¯
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H') PORT_CHAR(0x02c6) // ˆ
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y') PORT_CHAR(0x00a4) PORT_CHAR(0x00a5) // ¤ ¥
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('^') PORT_CHAR(0x00bd) // ½
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N') PORT_CHAR(0xad) PORT_CHAR(U'¯') // soft hyphen
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H') PORT_CHAR(U'ˆ')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y') PORT_CHAR(U'¤') PORT_CHAR(U'¥')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('^') PORT_CHAR(U'½')
PORT_MODIFY("ROW7")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M') PORT_CHAR(0x00b8) PORT_CHAR(0x00bf) // ¸ ¿
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J') PORT_CHAR(0x02dc) // ˜
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U') PORT_CHAR(0x00b5) // µ
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('&') PORT_CHAR(0x00be) // ¾
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M') PORT_CHAR(U'¸') PORT_CHAR(U'¿')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J') PORT_CHAR(U'˜')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U') PORT_CHAR(U'µ')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('&') PORT_CHAR(U'¾')
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SCRLOCK) PORT_CHAR(UCHAR_MAMEKEY(SCRLOCK)) PORT_NAME("Keypad )")
PORT_MODIFY("ROW8")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<')
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K') PORT_CHAR(0x00a8) // ¨
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I') PORT_CHAR(0x00a1) PORT_CHAR(0x00a6) // ¡ ¦
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('*') PORT_CHAR(0x00b7) // ·
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K') PORT_CHAR(U'¨')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I') PORT_CHAR(U'¡') PORT_CHAR(U'¦')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('*') PORT_CHAR(U'·')
PORT_MODIFY("ROW9")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>')
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L') PORT_CHAR(0x00a3) // £
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O') PORT_CHAR(0x00f8) PORT_CHAR(0x00d8) // ø Ø
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR('(') PORT_CHAR(0x00ab) // «
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L') PORT_CHAR(U'£')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O') PORT_CHAR(U'ø') PORT_CHAR(U'Ø')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR('(') PORT_CHAR(U'«')
PORT_MODIFY("ROW10")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?')
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR(':')
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P') PORT_CHAR(0x00b6) // ¶
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR(')') PORT_CHAR(0x00bb) // »
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR(':')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P') PORT_CHAR(U'¶')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR(')') PORT_CHAR(U'»')
PORT_MODIFY("ROW11")
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR('\'') PORT_CHAR('"')
@@ -179,8 +179,8 @@ INPUT_PORTS_START(matrix_us)
PORT_MODIFY("ROW12")
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_UNUSED)
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(']') PORT_CHAR('}')
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=') PORT_CHAR('+')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(']') PORT_CHAR('}')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=') PORT_CHAR('+')
PORT_MODIFY("ROW13")
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('\\') PORT_CHAR('|')
@@ -190,79 +190,79 @@ INPUT_PORTS_START(matrix_de)
PORT_INCLUDE(matrix_common)
PORT_MODIFY("ROW0")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH2) PORT_CHAR('<') PORT_CHAR('>')
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH2) PORT_CHAR('<') PORT_CHAR('>')
PORT_MODIFY("ROW1")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('y') PORT_CHAR('Y') PORT_CHAR(0x00b1) PORT_CHAR(0x00ac) // ± ¬
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A') PORT_CHAR(0x00e6) PORT_CHAR(0x00c6) // æ Æ
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q') PORT_CHAR(0x00e5) PORT_CHAR(0x00c5) // å Å
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!') PORT_CHAR(0x00b9) // ¹
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('y') PORT_CHAR('Y') PORT_CHAR(U'±') PORT_CHAR(U'¬')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A') PORT_CHAR(U'æ') PORT_CHAR(U'Æ')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q') PORT_CHAR(U'å') PORT_CHAR(U'Å')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!') PORT_CHAR(U'¹')
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_NUMLOCK) PORT_CHAR(UCHAR_MAMEKEY(NUMLOCK)) PORT_NAME("Keypad [ {")
PORT_MODIFY("ROW2")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X') PORT_CHAR(0x00d7) PORT_CHAR(0x00f7) // × ÷
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S') PORT_CHAR(0x00df) PORT_CHAR(0x00a7) // ß §
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W') PORT_CHAR(0x00b0) // °
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('"') PORT_CHAR('@') PORT_CHAR(0x00b2) // ²
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X') PORT_CHAR(U'×') PORT_CHAR(U'÷')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S') PORT_CHAR(U'ß') PORT_CHAR(U'§')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W') PORT_CHAR(U'°')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('"') PORT_CHAR('@') PORT_CHAR(U'²')
PORT_MODIFY("ROW3")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C') PORT_CHAR(0x00e7) PORT_CHAR(0x00c7) // ç Ç
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D') PORT_CHAR(0x00f0) PORT_CHAR(0x00d0) // ð Ð
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E') PORT_CHAR(0x00a9) // ©
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR(0x00a7) PORT_CHAR(0x00b3) // § ³
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C') PORT_CHAR(U'ç') PORT_CHAR(U'Ç')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D') PORT_CHAR(U'ð') PORT_CHAR(U'Ð')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E') PORT_CHAR(U'©')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR(U'§') PORT_CHAR(U'³')
PORT_MODIFY("ROW4")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V') PORT_CHAR(0x00aa) // ª
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F') PORT_CHAR(0x00b4) // ´
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R') PORT_CHAR(0x00ae) // ®
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$') PORT_CHAR(0x00b0) PORT_CHAR(0x00a2) // ° ¢
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V') PORT_CHAR(U'ª')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F') PORT_CHAR(U'´')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R') PORT_CHAR(U'®')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$') PORT_CHAR(U'°') PORT_CHAR(U'¢')
PORT_MODIFY("ROW5")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B') PORT_CHAR(0x00ba) // º
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G') PORT_CHAR(0x02cb) // ˋ
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T') PORT_CHAR(0x00fe) PORT_CHAR(0x00de) // þ Þ
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%') PORT_CHAR(0x00bc) // ¼
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B') PORT_CHAR(U'º')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G') PORT_CHAR(U'ˋ')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T') PORT_CHAR(U'þ') PORT_CHAR(U'Þ')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%') PORT_CHAR(U'¼')
PORT_MODIFY("ROW6")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N') PORT_CHAR(0x00ad) PORT_CHAR(0x00af) // soft hyphen ¯
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H') PORT_CHAR(0x02c6) // ˆ
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Y) PORT_CHAR('z') PORT_CHAR('Z') PORT_CHAR(0x00a4) PORT_CHAR(0x00a5) // ¤ ¥
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('&') PORT_CHAR(0x00bd) // ½
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N') PORT_CHAR(0xad) PORT_CHAR(U'¯') // soft hyphen
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H') PORT_CHAR(U'ˆ')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Y) PORT_CHAR('z') PORT_CHAR('Z') PORT_CHAR(U'¤') PORT_CHAR(U'¥')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('&') PORT_CHAR(U'½')
PORT_MODIFY("ROW7")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M') PORT_CHAR(0x00b8) PORT_CHAR(0x00bf) // ¸ ¿
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J') PORT_CHAR(0x02dc) // ˜
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U') PORT_CHAR(0x00b5) // µ
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('/') PORT_CHAR(0x00be) // ¾
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M') PORT_CHAR(U'¸') PORT_CHAR(U'¿')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J') PORT_CHAR(U'˜')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U') PORT_CHAR(U'µ')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('/') PORT_CHAR(U'¾')
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SCRLOCK) PORT_CHAR(UCHAR_MAMEKEY(SCRLOCK)) PORT_NAME("Keypad ] }")
PORT_MODIFY("ROW8")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR(';')
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K') PORT_CHAR(0x02dc) // ˜
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I') PORT_CHAR(0x00a1) PORT_CHAR(0x00a6) // ¡ ¦
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('(') PORT_CHAR(0x00b7) // ·
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR(';')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K') PORT_CHAR(U'˜')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I') PORT_CHAR(U'¡') PORT_CHAR(U'¦')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('(') PORT_CHAR(U'·')
PORT_MODIFY("ROW9")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR(':')
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L') PORT_CHAR(0x00a3) // £
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O') PORT_CHAR(0x00f8) PORT_CHAR(0x00d8) // ø Ø
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR(')') PORT_CHAR(0x00ab) // «
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR(':')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L') PORT_CHAR(U'£')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O') PORT_CHAR(U'ø') PORT_CHAR(U'Ø')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR(')') PORT_CHAR(U'«')
PORT_MODIFY("ROW10")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('-') PORT_CHAR('_')
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(0x00f6) PORT_CHAR(0x00d6) // ö Ö
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P') PORT_CHAR(0x00b6) // ¶
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR('=') PORT_CHAR(0x00bb) // »
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('-') PORT_CHAR('_')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(U'ö') PORT_CHAR(U'Ö')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P') PORT_CHAR(U'¶')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR('=') PORT_CHAR(U'»')
PORT_MODIFY("ROW11")
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(0x00e4) PORT_CHAR(0x00c4) PORT_CHAR('\'') // ä Ä
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR(0x00fc) PORT_CHAR(0x00dc) PORT_CHAR('[') PORT_CHAR('{') // ü Ü
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS) PORT_CHAR(0x00df) PORT_CHAR('?') // ß
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(U'ä') PORT_CHAR(U'Ä') PORT_CHAR('\'')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR(U'ü') PORT_CHAR(U'Ü') PORT_CHAR('[') PORT_CHAR('{')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS) PORT_CHAR(U'ß') PORT_CHAR('?')
PORT_MODIFY("ROW12")
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('#') PORT_CHAR('^')
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR('+') PORT_CHAR('*') PORT_CHAR(']') PORT_CHAR('}')
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR(0x00b4) PORT_CHAR(0x02cb) // ´ ˋ
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('#') PORT_CHAR('^')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR('+') PORT_CHAR('*') PORT_CHAR(']') PORT_CHAR('}')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR(U'´') PORT_CHAR(U'ˋ')
INPUT_PORTS_END
INPUT_PORTS_START(matrix_fr)
@@ -272,392 +272,392 @@ INPUT_PORTS_START(matrix_fr)
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH2) PORT_CHAR('<') PORT_CHAR('>')
PORT_MODIFY("ROW1")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('w') PORT_CHAR('W') PORT_CHAR(0x00b1) PORT_CHAR(0x00ac) // ± ¬
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('q') PORT_CHAR('Q') PORT_CHAR(0x00e6) PORT_CHAR(0x00c6) // æ Æ
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('a') PORT_CHAR('A') PORT_CHAR(0x00e5) PORT_CHAR(0x00c5) // å Å
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('&') PORT_CHAR('1') PORT_CHAR(0x00b9) PORT_CHAR('!') // ¹
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('w') PORT_CHAR('W') PORT_CHAR(U'±') PORT_CHAR(U'¬')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('q') PORT_CHAR('Q') PORT_CHAR(U'æ') PORT_CHAR(U'Æ')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('a') PORT_CHAR('A') PORT_CHAR(U'å') PORT_CHAR(U'Å')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('&') PORT_CHAR('1') PORT_CHAR(U'¹') PORT_CHAR('!')
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_NUMLOCK) PORT_CHAR(UCHAR_MAMEKEY(NUMLOCK)) PORT_NAME("Keypad [ {")
PORT_MODIFY("ROW2")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X') PORT_CHAR(0x00d7) PORT_CHAR(0x00f7) // × ÷
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S') PORT_CHAR(0x00df) PORT_CHAR(0x00a7) // ß §
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('z') PORT_CHAR('Z') PORT_CHAR(0x00b0) // °
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR(0x00e9) PORT_CHAR('2') PORT_CHAR(0x00b2) PORT_CHAR('@') // é ²
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X') PORT_CHAR(U'×') PORT_CHAR(U'÷')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S') PORT_CHAR(U'ß') PORT_CHAR(U'§')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('z') PORT_CHAR('Z') PORT_CHAR(U'°')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR(U'é') PORT_CHAR('2') PORT_CHAR(U'²') PORT_CHAR('@')
PORT_MODIFY("ROW3")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C') PORT_CHAR(0x00e7) PORT_CHAR(0x00c7) // ç Ç
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D') PORT_CHAR(0x00f0) PORT_CHAR(0x00d0) // ð Ð
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E') PORT_CHAR(0x00a9) // ©
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('"') PORT_CHAR('3') PORT_CHAR(0x00b3) PORT_CHAR('#') // ³
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C') PORT_CHAR(U'ç') PORT_CHAR(U'Ç')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D') PORT_CHAR(U'ð') PORT_CHAR(U'Ð')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E') PORT_CHAR(U'©')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('"') PORT_CHAR('3') PORT_CHAR(U'³') PORT_CHAR('#')
PORT_MODIFY("ROW4")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V') PORT_CHAR(0x00aa) // ª
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F') PORT_CHAR(0x00b4) // ´
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R') PORT_CHAR(0x00ae) // ®
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('\'') PORT_CHAR('4') PORT_CHAR(0x00a2) PORT_CHAR('$') // ¢
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V') PORT_CHAR(U'ª')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F') PORT_CHAR(U'´')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R') PORT_CHAR(U'®')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('\'') PORT_CHAR('4') PORT_CHAR(U'¢') PORT_CHAR('$')
PORT_MODIFY("ROW5")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B') PORT_CHAR(0x00ba) // º
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G') PORT_CHAR(0x02cb) // ˋ
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T') PORT_CHAR(0x00fe) PORT_CHAR(0x00de) // þ Þ
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('(') PORT_CHAR('5') PORT_CHAR(0x00bc) PORT_CHAR('%') // ¼
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B') PORT_CHAR(U'º')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G') PORT_CHAR(U'ˋ')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T') PORT_CHAR(U'þ') PORT_CHAR(U'Þ')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('(') PORT_CHAR('5') PORT_CHAR(U'¼') PORT_CHAR('%')
PORT_MODIFY("ROW6")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N') PORT_CHAR(0x00ad) PORT_CHAR(0x00af) // soft hyphen ¯
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H') PORT_CHAR(0x02c6) // ˆ
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y') PORT_CHAR(0x00a4) PORT_CHAR(0x00a5) // ¤ ¥
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR(0x00a7) PORT_CHAR('6') PORT_CHAR(0x00bd) PORT_CHAR('^') // § ½
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N') PORT_CHAR(0xad) PORT_CHAR(U'¯') // soft hyphen
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H') PORT_CHAR(U'ˆ')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y') PORT_CHAR(U'¤') PORT_CHAR(U'¥')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR(U'§') PORT_CHAR('6') PORT_CHAR(U'½') PORT_CHAR('^')
PORT_MODIFY("ROW7")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR(',') PORT_CHAR('?') PORT_CHAR(0x00b8) PORT_CHAR(0x00bf) // ¸ ¿
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J') PORT_CHAR(0x02dc) // ˜
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U') PORT_CHAR(0x00b5) // µ
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR(0x00e8) PORT_CHAR('7') PORT_CHAR(0x00be) PORT_CHAR('&') // è ¾
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR(',') PORT_CHAR('?') PORT_CHAR(U'¸') PORT_CHAR(U'¿')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J') PORT_CHAR(U'˜')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U') PORT_CHAR(U'µ')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR(U'è') PORT_CHAR('7') PORT_CHAR(U'¾') PORT_CHAR('&')
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SCRLOCK) PORT_CHAR(UCHAR_MAMEKEY(SCRLOCK)) PORT_NAME("Keypad ] }")
PORT_MODIFY("ROW8")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(';') PORT_CHAR('.') PORT_CHAR(',') PORT_CHAR('<')
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K') PORT_CHAR(0x00a8) // ¨
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I') PORT_CHAR(0x00a1) PORT_CHAR(0x00a6) // ¡ ¦
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('!') PORT_CHAR('8') PORT_CHAR(0x00b7) PORT_CHAR('*') // ·
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(';') PORT_CHAR('.') PORT_CHAR(',') PORT_CHAR('<')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K') PORT_CHAR(U'¨')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I') PORT_CHAR(U'¡') PORT_CHAR(U'¦')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('!') PORT_CHAR('8') PORT_CHAR(U'·') PORT_CHAR('*')
PORT_MODIFY("ROW9")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR(':') PORT_CHAR('/') PORT_CHAR('.') PORT_CHAR(':')
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L') PORT_CHAR(0x00a3) // £
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O') PORT_CHAR(0x00f8) PORT_CHAR(0x00d8) // ø Ø
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR(0x00e7) PORT_CHAR('9') PORT_CHAR(0x00ab) PORT_CHAR('(') // ç «
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR(':') PORT_CHAR('/') PORT_CHAR('.') PORT_CHAR(':')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L') PORT_CHAR(U'£')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O') PORT_CHAR(U'ø') PORT_CHAR(U'Ø')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR(U'ç') PORT_CHAR('9') PORT_CHAR(U'«') PORT_CHAR('(')
PORT_MODIFY("ROW10")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('=') PORT_CHAR('+') PORT_CHAR('/') PORT_CHAR('?')
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR('m') PORT_CHAR('M') PORT_CHAR(';') PORT_CHAR(':')
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P') PORT_CHAR(0x00b6) // ¶
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR(0x00e0) PORT_CHAR('0') PORT_CHAR(0x00bb) PORT_CHAR(')') // à »
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('=') PORT_CHAR('+') PORT_CHAR('/') PORT_CHAR('?')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR('m') PORT_CHAR('M') PORT_CHAR(';') PORT_CHAR(':')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P') PORT_CHAR(U'¶')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR(U'à') PORT_CHAR('0') PORT_CHAR(U'»') PORT_CHAR(')')
PORT_MODIFY("ROW11")
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(0x00f9) PORT_CHAR('%') PORT_CHAR('\'') PORT_CHAR('"') // ù
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR(0x02c6) PORT_CHAR(0x00a8) PORT_CHAR('[') PORT_CHAR('{') // ˆ ¨
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS) PORT_CHAR(')') PORT_CHAR(0x00b0) PORT_CHAR('-') PORT_CHAR('_') // °
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(U'ù') PORT_CHAR('%') PORT_CHAR('\'') PORT_CHAR('"')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR(U'ˆ') PORT_CHAR(U'¨') PORT_CHAR('[') PORT_CHAR('{')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS) PORT_CHAR(')') PORT_CHAR(U'°') PORT_CHAR('-') PORT_CHAR('_')
PORT_MODIFY("ROW12")
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR(0x00b5) PORT_CHAR(0x00a3) // µ £
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR('$') PORT_CHAR('*') PORT_CHAR(']') PORT_CHAR('}')
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('-') PORT_CHAR('_') PORT_CHAR('=') PORT_CHAR('+')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR(U'µ') PORT_CHAR(U'£')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR('$') PORT_CHAR('*') PORT_CHAR(']') PORT_CHAR('}')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('-') PORT_CHAR('_') PORT_CHAR('=') PORT_CHAR('+')
INPUT_PORTS_END
INPUT_PORTS_START(matrix_it)
PORT_INCLUDE(matrix_common)
PORT_MODIFY("ROW0")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH2) PORT_CHAR('<') PORT_CHAR('>')
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH2) PORT_CHAR('<') PORT_CHAR('>')
PORT_MODIFY("ROW1")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z') PORT_CHAR(0x00b1) PORT_CHAR(0x00ac) // ± ¬
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A') PORT_CHAR(0x00e6) PORT_CHAR(0x00c6) // æ Æ
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q') PORT_CHAR(0x00e5) PORT_CHAR(0x00c5) // å Å
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!') PORT_CHAR(0x00b9) // ¹
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z') PORT_CHAR(U'±') PORT_CHAR(U'¬')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A') PORT_CHAR(U'æ') PORT_CHAR(U'Æ')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q') PORT_CHAR(U'å') PORT_CHAR(U'Å')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!') PORT_CHAR(U'¹')
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_NUMLOCK) PORT_CHAR(UCHAR_MAMEKEY(NUMLOCK)) PORT_NAME("Keypad [ {")
PORT_MODIFY("ROW2")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X') PORT_CHAR(0x00d7) PORT_CHAR(0x00f7) // × ÷
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S') PORT_CHAR(0x00df) // ß
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W') PORT_CHAR(0x00b0) // °
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('"') PORT_CHAR(0x00b2) // ²
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X') PORT_CHAR(U'×') PORT_CHAR(U'÷')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S') PORT_CHAR(U'ß')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W') PORT_CHAR(U'°')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('"') PORT_CHAR(U'²')
PORT_MODIFY("ROW3")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C') PORT_CHAR(0x00e7) PORT_CHAR(0x00c7) // ç Ç
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D') PORT_CHAR(0x00f0) PORT_CHAR(0x00d0) // ð Ð
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E') PORT_CHAR(0x00a9) // ©
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR(0x00a3) PORT_CHAR(0x00b3) // £ ³
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C') PORT_CHAR(U'ç') PORT_CHAR(U'Ç')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D') PORT_CHAR(U'ð') PORT_CHAR(U'Ð')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E') PORT_CHAR(U'©')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR(U'£') PORT_CHAR(U'³')
PORT_MODIFY("ROW4")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V') PORT_CHAR(0x00aa) // ª
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F') PORT_CHAR(0x00b4) // ´
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R') PORT_CHAR(0x00ae) // ®
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$') PORT_CHAR(0x00a2) PORT_CHAR(0x00b0) // ¢ °
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V') PORT_CHAR(U'ª')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F') PORT_CHAR(U'´')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R') PORT_CHAR(U'®')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$') PORT_CHAR(U'¢') PORT_CHAR(U'°')
PORT_MODIFY("ROW5")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B') PORT_CHAR(0x00ba) // º
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G') PORT_CHAR(0x02cb) // ˋ
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T') PORT_CHAR(0x00fe) PORT_CHAR(0x00de) // þ Þ
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%') PORT_CHAR(0x00bc) // ¼
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B') PORT_CHAR(U'º')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G') PORT_CHAR(U'ˋ')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T') PORT_CHAR(U'þ') PORT_CHAR(U'Þ')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%') PORT_CHAR(U'¼')
PORT_MODIFY("ROW6")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N') PORT_CHAR(0x00ad) PORT_CHAR(0x00af) // soft hyphen ¯
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H')
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y') PORT_CHAR(0x00a4) PORT_CHAR(0x00a5) // ¤ ¥
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('&') PORT_CHAR(0x00bd) PORT_CHAR('^') // ½
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N') PORT_CHAR(0xad) PORT_CHAR(U'¯') // soft hyphen
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y') PORT_CHAR(U'¤') PORT_CHAR(U'¥')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('&') PORT_CHAR(U'½') PORT_CHAR('^')
PORT_MODIFY("ROW7")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M') PORT_CHAR(0x00b8) PORT_CHAR(0x00bf) // ¸ ¿
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J') PORT_CHAR(0x02dc) // ˜
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U') PORT_CHAR(0x00b5) // µ
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('/') PORT_CHAR(0x00be) PORT_CHAR('&') // ¾
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M') PORT_CHAR(U'¸') PORT_CHAR(U'¿')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J') PORT_CHAR(U'˜')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U') PORT_CHAR(U'µ')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('/') PORT_CHAR(U'¾') PORT_CHAR('&')
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SCRLOCK) PORT_CHAR(UCHAR_MAMEKEY(SCRLOCK)) PORT_NAME("Keypad ] }")
PORT_MODIFY("ROW8")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR(';')
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K') PORT_CHAR(0x00a8) // ¨
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I') PORT_CHAR(0x00a1) PORT_CHAR(0x00a6) // ¡ ¦
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('(') PORT_CHAR(0x00b7) // ·
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR(';')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K') PORT_CHAR(U'¨')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I') PORT_CHAR(U'¡') PORT_CHAR(U'¦')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('(') PORT_CHAR(U'·')
PORT_MODIFY("ROW9")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR(':')
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L') PORT_CHAR(0x00a3) // £
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O') PORT_CHAR(0x00f8) PORT_CHAR(0x00d8) // ø Ø
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR(')') PORT_CHAR(0x00ab) // «
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR(':')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L') PORT_CHAR(U'£')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O') PORT_CHAR(U'ø') PORT_CHAR(U'Ø')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR(')') PORT_CHAR(U'«')
PORT_MODIFY("ROW10")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('-') PORT_CHAR('_')
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(0x00f2) PORT_CHAR('@') // ò
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P') PORT_CHAR(0x00b6) // ¶
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR('=') PORT_CHAR(0x00bb) // »
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('-') PORT_CHAR('_')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(U'ò') PORT_CHAR('@')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P') PORT_CHAR(U'¶')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR('=') PORT_CHAR(U'»')
PORT_MODIFY("ROW11")
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(0x00e0) PORT_CHAR('#') // à
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR(0x00e8) PORT_CHAR(0x00e9) PORT_CHAR('[') PORT_CHAR('{') // è é
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(U'à') PORT_CHAR('#')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR(U'è') PORT_CHAR(U'é') PORT_CHAR('[') PORT_CHAR('{')
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('\'') PORT_CHAR('?')
PORT_MODIFY("ROW12")
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR(0x00f9) PORT_CHAR(0x00a7) // ù §
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR('+') PORT_CHAR('*') PORT_CHAR(']') PORT_CHAR('}')
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR(0x00ec) PORT_CHAR(0x02c6) // ì ˆ
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR(U'ù') PORT_CHAR(U'§')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR('+') PORT_CHAR('*') PORT_CHAR(']') PORT_CHAR('}')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR(U'ì') PORT_CHAR(U'ˆ')
INPUT_PORTS_END
INPUT_PORTS_START(matrix_se)
PORT_INCLUDE(matrix_common)
PORT_MODIFY("ROW0")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH2) PORT_CHAR('<') PORT_CHAR('>')
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH2) PORT_CHAR('<') PORT_CHAR('>')
PORT_MODIFY("ROW1")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z') PORT_CHAR(0x00b1) PORT_CHAR(0x00ac) // ± ¬
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A') PORT_CHAR(0x00e6) PORT_CHAR(0x00c6) // æ Æ
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q') PORT_CHAR(0x00e5) PORT_CHAR(0x00c5) // å Å
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!') PORT_CHAR(0x00b9) // ¹
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z') PORT_CHAR(U'±') PORT_CHAR(U'¬')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A') PORT_CHAR(U'æ') PORT_CHAR(U'Æ')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q') PORT_CHAR(U'å') PORT_CHAR(U'Å')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!') PORT_CHAR(U'¹')
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_NUMLOCK) PORT_CHAR(UCHAR_MAMEKEY(NUMLOCK)) PORT_NAME("Keypad [ {")
PORT_MODIFY("ROW2")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X') PORT_CHAR(0x00d7) PORT_CHAR(0x00f7) // × ÷
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S') PORT_CHAR(0x00df) PORT_CHAR(0x00a7) // ß §
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W') PORT_CHAR(0x00b0) // °
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('"') PORT_CHAR(0x00b2) PORT_CHAR('@') // ²
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X') PORT_CHAR(U'×') PORT_CHAR(U'÷')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S') PORT_CHAR(U'ß') PORT_CHAR(U'§')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W') PORT_CHAR(U'°')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('"') PORT_CHAR(U'²') PORT_CHAR('@')
PORT_MODIFY("ROW3")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C') PORT_CHAR(0x00e7) PORT_CHAR(0x00c7) // ç Ç
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D') PORT_CHAR(0x00f0) PORT_CHAR(0x00d0) // ð Ð
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E') PORT_CHAR(0x00a9) // ©
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR(0x00a3) PORT_CHAR(0x00b3) PORT_CHAR('#') // £ ³
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C') PORT_CHAR(U'ç') PORT_CHAR(U'Ç')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D') PORT_CHAR(U'ð') PORT_CHAR(U'Ð')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E') PORT_CHAR(U'©')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR(U'£') PORT_CHAR(U'³') PORT_CHAR('#')
PORT_MODIFY("ROW4")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V') PORT_CHAR(0x00aa) // ª
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F') PORT_CHAR(0x00b4) // ´
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R') PORT_CHAR(0x00ae) // ®
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$') PORT_CHAR(0x00a2) // ¢
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V') PORT_CHAR(U'ª')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F') PORT_CHAR(U'´')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R') PORT_CHAR(U'®')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$') PORT_CHAR(U'¢')
PORT_MODIFY("ROW5")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B') PORT_CHAR(0x00ba) // º
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G') PORT_CHAR(0x02cb) // ˋ
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T') PORT_CHAR(0x00fe) PORT_CHAR(0x00de) // þ Þ
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%') PORT_CHAR(0x00bc) // ¼
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B') PORT_CHAR(U'º')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G') PORT_CHAR(U'ˋ')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T') PORT_CHAR(U'þ') PORT_CHAR(U'Þ')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%') PORT_CHAR(U'¼')
PORT_MODIFY("ROW6")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N') PORT_CHAR(0x00ad) PORT_CHAR(0x00af) // soft hyphen ¯
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H') PORT_CHAR(0x02c6) // ˆ
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y') PORT_CHAR(0x00a4) PORT_CHAR(0x00a5) // ¤ ¥
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('&') PORT_CHAR(0x00bd) PORT_CHAR('^') // ½
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N') PORT_CHAR(0xad) PORT_CHAR(U'¯') // soft hyphen
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H') PORT_CHAR(U'ˆ')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y') PORT_CHAR(U'¤') PORT_CHAR(U'¥')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('&') PORT_CHAR(U'½') PORT_CHAR('^')
PORT_MODIFY("ROW7")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M') PORT_CHAR(0x00b8) PORT_CHAR(0x00bf) // ¸ ¿
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J') PORT_CHAR(0x02dc) // ˜
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U') PORT_CHAR(0x00b5) // µ
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('/') PORT_CHAR(0x00be) // ¾
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M') PORT_CHAR(U'¸') PORT_CHAR(U'¿')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J') PORT_CHAR(U'˜')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U') PORT_CHAR(U'µ')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('/') PORT_CHAR(U'¾')
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SCRLOCK) PORT_CHAR(UCHAR_MAMEKEY(SCRLOCK)) PORT_NAME("Keypad ] }")
PORT_MODIFY("ROW8")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR(';')
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K')
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I') PORT_CHAR(0x00a1) PORT_CHAR(0x00a6) // ¡ ¦
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('(') PORT_CHAR(0x00b7) // ·
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR(';')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I') PORT_CHAR(U'¡') PORT_CHAR(U'¦')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('(') PORT_CHAR(U'·')
PORT_MODIFY("ROW9")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR(':')
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L') PORT_CHAR(0x00a3) // £
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O') PORT_CHAR(0x00f8) PORT_CHAR(0x00d8) // ø Ø
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR(')') PORT_CHAR(0x00ab) // «
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR(':')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L') PORT_CHAR(U'£')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O') PORT_CHAR(U'ø') PORT_CHAR(U'Ø')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR(')') PORT_CHAR(U'«')
PORT_MODIFY("ROW10")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('-') PORT_CHAR('_')
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(0x00f6) PORT_CHAR(0x00d6) // ö Ö
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P') PORT_CHAR(0x00b6) // ¶
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR('=') PORT_CHAR(0x00bb) // »
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('-') PORT_CHAR('_')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(U'ö') PORT_CHAR(U'Ö')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P') PORT_CHAR(U'¶')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR('=') PORT_CHAR(U'»')
PORT_MODIFY("ROW11")
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(0x00e4) PORT_CHAR(0x00c4) // ä Ä
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR(0x00e5) PORT_CHAR(0x00c5) PORT_CHAR('[') PORT_CHAR('{') // å Å
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('+') PORT_CHAR('?')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(U'ä') PORT_CHAR(U'Ä')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR(U'å') PORT_CHAR(U'Å') PORT_CHAR('[') PORT_CHAR('{')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('+') PORT_CHAR('?')
PORT_MODIFY("ROW12")
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('\'') PORT_CHAR('*') PORT_CHAR(0x00fc) PORT_CHAR(0x00dc) // ü Ü
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(0x00a8) PORT_CHAR(0x2c6) PORT_CHAR(']') PORT_CHAR('}') // ¨ ˆ
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR(0x00b4) PORT_CHAR(0x02cb) // ´ ˋ
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('\'') PORT_CHAR('*') PORT_CHAR(U'ü') PORT_CHAR(U'Ü')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(U'¨') PORT_CHAR(U'ˆ') PORT_CHAR(']') PORT_CHAR('}')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR(U'´') PORT_CHAR(U'ˋ')
INPUT_PORTS_END
INPUT_PORTS_START(matrix_es)
PORT_INCLUDE(matrix_common)
PORT_MODIFY("ROW0")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH2) PORT_CHAR('<') PORT_CHAR('>') PORT_CHAR(0x00ab) PORT_CHAR(0x00bb) // « »
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH2) PORT_CHAR('<') PORT_CHAR('>') PORT_CHAR(U'«') PORT_CHAR(U'»')
PORT_MODIFY("ROW1")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z') PORT_CHAR(0x00b1) PORT_CHAR(0x00ac) // ± ¬
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A') PORT_CHAR(0x00e6) PORT_CHAR(0x00c6) // æ Æ
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q') PORT_CHAR(0x00e5) PORT_CHAR(0x00c5) // å Å
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR(0x00a1) PORT_CHAR(0x00b9) // ¡ ¹
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z') PORT_CHAR(U'±') PORT_CHAR(U'¬')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A') PORT_CHAR(U'æ') PORT_CHAR(U'Æ')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q') PORT_CHAR(U'å') PORT_CHAR(U'Å')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR(U'¡') PORT_CHAR(U'¹')
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_NUMLOCK) PORT_CHAR(UCHAR_MAMEKEY(NUMLOCK)) PORT_NAME("Keypad [ {")
PORT_MODIFY("ROW2")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X') PORT_CHAR(0x00d7) PORT_CHAR(0x00f7) // × ÷
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S') PORT_CHAR(0x00df) PORT_CHAR(0x00a7) // ß §
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W') PORT_CHAR(0x00b0) // °
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR(0x00bf) PORT_CHAR(0x00b2) PORT_CHAR('@') // ¿ ²
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X') PORT_CHAR(U'×') PORT_CHAR(U'÷')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S') PORT_CHAR(U'ß') PORT_CHAR(U'§')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W') PORT_CHAR(U'°')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR(U'¿') PORT_CHAR(U'²') PORT_CHAR('@')
PORT_MODIFY("ROW3")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C')
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D') PORT_CHAR(0x00f0) PORT_CHAR(0x00d0) // ð Ð
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E') PORT_CHAR(0x00a9) // ©
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#') PORT_CHAR(0x00b3) // ³
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D') PORT_CHAR(U'ð') PORT_CHAR(U'Ð')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E') PORT_CHAR(U'©')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#') PORT_CHAR(U'³')
PORT_MODIFY("ROW4")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V')
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F') PORT_CHAR(0x00b4) // ´
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R') PORT_CHAR(0x00ae) // ®
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$') PORT_CHAR(0x00a2) PORT_CHAR(0x00b0) // ¢ °
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F') PORT_CHAR(U'´')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R') PORT_CHAR(U'®')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$') PORT_CHAR(U'¢') PORT_CHAR(U'°')
PORT_MODIFY("ROW5")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B')
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G') PORT_CHAR(0x02cb) // ˋ
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T') PORT_CHAR(0x00fe) PORT_CHAR(0x00de) // þ Þ
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%') PORT_CHAR(0x00bc) // ¼
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G') PORT_CHAR(U'ˋ')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T') PORT_CHAR(U'þ') PORT_CHAR(U'Þ')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%') PORT_CHAR(U'¼')
PORT_MODIFY("ROW6")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N') PORT_CHAR(0x00ad) PORT_CHAR(0x00af) // soft hyphen ¯
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H') PORT_CHAR(0x02c6) // ˆ
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y') PORT_CHAR(0x00a4) PORT_CHAR(0x00a5) // ¤ ¥
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('/') PORT_CHAR(0x00bd) PORT_CHAR('^') // ½
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N') PORT_CHAR(0xad) PORT_CHAR(U'¯') // soft hyphen
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H') PORT_CHAR(U'ˆ')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y') PORT_CHAR(U'¤') PORT_CHAR(U'¥')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('/') PORT_CHAR(U'½') PORT_CHAR('^')
PORT_MODIFY("ROW7")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M') PORT_CHAR(0x00b8) // ¸
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J') PORT_CHAR(0x02dc) // ˜
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U') PORT_CHAR(0x00b5) // µ
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('&') PORT_CHAR(0x00be) // ¾
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M') PORT_CHAR(U'¸')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J') PORT_CHAR(U'˜')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U') PORT_CHAR(U'µ')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('&') PORT_CHAR(U'¾')
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SCRLOCK) PORT_CHAR(UCHAR_MAMEKEY(SCRLOCK)) PORT_NAME("Keypad ] }")
PORT_MODIFY("ROW8")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('?')
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K') PORT_CHAR(0x00a8) // ¨
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I') PORT_CHAR(0x00a1) PORT_CHAR(0x00a6) // ¡ ¦
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('*') PORT_CHAR(0x00b7) // ·
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('?')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K') PORT_CHAR(U'¨')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I') PORT_CHAR(U'¡') PORT_CHAR(U'¦')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('*') PORT_CHAR(U'·')
PORT_MODIFY("ROW9")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('!')
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L') PORT_CHAR(0x00a3) // £
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O') PORT_CHAR(0x00f8) PORT_CHAR(0x00d8) // ø Ø
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR('(')
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('!')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L') PORT_CHAR(U'£')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O') PORT_CHAR(U'ø') PORT_CHAR(U'Ø')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR('(')
PORT_MODIFY("ROW10")
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('\'') PORT_CHAR('"')
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(0x00f1) PORT_CHAR(0x00d1) // ñ Ñ
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P') PORT_CHAR(0x00b6) // ¶
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR(')')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(U'ñ') PORT_CHAR(U'Ñ')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P') PORT_CHAR(U'¶')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR(')')
PORT_MODIFY("ROW11")
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(';') PORT_CHAR(':')
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR(0x00b4) PORT_CHAR(0x00a8) PORT_CHAR('[') PORT_CHAR('{') // ´ ¨
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(';') PORT_CHAR(':')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR(U'´') PORT_CHAR(U'¨') PORT_CHAR('[') PORT_CHAR('{')
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHAR('_')
PORT_MODIFY("ROW12")
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR(0x00e7) PORT_CHAR(0x00c7) PORT_CHAR(0x00aa) PORT_CHAR(0x00ba) // ç Ç ª º
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(0x02cb) PORT_CHAR(0x02c6) PORT_CHAR(']') PORT_CHAR('}') // ˋ ˆ
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=') PORT_CHAR('+')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR(U'ç') PORT_CHAR(U'Ç') PORT_CHAR(U'ª') PORT_CHAR(U'º')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(U'ˋ') PORT_CHAR(U'ˆ') PORT_CHAR(']') PORT_CHAR('}')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=') PORT_CHAR('+')
INPUT_PORTS_END
INPUT_PORTS_START(matrix_dk)
PORT_INCLUDE(matrix_common)
PORT_MODIFY("ROW0")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH2) PORT_CHAR('<') PORT_CHAR('>') PORT_CHAR(0x00ab) PORT_CHAR(0x00bb) // « »
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH2) PORT_CHAR('<') PORT_CHAR('>') PORT_CHAR(U'«') PORT_CHAR(U'»')
PORT_MODIFY("ROW1")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z') PORT_CHAR(0x00b1) PORT_CHAR(0x00ac) // ± ¬
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A') PORT_CHAR(0x00e6) PORT_CHAR(0x00c6) // æ Æ
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q') PORT_CHAR(0x00e5) PORT_CHAR(0x00c5) // å Å
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!') PORT_CHAR(0x00b9) // ¹
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z') PORT_CHAR(U'±') PORT_CHAR(U'¬')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A') PORT_CHAR(U'æ') PORT_CHAR(U'Æ')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q') PORT_CHAR(U'å') PORT_CHAR(U'Å')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!') PORT_CHAR(U'¹')
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_NUMLOCK) PORT_CHAR(UCHAR_MAMEKEY(NUMLOCK)) PORT_NAME("Keypad [ {")
PORT_MODIFY("ROW2")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X') PORT_CHAR(0x00d7) PORT_CHAR(0x00f7) // × ÷
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S') PORT_CHAR(0x00df) PORT_CHAR(0x00a7) // ß §
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W') PORT_CHAR(0x00b0) // °
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('"') PORT_CHAR(0x00b2) PORT_CHAR('@') // ²
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X') PORT_CHAR(U'×') PORT_CHAR(U'÷')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S') PORT_CHAR(U'ß') PORT_CHAR(U'§')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W') PORT_CHAR(U'°')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('"') PORT_CHAR(U'²') PORT_CHAR('@')
PORT_MODIFY("ROW3")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C') PORT_CHAR(0x00e7) PORT_CHAR(0x00c7) // ç Ç
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D') PORT_CHAR(0x00f0) PORT_CHAR(0x00d0) // ð Ð
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E') PORT_CHAR(0x00a9) // ©
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#') PORT_CHAR(0x00b3) // ³
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C') PORT_CHAR(U'ç') PORT_CHAR(U'Ç')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D') PORT_CHAR(U'ð') PORT_CHAR(U'Ð')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E') PORT_CHAR(U'©')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#') PORT_CHAR(U'³')
PORT_MODIFY("ROW4")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V') PORT_CHAR(0x00aa) // ª
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F') PORT_CHAR(0x00b4) // ´
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R') PORT_CHAR(0x00ae) // ®
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR(0x00a4) PORT_CHAR(0x00a2) PORT_CHAR('$') // ¤ ¢
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V') PORT_CHAR(U'ª')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F') PORT_CHAR(U'´')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R') PORT_CHAR(U'®')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR(U'¤') PORT_CHAR(U'¢') PORT_CHAR('$')
PORT_MODIFY("ROW5")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B') PORT_CHAR(0x00ba) // º
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G') PORT_CHAR(0x02cb) // ˋ
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T') PORT_CHAR(0x00fe) PORT_CHAR(0x00de) // þ Þ
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%') PORT_CHAR(0x00bc) // ¼
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B') PORT_CHAR(U'º')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G') PORT_CHAR(U'ˋ')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T') PORT_CHAR(U'þ') PORT_CHAR(U'Þ')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%') PORT_CHAR(U'¼')
PORT_MODIFY("ROW6")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N') PORT_CHAR(0x00ad) PORT_CHAR(0x00af) // soft hyphen ¯
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H') PORT_CHAR(0x02c6) // ˆ
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y') PORT_CHAR(0x00a4) PORT_CHAR(0x00a5) // ¤ ¥
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('&') PORT_CHAR(0x00bd) PORT_CHAR('^') // ½
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N') PORT_CHAR(0xad) PORT_CHAR(U'¯') // soft hyphen
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H') PORT_CHAR(U'ˆ')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y') PORT_CHAR(U'¤') PORT_CHAR(U'¥')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('&') PORT_CHAR(U'½') PORT_CHAR('^')
PORT_MODIFY("ROW7")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M') PORT_CHAR(0x00b8) PORT_CHAR(0x00bf) // ¸ ¿
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J') PORT_CHAR(0x02dc) // ˜
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U') PORT_CHAR(0x00b5) // µ
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('/') PORT_CHAR(0x00be) // ¾
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M') PORT_CHAR(U'¸') PORT_CHAR(U'¿')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J') PORT_CHAR(U'˜')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U') PORT_CHAR(U'µ')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('/') PORT_CHAR(U'¾')
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SCRLOCK) PORT_CHAR(UCHAR_MAMEKEY(SCRLOCK)) PORT_NAME("Keypad ] }")
PORT_MODIFY("ROW8")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR(';')
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K') PORT_CHAR(0x00a8) // ¨
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I') PORT_CHAR(0x00a1) PORT_CHAR(0x00a6) // ¡ ¦
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('(') PORT_CHAR(0x00b7) // ·
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR(';')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K') PORT_CHAR(U'¨')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I') PORT_CHAR(U'¡') PORT_CHAR(U'¦')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('(') PORT_CHAR(U'·')
PORT_MODIFY("ROW9")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR(':')
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L') PORT_CHAR(0x00a3) // £
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O') PORT_CHAR(0x00f8) PORT_CHAR(0x00d8) // ø Ø
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR(')')
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR(':')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L') PORT_CHAR(U'£')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O') PORT_CHAR(U'ø') PORT_CHAR(U'Ø')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR(')')
PORT_MODIFY("ROW10")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('-') PORT_CHAR('_') PORT_CHAR('/') PORT_CHAR('?')
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(0x00e6) PORT_CHAR(0x00c6) PORT_CHAR(';') PORT_CHAR(':') // æ Æ
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P') PORT_CHAR(0x00b6) // ¶
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR('=')
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('-') PORT_CHAR('_') PORT_CHAR('/') PORT_CHAR('?')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(U'æ') PORT_CHAR(U'Æ') PORT_CHAR(';') PORT_CHAR(':')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P') PORT_CHAR(u'¶')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR('=')
PORT_MODIFY("ROW11")
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(0x00f8) PORT_CHAR(0x00d8) PORT_CHAR('\'') PORT_CHAR('"') // ø Ø
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR(0x00e5) PORT_CHAR(0x00c5) PORT_CHAR('[') PORT_CHAR('{') // å Å
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(U'ø') PORT_CHAR(U'Ø') PORT_CHAR('\'') PORT_CHAR('"')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR(U'å') PORT_CHAR(U'Å') PORT_CHAR('[') PORT_CHAR('{')
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('+') PORT_CHAR('?')
PORT_MODIFY("ROW12")
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('\'') PORT_CHAR('*')
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(0x00a8) PORT_CHAR(0x02c6) PORT_CHAR(']') PORT_CHAR('}') // ¨ ˆ
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR(0x00b4) PORT_CHAR(0x02cb) // ´ ˋ
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(U'¨') PORT_CHAR(U'ˆ') PORT_CHAR(']') PORT_CHAR('}')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR(U'´') PORT_CHAR(U'ˋ')
INPUT_PORTS_END
INPUT_PORTS_START(matrix_ch)
@@ -669,106 +669,106 @@ INPUT_PORTS_START(matrix_ch)
PORT_CONFSETTING( 0x00, "German" )
PORT_MODIFY("ROW0")
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_TILDE) PORT_CHAR('`') PORT_CHAR(0x02dc) PORT_CHAR('`') PORT_CHAR('~') // ˜
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH2) PORT_CHAR('<') PORT_CHAR('>') PORT_CHAR(0x00ab) PORT_CHAR(0x00bb) // « »
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_TILDE) PORT_CHAR('`') PORT_CHAR(U'˜') PORT_CHAR('`') PORT_CHAR('~')
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH2) PORT_CHAR('<') PORT_CHAR('>') PORT_CHAR(U'«') PORT_CHAR(U'»')
PORT_MODIFY("ROW1")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('y') PORT_CHAR('Y') PORT_CHAR(0x00b1) PORT_CHAR(0x00ac) // ± ¬
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A') PORT_CHAR(0x00e6) PORT_CHAR(0x00c6) // æ Æ
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q') PORT_CHAR(0x00e5) PORT_CHAR(0x00c5) // å Å
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('+') PORT_CHAR(0x00b9) // ¹
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('y') PORT_CHAR('Y') PORT_CHAR(U'±') PORT_CHAR(U'¬')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A') PORT_CHAR(U'æ') PORT_CHAR(U'Æ')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q') PORT_CHAR(U'å') PORT_CHAR(U'Å')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('+') PORT_CHAR(U'¹')
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_NUMLOCK) PORT_CHAR(UCHAR_MAMEKEY(NUMLOCK)) PORT_NAME("Keypad [ {")
PORT_MODIFY("ROW2")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X') PORT_CHAR(0x00d7) PORT_CHAR(0x00f7) // × ÷
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S') PORT_CHAR(0x00df) PORT_CHAR(0x00a7) // ß §
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W') PORT_CHAR(0x00b0) // °
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('"') PORT_CHAR(0x00b2) PORT_CHAR('@') // ²
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X') PORT_CHAR(U'×') PORT_CHAR(U'÷')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S') PORT_CHAR(U'ß') PORT_CHAR(U'§')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W') PORT_CHAR(U'°')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('"') PORT_CHAR(U'²') PORT_CHAR('@')
PORT_MODIFY("ROW3")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C') PORT_CHAR(0x00e7) PORT_CHAR(0x00c7) // ç Ç
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D') PORT_CHAR(0x00f0) PORT_CHAR(0x00d0) // ð Ð
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E') PORT_CHAR(0x00a9) // ©
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('*') PORT_CHAR(0x00b3) PORT_CHAR('#') // ³
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C') PORT_CHAR(U'ç') PORT_CHAR(U'Ç')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D') PORT_CHAR(U'ð') PORT_CHAR(U'Ð')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E') PORT_CHAR(U'©')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('*') PORT_CHAR(U'³') PORT_CHAR('#')
PORT_MODIFY("ROW4")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V') PORT_CHAR(0x00aa) // ª
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F') PORT_CHAR(0x00b4) // ´
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R') PORT_CHAR(0x00ae) // ®
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR(0x00e7) PORT_CHAR(0x00a2) // ç ¢
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V') PORT_CHAR(U'ª')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F') PORT_CHAR(U'´')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R') PORT_CHAR(U'®')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR(U'ç') PORT_CHAR(U'¢')
PORT_MODIFY("ROW5")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B') PORT_CHAR(0x00ba) // º
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G') PORT_CHAR(0x02cb) // ˋ
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T') PORT_CHAR(0x00fe) PORT_CHAR(0x00de) // þ Þ
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%') PORT_CHAR(0x00bc) PORT_CHAR(0x00a7) // ¼ §
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B') PORT_CHAR(U'º')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G') PORT_CHAR(U'ˋ')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T') PORT_CHAR(U'þ') PORT_CHAR(U'Þ')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%') PORT_CHAR(U'¼') PORT_CHAR(U'§')
PORT_MODIFY("ROW6")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N') PORT_CHAR(0x00ad) PORT_CHAR(0x00af) // soft hyphen ¯
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H') PORT_CHAR(0x02c6) // ˆ
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y') PORT_CHAR(0x00a4) PORT_CHAR(0x00a5) // ¤ ¥
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('&') PORT_CHAR(0x00bd) PORT_CHAR('^') // ½
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N') PORT_CHAR(0xad) PORT_CHAR(U'¯') // soft hyphen
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H') PORT_CHAR(U'ˆ')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y') PORT_CHAR(U'¤') PORT_CHAR(U'¥')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('&') PORT_CHAR(U'½') PORT_CHAR('^')
PORT_MODIFY("ROW7")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M') PORT_CHAR(0x00b8) PORT_CHAR(0x00bf) // ¸ ¿
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J') PORT_CHAR(0x02dc) // ˜
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U') PORT_CHAR(0x00b5) // µ
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('/') PORT_CHAR(0x00be) // ¾
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M') PORT_CHAR(U'¸') PORT_CHAR(U'¿')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J') PORT_CHAR(U'˜')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U') PORT_CHAR(U'µ')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('/') PORT_CHAR(U'¾')
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SCRLOCK) PORT_CHAR(UCHAR_MAMEKEY(SCRLOCK)) PORT_NAME("Keypad ] }")
PORT_MODIFY("ROW8")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR(';')
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K') PORT_CHAR(0x00a8) // ¨
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I') PORT_CHAR(0x00a1) PORT_CHAR(0x00a6) // ¡ ¦
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('(') PORT_CHAR(0x00b7) // ·
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR(';')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K') PORT_CHAR(U'¨')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I') PORT_CHAR(U'¡') PORT_CHAR(U'¦')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('(') PORT_CHAR(U'·')
PORT_MODIFY("ROW9")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR(':')
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L') PORT_CHAR(0x00a3) // £
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O') PORT_CHAR(0x00f8) PORT_CHAR(0x00d8) // ø Ø
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR(')')
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR(':')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L') PORT_CHAR(U'£')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O') PORT_CHAR(U'ø') PORT_CHAR(U'Ø')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR(')')
PORT_MODIFY("ROW10")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('-') PORT_CHAR('_') PORT_CHAR('/') PORT_CHAR('?')
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(0x00e9) PORT_CHAR(0x00f6) PORT_CONDITION("CFG", 0x01, EQUALS, 0x01) // é ö
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(0x00f6) PORT_CHAR(0x00e9) PORT_CONDITION("CFG", 0x01, EQUALS, 0x00) // ö é
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P') PORT_CHAR(0x00b6) // ¶
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR('=')
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('-') PORT_CHAR('_') PORT_CHAR('/') PORT_CHAR('?')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(U'é') PORT_CHAR(U'ö') PORT_CONDITION("CFG", 0x01, EQUALS, 0x01)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(U'ö') PORT_CHAR(U'é') PORT_CONDITION("CFG", 0x01, EQUALS, 0x00)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P') PORT_CHAR(U'¶')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR('=')
PORT_MODIFY("ROW11")
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(0x00e0) PORT_CHAR(0x00e4) PORT_CONDITION("CFG", 0x01, EQUALS, 0x01) // à ä
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(0x00e4) PORT_CHAR(0x00e0) PORT_CONDITION("CFG", 0x01, EQUALS, 0x00) // ä à
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR(0x00e8) PORT_CHAR(0x00fc) PORT_CHAR('[') PORT_CHAR('{') PORT_CONDITION("CFG", 0x01, EQUALS, 0x01) // è ü
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR(0x00fc) PORT_CHAR(0x00e8) PORT_CHAR('[') PORT_CHAR('{') PORT_CONDITION("CFG", 0x01, EQUALS, 0x00) // ü è
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(U'à') PORT_CHAR(U'ä') PORT_CONDITION("CFG", 0x01, EQUALS, 0x01)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(U'ä') PORT_CHAR(U'à') PORT_CONDITION("CFG", 0x01, EQUALS, 0x00)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR(U'è') PORT_CHAR(U'ü') PORT_CHAR('[') PORT_CHAR('{') PORT_CONDITION("CFG", 0x01, EQUALS, 0x01)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR(U'ü') PORT_CHAR(U'è') PORT_CHAR('[') PORT_CHAR('{') PORT_CONDITION("CFG", 0x01, EQUALS, 0x00)
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('\'') PORT_CHAR('?')
PORT_MODIFY("ROW12")
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('$') PORT_CHAR(0x00a3) // £
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(0x00a8) PORT_CHAR('!') PORT_CHAR(']') PORT_CHAR('}') // ¨
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR(0x02c6) PORT_CHAR(0x02cb) PORT_CHAR('=') PORT_CHAR(0x00b4) // ˆ ˋ ´
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('$') PORT_CHAR(U'£')
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(U'¨') PORT_CHAR('!') PORT_CHAR(']') PORT_CHAR('}')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR(U'ˆ') PORT_CHAR(U'ˋ') PORT_CHAR('=') PORT_CHAR(U'´')
INPUT_PORTS_END
INPUT_PORTS_START(matrix_no)
PORT_INCLUDE(matrix_dk)
PORT_MODIFY("ROW0")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH2) PORT_CHAR('<') PORT_CHAR('>') PORT_CHAR('\\') PORT_CHAR('|')
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH2) PORT_CHAR('<') PORT_CHAR('>') PORT_CHAR('\\') PORT_CHAR('|')
PORT_MODIFY("ROW3")
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR(0x00a3) PORT_CHAR(0x00b3) PORT_CHAR('#') // £ ³
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR(U'£') PORT_CHAR(U'³') PORT_CHAR('#')
PORT_MODIFY("ROW4")
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$') PORT_CHAR(0x00a2) // ¢
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$') PORT_CHAR(U'¢')
PORT_MODIFY("ROW9")
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR(')') PORT_CHAR(0x00ab) // «
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR(')') PORT_CHAR(U'«')
PORT_MODIFY("ROW10")
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(0x00f8) PORT_CHAR(0x00d8) PORT_CHAR(';') PORT_CHAR(':') // ø Ø
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR('=') PORT_CHAR(0x00bb) // »
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(U'ø') PORT_CHAR(U'Ø') PORT_CHAR(';') PORT_CHAR(':')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR('=') PORT_CHAR(U'»')
PORT_MODIFY("ROW11")
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(0x00e6) PORT_CHAR(0x00c6) PORT_CHAR('\'') PORT_CHAR('"') // æ Æ
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(U'æ') PORT_CHAR(U'Æ') PORT_CHAR('\'') PORT_CHAR('"')
INPUT_PORTS_END
INPUT_PORTS_START(matrix_gb)
@@ -778,13 +778,13 @@ INPUT_PORTS_START(matrix_gb)
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH2) PORT_NAME("Left Blank")
PORT_MODIFY("ROW2")
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('"') PORT_CHAR(0x00b2) // ²
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('"') PORT_CHAR(U'²')
PORT_MODIFY("ROW3")
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR(0x00a3) PORT_CHAR(0x00b3) // £ ³
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR(U'£') PORT_CHAR(U'³')
PORT_MODIFY("ROW11")
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR('#') PORT_CHAR('@') PORT_CHAR('\'') PORT_CHAR('"')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR('#') PORT_CHAR('@') PORT_CHAR('\'') PORT_CHAR('"')
PORT_MODIFY("ROW12")
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F11) PORT_NAME("Right Blank")
diff --git a/src/devices/bus/amiga/keyboard/mitsumi.cpp b/src/devices/bus/amiga/keyboard/mitsumi.cpp
index ccc68d5d1d4..0e6f219192d 100644
--- a/src/devices/bus/amiga/keyboard/mitsumi.cpp
+++ b/src/devices/bus/amiga/keyboard/mitsumi.cpp
@@ -106,13 +106,13 @@ ROM_END
class mitsumi_keyboard_base : public device_t, public device_amiga_keyboard_interface
{
public:
- virtual WRITE_LINE_MEMBER(kdat_w) override
+ virtual void kdat_w(int state) override
{
m_kdat_in = state ? 0x01U : 0x00U;
m_mcu->pa_w(m_meta->read());
}
- READ_LINE_MEMBER(kdat_r)
+ int kdat_r()
{
return m_kdat_in ^ 0x01U;
}
@@ -128,7 +128,7 @@ public:
return (result >> 2) ^ 0x3fU;
}
- READ_LINE_MEMBER(reset_r)
+ int reset_r()
{
return m_ctrl_a_a;
}
@@ -230,7 +230,7 @@ protected:
}
private:
- WRITE_LINE_MEMBER(pd7_w)
+ void pd7_w(int state)
{
if (bool(state) != bool(m_pd7))
{
@@ -366,7 +366,7 @@ protected:
}
private:
- WRITE_LINE_MEMBER(reset_trigger)
+ void reset_trigger(int state)
{
if (bool(state) != bool(m_reset_trigger))
{
diff --git a/src/devices/bus/amiga/zorro/a2052.cpp b/src/devices/bus/amiga/zorro/a2052.cpp
index 379a75270c5..66eb712f7ff 100644
--- a/src/devices/bus/amiga/zorro/a2052.cpp
+++ b/src/devices/bus/amiga/zorro/a2052.cpp
@@ -85,7 +85,7 @@ void a2052_device::autoconfig_base_address(offs_t address)
m_slot->cfgout_w(0);
}
-WRITE_LINE_MEMBER( a2052_device::cfgin_w )
+void a2052_device::cfgin_w(int state)
{
LOG("%s: configin_w (%d)\n", shortname(), state);
diff --git a/src/devices/bus/amiga/zorro/a2052.h b/src/devices/bus/amiga/zorro/a2052.h
index f64bf06196d..89cb17ee09b 100644
--- a/src/devices/bus/amiga/zorro/a2052.h
+++ b/src/devices/bus/amiga/zorro/a2052.h
@@ -36,7 +36,7 @@ protected:
virtual void device_start() override ATTR_COLD;
// device_zorro2_card_interface overrides
- virtual DECLARE_WRITE_LINE_MEMBER( cfgin_w ) override;
+ virtual void cfgin_w(int state) override;
// amiga_autoconfig overrides
virtual void autoconfig_base_address(offs_t address) override;
diff --git a/src/devices/bus/amiga/zorro/a2058.cpp b/src/devices/bus/amiga/zorro/a2058.cpp
index 26d5f393222..4077306ad6b 100644
--- a/src/devices/bus/amiga/zorro/a2058.cpp
+++ b/src/devices/bus/amiga/zorro/a2058.cpp
@@ -92,7 +92,7 @@ void a2058_device::autoconfig_base_address(offs_t address)
m_slot->cfgout_w(0);
}
-WRITE_LINE_MEMBER( a2058_device::cfgin_w )
+void a2058_device::cfgin_w(int state)
{
LOG("%s: configin_w (%d)\n", shortname(), state);
diff --git a/src/devices/bus/amiga/zorro/a2058.h b/src/devices/bus/amiga/zorro/a2058.h
index 9b361b403e4..1b9badf9382 100644
--- a/src/devices/bus/amiga/zorro/a2058.h
+++ b/src/devices/bus/amiga/zorro/a2058.h
@@ -36,7 +36,7 @@ protected:
virtual void device_start() override ATTR_COLD;
// device_zorro2_card_interface overrides
- virtual DECLARE_WRITE_LINE_MEMBER( cfgin_w ) override;
+ virtual void cfgin_w(int state) override;
// amiga_autoconfig overrides
virtual void autoconfig_base_address(offs_t address) override;
diff --git a/src/devices/bus/amiga/zorro/a2065.cpp b/src/devices/bus/amiga/zorro/a2065.cpp
index a76b289bb7f..0c283e19f16 100644
--- a/src/devices/bus/amiga/zorro/a2065.cpp
+++ b/src/devices/bus/amiga/zorro/a2065.cpp
@@ -105,7 +105,7 @@ void a2065_device::autoconfig_base_address(offs_t address)
m_slot->cfgout_w(0);
}
-WRITE_LINE_MEMBER( a2065_device::cfgin_w )
+void a2065_device::cfgin_w(int state)
{
LOG("%s: configin_w (%d)\n", shortname(), state);
@@ -158,7 +158,7 @@ void a2065_device::lance_ram_w(offs_t offset, uint16_t data, uint16_t mem_mask)
COMBINE_DATA(&m_ram[offset]);
}
-WRITE_LINE_MEMBER( a2065_device::lance_irq_w )
+void a2065_device::lance_irq_w(int state)
{
// default is irq 2, can be changed via jumper
m_slot->int2_w(!state);
diff --git a/src/devices/bus/amiga/zorro/a2065.h b/src/devices/bus/amiga/zorro/a2065.h
index 43e66c29678..7730370255e 100644
--- a/src/devices/bus/amiga/zorro/a2065.h
+++ b/src/devices/bus/amiga/zorro/a2065.h
@@ -37,7 +37,7 @@ public:
uint16_t lance_ram_r(offs_t offset);
void lance_ram_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
- DECLARE_WRITE_LINE_MEMBER( lance_irq_w );
+ void lance_irq_w(int state);
protected:
// device-level overrides
@@ -45,7 +45,7 @@ protected:
virtual void device_start() override ATTR_COLD;
// device_zorro2_card_interface overrides
- virtual DECLARE_WRITE_LINE_MEMBER( cfgin_w ) override;
+ virtual void cfgin_w(int state) override;
// amiga_autoconfig overrides
virtual void autoconfig_base_address(offs_t address) override;
diff --git a/src/devices/bus/amiga/zorro/a2232.cpp b/src/devices/bus/amiga/zorro/a2232.cpp
index b9d6726bc7e..af33b31a99f 100644
--- a/src/devices/bus/amiga/zorro/a2232.cpp
+++ b/src/devices/bus/amiga/zorro/a2232.cpp
@@ -11,7 +11,6 @@
#include "emu.h"
#include "a2232.h"
-#define LOG_GENERAL (1U << 0)
#define LOG_DATA (1U << 1)
//#define VERBOSE (LOG_GENERAL | LOG_DATA)
#include "logmacro.h"
@@ -208,7 +207,7 @@ void a2232_device::autoconfig_base_address(offs_t address)
m_slot->cfgout_w(0);
}
-WRITE_LINE_MEMBER( a2232_device::cfgin_w )
+void a2232_device::cfgin_w(int state)
{
LOG("%s: configin_w (%d)\n", shortname(), state);
@@ -378,19 +377,19 @@ void a2232_device::cia_port_b_w(uint8_t data)
// RS232
//**************************************************************************
-WRITE_LINE_MEMBER( a2232_device::rs232_1_rxd_w )
+void a2232_device::rs232_1_rxd_w(int state)
{
m_acia[0]->write_rxd(state);
m_cia->sp_w(state);
}
-WRITE_LINE_MEMBER( a2232_device::rs232_1_dcd_w )
+void a2232_device::rs232_1_dcd_w(int state)
{
m_cia_port_a &= ~0x01;
m_cia_port_a |= state << 0;
}
-WRITE_LINE_MEMBER( a2232_device::rs232_1_cts_w )
+void a2232_device::rs232_1_cts_w(int state)
{
m_cia_port_b &= ~0x01;
m_cia_port_b |= state << 0;
@@ -398,73 +397,73 @@ WRITE_LINE_MEMBER( a2232_device::rs232_1_cts_w )
m_cia->cnt_w(state);
}
-WRITE_LINE_MEMBER( a2232_device::rs232_2_dcd_w )
+void a2232_device::rs232_2_dcd_w(int state)
{
m_cia_port_a &= ~0x02;
m_cia_port_a |= state << 1;
}
-WRITE_LINE_MEMBER( a2232_device::rs232_2_cts_w )
+void a2232_device::rs232_2_cts_w(int state)
{
m_cia_port_b &= ~0x02;
m_cia_port_b |= state << 1;
}
-WRITE_LINE_MEMBER( a2232_device::rs232_3_dcd_w )
+void a2232_device::rs232_3_dcd_w(int state)
{
m_cia_port_a &= ~0x04;
m_cia_port_a |= state << 2;
}
-WRITE_LINE_MEMBER( a2232_device::rs232_3_cts_w )
+void a2232_device::rs232_3_cts_w(int state)
{
m_cia_port_b &= ~0x04;
m_cia_port_b |= state << 2;
}
-WRITE_LINE_MEMBER( a2232_device::rs232_4_dcd_w )
+void a2232_device::rs232_4_dcd_w(int state)
{
m_cia_port_a &= ~0x08;
m_cia_port_a |= state << 3;
}
-WRITE_LINE_MEMBER( a2232_device::rs232_4_cts_w )
+void a2232_device::rs232_4_cts_w(int state)
{
m_cia_port_b &= ~0x08;
m_cia_port_b |= state << 3;
}
-WRITE_LINE_MEMBER( a2232_device::rs232_5_dcd_w )
+void a2232_device::rs232_5_dcd_w(int state)
{
m_cia_port_a &= ~0x10;
m_cia_port_a |= state << 4;
}
-WRITE_LINE_MEMBER( a2232_device::rs232_5_cts_w )
+void a2232_device::rs232_5_cts_w(int state)
{
m_cia_port_b &= ~0x10;
m_cia_port_b |= state << 4;
}
-WRITE_LINE_MEMBER( a2232_device::rs232_6_dcd_w )
+void a2232_device::rs232_6_dcd_w(int state)
{
m_cia_port_a &= ~0x20;
m_cia_port_a |= state << 5;
}
-WRITE_LINE_MEMBER( a2232_device::rs232_6_cts_w )
+void a2232_device::rs232_6_cts_w(int state)
{
m_cia_port_b &= ~0x20;
m_cia_port_b |= state << 5;
}
-WRITE_LINE_MEMBER( a2232_device::rs232_7_dcd_w )
+void a2232_device::rs232_7_dcd_w(int state)
{
m_cia_port_a &= ~0x40;
m_cia_port_a |= state << 6;
}
-WRITE_LINE_MEMBER( a2232_device::rs232_7_cts_w )
+void a2232_device::rs232_7_cts_w(int state)
{
m_cia_port_b &= ~0x40;
m_cia_port_b |= state << 6;
diff --git a/src/devices/bus/amiga/zorro/a2232.h b/src/devices/bus/amiga/zorro/a2232.h
index e8a5da3258c..95d545aa203 100644
--- a/src/devices/bus/amiga/zorro/a2232.h
+++ b/src/devices/bus/amiga/zorro/a2232.h
@@ -58,7 +58,7 @@ protected:
virtual void device_reset_after_children() override;
// device_zorro2_card_interface overrides
- virtual DECLARE_WRITE_LINE_MEMBER( cfgin_w ) override;
+ virtual void cfgin_w(int state) override;
// amiga_autoconfig overrides
virtual void autoconfig_base_address(offs_t address) override;
@@ -80,21 +80,21 @@ private:
void cia_w(offs_t offset, uint8_t data);
// rs232
- DECLARE_WRITE_LINE_MEMBER( rs232_1_rxd_w );
- DECLARE_WRITE_LINE_MEMBER( rs232_1_dcd_w );
- DECLARE_WRITE_LINE_MEMBER( rs232_1_cts_w );
- DECLARE_WRITE_LINE_MEMBER( rs232_2_dcd_w );
- DECLARE_WRITE_LINE_MEMBER( rs232_2_cts_w );
- DECLARE_WRITE_LINE_MEMBER( rs232_3_dcd_w );
- DECLARE_WRITE_LINE_MEMBER( rs232_3_cts_w );
- DECLARE_WRITE_LINE_MEMBER( rs232_4_dcd_w );
- DECLARE_WRITE_LINE_MEMBER( rs232_4_cts_w );
- DECLARE_WRITE_LINE_MEMBER( rs232_5_dcd_w );
- DECLARE_WRITE_LINE_MEMBER( rs232_5_cts_w );
- DECLARE_WRITE_LINE_MEMBER( rs232_6_dcd_w );
- DECLARE_WRITE_LINE_MEMBER( rs232_6_cts_w );
- DECLARE_WRITE_LINE_MEMBER( rs232_7_dcd_w );
- DECLARE_WRITE_LINE_MEMBER( rs232_7_cts_w );
+ void rs232_1_rxd_w(int state);
+ void rs232_1_dcd_w(int state);
+ void rs232_1_cts_w(int state);
+ void rs232_2_dcd_w(int state);
+ void rs232_2_cts_w(int state);
+ void rs232_3_dcd_w(int state);
+ void rs232_3_cts_w(int state);
+ void rs232_4_dcd_w(int state);
+ void rs232_4_cts_w(int state);
+ void rs232_5_dcd_w(int state);
+ void rs232_5_cts_w(int state);
+ void rs232_6_dcd_w(int state);
+ void rs232_6_cts_w(int state);
+ void rs232_7_dcd_w(int state);
+ void rs232_7_cts_w(int state);
required_device<m65ce02_device> m_iocpu;
required_device<input_merger_device> m_ioirq;
diff --git a/src/devices/bus/amiga/zorro/a590.cpp b/src/devices/bus/amiga/zorro/a590.cpp
index 3fe72c69a42..d2d43bf24de 100644
--- a/src/devices/bus/amiga/zorro/a590.cpp
+++ b/src/devices/bus/amiga/zorro/a590.cpp
@@ -318,7 +318,7 @@ void a2091_device::device_reset()
// IMPLEMENTATION
//**************************************************************************
-WRITE_LINE_MEMBER( a590_device::cfgin_w )
+void a590_device::cfgin_w(int state)
{
// make sure we configure ourselves first
m_int6 = m_jp4->read() & 0x01;
@@ -328,7 +328,7 @@ WRITE_LINE_MEMBER( a590_device::cfgin_w )
m_dmac->configin_w(state);
}
-WRITE_LINE_MEMBER( a2091_device::cfgin_w )
+void a2091_device::cfgin_w(int state)
{
// make sure we configure ourselves first
m_int6 = m_jp3->read() & 0x01;
@@ -358,7 +358,7 @@ void dmac_hdc_device_base::dmac_scsi_w(offs_t offset, uint8_t data)
}
}
-WRITE_LINE_MEMBER( dmac_hdc_device_base::dmac_int_w )
+void dmac_hdc_device_base::dmac_int_w(int state)
{
if (m_int6)
int6_w(state);
@@ -366,13 +366,13 @@ WRITE_LINE_MEMBER( dmac_hdc_device_base::dmac_int_w )
int2_w(state);
}
-WRITE_LINE_MEMBER( dmac_hdc_device_base::scsi_irq_w )
+void dmac_hdc_device_base::scsi_irq_w(int state)
{
// should be or'ed with xt-ide IRQ
m_dmac->intx_w(state);
}
-WRITE_LINE_MEMBER( dmac_hdc_device_base::scsi_drq_w )
+void dmac_hdc_device_base::scsi_drq_w(int state)
{
m_dmac->xdreq_w(state);
}
diff --git a/src/devices/bus/amiga/zorro/a590.h b/src/devices/bus/amiga/zorro/a590.h
index ab2a71bb0ce..711ac95ece5 100644
--- a/src/devices/bus/amiga/zorro/a590.h
+++ b/src/devices/bus/amiga/zorro/a590.h
@@ -60,10 +60,10 @@ protected:
private:
uint8_t dmac_scsi_r(offs_t offset);
void dmac_scsi_w(offs_t offset, uint8_t data);
- DECLARE_WRITE_LINE_MEMBER( dmac_int_w );
- DECLARE_WRITE_LINE_MEMBER( dmac_cfgout_w ) { cfgout_w(state); }
- DECLARE_WRITE_LINE_MEMBER( scsi_irq_w );
- DECLARE_WRITE_LINE_MEMBER( scsi_drq_w );
+ void dmac_int_w(int state);
+ void dmac_cfgout_w(int state) { cfgout_w(state); }
+ void scsi_irq_w(int state);
+ void scsi_drq_w(int state);
static void scsi_devices(device_slot_interface &device) ATTR_COLD;
void wd33c93(device_t *device);
@@ -91,7 +91,7 @@ protected:
virtual void int6_w(int state) override { m_slot->int6_w(state); }
// input from slot
- virtual DECLARE_WRITE_LINE_MEMBER( cfgin_w ) override;
+ virtual void cfgin_w(int state) override;
private:
required_ioport m_dips;
@@ -122,7 +122,7 @@ protected:
virtual void int6_w(int state) override { m_slot->int6_w(state); }
// input from slot
- virtual DECLARE_WRITE_LINE_MEMBER( cfgin_w ) override;
+ virtual void cfgin_w(int state) override;
private:
required_ioport m_jp1;
diff --git a/src/devices/bus/amiga/zorro/buddha.cpp b/src/devices/bus/amiga/zorro/buddha.cpp
index 16a27d07ff2..c515096a28a 100644
--- a/src/devices/bus/amiga/zorro/buddha.cpp
+++ b/src/devices/bus/amiga/zorro/buddha.cpp
@@ -155,7 +155,7 @@ void buddha_device::autoconfig_base_address(offs_t address)
m_slot->cfgout_w(0);
}
-WRITE_LINE_MEMBER( buddha_device::cfgin_w )
+void buddha_device::cfgin_w(int state)
{
LOG("configin_w (%d)\n", state);
@@ -196,7 +196,7 @@ void buddha_device::speed_w(offs_t offset, uint16_t data, uint16_t mem_mask)
LOG("speed_w %04x [mask = %04x]\n", data, mem_mask);
}
-WRITE_LINE_MEMBER( buddha_device::ide_0_interrupt_w )
+void buddha_device::ide_0_interrupt_w(int state)
{
LOG("ide_0_interrupt_w (%d)\n", state);
@@ -206,7 +206,7 @@ WRITE_LINE_MEMBER( buddha_device::ide_0_interrupt_w )
m_slot->int2_w(state);
}
-WRITE_LINE_MEMBER( buddha_device::ide_1_interrupt_w )
+void buddha_device::ide_1_interrupt_w(int state)
{
LOG("ide_1_interrupt_w (%d)\n", state);
diff --git a/src/devices/bus/amiga/zorro/buddha.h b/src/devices/bus/amiga/zorro/buddha.h
index 80fce2682c5..1ecf8ccd99a 100644
--- a/src/devices/bus/amiga/zorro/buddha.h
+++ b/src/devices/bus/amiga/zorro/buddha.h
@@ -41,7 +41,7 @@ protected:
virtual void device_reset() override;
// device_zorro2_card_interface overrides
- virtual DECLARE_WRITE_LINE_MEMBER( cfgin_w ) override;
+ virtual void cfgin_w(int state) override;
// amiga_autoconfig overrides
virtual void autoconfig_base_address(offs_t address) override;
@@ -65,8 +65,8 @@ private:
uint16_t ide_0_interrupt_r(offs_t offset, uint16_t mem_mask = ~0);
uint16_t ide_1_interrupt_r(offs_t offset, uint16_t mem_mask = ~0);
void ide_interrupt_enable_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
- DECLARE_WRITE_LINE_MEMBER( ide_0_interrupt_w );
- DECLARE_WRITE_LINE_MEMBER( ide_1_interrupt_w );
+ void ide_0_interrupt_w(int state);
+ void ide_1_interrupt_w(int state);
void mmio_map(address_map &map) ATTR_COLD;
diff --git a/src/devices/bus/amiga/zorro/zorro.cpp b/src/devices/bus/amiga/zorro/zorro.cpp
index 6bd8b280c86..e83f939760e 100644
--- a/src/devices/bus/amiga/zorro/zorro.cpp
+++ b/src/devices/bus/amiga/zorro/zorro.cpp
@@ -74,20 +74,6 @@ zorro_bus_device_base::zorro_bus_device_base(const machine_config &mconfig, devi
}
//-------------------------------------------------
-// device_resolve_objects - resolve objects that
-// may be needed for other devices to set
-// initial conditions at start time
-//-------------------------------------------------
-
-void zorro_bus_device_base::device_resolve_objects()
-{
- // resolve callbacks
- m_ovr_handler.resolve_safe();
- m_int2_handler.resolve_safe();
- m_int6_handler.resolve_safe();
-}
-
-//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
@@ -96,9 +82,9 @@ void zorro_bus_device_base::device_start()
}
// from slot device
-WRITE_LINE_MEMBER( zorro_bus_device_base::ovr_w ) { m_ovr_handler(state); }
-WRITE_LINE_MEMBER( zorro_bus_device_base::int2_w ) { m_int2_handler(state); }
-WRITE_LINE_MEMBER( zorro_bus_device_base::int6_w ) { m_int6_handler(state); }
+void zorro_bus_device_base::ovr_w(int state) { m_ovr_handler(state); }
+void zorro_bus_device_base::int2_w(int state) { m_int2_handler(state); }
+void zorro_bus_device_base::int6_w(int state) { m_int6_handler(state); }
//**************************************************************************
@@ -124,21 +110,6 @@ exp_slot_device::exp_slot_device(const machine_config &mconfig, device_type type
}
//-------------------------------------------------
-// device_resolve_objects - resolve objects that
-// may be needed for other devices to set
-// initial conditions at start time
-//-------------------------------------------------
-
-void exp_slot_device::device_resolve_objects()
-{
- // call base device
- zorro_bus_device_base::device_resolve_objects();
-
- // resolve callbacks
- m_ipl_handler.resolve_safe();
-}
-
-//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
@@ -196,7 +167,7 @@ zorro2_bus_device::zorro2_bus_device(const machine_config &mconfig, device_type
m_eint4_handler(*this),
m_eint5_handler(*this),
m_eint7_handler(*this),
- m_autoconfig_device(nullptr)
+ m_autoconfig_device(0)
{
}
@@ -206,25 +177,17 @@ zorro2_bus_device::zorro2_bus_device(const machine_config &mconfig, device_type
zorro2_bus_device::~zorro2_bus_device()
{
- m_dev.detach_all();
}
//-------------------------------------------------
-// device_resolve_objects - resolve objects that
-// may be needed for other devices to set
-// initial conditions at start time
+// device_start - device-specific start
//-------------------------------------------------
-void zorro2_bus_device::device_resolve_objects()
+void zorro2_bus_device::device_start()
{
- // call base device
- zorro_bus_device_base::device_resolve_objects();
+ zorro_bus_device_base::device_start();
- // resolve callbacks
- m_eint1_handler.resolve_safe();
- m_eint4_handler.resolve_safe();
- m_eint5_handler.resolve_safe();
- m_eint7_handler.resolve_safe();
+ save_item(NAME(m_autoconfig_device));
}
//-------------------------------------------------
@@ -237,11 +200,11 @@ void zorro2_bus_device::device_reset()
zorro_bus_device_base::device_reset();
// initiate autoconfig
- m_autoconfig_device = m_dev.first();
+ m_autoconfig_device = 0;
// if we have a device, start the autoconfig chain
- if (m_autoconfig_device)
- m_autoconfig_device->cfgin_w(0);
+ if (m_dev.size() > m_autoconfig_device)
+ m_dev[m_autoconfig_device].get().cfgin_w(0);
}
//-------------------------------------------------
@@ -258,34 +221,27 @@ void zorro2_bus_device::add_card(device_zorro_card_interface &card)
tag(), card.device().tag(), card.device().name());
}
card.set_zorro_bus(*this);
- m_dev.append(*zorro2_card);
+ m_dev.emplace_back(*zorro2_card);
}
// from slot device
-WRITE_LINE_MEMBER( zorro2_bus_device::eint1_w ) { m_eint1_handler(state); }
-WRITE_LINE_MEMBER( zorro2_bus_device::eint4_w ) { m_eint4_handler(state); }
-WRITE_LINE_MEMBER( zorro2_bus_device::eint5_w ) { m_eint5_handler(state); }
-WRITE_LINE_MEMBER( zorro2_bus_device::eint7_w ) { m_eint7_handler(state); }
+void zorro2_bus_device::eint1_w(int state) { m_eint1_handler(state); }
+void zorro2_bus_device::eint4_w(int state) { m_eint4_handler(state); }
+void zorro2_bus_device::eint5_w(int state) { m_eint5_handler(state); }
+void zorro2_bus_device::eint7_w(int state) { m_eint7_handler(state); }
-WRITE_LINE_MEMBER( zorro2_bus_device::cfgout_w )
+void zorro2_bus_device::cfgout_w(int state)
{
- m_autoconfig_device = m_autoconfig_device->next();
-
// if there is still a device in the chain, tell it to configure itself
- if (m_autoconfig_device)
- m_autoconfig_device->cfgin_w(0);
+ if (m_dev.size() > ++m_autoconfig_device)
+ m_dev[m_autoconfig_device].get().cfgin_w(0);
}
// from host
void zorro2_bus_device::fc_w(int code)
{
- device_zorro2_card_interface *entry = m_dev.first();
-
- while (entry)
- {
- entry->fc_w(code);
- entry = entry->next();
- }
+ for (device_zorro2_card_interface &entry : m_dev)
+ entry.fc_w(code);
}
@@ -321,7 +277,7 @@ void device_zorro_card_interface::fc_w(int code)
{
}
-WRITE_LINE_MEMBER( device_zorro_card_interface::cfgin_w )
+void device_zorro_card_interface::cfgin_w(int state)
{
}
@@ -375,7 +331,6 @@ void device_exp_card_interface::interface_pre_start()
device_zorro2_card_interface::device_zorro2_card_interface(const machine_config &mconfig, device_t &device) :
device_zorro_card_interface(mconfig, device),
- m_next(nullptr),
m_slot(nullptr)
{
}
diff --git a/src/devices/bus/amiga/zorro/zorro.h b/src/devices/bus/amiga/zorro/zorro.h
index 632a5de9f6a..667ac6cbbc9 100644
--- a/src/devices/bus/amiga/zorro/zorro.h
+++ b/src/devices/bus/amiga/zorro/zorro.h
@@ -143,6 +143,10 @@
#pragma once
+#include <functional>
+#include <utility>
+#include <vector>
+
//**************************************************************************
// TYPE DEFINITIONS
@@ -178,7 +182,7 @@ public:
protected:
zorro_slot_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
- // device-level overrides
+ // device_t implementation
virtual void device_start() override ATTR_COLD;
// configuration
@@ -203,11 +207,11 @@ public:
virtual void add_card(device_zorro_card_interface &card) ATTR_COLD = 0;
// interface (from slot device)
- virtual DECLARE_WRITE_LINE_MEMBER( cfgout_w ) { }
+ virtual void cfgout_w(int state) { }
- DECLARE_WRITE_LINE_MEMBER( int2_w );
- DECLARE_WRITE_LINE_MEMBER( int6_w );
- DECLARE_WRITE_LINE_MEMBER( ovr_w );
+ void int2_w(int state);
+ void int6_w(int state);
+ void ovr_w(int state);
// interface (from host)
virtual void fc_w(int code) = 0;
@@ -219,8 +223,7 @@ protected:
// construction/destruction
zorro_bus_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
- // device-level overrides
- virtual void device_resolve_objects() override ATTR_COLD;
+ // device_t implementation
virtual void device_start() override ATTR_COLD;
private:
@@ -253,8 +256,7 @@ public:
protected:
exp_slot_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
- // device-level overrides
- virtual void device_resolve_objects() override ATTR_COLD;
+ // device_t implementation
virtual void device_reset() override;
private:
@@ -284,12 +286,12 @@ public:
virtual void add_card(device_zorro_card_interface &card) override ATTR_COLD;
// interface (from slot device)
- virtual DECLARE_WRITE_LINE_MEMBER( cfgout_w ) override;
+ virtual void cfgout_w(int state) override;
- DECLARE_WRITE_LINE_MEMBER( eint1_w );
- DECLARE_WRITE_LINE_MEMBER( eint4_w );
- DECLARE_WRITE_LINE_MEMBER( eint5_w );
- DECLARE_WRITE_LINE_MEMBER( eint7_w );
+ void eint1_w(int state);
+ void eint4_w(int state);
+ void eint5_w(int state);
+ void eint7_w(int state);
// interface (from host)
virtual void fc_w(int code) override;
@@ -297,20 +299,22 @@ public:
protected:
zorro2_bus_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
- // device-level overrides
- virtual void device_resolve_objects() override ATTR_COLD;
+ // device_t implementation
+ virtual void device_start() override;
virtual void device_reset() override;
private:
+ using card_vector = std::vector<std::reference_wrapper<device_zorro2_card_interface> >;
+
devcb_write_line m_eint1_handler;
devcb_write_line m_eint4_handler;
devcb_write_line m_eint5_handler;
devcb_write_line m_eint7_handler;
- simple_list<device_zorro2_card_interface> m_dev;
+ card_vector m_dev;
// the device which is currently configuring
- device_zorro2_card_interface *m_autoconfig_device;
+ uint8_t m_autoconfig_device;
};
// device type definition
@@ -332,7 +336,7 @@ public:
// interface (from host)
virtual void fc_w(int code);
- virtual DECLARE_WRITE_LINE_MEMBER( cfgin_w );
+ virtual void cfgin_w(int state);
protected:
device_zorro_card_interface(const machine_config &mconfig, device_t &device);
@@ -364,9 +368,6 @@ public:
// construction/destruction
virtual ~device_zorro2_card_interface();
- device_zorro2_card_interface *next() const { return m_next; }
- device_zorro2_card_interface *m_next;
-
protected:
device_zorro2_card_interface(const machine_config &mconfig, device_t &device);
diff --git a/src/devices/bus/apf/slot.cpp b/src/devices/bus/apf/slot.cpp
index 32efe21adf3..2c5c3edb7f7 100644
--- a/src/devices/bus/apf/slot.cpp
+++ b/src/devices/bus/apf/slot.cpp
@@ -44,11 +44,11 @@ device_apf_cart_interface::~device_apf_cart_interface()
// rom_alloc - alloc the space for the cart
//-------------------------------------------------
-void device_apf_cart_interface::rom_alloc(uint32_t size, const char *tag)
+void device_apf_cart_interface::rom_alloc(uint32_t size)
{
if (m_rom == nullptr)
{
- m_rom = device().machine().memory().region_alloc(std::string(tag).append(APFSLOT_ROM_REGION_TAG).c_str(), size, 1, ENDIANNESS_LITTLE)->base();
+ m_rom = device().machine().memory().region_alloc(device().subtag("^cart:rom"), size, 1, ENDIANNESS_LITTLE)->base();
m_rom_size = size;
}
}
@@ -144,19 +144,16 @@ static const char *apf_get_slot(int type)
call load
-------------------------------------------------*/
-image_init_result apf_cart_slot_device::call_load()
+std::pair<std::error_condition, std::string> apf_cart_slot_device::call_load()
{
if (m_cart)
{
- uint32_t size = !loaded_through_softlist() ? length() : get_software_region_length("rom");
+ uint32_t const size = !loaded_through_softlist() ? length() : get_software_region_length("rom");
if (size > 0x3800)
- {
- seterror(image_error::INVALIDIMAGE, "Image extends beyond the expected size for an APF cart");
- return image_init_result::FAIL;
- }
+ return std::make_pair(image_error::INVALIDLENGTH, "Image exceeds the expected size for an APF cartridge (14K)");
- m_cart->rom_alloc(size, tag());
+ m_cart->rom_alloc(size);
if (!loaded_through_softlist())
fread(m_cart->get_rom_base(), size);
@@ -186,11 +183,9 @@ image_init_result apf_cart_slot_device::call_load()
}
//printf("Type: %s\n", apf_get_slot(m_type));
-
- return image_init_result::PASS;
}
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
diff --git a/src/devices/bus/apf/slot.h b/src/devices/bus/apf/slot.h
index b85715ae0e1..635cf3b8a71 100644
--- a/src/devices/bus/apf/slot.h
+++ b/src/devices/bus/apf/slot.h
@@ -34,7 +34,7 @@ public:
virtual uint8_t read_ram(offs_t offset) { return 0xff; }
virtual void write_ram(offs_t offset, uint8_t data) {}
- void rom_alloc(uint32_t size, const char *tag);
+ void rom_alloc(uint32_t size);
void ram_alloc(uint32_t size);
uint8_t* get_rom_base() { return m_rom; }
uint8_t* get_ram_base() { return &m_ram[0]; }
@@ -72,15 +72,15 @@ public:
apf_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
virtual ~apf_cart_slot_device();
- // image-level overrides
- virtual image_init_result call_load() override;
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
virtual void call_unload() override {}
virtual bool is_reset_on_load() const noexcept override { return true; }
virtual const char *image_interface() const noexcept override { return "apfm1000_cart"; }
virtual const char *file_extensions() const noexcept override { return "bin"; }
- // slot interface overrides
+ // device_slot_interface implementation
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
int get_type() { return m_type; }
@@ -94,23 +94,15 @@ public:
void write_ram(offs_t offset, uint8_t data);
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
int m_type;
- device_apf_cart_interface* m_cart;
+ device_apf_cart_interface *m_cart;
};
-
// device type definition
DECLARE_DEVICE_TYPE(APF_CART_SLOT, apf_cart_slot_device)
-
-/***************************************************************************
- DEVICE CONFIGURATION MACROS
- ***************************************************************************/
-
-#define APFSLOT_ROM_REGION_TAG ":cart:rom"
-
#endif // MAME_BUS_APF_SLOT_H
diff --git a/src/devices/bus/apricot/expansion/expansion.cpp b/src/devices/bus/apricot/expansion/expansion.cpp
index 0949e1ae781..606e2b913fe 100644
--- a/src/devices/bus/apricot/expansion/expansion.cpp
+++ b/src/devices/bus/apricot/expansion/expansion.cpp
@@ -78,7 +78,6 @@ apricot_expansion_bus_device::apricot_expansion_bus_device(const machine_config
apricot_expansion_bus_device::~apricot_expansion_bus_device()
{
- m_dev.detach_all();
}
//-------------------------------------------------
@@ -87,13 +86,6 @@ apricot_expansion_bus_device::~apricot_expansion_bus_device()
void apricot_expansion_bus_device::device_start()
{
- // resolve callbacks
- m_dma1_handler.resolve_safe();
- m_dma2_handler.resolve_safe();
- m_ext1_handler.resolve_safe();
- m_ext2_handler.resolve_safe();
- m_int2_handler.resolve_safe();
- m_int3_handler.resolve_safe();
}
//-------------------------------------------------
@@ -103,16 +95,16 @@ void apricot_expansion_bus_device::device_start()
void apricot_expansion_bus_device::add_card(device_apricot_expansion_card_interface *card)
{
card->set_bus_device(this);
- m_dev.append(*card);
+ m_dev.emplace_back(*card);
}
// callbacks from slot device to the host
-WRITE_LINE_MEMBER( apricot_expansion_bus_device::dma1_w ) { m_dma1_handler(state); }
-WRITE_LINE_MEMBER( apricot_expansion_bus_device::dma2_w ) { m_dma2_handler(state); }
-WRITE_LINE_MEMBER( apricot_expansion_bus_device::ext1_w ) { m_ext1_handler(state); }
-WRITE_LINE_MEMBER( apricot_expansion_bus_device::ext2_w ) { m_ext2_handler(state); }
-WRITE_LINE_MEMBER( apricot_expansion_bus_device::int2_w ) { m_int2_handler(state); }
-WRITE_LINE_MEMBER( apricot_expansion_bus_device::int3_w ) { m_int3_handler(state); }
+void apricot_expansion_bus_device::dma1_w(int state) { m_dma1_handler(state); }
+void apricot_expansion_bus_device::dma2_w(int state) { m_dma2_handler(state); }
+void apricot_expansion_bus_device::ext1_w(int state) { m_ext1_handler(state); }
+void apricot_expansion_bus_device::ext2_w(int state) { m_ext2_handler(state); }
+void apricot_expansion_bus_device::int2_w(int state) { m_int2_handler(state); }
+void apricot_expansion_bus_device::int3_w(int state) { m_int3_handler(state); }
//-------------------------------------------------
// install_ram - attach ram to cpu/iop
@@ -137,8 +129,7 @@ void apricot_expansion_bus_device::install_ram(offs_t addrstart, offs_t addrend,
device_apricot_expansion_card_interface::device_apricot_expansion_card_interface(const machine_config &mconfig, device_t &device) :
device_interface(device, "apricotexp"),
- m_bus(nullptr),
- m_next(nullptr)
+ m_bus(nullptr)
{
}
diff --git a/src/devices/bus/apricot/expansion/expansion.h b/src/devices/bus/apricot/expansion/expansion.h
index f5a1994861d..24809d4a37f 100644
--- a/src/devices/bus/apricot/expansion/expansion.h
+++ b/src/devices/bus/apricot/expansion/expansion.h
@@ -46,6 +46,9 @@
#pragma once
+#include <functional>
+#include <vector>
+
//**************************************************************************
// TYPE DEFINITIONS
@@ -75,7 +78,7 @@ public:
protected:
apricot_expansion_slot_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
};
@@ -107,16 +110,17 @@ public:
void add_card(device_apricot_expansion_card_interface *card);
// from cards
- DECLARE_WRITE_LINE_MEMBER( dma1_w );
- DECLARE_WRITE_LINE_MEMBER( dma2_w );
- DECLARE_WRITE_LINE_MEMBER( ext1_w );
- DECLARE_WRITE_LINE_MEMBER( ext2_w );
- DECLARE_WRITE_LINE_MEMBER( int2_w );
- DECLARE_WRITE_LINE_MEMBER( int3_w );
+ void dma1_w(int state);
+ void dma2_w(int state);
+ void ext1_w(int state);
+ void ext2_w(int state);
+ void int2_w(int state);
+ void int3_w(int state);
void install_ram(offs_t addrstart, offs_t addrend, void *baseptr);
- template<typename T> void install_io_device(offs_t addrstart, offs_t addrend, T &device, void (T::*map)(class address_map &map), uint64_t unitmask = ~u64(0))
+ template <typename T>
+ void install_io_device(offs_t addrstart, offs_t addrend, T &device, void (T::*map)(class address_map &map), uint64_t unitmask = ~u64(0))
{
m_io->install_device(addrstart, addrend, device, map, unitmask);
@@ -125,11 +129,13 @@ public:
}
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
private:
- simple_list<device_apricot_expansion_card_interface> m_dev;
+ using card_vector = std::vector<std::reference_wrapper<device_apricot_expansion_card_interface> >;
+
+ card_vector m_dev;
// address spaces we have access to
required_address_space m_program;
@@ -153,22 +159,16 @@ DECLARE_DEVICE_TYPE(APRICOT_EXPANSION_BUS, apricot_expansion_bus_device)
class device_apricot_expansion_card_interface : public device_interface
{
- template <class ElementType> friend class simple_list;
-
public:
// construction/destruction
virtual ~device_apricot_expansion_card_interface();
void set_bus_device(apricot_expansion_bus_device *bus);
- device_apricot_expansion_card_interface *next() const { return m_next; }
-
protected:
device_apricot_expansion_card_interface(const machine_config &mconfig, device_t &device);
apricot_expansion_bus_device *m_bus;
-
- device_apricot_expansion_card_interface *m_next;
};
diff --git a/src/devices/bus/apricot/expansion/winchester.cpp b/src/devices/bus/apricot/expansion/winchester.cpp
index e48751851fb..baabcb6f439 100644
--- a/src/devices/bus/apricot/expansion/winchester.cpp
+++ b/src/devices/bus/apricot/expansion/winchester.cpp
@@ -13,9 +13,8 @@
#include "imagedev/harddriv.h"
#include "machine/74259.h"
-//#define LOG_GENERAL (1U << 0)
-#define LOG_REGS (1U << 1)
-#define LOG_DATA (1U << 2)
+#define LOG_REGS (1U << 1)
+#define LOG_DATA (1U << 2)
//#define VERBOSE (LOG_REGS)
//#define LOG_OUTPUT_STREAM std::cout
@@ -124,7 +123,7 @@ void apricot_winchester_device::device_reset()
// IMPLEMENTATION
//**************************************************************************
-WRITE_LINE_MEMBER( apricot_winchester_device::hdc_intrq_w )
+void apricot_winchester_device::hdc_intrq_w(int state)
{
LOGREGS("hdc_intrq_w: %d\n", state);
@@ -166,7 +165,7 @@ uint8_t apricot_winchester_device::int_r()
}
template<int N>
-WRITE_LINE_MEMBER( apricot_winchester_device::head_w )
+void apricot_winchester_device::head_w(int state)
{
m_head = (m_head & ~(1 << N)) | (state << N);
LOGREGS("Select head: %d\n", m_head);
@@ -174,7 +173,7 @@ WRITE_LINE_MEMBER( apricot_winchester_device::head_w )
}
template<int N>
-WRITE_LINE_MEMBER( apricot_winchester_device::drive_w )
+void apricot_winchester_device::drive_w(int state)
{
m_drive = (m_drive & ~(1 << N)) | (state << N);
LOGREGS("Select drive: %d\n", m_drive);
@@ -202,14 +201,14 @@ WRITE_LINE_MEMBER( apricot_winchester_device::drive_w )
m_hdc->drdy_w(drive != nullptr && drive->exists());
}
-WRITE_LINE_MEMBER( apricot_winchester_device::xferd_w )
+void apricot_winchester_device::xferd_w(int state)
{
LOGREGS("xferd_w: %02x\n", state);
m_hdc->brdy_w(state);
}
-WRITE_LINE_MEMBER( apricot_winchester_device::hbcr_w )
+void apricot_winchester_device::hbcr_w(int state)
{
LOGREGS("hbcr_w: %02x\n", state);
@@ -220,7 +219,7 @@ WRITE_LINE_MEMBER( apricot_winchester_device::hbcr_w )
m_hbcr = state;
}
-WRITE_LINE_MEMBER( apricot_winchester_device::clksel_w )
+void apricot_winchester_device::clksel_w(int state)
{
LOGREGS("clksel_w: %02x\n", state);
diff --git a/src/devices/bus/apricot/expansion/winchester.h b/src/devices/bus/apricot/expansion/winchester.h
index fc082776d8c..c5ed5ec9a59 100644
--- a/src/devices/bus/apricot/expansion/winchester.h
+++ b/src/devices/bus/apricot/expansion/winchester.h
@@ -34,15 +34,15 @@ protected:
virtual void device_reset() override;
private:
- DECLARE_WRITE_LINE_MEMBER(hdc_intrq_w);
+ void hdc_intrq_w(int state);
uint8_t hdc_data_r();
void hdc_data_w(uint8_t data);
uint8_t int_r();
- template<int N> DECLARE_WRITE_LINE_MEMBER(head_w);
- template<int N> DECLARE_WRITE_LINE_MEMBER(drive_w);
- DECLARE_WRITE_LINE_MEMBER(xferd_w);
- DECLARE_WRITE_LINE_MEMBER(hbcr_w);
- DECLARE_WRITE_LINE_MEMBER(clksel_w);
+ template<int N> void head_w(int state);
+ template<int N> void drive_w(int state);
+ void xferd_w(int state);
+ void hbcr_w(int state);
+ void clksel_w(int state);
uint8_t data_r();
void data_w(uint8_t data);
diff --git a/src/devices/bus/apricot/keyboard/keyboard.cpp b/src/devices/bus/apricot/keyboard/keyboard.cpp
index 4a87d6b0493..bb63a0e20c5 100644
--- a/src/devices/bus/apricot/keyboard/keyboard.cpp
+++ b/src/devices/bus/apricot/keyboard/keyboard.cpp
@@ -50,16 +50,13 @@ void apricot_keyboard_bus_device::device_start()
{
// get connected keyboard
m_kbd = get_card_device();
-
- // resolve callbacks
- m_in_handler.resolve_safe();
}
//-------------------------------------------------
// host to module interface
//-------------------------------------------------
-WRITE_LINE_MEMBER( apricot_keyboard_bus_device::out_w )
+void apricot_keyboard_bus_device::out_w(int state)
{
if (m_kbd)
m_kbd->out_w(state);
diff --git a/src/devices/bus/apricot/keyboard/keyboard.h b/src/devices/bus/apricot/keyboard/keyboard.h
index e19605b2459..7a04bbc2e99 100644
--- a/src/devices/bus/apricot/keyboard/keyboard.h
+++ b/src/devices/bus/apricot/keyboard/keyboard.h
@@ -62,10 +62,10 @@ public:
auto in_handler() { return m_in_handler.bind(); }
// called from keyboard
- DECLARE_WRITE_LINE_MEMBER( in_w ) { m_in_handler(state); }
+ void in_w(int state) { m_in_handler(state); }
// called from host
- DECLARE_WRITE_LINE_MEMBER( out_w );
+ void out_w(int state);
protected:
// device-level overrides
diff --git a/src/devices/bus/apricot/video/video.cpp b/src/devices/bus/apricot/video/video.cpp
index 13e91b04a58..8543ff4d571 100644
--- a/src/devices/bus/apricot/video/video.cpp
+++ b/src/devices/bus/apricot/video/video.cpp
@@ -49,9 +49,6 @@ void apricot_video_slot_device::device_start()
{
// get inserted module
m_card = get_card_device();
-
- // resolve callbacks
- m_apvid_handler.resolve_safe();
}
//-------------------------------------------------
diff --git a/src/devices/bus/apricot/video/video.h b/src/devices/bus/apricot/video/video.h
index 5b1a8b322f8..e1977107bd1 100644
--- a/src/devices/bus/apricot/video/video.h
+++ b/src/devices/bus/apricot/video/video.h
@@ -43,7 +43,7 @@ public:
auto apvid_handler() { return m_apvid_handler.bind(); }
// called from cart device
- DECLARE_WRITE_LINE_MEMBER( apvid_w ) { m_apvid_handler(state); }
+ void apvid_w(int state) { m_apvid_handler(state); }
// called from host
bool mem_r(offs_t offset, uint16_t &data, uint16_t mem_mask);
diff --git a/src/devices/bus/aquarius/slot.cpp b/src/devices/bus/aquarius/slot.cpp
index ab2966afe61..aa3863963c6 100644
--- a/src/devices/bus/aquarius/slot.cpp
+++ b/src/devices/bus/aquarius/slot.cpp
@@ -38,11 +38,11 @@ device_aquarius_cartridge_interface::device_aquarius_cartridge_interface(const m
// rom_alloc - alloc the space for the ROM
//-------------------------------------------------
-void device_aquarius_cartridge_interface::rom_alloc(uint32_t size, const char *tag)
+void device_aquarius_cartridge_interface::rom_alloc(uint32_t size)
{
if (m_rom == nullptr)
{
- m_rom = device().machine().memory().region_alloc(std::string(tag).append(AQUARIUS_CART_ROM_REGION_TAG).c_str(), size, 1, ENDIANNESS_LITTLE)->base();
+ m_rom = device().machine().memory().region_alloc(device().subtag("^cart:rom"), size, 1, ENDIANNESS_LITTLE)->base();
m_rom_size = size;
}
}
@@ -73,29 +73,22 @@ aquarius_cartridge_slot_device::aquarius_cartridge_slot_device(const machine_con
void aquarius_cartridge_slot_device::device_start()
{
m_cart = get_card_device();
-
- // resolve callbacks
- m_irq_handler.resolve_safe();
- m_nmi_handler.resolve_safe();
}
//-------------------------------------------------
// call_load
//-------------------------------------------------
-image_init_result aquarius_cartridge_slot_device::call_load()
+std::pair<std::error_condition, std::string> aquarius_cartridge_slot_device::call_load()
{
if (m_cart)
{
- uint32_t size = !loaded_through_softlist() ? length() : get_software_region_length("rom");
+ uint32_t const size = !loaded_through_softlist() ? length() : get_software_region_length("rom");
if (size % 0x1000)
- {
- seterror(image_error::INVALIDIMAGE, "Invalid ROM size");
- return image_init_result::FAIL;
- }
+ return std::make_pair(image_error::INVALIDLENGTH, "Invalid ROM size (must be a multiple of 4K)");
- m_cart->rom_alloc(size, tag());
+ m_cart->rom_alloc(size);
if (!loaded_through_softlist())
fread(m_cart->get_rom_base(), size);
@@ -103,7 +96,7 @@ image_init_result aquarius_cartridge_slot_device::call_load()
memcpy(m_cart->get_rom_base(), get_software_region("rom"), size);
}
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
//-------------------------------------------------
@@ -125,9 +118,8 @@ std::string aquarius_cartridge_slot_device::get_default_card_software(get_defaul
{
uint8_t header[16];
- size_t actual;
hook.image_file()->seek(len - 0x2000, SEEK_SET); // FIXME: check error return
- hook.image_file()->read(&header[0], 16, actual); // FIXME: check error return or read returning short
+ read(*hook.image_file(), &header[0], 16); // FIXME: check error return or read returning short
// detect SuperCart header
if (!memcmp(&header[0], SC08_HEADER, 16) || !memcmp(&header[0], SC16_HEADER, 16))
diff --git a/src/devices/bus/aquarius/slot.h b/src/devices/bus/aquarius/slot.h
index f165c146708..59a446edb65 100644
--- a/src/devices/bus/aquarius/slot.h
+++ b/src/devices/bus/aquarius/slot.h
@@ -14,8 +14,6 @@
#include "imagedev/cartrom.h"
-#define AQUARIUS_CART_ROM_REGION_TAG ":cart:rom"
-
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
@@ -46,14 +44,14 @@ public:
auto irq_handler() { return m_irq_handler.bind(); }
auto nmi_handler() { return m_nmi_handler.bind(); }
- // image-level overrides
- virtual image_init_result call_load() override;
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
virtual bool is_reset_on_load() const noexcept override { return true; }
virtual const char *image_interface() const noexcept override { return "aquarius_cart"; }
virtual const char *file_extensions() const noexcept override { return "rom,bin"; }
- // slot interface overrides
+ // device_slot_interface implementation
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
// reading and writing
@@ -64,11 +62,11 @@ public:
uint8_t iorq_r(offs_t offset);
void iorq_w(offs_t offset, uint8_t data);
- DECLARE_WRITE_LINE_MEMBER( irq_w ) { m_irq_handler(state); }
- DECLARE_WRITE_LINE_MEMBER( nmi_w ) { m_nmi_handler(state); }
+ void irq_w(int state) { m_irq_handler(state); }
+ void nmi_w(int state) { m_nmi_handler(state); }
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
device_aquarius_cartridge_interface *m_cart;
@@ -92,7 +90,7 @@ public:
virtual uint8_t iorq_r(offs_t offset) { return 0xff; }
virtual void iorq_w(offs_t offset, uint8_t data) { }
- void rom_alloc(uint32_t size, const char *tag);
+ void rom_alloc(uint32_t size);
uint8_t* get_rom_base() { return m_rom; }
uint32_t get_rom_size() { return m_rom_size; }
diff --git a/src/devices/bus/arcadia/slot.cpp b/src/devices/bus/arcadia/slot.cpp
index 7fc145ccc64..5390ca91bf4 100644
--- a/src/devices/bus/arcadia/slot.cpp
+++ b/src/devices/bus/arcadia/slot.cpp
@@ -44,11 +44,11 @@ device_arcadia_cart_interface::~device_arcadia_cart_interface()
// rom_alloc - alloc the space for the cart
//-------------------------------------------------
-void device_arcadia_cart_interface::rom_alloc(uint32_t size, const char *tag)
+void device_arcadia_cart_interface::rom_alloc(uint32_t size)
{
if (m_rom == nullptr)
{
- m_rom = device().machine().memory().region_alloc(std::string(tag).append(EA2001SLOT_ROM_REGION_TAG).c_str(), size, 1, ENDIANNESS_LITTLE)->base();
+ m_rom = device().machine().memory().region_alloc(device().subtag("^cart:rom"), size, 1, ENDIANNESS_LITTLE)->base();
m_rom_size = size;
}
}
@@ -133,13 +133,13 @@ static const char *arcadia_get_slot(int type)
call load
-------------------------------------------------*/
-image_init_result arcadia_cart_slot_device::call_load()
+std::pair<std::error_condition, std::string> arcadia_cart_slot_device::call_load()
{
if (m_cart)
{
- uint32_t len = !loaded_through_softlist() ? length() : get_software_region_length("rom");
+ uint32_t const len = !loaded_through_softlist() ? length() : get_software_region_length("rom");
- m_cart->rom_alloc(len, tag());
+ m_cart->rom_alloc(len);
if (!loaded_through_softlist())
fread(m_cart->get_rom_base(), len);
@@ -193,11 +193,9 @@ image_init_result arcadia_cart_slot_device::call_load()
}
//printf("Type: %s\n", arcadia_get_slot(m_type));
-
- return image_init_result::PASS;
}
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
diff --git a/src/devices/bus/arcadia/slot.h b/src/devices/bus/arcadia/slot.h
index f0f8eefb902..5aff49656fe 100644
--- a/src/devices/bus/arcadia/slot.h
+++ b/src/devices/bus/arcadia/slot.h
@@ -5,7 +5,6 @@
#include "imagedev/cartrom.h"
-#define EA2001SLOT_ROM_REGION_TAG ":cart:rom"
/***************************************************************************
TYPE DEFINITIONS
@@ -31,7 +30,7 @@ public:
virtual uint8_t read_rom(offs_t offset) { return 0xff; }
virtual uint8_t extra_rom(offs_t offset) { return 0xff; }
- void rom_alloc(uint32_t size, const char *tag);
+ void rom_alloc(uint32_t size);
uint8_t* get_rom_base() { return m_rom; }
uint32_t get_rom_size() { return m_rom_size; }
@@ -62,15 +61,15 @@ public:
arcadia_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual ~arcadia_cart_slot_device();
- // image-level overrides
- virtual image_init_result call_load() override;
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
virtual void call_unload() override {}
virtual bool is_reset_on_load() const noexcept override { return true; }
virtual const char *image_interface() const noexcept override { return "arcadia_cart"; }
virtual const char *file_extensions() const noexcept override { return "bin"; }
- // slot interface overrides
+ // device_slot_interface implementation
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
int get_type() { return m_type; }
@@ -80,11 +79,11 @@ public:
uint8_t extra_rom(offs_t offset);
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
int m_type;
- device_arcadia_cart_interface* m_cart;
+ device_arcadia_cart_interface *m_cart;
};
DECLARE_DEVICE_TYPE(EA2001_CART_SLOT, arcadia_cart_slot_device)
diff --git a/src/devices/bus/archimedes/econet/slot.cpp b/src/devices/bus/archimedes/econet/slot.cpp
index c15e13698c3..c6417eeb268 100644
--- a/src/devices/bus/archimedes/econet/slot.cpp
+++ b/src/devices/bus/archimedes/econet/slot.cpp
@@ -57,9 +57,6 @@ archimedes_econet_slot_device::archimedes_econet_slot_device(const machine_confi
void archimedes_econet_slot_device::device_start()
{
m_device = get_card_device();
-
- // resolve callbacks
- m_efiq_handler.resolve_safe();
}
diff --git a/src/devices/bus/archimedes/econet/slot.h b/src/devices/bus/archimedes/econet/slot.h
index 4d963fd608e..5c45fcc58ee 100644
--- a/src/devices/bus/archimedes/econet/slot.h
+++ b/src/devices/bus/archimedes/econet/slot.h
@@ -65,7 +65,7 @@ public:
virtual u8 read(offs_t offset);
virtual void write(offs_t offset, u8 data);
- DECLARE_WRITE_LINE_MEMBER( efiq_w ) { m_efiq_handler(state); }
+ void efiq_w(int state) { m_efiq_handler(state); }
protected:
// device-level overrides
diff --git a/src/devices/bus/archimedes/podule/ether1.cpp b/src/devices/bus/archimedes/podule/ether1.cpp
index e4e23704360..1de47a69558 100644
--- a/src/devices/bus/archimedes/podule/ether1.cpp
+++ b/src/devices/bus/archimedes/podule/ether1.cpp
@@ -12,19 +12,19 @@
#include "ether1.h"
#include "machine/i82586.h"
+#include "multibyte.h"
+
namespace {
-class arc_ether1_aka25_device :
- public device_t,
- public device_archimedes_podule_interface
+class arc_ether1_aka25_device : public device_t, public device_archimedes_podule_interface
{
public:
// construction/destruction
arc_ether1_aka25_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
protected:
- // device-level overrides
+ // device_t overrides
virtual void device_start() override;
virtual void device_reset() override;
@@ -52,10 +52,10 @@ private:
void arc_ether1_aka25_device::ioc_map(address_map &map)
{
- map(0x0000, 0x003f).lr8(NAME([this](offs_t offset) { return m_podule_rom->base()[offset | ((m_rom_page << 4) & 0x1f)]; })).umask32(0x000000ff);
+ map(0x0000, 0x003f).mirror(0x1fc0).lr8(NAME([this](offs_t offset) { return m_podule_rom->base()[offset | ((m_rom_page << 4) & 0x1f)]; })).umask32(0x000000ff);
map(0x0000, 0x0000).lw8(NAME([this](u8 data) { m_ram_page = data & 0x0f; }));
map(0x0004, 0x0004).w(FUNC(arc_ether1_aka25_device::control_w));
- map(0x2000, 0x3fff).lrw8(NAME([this](offs_t offset) { return m_ram[offset | (m_ram_page << 11)]; }), NAME([this](offs_t offset, u16 data) { m_ram[offset | (m_ram_page << 11)] = data; })).umask32(0x0000ffff);
+ map(0x2000, 0x3fff).lrw16(NAME([this](offs_t offset) { return m_ram[offset | (m_ram_page << 11)]; }), NAME([this](offs_t offset, u16 data) { m_ram[offset | (m_ram_page << 11)] = data; })).umask32(0x0000ffff);
}
@@ -160,7 +160,7 @@ void arc_ether1_aka25_device::checksum()
}
// get CRC from PROM
- u32 checksum = (m_podule_rom->base()[31] << 24) | (m_podule_rom->base()[30] << 16) | (m_podule_rom->base()[29] << 8) | (m_podule_rom->base()[28] << 0);
+ u32 checksum = get_u32le(&m_podule_rom->base()[28]);
// test to see if the same
logerror("checksum: %08x %s\n", chk, checksum == chk ? "Pass" : "Fail");
diff --git a/src/devices/bus/archimedes/podule/ether2.cpp b/src/devices/bus/archimedes/podule/ether2.cpp
new file mode 100644
index 00000000000..b702b2685db
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/ether2.cpp
@@ -0,0 +1,134 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Acorn AEH50 Ethernet II
+
+ http://chrisacorns.computinghistory.org.uk/32bit_UpgradesA2G/Acorn_AEH50_Ethernet.html
+
+ TODO:
+ - everything, this is skeleton with ROM.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "ether2.h"
+#include "machine/dp8390.h"
+
+
+namespace {
+
+class arc_ether2_aeh50_device :
+ public device_t,
+ public device_archimedes_podule_interface
+{
+public:
+ // construction/destruction
+ arc_ether2_aeh50_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ static constexpr feature_type unemulated_features() { return feature::COMMS; }
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+ // device_archimedes_podule_interface overrides
+ virtual void ioc_map(address_map &map) override;
+ virtual void memc_map(address_map &map) override;
+
+private:
+ required_memory_region m_podule_rom;
+ required_device <dp8390_device> m_dp8390;
+
+ u8 m_rom_page;
+};
+
+
+void arc_ether2_aeh50_device::ioc_map(address_map &map)
+{
+ map(0x0000, 0x1fff).lr8(NAME([this](offs_t offset) { return m_podule_rom->base()[offset | ((m_rom_page << 11) & 0x3800)]; })).umask32(0x000000ff);
+ map(0x3000, 0x3000).lw8(NAME([this](u8 data) { m_rom_page = data; }));
+}
+
+void arc_ether2_aeh50_device::memc_map(address_map &map)
+{
+}
+
+
+//-------------------------------------------------
+// ROM( ether2_aeh50 )
+//-------------------------------------------------
+
+ROM_START( ether2_aeh50 )
+ ROM_REGION(0x4000, "podule_rom", 0)
+ ROM_LOAD("0273,270.01_enet_id.rom", 0x0000, 0x4000, CRC(87d4fbc6) SHA1(417000f1fa8f61f8092f8f74a0359ffb3ce72768))
+ROM_END
+
+const tiny_rom_entry *arc_ether2_aeh50_device::device_rom_region() const
+{
+ return ROM_NAME( ether2_aeh50 );
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void arc_ether2_aeh50_device::device_add_mconfig(machine_config &config)
+{
+ DP8390D(config, m_dp8390, 20_MHz_XTAL);
+ m_dp8390->irq_callback().set([this](int state) { set_pirq(state); });
+ //m_dp8390->mem_read_callback().set(FUNC(arc_ether2_aeh50_device::mem_read));
+ //m_dp8390->mem_write_callback().set(FUNC(arc_ether2_aeh50_device::mem_write));
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// arc_ether2_aeh50_device - constructor
+//-------------------------------------------------
+
+arc_ether2_aeh50_device::arc_ether2_aeh50_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, ARC_ETHER2_AEH50, tag, owner, clock)
+ , device_archimedes_podule_interface(mconfig, *this)
+ , m_podule_rom(*this, "podule_rom")
+ , m_dp8390(*this, "dp8390")
+ , m_rom_page(0)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void arc_ether2_aeh50_device::device_start()
+{
+ save_item(NAME(m_rom_page));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void arc_ether2_aeh50_device::device_reset()
+{
+ m_rom_page = 0x00;
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(ARC_ETHER2_AEH50, device_archimedes_podule_interface, arc_ether2_aeh50_device, "arc_ether2_aeh50", "Acorn AEH50 Ethernet II")
diff --git a/src/devices/bus/archimedes/podule/ether2.h b/src/devices/bus/archimedes/podule/ether2.h
new file mode 100644
index 00000000000..81aa4e59875
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/ether2.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Acorn AEH50 Ethernet II
+
+**********************************************************************/
+
+#ifndef MAME_BUS_ARCHIMEDES_PODULE_ETHER2_H
+#define MAME_BUS_ARCHIMEDES_PODULE_ETHER2_H
+
+#pragma once
+
+#include "slot.h"
+
+// device type definition
+DECLARE_DEVICE_TYPE(ARC_ETHER2_AEH50, device_archimedes_podule_interface)
+
+#endif // MAME_BUS_ARCHIMEDES_PODULE_ETHER2_H
diff --git a/src/devices/bus/archimedes/podule/ether3.cpp b/src/devices/bus/archimedes/podule/ether3.cpp
new file mode 100644
index 00000000000..7f8a7808e39
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/ether3.cpp
@@ -0,0 +1,122 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Acorn AEH54 10Base2 Ethernet Podule
+
+ http://chrisacorns.computinghistory.org.uk/32bit_UpgradesA2G/Acorn_AEH54_Ethernet.html
+
+ TODO:
+ - everything, this is skeleton with ROM.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "ether3.h"
+
+
+namespace {
+
+class arc_ether3_aeh54_device :
+ public device_t,
+ public device_archimedes_podule_interface
+{
+public:
+ // construction/destruction
+ arc_ether3_aeh54_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ static constexpr feature_type unemulated_features() { return feature::COMMS; }
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+ // device_archimedes_podule_interface overrides
+ virtual void ioc_map(address_map &map) override;
+
+private:
+ required_memory_region m_podule_rom;
+
+ u8 m_rom_page;
+};
+
+
+void arc_ether3_aeh54_device::ioc_map(address_map &map)
+{
+ map(0x0000, 0x3fff).lr8(NAME([this](offs_t offset) { return m_podule_rom->base()[offset | ((m_rom_page << 12) & 0x1f000)]; })).umask32(0x000000ff);
+ map(0x0000, 0x0000).lw8(NAME([this](u8 data) { m_rom_page = data; }));
+}
+
+
+//-------------------------------------------------
+// ROM( ether3_aeh54 )
+//-------------------------------------------------
+
+ROM_START( ether3_aeh54 )
+ ROM_REGION(0x20000, "podule_rom", 0)
+ ROM_LOAD("aun_client_rom.rom", 0x0000, 0x20000, CRC(8137b9eb) SHA1(103318a527ea5f9a3fe373bfb8f8d0ad3697617f))
+ROM_END
+
+const tiny_rom_entry *arc_ether3_aeh54_device::device_rom_region() const
+{
+ return ROM_NAME( ether3_aeh54 );
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void arc_ether3_aeh54_device::device_add_mconfig(machine_config &config)
+{
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// arc_ether3_aeh54_device - constructor
+//-------------------------------------------------
+
+arc_ether3_aeh54_device::arc_ether3_aeh54_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, ARC_ETHER3_AEH54, tag, owner, clock)
+ , device_archimedes_podule_interface(mconfig, *this)
+ , m_podule_rom(*this, "podule_rom")
+ , m_rom_page(0)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void arc_ether3_aeh54_device::device_start()
+{
+ save_item(NAME(m_rom_page));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void arc_ether3_aeh54_device::device_reset()
+{
+ m_rom_page = 0x00;
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(ARC_ETHER3_AEH54, device_archimedes_podule_interface, arc_ether3_aeh54_device, "arc_ether3_aeh54", "Acorn AEH54 10Base2 Ethernet Podule")
diff --git a/src/devices/bus/archimedes/podule/ether3.h b/src/devices/bus/archimedes/podule/ether3.h
new file mode 100644
index 00000000000..aee4db6a02c
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/ether3.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Acorn AEH54 10Base2 Ethernet Podule
+
+**********************************************************************/
+
+#ifndef MAME_BUS_ARCHIMEDES_PODULE_ETHER3_H
+#define MAME_BUS_ARCHIMEDES_PODULE_ETHER3_H
+
+#pragma once
+
+#include "slot.h"
+
+// device type definition
+DECLARE_DEVICE_TYPE(ARC_ETHER3_AEH54, device_archimedes_podule_interface)
+
+#endif // MAME_BUS_ARCHIMEDES_PODULE_ETHER3_H
diff --git a/src/devices/bus/archimedes/podule/ethera.cpp b/src/devices/bus/archimedes/podule/ethera.cpp
new file mode 100644
index 00000000000..e1afb2697fd
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/ethera.cpp
@@ -0,0 +1,123 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ ANT Ethernet 10base2 mini-podule
+
+ http://chrisacorns.computinghistory.org.uk/32bit_UpgradesA2G/ANT_Ethernet10base2Mini.html
+
+ TODO:
+ - everything, this is skeleton with ROM.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "ethera.h"
+
+
+namespace {
+
+class arc_ethera_device :
+ public device_t,
+ public device_archimedes_podule_interface
+{
+public:
+ // construction/destruction
+ arc_ethera_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ static constexpr feature_type unemulated_features() { return feature::COMMS; }
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+ // device_archimedes_podule_interface overrides
+ virtual void ioc_map(address_map &map) override;
+
+private:
+ required_memory_region m_podule_rom;
+
+ u8 m_rom_page;
+};
+
+
+void arc_ethera_device::ioc_map(address_map &map)
+{
+ map(0x0000, 0x0fff).lr8(NAME([this](offs_t offset) { return m_podule_rom->base()[offset | ((m_rom_page << 10) & 0x3f800)]; })).umask32(0x000000ff);
+ map(0x0000, 0x0000).lw8(NAME([this](u8 data) { m_rom_page = data; }));
+}
+
+
+//-------------------------------------------------
+// ROM( ethera )
+//-------------------------------------------------
+
+ROM_START( ethera )
+ ROM_REGION(0x40000, "podule_rom", 0)
+ ROM_LOAD("ethernet5.rom", 0x0000, 0x40000, CRC(7bb0f699) SHA1(c6c9c9630b6777f4d49824b051fcd16fcb21b8f3))
+ROM_END
+
+const tiny_rom_entry *arc_ethera_device::device_rom_region() const
+{
+ return ROM_NAME( ethera );
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void arc_ethera_device::device_add_mconfig(machine_config &config)
+{
+ //NQ8005(config, "edlc", 20_MHz_XTAL);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// arc_ethera_device - constructor
+//-------------------------------------------------
+
+arc_ethera_device::arc_ethera_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, ARC_ETHERA, tag, owner, clock)
+ , device_archimedes_podule_interface(mconfig, *this)
+ , m_podule_rom(*this, "podule_rom")
+ , m_rom_page(0)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void arc_ethera_device::device_start()
+{
+ save_item(NAME(m_rom_page));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void arc_ethera_device::device_reset()
+{
+ m_rom_page = 0x00;
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(ARC_ETHERA, device_archimedes_podule_interface, arc_ethera_device, "arc_ethera", "ANT Ethernet 10base2 mini-podule")
diff --git a/src/devices/bus/archimedes/podule/ethera.h b/src/devices/bus/archimedes/podule/ethera.h
new file mode 100644
index 00000000000..42830b92245
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/ethera.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ ANT Ethernet 10base2 mini-podule
+
+**********************************************************************/
+
+#ifndef MAME_BUS_ARCHIMEDES_PODULE_ETHERA_H
+#define MAME_BUS_ARCHIMEDES_PODULE_ETHERA_H
+
+#pragma once
+
+#include "slot.h"
+
+// device type definition
+DECLARE_DEVICE_TYPE(ARC_ETHERA, device_archimedes_podule_interface)
+
+#endif // MAME_BUS_ARCHIMEDES_PODULE_ETHERA_H
diff --git a/src/devices/bus/archimedes/podule/io.cpp b/src/devices/bus/archimedes/podule/io.cpp
index 829ad1585de..698cf94114b 100644
--- a/src/devices/bus/archimedes/podule/io.cpp
+++ b/src/devices/bus/archimedes/podule/io.cpp
@@ -425,7 +425,7 @@ u8 arc_io_aka_device::pa_r()
int arc_io_aka_device::get_analogue_input(int channel_number)
{
- return (0xff - m_analog->ch_r(channel_number)) << 8;
+ return m_analog->ch_r(channel_number) << 8;
}
void arc_io_aka_device::upd7002_eoc(int state)
diff --git a/src/devices/bus/archimedes/podule/io_hccs.cpp b/src/devices/bus/archimedes/podule/io_hccs.cpp
index 7daabf0f980..16c73b22b7d 100644
--- a/src/devices/bus/archimedes/podule/io_hccs.cpp
+++ b/src/devices/bus/archimedes/podule/io_hccs.cpp
@@ -130,7 +130,7 @@ void arc_upa_hccs_device::device_start()
int arc_upa_hccs_device::get_analogue_input(int channel_number)
{
- return (0xff - m_analog->ch_r(channel_number)) << 8;
+ return m_analog->ch_r(channel_number) << 8;
}
} // anonymous namespace
diff --git a/src/devices/bus/archimedes/podule/io_morley.cpp b/src/devices/bus/archimedes/podule/io_morley.cpp
index 284e26f5f9b..3e6bccc755b 100644
--- a/src/devices/bus/archimedes/podule/io_morley.cpp
+++ b/src/devices/bus/archimedes/podule/io_morley.cpp
@@ -318,7 +318,7 @@ void arc_io_morley_device::device_reset()
int arc_io_morley_device::get_analogue_input(int channel_number)
{
- return (0xff - m_analog->ch_r(channel_number)) << 8;
+ return m_analog->ch_r(channel_number) << 8;
}
void arc_io_morley_device::upd7002_eoc(int state)
diff --git a/src/devices/bus/archimedes/podule/io_we.cpp b/src/devices/bus/archimedes/podule/io_we.cpp
index e7916c15b21..40d5092d824 100644
--- a/src/devices/bus/archimedes/podule/io_we.cpp
+++ b/src/devices/bus/archimedes/podule/io_we.cpp
@@ -169,7 +169,7 @@ void arc_bbcio_we_device::device_reset()
int arc_bbcio_we_device::get_analogue_input(int channel_number)
{
- return (0xff - m_analog->ch_r(channel_number)) << 8;
+ return m_analog->ch_r(channel_number) << 8;
}
void arc_bbcio_we_device::upd7002_eoc(int state)
diff --git a/src/devices/bus/archimedes/podule/rom.cpp b/src/devices/bus/archimedes/podule/rom.cpp
index be073229e5e..265cdddcced 100644
--- a/src/devices/bus/archimedes/podule/rom.cpp
+++ b/src/devices/bus/archimedes/podule/rom.cpp
@@ -30,7 +30,9 @@ public:
static constexpr feature_type unemulated_features() { return feature::ROM; }
protected:
- // device-level overrides
+ arc_rom_aka05_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
+ // device_t overrides
virtual void device_start() override;
virtual void device_reset() override;
@@ -43,7 +45,7 @@ protected:
private:
required_memory_region m_podule_rom;
- required_device_array<generic_slot_device, 7> m_rom;
+ required_device_array<generic_slot_device, 8> m_rom;
u8 rom_r(offs_t offset);
void rom_w(offs_t offset, u8 data);
@@ -52,6 +54,19 @@ private:
u8 m_rom_page;
};
+// ======================> arc_rom_r225_device
+
+class arc_rom_r225_device : public arc_rom_aka05_device
+{
+public:
+ // construction/destruction
+ arc_rom_r225_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // optional information overrides
+ virtual const tiny_rom_entry *device_rom_region() const override;
+};
+
void arc_rom_aka05_device::ioc_map(address_map &map)
{
@@ -72,11 +87,22 @@ ROM_START( rom_aka05 )
ROMX_LOAD("0276,221-02_manager.bin", 0x0000, 0x4000, CRC(23ec4ddb) SHA1(e699157895433010b1ea110c78fbc80a4bc58f09), ROM_BIOS(0))
ROM_END
+ROM_START( rom_r225 )
+ ROM_REGION(0x40000, "podule_rom", ROMREGION_ERASEFF)
+ ROM_LOAD("0270,751-01_r225_boot_rom1.bin", 0x00000, 0x20000, CRC(69117329) SHA1(3ce1a3630bc5d3475216cc403df348f55cad681a))
+ ROM_LOAD("0270,752-01_r225_boot_rom2.bin", 0x20000, 0x20000, CRC(2756ee10) SHA1(bb0825670bde59c80a73895141b2d8ad6ea87a2f))
+ROM_END
+
const tiny_rom_entry *arc_rom_aka05_device::device_rom_region() const
{
return ROM_NAME( rom_aka05 );
}
+const tiny_rom_entry *arc_rom_r225_device::device_rom_region() const
+{
+ return ROM_NAME( rom_r225 );
+}
+
void arc_ram_devices(device_slot_interface &device)
{
@@ -89,16 +115,17 @@ void arc_ram_devices(device_slot_interface &device)
void arc_rom_aka05_device::device_add_mconfig(machine_config &config)
{
- // rom sockets 5 x 128K
+ // rom sockets 6 x 128K
GENERIC_SOCKET(config, m_rom[0], generic_plain_slot, "bbc_rom", "bin,rom");
GENERIC_SOCKET(config, m_rom[1], generic_plain_slot, "bbc_rom", "bin,rom");
GENERIC_SOCKET(config, m_rom[2], generic_plain_slot, "bbc_rom", "bin,rom");
GENERIC_SOCKET(config, m_rom[3], generic_plain_slot, "bbc_rom", "bin,rom");
GENERIC_SOCKET(config, m_rom[4], generic_plain_slot, "bbc_rom", "bin,rom");
+ GENERIC_SOCKET(config, m_rom[5], generic_plain_slot, "bbc_rom", "bin,rom");
// ram sockets 2 x 32K
- GENERIC_SOCKET(config, m_rom[5], arc_ram_devices, "bbc_rom", "bin,rom").set_user_loadable(false);
GENERIC_SOCKET(config, m_rom[6], arc_ram_devices, "bbc_rom", "bin,rom").set_user_loadable(false);
+ GENERIC_SOCKET(config, m_rom[7], arc_ram_devices, "bbc_rom", "bin,rom").set_user_loadable(false);
SOFTWARE_LIST(config, "rom_ls").set_original("bbc_rom").set_filter("B");
}
@@ -112,8 +139,8 @@ void arc_rom_aka05_device::device_add_mconfig(machine_config &config)
// arc_rom_aka05_device - constructor
//-------------------------------------------------
-arc_rom_aka05_device::arc_rom_aka05_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
- : device_t(mconfig, ARC_ROM_AKA05, tag, owner, clock)
+arc_rom_aka05_device::arc_rom_aka05_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, type, tag, owner, clock)
, device_archimedes_podule_interface(mconfig, *this)
, m_podule_rom(*this, "podule_rom")
, m_rom(*this, "rom%u", 1U)
@@ -122,6 +149,16 @@ arc_rom_aka05_device::arc_rom_aka05_device(const machine_config &mconfig, const
{
}
+arc_rom_aka05_device::arc_rom_aka05_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : arc_rom_aka05_device(mconfig, ARC_ROM_AKA05, tag, owner, clock)
+{
+}
+
+arc_rom_r225_device::arc_rom_r225_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : arc_rom_aka05_device(mconfig, ARC_ROM_R225, tag, owner, clock)
+{
+}
+
//-------------------------------------------------
// device_start - device-specific startup
@@ -152,19 +189,19 @@ void arc_rom_aka05_device::device_reset()
u8 arc_rom_aka05_device::rom_r(offs_t offset)
{
u8 data = 0xff;
+ u32 const addr = offset | (m_rom_page << 11);
switch (m_rom_select)
{
- case 0:
- data = m_podule_rom->base()[offset | (m_rom_page << 11)];
- break;
-
- case 1: case 2: case 3: case 4: case 5:
- data = m_rom[m_rom_select - 1]->read_rom(offset | (m_rom_page << 11));
+ case 0: case 1: case 2: case 3: case 4: case 5:
+ if ((m_rom_select * 0x20000) < m_podule_rom->bytes())
+ data = m_podule_rom->base()[(m_rom_select * 0x20000) | addr];
+ else
+ data = m_rom[m_rom_select]->read_rom(addr);
break;
case 6: case 7:
- data = m_rom[m_rom_select - 1]->read_ram(offset | (m_rom_page << 11));
+ data = m_rom[m_rom_select]->read_ram(addr);
break;
}
@@ -173,10 +210,12 @@ u8 arc_rom_aka05_device::rom_r(offs_t offset)
void arc_rom_aka05_device::rom_w(offs_t offset, u8 data)
{
+ u32 const addr = offset | (m_rom_page << 11);
+
switch (m_rom_select)
{
case 6: case 7:
- m_rom[m_rom_select - 1]->write_ram(offset | (m_rom_page << 11), data);
+ m_rom[m_rom_select]->write_ram(addr, data);
break;
}
}
@@ -189,3 +228,4 @@ void arc_rom_aka05_device::rom_w(offs_t offset, u8 data)
//**************************************************************************
DEFINE_DEVICE_TYPE_PRIVATE(ARC_ROM_AKA05, device_archimedes_podule_interface, arc_rom_aka05_device, "arc_rom_aka05", "Acorn AKA05 ROM Podule")
+DEFINE_DEVICE_TYPE_PRIVATE(ARC_ROM_R225, device_archimedes_podule_interface, arc_rom_r225_device, "arc_rom_r225", "Acorn AKA05 ROM (with DiscLess Bootstrap support)")
diff --git a/src/devices/bus/archimedes/podule/rom.h b/src/devices/bus/archimedes/podule/rom.h
index 6a583839a90..980e66eb9be 100644
--- a/src/devices/bus/archimedes/podule/rom.h
+++ b/src/devices/bus/archimedes/podule/rom.h
@@ -15,5 +15,6 @@
// device type definition
DECLARE_DEVICE_TYPE(ARC_ROM_AKA05, device_archimedes_podule_interface)
+DECLARE_DEVICE_TYPE(ARC_ROM_R225, device_archimedes_podule_interface)
#endif // MAME_BUS_ARCHIMEDES_PODULE_ROM_H
diff --git a/src/devices/bus/archimedes/podule/scsi_a500.cpp b/src/devices/bus/archimedes/podule/scsi_a500.cpp
new file mode 100644
index 00000000000..0efcd568c8a
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/scsi_a500.cpp
@@ -0,0 +1,130 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Acorn A500 SCSI Interface
+
+ https://www.domesday86.com/?page_id=936#Prototype_SCSI_card
+
+ As this podule contains no identification in ROM then the SCSI modules
+ loaded from hard drive would expect to find the SCSI controller in
+ podule slot 1.
+
+ TODO:
+ - map SCSI controller
+
+**********************************************************************/
+
+#include "emu.h"
+#include "scsi_a500.h"
+#include "machine/wd33c9x.h"
+#include "bus/nscsi/devices.h"
+
+
+namespace {
+
+class arc_scsi_a500_device :
+ public device_t,
+ public device_archimedes_podule_interface
+{
+public:
+ // construction/destruction
+ arc_scsi_a500_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ static constexpr feature_type unemulated_features() { return feature::DISK; }
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+ // device_archimedes_podule_interface overrides
+ virtual void ioc_map(address_map &map) override;
+
+private:
+ required_device<wd33c93_device> m_wd33c93;
+ required_memory_region m_podule_rom;
+};
+
+
+void arc_scsi_a500_device::ioc_map(address_map &map)
+{
+ map(0x0000, 0x1fff).lr8(NAME([this](offs_t offset) { return m_podule_rom->base()[offset]; })).umask32(0x000000ff);
+ //map(0x2000, 0x2007).rw(m_wd33c93, FUNC(wd33c93_device::indir_r), FUNC(wd33c93_device::indir_w)).umask32(0x000000ff);
+}
+
+
+//-------------------------------------------------
+// ROM( scsi_a500 )
+//-------------------------------------------------
+
+ROM_START( scsi_a500 )
+ ROM_REGION(0x2000, "podule_rom", ROMREGION_ERASEFF)
+ ROM_LOAD("blank.rom", 0x0000, 0x2000, NO_DUMP) // ROM is labelled 'blank' and contains FF's
+ROM_END
+
+const tiny_rom_entry *arc_scsi_a500_device::device_rom_region() const
+{
+ return ROM_NAME( scsi_a500 );
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void arc_scsi_a500_device::device_add_mconfig(machine_config &config)
+{
+ NSCSI_BUS(config, "scsi");
+ NSCSI_CONNECTOR(config, "scsi:0", default_scsi_devices, nullptr, false); // Philips VP415
+ NSCSI_CONNECTOR(config, "scsi:1", default_scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi:2", default_scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi:3", default_scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi:4", default_scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi:5", default_scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi:6", default_scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi:7").option_set("wd33c93", WD33C93).clock(DERIVED_CLOCK(1, 1))
+ .machine_config([this](device_t *device)
+ {
+ wd33c93_device &wd33c93(downcast<wd33c93_device &>(*device));
+ wd33c93.irq_cb().set([this](int state) { set_pirq(state); });
+ });
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// arc_scsi_a500_device - constructor
+//-------------------------------------------------
+
+arc_scsi_a500_device::arc_scsi_a500_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, ARC_SCSI_A500, tag, owner, clock)
+ , device_archimedes_podule_interface(mconfig, *this)
+ , m_wd33c93(*this, "scsi:7:wd33c93")
+ , m_podule_rom(*this, "podule_rom")
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void arc_scsi_a500_device::device_start()
+{
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(ARC_SCSI_A500, device_archimedes_podule_interface, arc_scsi_a500_device, "arc_scsi_a500", "Acorn A500 SCSI Interface")
diff --git a/src/devices/bus/archimedes/podule/scsi_a500.h b/src/devices/bus/archimedes/podule/scsi_a500.h
new file mode 100644
index 00000000000..650f71c43a6
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/scsi_a500.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Acorn A500 SCSI Interface
+
+**********************************************************************/
+
+#ifndef MAME_BUS_ARCHIMEDES_PODULE_SCSI_A500_H
+#define MAME_BUS_ARCHIMEDES_PODULE_SCSI_A500_H
+
+#pragma once
+
+#include "slot.h"
+
+// device type definition
+DECLARE_DEVICE_TYPE(ARC_SCSI_A500, device_archimedes_podule_interface)
+
+#endif // MAME_BUS_ARCHIMEDES_PODULE_SCSI_A500_H
diff --git a/src/devices/bus/archimedes/podule/scsi_acorn.cpp b/src/devices/bus/archimedes/podule/scsi_acorn.cpp
new file mode 100644
index 00000000000..fc6b45581c1
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/scsi_acorn.cpp
@@ -0,0 +1,253 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Acorn AKA31 SCSI Expansion Card
+
+ http://chrisacorns.computinghistory.org.uk/32bit_UpgradesA2G/Acorn_AKA31_SCSI.html
+
+ Acorn AKA32 CDFS & SCSI Expansion Card
+
+ http://chrisacorns.computinghistory.org.uk/32bit_UpgradesA2G/Acorn_AKA32_SCSI.html
+
+ TODO:
+ - everything, this is skeleton with ROM.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "scsi_acorn.h"
+#include "machine/upd71071.h"
+#include "machine/wd33c9x.h"
+#include "bus/nscsi/devices.h"
+
+
+namespace {
+
+// ======================> arc_scsi_aka31_device
+
+class arc_scsi_aka31_device :
+ public device_t,
+ public device_archimedes_podule_interface
+{
+public:
+ // construction/destruction
+ arc_scsi_aka31_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ static constexpr feature_type unemulated_features() { return feature::DISK; }
+
+protected:
+ arc_scsi_aka31_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+ // device_archimedes_podule_interface overrides
+ virtual void ioc_map(address_map &map) override;
+ virtual void memc_map(address_map &map) override;
+
+private:
+ required_device<wd33c93a_device> m_wd33c93;
+ required_device<upd71071_device> m_dmac;
+ required_memory_region m_podule_rom;
+
+ void update_interrupts();
+
+ u8 m_memory_page;
+ u8 m_interrupt_status;
+ int m_sbic_int;
+ int m_dmac_int;
+ std::unique_ptr<u16[]> m_podule_ram;
+};
+
+
+// ======================> arc_scsi_aka32_device
+
+class arc_scsi_aka32_device : public arc_scsi_aka31_device
+{
+public:
+ // construction/destruction
+ arc_scsi_aka32_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // optional information overrides
+ virtual const tiny_rom_entry *device_rom_region() const override;
+};
+
+
+void arc_scsi_aka31_device::ioc_map(address_map &map)
+{
+ map(0x0000, 0x1fff).lr8(NAME([this](offs_t offset) { return m_podule_rom->base()[offset | (((m_memory_page & 0x3f) << 11) & 0xf800)]; })).umask32(0x000000ff);
+ map(0x2000, 0x2fff).lrw8([this]() { return m_interrupt_status; }, "isr_r", [this](u8 data) { m_dmac_int = 0; update_interrupts(); }, "clrint_w").umask32(0x000000ff);
+ map(0x3000, 0x3000).mirror(0x0fff).lw8(NAME([this](u8 data) { m_memory_page = data; m_wd33c93->reset_w(BIT(data, 7)); update_interrupts(); }));
+}
+
+void arc_scsi_aka31_device::memc_map(address_map &map)
+{
+ map(0x0000, 0x1fff).lr16(NAME([this](offs_t offset) { return m_podule_ram[offset | (((m_memory_page & 0x3f) << 11) & 0xf800)]; })).umask32(0x0000ffff);
+ map(0x2000, 0x2007).mirror(0x0ff8).rw(m_wd33c93, FUNC(wd33c93a_device::indir_r), FUNC(wd33c93a_device::indir_w)).umask32(0x000000ff);
+ map(0x3000, 0x33ff).mirror(0x0c00).lr8(NAME([this](offs_t offset) { return m_dmac->read(bitswap<8>(offset, 0, 6, 5, 4, 3, 2, 1, 7)); })).umask32(0x000000ff);
+ map(0x3000, 0x33ff).mirror(0x0c00).lw8(NAME([this](offs_t offset, u8 data) { m_dmac->write(bitswap<8>(offset, 0, 6, 5, 4, 3, 2, 1, 7), data); })).umask32(0x000000ff);
+}
+
+
+//-------------------------------------------------
+// ROM( aka31 )
+//-------------------------------------------------
+
+ROM_START( aka31 )
+ ROM_REGION(0x10000, "podule_rom", 0)
+ ROM_LOAD("aka31_0273,210-03_scsi_id_prom.rom", 0x0000, 0x10000, CRC(d8a51876) SHA1(fedbd8d8dafb225b931c76704ccb93d4ebdaea10))
+ROM_END
+
+ROM_START( aka32 )
+ ROM_REGION(0x10000, "podule_rom", 0)
+ ROM_SYSTEM_BIOS(0, "aka35", "AKA35")
+ ROMX_LOAD("aka35.rom", 0x0000, 0x10000, CRC(2d00a646) SHA1(80e7a88d17bdf5d2111e4e2d1b406a1d8692d41b), ROM_BIOS(0))
+ ROM_SYSTEM_BIOS(1, "aka33", "AKA33")
+ ROMX_LOAD("aka33.rom", 0x0000, 0x10000, CRC(f5b4b6b8) SHA1(ab47366e569add39aea0c6e90e92a4dfd16cb898), ROM_BIOS(1))
+ ROM_SYSTEM_BIOS(2, "aka32", "AKA32")
+ ROMX_LOAD("aka32_acorn_cdfs_version_2.20.rom", 0x0000, 0x10000, CRC(65d74620) SHA1(42bddbe2841de7085371c5fe11d7c9b152070886), ROM_BIOS(2))
+ROM_END
+
+const tiny_rom_entry *arc_scsi_aka31_device::device_rom_region() const
+{
+ return ROM_NAME( aka31 );
+}
+
+const tiny_rom_entry *arc_scsi_aka32_device::device_rom_region() const
+{
+ return ROM_NAME( aka32 );
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void arc_scsi_aka31_device::device_add_mconfig(machine_config &config)
+{
+ NSCSI_BUS(config, "scsi");
+ NSCSI_CONNECTOR(config, "scsi:0", default_scsi_devices, "harddisk", false);
+ NSCSI_CONNECTOR(config, "scsi:1", default_scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi:2", default_scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi:3", default_scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi:4", default_scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi:5", default_scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi:6", default_scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi:7").option_set("wd33c93a", WD33C93A).clock(DERIVED_CLOCK(1, 1))
+ .machine_config([this](device_t *device)
+ {
+ wd33c93a_device &wd33c93(downcast<wd33c93a_device &>(*device));
+ wd33c93.irq_cb().set([this](int state) { m_sbic_int = state; update_interrupts(); });
+ wd33c93.drq_cb().set([this](int state) { m_dmac->dmarq(state, 0); });
+ });
+
+ UPD71071(config, m_dmac, 0);
+ m_dmac->set_cpu_tag(":maincpu");
+ m_dmac->set_clock(DERIVED_CLOCK(1, 1));
+ m_dmac->out_eop_callback().set([this](int state) { m_dmac_int = state; update_interrupts(); });
+ m_dmac->dma_read_callback<0>().set(m_wd33c93, FUNC(wd33c93a_device::dma_r));
+ m_dmac->dma_write_callback<0>().set(m_wd33c93, FUNC(wd33c93a_device::dma_w));
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// arc_scsi_aka31_device - constructor
+//-------------------------------------------------
+
+arc_scsi_aka31_device::arc_scsi_aka31_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, type, tag, owner, clock)
+ , device_archimedes_podule_interface(mconfig, *this)
+ , m_wd33c93(*this, "scsi:7:wd33c93a")
+ , m_dmac(*this, "dma")
+ , m_podule_rom(*this, "podule_rom")
+ , m_memory_page(0)
+ , m_interrupt_status(0)
+ , m_sbic_int(0)
+ , m_dmac_int(0)
+{
+}
+
+arc_scsi_aka31_device::arc_scsi_aka31_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : arc_scsi_aka31_device(mconfig, ARC_SCSI_AKA31, tag, owner, clock)
+{
+}
+
+arc_scsi_aka32_device::arc_scsi_aka32_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : arc_scsi_aka31_device(mconfig, ARC_SCSI_AKA32, tag, owner, clock)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void arc_scsi_aka31_device::device_start()
+{
+ m_podule_ram = std::make_unique<u16[]>(0x8000);
+
+ save_item(NAME(m_memory_page));
+ save_item(NAME(m_interrupt_status));
+ save_pointer(NAME(m_podule_ram), 0x8000);
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void arc_scsi_aka31_device::device_reset()
+{
+ m_memory_page = 0x00;
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+void arc_scsi_aka31_device::update_interrupts()
+{
+ // SBIC interrupt
+ if (m_sbic_int)
+ m_interrupt_status |= m_sbic_int << 3;
+ else
+ m_interrupt_status &= ~(m_sbic_int << 3);
+
+ // DMAC terminal count interrupt
+ if (m_dmac_int)
+ m_interrupt_status |= m_dmac_int << 1;
+ else
+ m_interrupt_status &= ~(m_dmac_int << 1);
+
+ // SEC requesting IRQ
+ if (m_dmac_int || m_sbic_int)
+ m_interrupt_status |= 0x01;
+ else
+ m_interrupt_status &= ~(0x01);
+
+ if (BIT(m_memory_page, 6)) // interrupts enabled
+ set_pirq(BIT(m_interrupt_status, 0));
+ else
+ set_pirq(0);
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(ARC_SCSI_AKA31, device_archimedes_podule_interface, arc_scsi_aka31_device, "arc_scsi_aka31", "Acorn AKA31 SCSI Expansion Card")
+DEFINE_DEVICE_TYPE_PRIVATE(ARC_SCSI_AKA32, device_archimedes_podule_interface, arc_scsi_aka32_device, "arc_scsi_aka32", "Acorn AKA32 CDFS & SCSI Expansion Card")
diff --git a/src/devices/bus/archimedes/podule/scsi_acorn.h b/src/devices/bus/archimedes/podule/scsi_acorn.h
new file mode 100644
index 00000000000..670ee296c3d
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/scsi_acorn.h
@@ -0,0 +1,21 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Acorn CDFS & SCSI Expansion Card
+
+**********************************************************************/
+
+#ifndef MAME_BUS_ARCHIMEDES_PODULE_SCSI_ACORN_H
+#define MAME_BUS_ARCHIMEDES_PODULE_SCSI_ACORN_H
+
+#pragma once
+
+#include "slot.h"
+
+// device type definition
+DECLARE_DEVICE_TYPE(ARC_SCSI_AKA31, device_archimedes_podule_interface)
+DECLARE_DEVICE_TYPE(ARC_SCSI_AKA32, device_archimedes_podule_interface)
+DECLARE_DEVICE_TYPE(ARC_SCSI_AKA35, device_archimedes_podule_interface)
+
+#endif // MAME_BUS_ARCHIMEDES_PODULE_SCSI_ACORN_H
diff --git a/src/devices/bus/archimedes/podule/scsi_cumana.cpp b/src/devices/bus/archimedes/podule/scsi_cumana.cpp
new file mode 100644
index 00000000000..0fcbe8bb225
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/scsi_cumana.cpp
@@ -0,0 +1,153 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Cumana 16bit SCSI interface
+
+ http://chrisacorns.computinghistory.org.uk/32bit_UpgradesA2G/Cumana_16bitSCSI.html
+
+ TODO:
+ - everything, this is skeleton with ROM.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "scsi_cumana.h"
+#include "machine/eepromser.h"
+#include "machine/ncr5380.h"
+#include "bus/nscsi/devices.h"
+
+
+namespace {
+
+class arc_scsi_cumana_device :
+ public device_t,
+ public device_archimedes_podule_interface
+{
+public:
+ // construction/destruction
+ arc_scsi_cumana_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ static constexpr feature_type unemulated_features() { return feature::DISK; }
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+ // device_archimedes_podule_interface overrides
+ virtual void ioc_map(address_map &map) override;
+ virtual void memc_map(address_map &map) override;
+
+private:
+ required_device<ncr5380_device> m_ncr5380;
+ required_device<eeprom_serial_93cxx_device> m_eeprom;
+ required_memory_region m_podule_rom;
+
+ u8 m_rom_page;
+};
+
+
+void arc_scsi_cumana_device::ioc_map(address_map &map)
+{
+ map(0x0000, 0x1fff).lr8(NAME([this](offs_t offset) { return m_podule_rom->base()[offset | ((m_rom_page << 11) & 0xf800)]; })).umask32(0x000000ff);
+ map(0x0000, 0x1fff).lw8(NAME([this](u8 data) { m_rom_page = data; }));
+ //map(0x2000, 0x201f).mirror(0x0100).rw(m_ncr5380, FUNC(ncr5380_device::read), FUNC(ncr5380_device::write)).umask32(0x000000ff);
+ map(0x2100, 0x211f).m(m_ncr5380, FUNC(ncr5380_device::map)).umask32(0x000000ff);
+ //map(0x2100, 0x2100).r(m_ncr5380, FUNC(ncr5380_device::dma_r));
+ //map(0x2100, 0x2100).w(m_ncr5380, FUNC(ncr5380_device::dma_w));
+}
+
+void arc_scsi_cumana_device::memc_map(address_map &map)
+{
+}
+
+
+//-------------------------------------------------
+// ROM( scsi_cumana )
+//-------------------------------------------------
+
+ROM_START( scsi_cumana )
+ ROM_REGION(0x10000, "podule_rom", 0)
+ ROM_LOAD("cumana_930c.rom", 0x0000, 0x10000, CRC(d121025d) SHA1(293b1dabd02cfa34251116d95dd19e8b58d0f0a5))
+ROM_END
+
+const tiny_rom_entry *arc_scsi_cumana_device::device_rom_region() const
+{
+ return ROM_NAME( scsi_cumana );
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void arc_scsi_cumana_device::device_add_mconfig(machine_config &config)
+{
+ NSCSI_BUS(config, "scsi");
+ NSCSI_CONNECTOR(config, "scsi:0", default_scsi_devices, "harddisk", false);
+ NSCSI_CONNECTOR(config, "scsi:1", default_scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi:2", default_scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi:3", default_scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi:4", default_scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi:5", default_scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi:6", default_scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi:7").option_set("ncr5380", NCR5380) // DP8490
+ .machine_config([this](device_t *device)
+ {
+ downcast<ncr5380_device &>(*device).irq_handler().set([this](int state) { set_pirq(state); });
+ });
+
+ EEPROM_93C06_16BIT(config, m_eeprom);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// arc_scsi_cumana_device - constructor
+//-------------------------------------------------
+
+arc_scsi_cumana_device::arc_scsi_cumana_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, ARC_SCSI_CUMANA, tag, owner, clock)
+ , device_archimedes_podule_interface(mconfig, *this)
+ , m_ncr5380(*this, "scsi:7:ncr5380")
+ , m_eeprom(*this, "eeprom")
+ , m_podule_rom(*this, "podule_rom")
+ , m_rom_page(0)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void arc_scsi_cumana_device::device_start()
+{
+ save_item(NAME(m_rom_page));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void arc_scsi_cumana_device::device_reset()
+{
+ m_rom_page = 0x00;
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(ARC_SCSI_CUMANA, device_archimedes_podule_interface, arc_scsi_cumana_device, "arc_scsi_cumana", "Cumana 16bit SCSI Interface")
diff --git a/src/devices/bus/archimedes/podule/scsi_cumana.h b/src/devices/bus/archimedes/podule/scsi_cumana.h
new file mode 100644
index 00000000000..ab0d6ac00da
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/scsi_cumana.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Cumana 16bit SCSI interface
+
+**********************************************************************/
+
+#ifndef MAME_BUS_ARCHIMEDES_PODULE_SCSI_CUMANA_H
+#define MAME_BUS_ARCHIMEDES_PODULE_SCSI_CUMANA_H
+
+#pragma once
+
+#include "slot.h"
+
+// device type definition
+DECLARE_DEVICE_TYPE(ARC_SCSI_CUMANA, device_archimedes_podule_interface)
+
+#endif // MAME_BUS_ARCHIMEDES_PODULE_SCSI_CUMANA_H
diff --git a/src/devices/bus/archimedes/podule/scsi_ling.cpp b/src/devices/bus/archimedes/podule/scsi_ling.cpp
new file mode 100644
index 00000000000..ab2cd3fea51
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/scsi_ling.cpp
@@ -0,0 +1,149 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Lingenuity SCSI Podule
+
+ http://chrisacorns.computinghistory.org.uk/32bit_UpgradesH2Z/Lingenuity_SCSI.html
+
+ TODO:
+ - everything, this is skeleton with ROM.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "scsi_ling.h"
+#include "machine/ncr5380.h"
+#include "bus/nscsi/devices.h"
+
+
+namespace {
+
+class arc_scsi_ling_device :
+ public device_t,
+ public device_archimedes_podule_interface
+{
+public:
+ // construction/destruction
+ arc_scsi_ling_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ static constexpr feature_type unemulated_features() { return feature::DISK; }
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+ // device_archimedes_podule_interface overrides
+ virtual void ioc_map(address_map &map) override;
+ virtual void memc_map(address_map &map) override;
+
+private:
+ required_device<ncr5380_device> m_ncr5380;
+ required_memory_region m_podule_rom;
+
+ u8 m_rom_page;
+};
+
+
+void arc_scsi_ling_device::ioc_map(address_map &map)
+{
+ map(0x0000, 0x1fff).lr8(NAME([this](offs_t offset) { return m_podule_rom->base()[offset | ((m_rom_page << 11) & 0xf800)]; })).umask32(0x000000ff);
+ map(0x3800, 0x3800).lw8(NAME([this](u8 data) { m_rom_page = data; }));
+}
+
+void arc_scsi_ling_device::memc_map(address_map &map)
+{
+ //map(0x2000, 0x20ff).m(m_ncr5380, FUNC(ncr5380_device::map)).umask32(0x000000ff);
+ map(0x2000, 0x20ff).lr8(NAME([this](offs_t offset) { logerror("r: offset %02x\n", offset >> 3); return m_ncr5380->read(offset >> 3); })).umask32(0x000000ff);
+ map(0x2000, 0x20ff).lw8(NAME([this](offs_t offset, u8 data) { logerror("w: offset %02x data %02x\n", offset >> 3, data); m_ncr5380->write(offset >> 3, data); })).umask32(0x000000ff);
+ map(0x2100, 0x2100).r(m_ncr5380, FUNC(ncr5380_device::dma_r));
+ map(0x2100, 0x2100).w(m_ncr5380, FUNC(ncr5380_device::dma_w));
+}
+
+
+//-------------------------------------------------
+// ROM( scsi_ling )
+//-------------------------------------------------
+
+ROM_START( scsi_ling )
+ ROM_REGION(0x10000, "podule_rom", 0)
+ ROM_LOAD("scsi_2.54.rom", 0x0000, 0x10000, CRC(32926220) SHA1(c05ea28f33afa98bd9d18bfe7dafee0a5fe7f2f4))
+ROM_END
+
+const tiny_rom_entry *arc_scsi_ling_device::device_rom_region() const
+{
+ return ROM_NAME( scsi_ling );
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void arc_scsi_ling_device::device_add_mconfig(machine_config &config)
+{
+ NSCSI_BUS(config, "scsi");
+ NSCSI_CONNECTOR(config, "scsi:0", default_scsi_devices, "harddisk", false);
+ NSCSI_CONNECTOR(config, "scsi:1", default_scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi:2", default_scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi:3", default_scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi:4", default_scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi:5", default_scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi:6", default_scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi:7").option_set("ncr5380", NCR5380)
+ .machine_config([this](device_t *device)
+ {
+ downcast<ncr5380_device &>(*device).irq_handler().set([this](int state) { set_pirq(state); });
+ });
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// arc_scsi_ling_device - constructor
+//-------------------------------------------------
+
+arc_scsi_ling_device::arc_scsi_ling_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, ARC_SCSI_LING, tag, owner, clock)
+ , device_archimedes_podule_interface(mconfig, *this)
+ , m_ncr5380(*this, "scsi:7:ncr5380")
+ , m_podule_rom(*this, "podule_rom")
+ , m_rom_page(0)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void arc_scsi_ling_device::device_start()
+{
+ save_item(NAME(m_rom_page));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void arc_scsi_ling_device::device_reset()
+{
+ m_rom_page = 0x00;
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(ARC_SCSI_LING, device_archimedes_podule_interface, arc_scsi_ling_device, "arc_scsi_ling", "Lingenuity SCSI Podule")
diff --git a/src/devices/bus/archimedes/podule/scsi_ling.h b/src/devices/bus/archimedes/podule/scsi_ling.h
new file mode 100644
index 00000000000..7cf6e2562cc
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/scsi_ling.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Lingenuity SCSI Podule
+
+**********************************************************************/
+
+#ifndef MAME_BUS_ARCHIMEDES_PODULE_SCSI_LING_H
+#define MAME_BUS_ARCHIMEDES_PODULE_SCSI_LING_H
+
+#pragma once
+
+#include "slot.h"
+
+// device type definition
+DECLARE_DEVICE_TYPE(ARC_SCSI_LING, device_archimedes_podule_interface)
+
+#endif // MAME_BUS_ARCHIMEDES_PODULE_SCSI_LING_H
diff --git a/src/devices/bus/archimedes/podule/scsi_morley.cpp b/src/devices/bus/archimedes/podule/scsi_morley.cpp
new file mode 100644
index 00000000000..438fc65dafa
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/scsi_morley.cpp
@@ -0,0 +1,169 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Morley Electronics 16bit Cached SCSI card
+
+ http://chrisacorns.computinghistory.org.uk/32bit_UpgradesH2Z/Morley_16bitCachedSCSI.html
+
+ TODO:
+ - ESP216 SCSI controller
+ - everything, this is skeleton with ROM.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "scsi_morley.h"
+#include "machine/7200fifo.h"
+#include "machine/ncr53c90.h"
+#include "bus/nscsi/devices.h"
+
+
+namespace {
+
+class arc_scsi_morley_device :
+ public device_t,
+ public device_archimedes_podule_interface
+{
+public:
+ // construction/destruction
+ arc_scsi_morley_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ static constexpr feature_type unemulated_features() { return feature::DISK; }
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+ // device_archimedes_podule_interface overrides
+ virtual void ioc_map(address_map &map) override;
+ virtual void memc_map(address_map &map) override;
+
+private:
+ required_device<ncr53c94_device> m_esp216;
+ required_device<idt7201_device> m_fifo_in;
+ required_device<idt7201_device> m_fifo_out;
+ required_memory_region m_podule_rom;
+
+ u8 m_rom_page;
+};
+
+
+void arc_scsi_morley_device::ioc_map(address_map &map)
+{
+ map(0x0000, 0x0fff).lr8(NAME([this](offs_t offset) { return m_podule_rom->base()[offset | ((m_rom_page << 10) & 0xfc00)]; })).umask32(0x000000ff);
+ //map(0x3000, 0x3000).lrw8(NAME([this]() { return m_rom_page; }), NAME([this](u8 data) { m_rom_page = data; }));
+ //map(0x3000, 0x303f).rw(m_esp216, FUNC(ncr53c94_device::read), FUNC(ncr53c94_device::write)).umask32(0x000000ff);
+}
+
+void arc_scsi_morley_device::memc_map(address_map &map)
+{
+ map(0x0000, 0x0000).lrw8(NAME([this]() { return m_rom_page; }), NAME([this](u8 data) { m_rom_page = data; }));
+}
+
+
+//-------------------------------------------------
+// ROM( scsi_morley )
+//-------------------------------------------------
+
+ROM_START( scsi_morley )
+ ROM_REGION(0x10000, "podule_rom", ROMREGION_ERASE00)
+ ROM_SYSTEM_BIOS(0, "119", "V1.19")
+ ROMX_LOAD("morley_scsi_rom_v1.19.rom", 0x0000, 0x10000, CRC(78e2e0da) SHA1(08d8f6233d5cae8a3a04f29c16c8cf85788dad46), ROM_BIOS(0))
+ ROM_SYSTEM_BIOS(1, "117", "V1.17")
+ ROMX_LOAD("morley_scsi_rom_v1.17.rom", 0x0000, 0x10000, CRC(1397a7b3) SHA1(5b0b7d2bb123db85922b493213c6d60ad4d89020), ROM_BIOS(1))
+ ROM_SYSTEM_BIOS(2, "114", "V1.14")
+ ROMX_LOAD("morley_scsi_rom_v1.14.rom", 0x0000, 0x10000, CRC(c6e15260) SHA1(e2b591484d47d4b4e0edb823f992257f03d32bd6), ROM_BIOS(2))
+ ROM_SYSTEM_BIOS(3, "110", "V1.10")
+ ROMX_LOAD("morley_scsi_rom_v1.10.rom", 0x0000, 0x10000, CRC(a0941679) SHA1(e92902e67d955e8742a7ac92dd86a8f212801dc5), ROM_BIOS(3))
+ ROM_SYSTEM_BIOS(4, "108", "V1.08")
+ ROMX_LOAD("morley_scsi_rom_v1.08.rom", 0x0000, 0x08000, CRC(e8357473) SHA1(9164ef9edc9d2ed6a7a7c9ba6258e02db9b1d2cb), ROM_BIOS(4))
+ROM_END
+
+const tiny_rom_entry *arc_scsi_morley_device::device_rom_region() const
+{
+ return ROM_NAME( scsi_morley );
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void arc_scsi_morley_device::device_add_mconfig(machine_config &config)
+{
+ NSCSI_BUS(config, "scsi");
+ NSCSI_CONNECTOR(config, "scsi:0", default_scsi_devices, "harddisk", false);
+ NSCSI_CONNECTOR(config, "scsi:1", default_scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi:2", default_scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi:3", default_scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi:4", default_scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi:5", default_scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi:6", default_scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi:7").option_set("esp216", NCR53CF94).clock(24_MHz_XTAL) // ESP216
+ .machine_config([this](device_t *device)
+ {
+ ncr53c94_device &esp216(downcast<ncr53c94_device &>(*device));
+ esp216.set_busmd(ncr53c94_device::busmd_t::BUSMD_1);
+ esp216.irq_handler_cb().set([this](int state) { set_pirq(state); });
+ //esp216.drq_handler_cb().set([this](int state) { m_drq_status = state; });
+ });
+
+ IDT7201(config, m_fifo_out);
+ //m_fifo_out->hf_handler().set([this](int state) { set_irq(IRQ_FIFO_OUT, state); });
+ IDT7201(config, m_fifo_in);
+ //m_fifo_in->hf_handler().set([this](int state) { set_irq(IRQ_FIFO_IN, !state); });
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// arc_scsi_morley_device - constructor
+//-------------------------------------------------
+
+arc_scsi_morley_device::arc_scsi_morley_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, ARC_SCSI_MORLEY, tag, owner, clock)
+ , device_archimedes_podule_interface(mconfig, *this)
+ , m_esp216(*this, "scsi:7:esp216")
+ , m_fifo_in(*this, "fifo_in")
+ , m_fifo_out(*this, "fifo_out")
+ , m_podule_rom(*this, "podule_rom")
+ , m_rom_page(0)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void arc_scsi_morley_device::device_start()
+{
+ save_item(NAME(m_rom_page));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void arc_scsi_morley_device::device_reset()
+{
+ m_rom_page = 0x00;
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(ARC_SCSI_MORLEY, device_archimedes_podule_interface, arc_scsi_morley_device, "arc_scsi_morley", "Morley Electronics 16bit Cached SCSI card")
diff --git a/src/devices/bus/archimedes/podule/scsi_morley.h b/src/devices/bus/archimedes/podule/scsi_morley.h
new file mode 100644
index 00000000000..88375536c4a
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/scsi_morley.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Morley Electronics 16bit Cached SCSI card
+
+**********************************************************************/
+
+#ifndef MAME_BUS_ARCHIMEDES_PODULE_SCSI_MORLEY_H
+#define MAME_BUS_ARCHIMEDES_PODULE_SCSI_MORLEY_H
+
+#pragma once
+
+#include "slot.h"
+
+// device type definition
+DECLARE_DEVICE_TYPE(ARC_SCSI_MORLEY, device_archimedes_podule_interface)
+
+#endif // MAME_BUS_ARCHIMEDES_PODULE_SCSI_MORLEY_H
diff --git a/src/devices/bus/archimedes/podule/scsi_oak.cpp b/src/devices/bus/archimedes/podule/scsi_oak.cpp
new file mode 100644
index 00000000000..ffce5815993
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/scsi_oak.cpp
@@ -0,0 +1,263 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Oak Solutions SCSI Interface
+
+ http://chrisacorns.computinghistory.org.uk/32bit_UpgradesH2Z/Oak_SCSI.html
+
+ Podule space :
+ ROM: ROM a0..11 from podule A2..13,
+ ROM a12..15 come from latch.
+ A14,15 are inverted to allow any size from 2764 to 512 to be used without
+ link changes. Data is via D0..7
+
+
+ MEMC space :
+ All reads/writes set the latch from b8..11 of the address used,
+ unless b5,6 = 11 (eeprom read)
+
+ Address Address bit
+
+ 2,3,4 : 5380 register select :
+
+ &000 000 SCSI Data read/write
+ &004 001 Initiator command register
+ &008 010 Mode register
+ &00C 011 Target command register
+ &010 100 SCSI status/select enable
+ &014 101 Bus & status register /start dma send
+ &018 110 input data/start dma target receive
+ &01C 111 reset IRQ/start DMA init receive
+
+ 5,6 : Main address decode :
+ &000 00 Read/write 5380
+ &020 01 Read/write 5380 DMA data (uses DACK instead of CS)
+ (DMA mode bit determines 8 or 16 bit DMA mode)
+ &040 10 d8 = byte flag, d9 = irq state, d10 = DRQ state
+ &060 11 d0 = EEprom data
+
+ &100 8 : EEProm CS
+ &200 9 : ROM A12, 16 bit DMA enable
+ &400 10 : ROM A13, DMA mode select (1=write), EEProm data in
+ &800 11 : ROM !A14, EEProm Clock
+ &1000 12 : ROM !A15
+
+ When 16 bit DMA is enabled, and b5,6 = 01, the i/o cycle is stretched until
+ 2 bytes of data have been transferred from SCSI. There is a hardware timeout
+ of 125 microseconds. This period can be changed via a link. All other
+ accesses are fast MEMC cycles (250ns).
+
+ The latch and 5380 are reset after a hardware reset.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "scsi_oak.h"
+#include "machine/eepromser.h"
+#include "machine/ncr5380.h"
+#include "bus/nscsi/devices.h"
+
+
+namespace {
+
+class arc_scsi_oak_device :
+ public device_t,
+ public device_archimedes_podule_interface
+{
+public:
+ // construction/destruction
+ arc_scsi_oak_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ static constexpr feature_type unemulated_features() { return feature::DISK; }
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+ // device_archimedes_podule_interface overrides
+ virtual void ioc_map(address_map &map) override;
+ virtual void memc_map(address_map &map) override;
+
+private:
+ required_device<ncr5380_device> m_ncr5380;
+ required_device<eeprom_serial_93cxx_device> m_eeprom;
+ required_memory_region m_podule_rom;
+
+ u8 m_rom_page;
+ int m_irq_state;
+ int m_drq_state;
+};
+
+
+void arc_scsi_oak_device::ioc_map(address_map &map)
+{
+ map(0x0000, 0x3fff).lr8(NAME([this](offs_t offset) { return m_podule_rom->base()[offset | (((m_rom_page ^ 0x0c) << 12) & 0xf000)]; })).umask32(0x000000ff);
+}
+
+void arc_scsi_oak_device::memc_map(address_map &map)
+{
+ map(0x0000, 0x3fff).lrw16(
+ NAME([this](offs_t offset)
+ {
+ u16 data = 0xffff;
+
+ offset <<= 2;
+
+ if ((offset & 0xe0) != 0x60)
+ m_rom_page = (offset >> 9) & 0x0f;
+
+ m_eeprom->di_write(BIT(offset, 11));
+ m_eeprom->clk_write(BIT(offset, 10));
+ m_eeprom->cs_write(BIT(offset, 8));
+
+ switch (offset & 0xe0)
+ {
+ case 0x00:
+ data = m_ncr5380->read(offset >> 2);
+ break;
+
+ case 0x20:
+ data = m_ncr5380->dma_r();
+
+ if (offset & 0x200)
+ data |= m_ncr5380->dma_r() << 8;
+ break;
+
+ case 0x40:
+ data = 0x0000;
+ data |= m_irq_state << 9;
+ data |= m_drq_state << 8;
+ break;
+
+ case 0x60:
+ data = m_eeprom->do_read();
+ break;
+ }
+
+ return data;
+ }),
+ NAME([this](offs_t offset, u32 data)
+ {
+ offset <<= 2;
+
+ if ((offset & 0xe0) != 0x60)
+ m_rom_page = (offset >> 9) & 0x0f;
+
+ switch (offset & 0xe0)
+ {
+ case 0x00:
+ m_ncr5380->write(offset >> 2, data & 0xff);
+ break;
+
+ case 0x20:
+ m_ncr5380->dma_w(data & 0xff);
+
+ if (offset & 0x200)
+ m_ncr5380->dma_w(data >> 8);
+ break;
+ }
+ })).umask32(0x0000ffff);
+}
+
+
+//-------------------------------------------------
+// ROM( scsi_oak )
+//-------------------------------------------------
+
+ROM_START( scsi_oak )
+ ROM_REGION(0x10000, "podule_rom", ROMREGION_ERASE00)
+ ROM_SYSTEM_BIOS(0, "136", "Oak SCSI driver 1.36 (29 Nov 1993)")
+ ROMX_LOAD("scsi_rom_1.36.rom", 0x0000, 0x10000, CRC(9571ac99) SHA1(bf41e422135ceb8048b04efae10cea32eb4bb864), ROM_BIOS(0))
+ ROM_SYSTEM_BIOS(1, "116", "Oak SCSI driver 1.16 (04 Oct 1990)")
+ ROMX_LOAD("scsi_rom_1.16.rom", 0xc000, 0x04000, CRC(f05c414c) SHA1(de7f6cc27ff09b34b132d7ced5123926005be18d), ROM_BIOS(1))
+ ROM_SYSTEM_BIOS(2, "137", "Oak SCSI driver 1.37 (27 Jul 1994)")
+ ROMX_LOAD("scsi_rom_1.37.rom", 0x0000, 0x10000, CRC(c1e12d48) SHA1(cba365e35aa84d6a9ca98d678fa61fe3a7a7ac3c), ROM_BIOS(2))
+
+ ROM_REGION16_LE(0x20, "eeprom", ROMREGION_ERASEFF)
+ ROM_LOAD("93c06n", 0x00, 0x20, CRC(45badabc) SHA1(c102d90e4f5c16fedde1ba4637170a39ed7ab371))
+ROM_END
+
+const tiny_rom_entry *arc_scsi_oak_device::device_rom_region() const
+{
+ return ROM_NAME( scsi_oak );
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void arc_scsi_oak_device::device_add_mconfig(machine_config &config)
+{
+ NSCSI_BUS(config, "scsi");
+ NSCSI_CONNECTOR(config, "scsi:0", default_scsi_devices, "harddisk", false);
+ NSCSI_CONNECTOR(config, "scsi:1", default_scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi:2", default_scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi:3", default_scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi:4", default_scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi:5", default_scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi:6", default_scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi:7").option_set("ncr5380", NCR5380)
+ .machine_config([this](device_t *device)
+ {
+ downcast<ncr5380_device&>(*device).irq_handler().set([this](int state) { m_irq_state = state; });
+ downcast<ncr5380_device &>(*device).drq_handler().set([this](int state) { m_drq_state = state; });
+ });
+
+ EEPROM_93C06_16BIT(config, m_eeprom);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// arc_scsi_oak_device - constructor
+//-------------------------------------------------
+
+arc_scsi_oak_device::arc_scsi_oak_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, ARC_SCSI_OAK, tag, owner, clock)
+ , device_archimedes_podule_interface(mconfig, *this)
+ , m_ncr5380(*this, "scsi:7:ncr5380")
+ , m_eeprom(*this, "eeprom")
+ , m_podule_rom(*this, "podule_rom")
+ , m_rom_page(0)
+ , m_irq_state(0)
+ , m_drq_state(0)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void arc_scsi_oak_device::device_start()
+{
+ save_item(NAME(m_rom_page));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void arc_scsi_oak_device::device_reset()
+{
+ m_rom_page = 0x00;
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(ARC_SCSI_OAK, device_archimedes_podule_interface, arc_scsi_oak_device, "arc_scsi_oak", "Oak Solutions 16 bit SCSI Interface")
diff --git a/src/devices/bus/archimedes/podule/scsi_oak.h b/src/devices/bus/archimedes/podule/scsi_oak.h
new file mode 100644
index 00000000000..6d08e1f0a6f
--- /dev/null
+++ b/src/devices/bus/archimedes/podule/scsi_oak.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Oak Solutions SCSI Interface
+
+**********************************************************************/
+
+#ifndef MAME_BUS_ARCHIMEDES_PODULE_SCSI_OAK_H
+#define MAME_BUS_ARCHIMEDES_PODULE_SCSI_OAK_H
+
+#pragma once
+
+#include "slot.h"
+
+// device type definition
+DECLARE_DEVICE_TYPE(ARC_SCSI_OAK, device_archimedes_podule_interface)
+
+#endif // MAME_BUS_ARCHIMEDES_PODULE_SCSI_OAK_H
diff --git a/src/devices/bus/archimedes/podule/scsi_vti.cpp b/src/devices/bus/archimedes/podule/scsi_vti.cpp
index f0239dfeeb0..a64bb3b6845 100644
--- a/src/devices/bus/archimedes/podule/scsi_vti.cpp
+++ b/src/devices/bus/archimedes/podule/scsi_vti.cpp
@@ -16,7 +16,7 @@
#include "scsi_vti.h"
#include "machine/6522via.h"
#include "machine/eepromser.h"
-#include "machine/ncr5390.h"
+#include "machine/ncr53c90.h"
#include "bus/bbc/userport/userport.h"
#include "bus/nscsi/devices.h"
diff --git a/src/devices/bus/archimedes/podule/slot.cpp b/src/devices/bus/archimedes/podule/slot.cpp
index 75498df27a9..92544eb3433 100644
--- a/src/devices/bus/archimedes/podule/slot.cpp
+++ b/src/devices/bus/archimedes/podule/slot.cpp
@@ -96,13 +96,6 @@ void archimedes_exp_device::memc_map(address_map &map)
// device_start - device-specific startup
//-------------------------------------------------
-void archimedes_exp_device::device_resolve_objects()
-{
- // resolve callbacks
- m_out_pirq_cb.resolve_safe();
- m_out_pfiq_cb.resolve_safe();
-}
-
void archimedes_exp_device::device_start()
{
m_ioc = &space(AS_IO);
@@ -248,10 +241,10 @@ void device_archimedes_podule_interface::interface_post_start()
//#include "colourcard.h"
#include "eaglem2.h"
#include "ether1.h"
-//#include "ether2.h"
-//#include "ether3.h"
+#include "ether2.h"
+#include "ether3.h"
//#include "ether5.h"
-//#include "ethera.h"
+#include "ethera.h"
#include "etherd.h"
#include "etherr.h"
#include "faxpack.h"
@@ -272,6 +265,7 @@ void device_archimedes_podule_interface::interface_post_start()
#include "io.h"
#include "io_hccs.h"
#include "io_morley.h"
+//#include "io_oak.h"
#include "io_we.h"
#include "lark.h"
#include "laserd.h"
@@ -284,11 +278,12 @@ void device_archimedes_podule_interface::interface_post_start()
#include "rs423.h"
#include "scan256.h"
#include "scanlight.h"
-//#include "scsi_a500.h"
-//#include "scsi_acorn.h"
-//#include "scsi_ling.h"
-//#include "scsi_morley.h"
-//#include "scsi_oak.h"
+#include "scsi_a500.h"
+#include "scsi_acorn.h"
+#include "scsi_cumana.h"
+#include "scsi_ling.h"
+#include "scsi_morley.h"
+#include "scsi_oak.h"
#include "scsi_vti.h"
#include "serial.h"
#include "spectra.h"
@@ -314,8 +309,8 @@ void archimedes_exp_devices(device_slot_interface &device)
//device.option_add("ccgold", ARC_CCGOLD); // Wild Vision/Computer Concepts Colour Card Gold
device.option_add("eaglem2", ARC_EAGLEM2); // Wild Vision/Computer Concepts Eagle M2
device.option_add("ether1", ARC_ETHER1_AKA25); // Acorn AKA25 Ethernet
- //device.option_add("ether2", ARC_ETHER2_AEH50); // Acorn AEH50 Ethernet II
- //device.option_add("ether3_aeh54", ARC_ETHER3_AEH54); // Acorn AEH54 10Base2 Ethernet Podule
+ device.option_add("ether2", ARC_ETHER2_AEH50); // Acorn AEH50 Ethernet II
+ device.option_add("ether3_aeh54", ARC_ETHER3_AEH54); // Acorn AEH54 10Base2 Ethernet Podule
//device.option_add("ether5", ARC_ETHER5); // Atomwide Ethernet V Podule
device.option_add("etherr", ARC_ETHERR); // RISC Developments Ethernet Card
device.option_add("faxpack", ARC_FAXPACK); // Computer Concepts Fax-Pack
@@ -344,6 +339,7 @@ void archimedes_exp_devices(device_slot_interface &device)
//device.option_add("prisma3", ARC_PRISMA3); // Millipede PRISMA-3 Podule
//device.option_add("prisma3p", ARC_PRISMA3P); // Millipede PRISMA-3 Plus Podule
device.option_add("rom_aka05", ARC_ROM_AKA05); // Acorn AKA05 ROM Podule
+ device.option_add("rom_r225boot", ARC_ROM_R225); // Acorn AKA05 ROM (with DiscLess Bootstrap support)
//device.option_add("rom_cc", ARC_ROM_CC); // Computer Concepts ROM/RAM Podule
device.option_add("rs423", ARC_RS423); // Intelligent Interfaces Dual RS423 Serial Interface
device.option_add("scan256", ARC_SCAN256); // Watford Electronics 256 Grey-Scale Scanner
@@ -351,12 +347,13 @@ void archimedes_exp_devices(device_slot_interface &device)
device.option_add("scanjunior", ARC_SCANJUNIOR); // Computer Concepts ScanLight Junior
device.option_add("scanjunior3", ARC_SCANJUNIOR3); // Computer Concepts ScanLight Junior Mk3
device.option_add("scanvideo", ARC_SCANVIDEO); // Computer Concepts ScanLight Video 256
- //device.option_add("scsi_a500", ARC_SCSI_A500); // Acorn A500 SCSI Interface
- //device.option_add("scsi_aka31", ARC_SCSI_AKA31); // Acorn AKA31 SCSI Expansion Card
- //device.option_add("scsi_aka32", ARC_SCSI_AKA32); // Acorn AKA32 CDFS & SCSI Expansion Card
- //device.option_add("scsi_ling", ARC_SCSI_LING); // Lingenuity SCSI Podule
- //device.option_add("scsi_morley", ARC_SCSI_MORLEY); // Morley Electronics 16bit Cached SCSI card
- //device.option_add("scsi_oak", ARC_SCSI_OAK); // Oak Solutions SCSI Interface
+ device.option_add("scsi_a500", ARC_SCSI_A500); // Acorn A500 SCSI Interface
+ device.option_add("scsi_aka31", ARC_SCSI_AKA31); // Acorn AKA31 SCSI Expansion Card
+ device.option_add("scsi_aka32", ARC_SCSI_AKA32); // Acorn AKA32 CDFS & SCSI Expansion Card
+ device.option_add("scsi_cumana", ARC_SCSI_CUMANA); // Cumana 16bit SCSI interface
+ device.option_add("scsi_ling", ARC_SCSI_LING); // Lingenuity SCSI Podule
+ device.option_add("scsi_morley", ARC_SCSI_MORLEY); // Morley Electronics 16bit Cached SCSI card
+ device.option_add("scsi_oak", ARC_SCSI_OAK); // Oak Solutions SCSI Interface
device.option_add("scsi_vti", ARC_SCSI_VTI); // VTI User Port and SCSI Podule
device.option_add("serial", ARC_SERIAL); // Atomwide Serial Expansion Card
device.option_add("spectra", ARC_SPECTRA); // Beebug Spectra Colour Scanner
@@ -371,10 +368,11 @@ void archimedes_exp_devices(device_slot_interface &device)
void archimedes_mini_exp_devices(device_slot_interface &device)
{
+ //device.option_add("a3user_oak", ARC_A3USER_OAK); // Oak Solutions A3000 User/Analogue Port
device.option_add("bbcio_aga30", ARC_BBCIO_AGA30); // Acorn AGA30 BBC I/O Podule
device.option_add("bbcio_we", ARC_BBCIO_WE); // Watford BBC User I/O Card
//device.option_add("disc_a3k6", ARC_DISC_A3K6); // PRES A3K6 Disc Buffer
- //device.option_add("ethera", ARC_ETHERA); // ANT Ethernet 10base2 mini-podule
+ device.option_add("ethera", ARC_ETHERA); // ANT Ethernet 10base2 mini-podule
device.option_add("etherd", ARC_ETHERD); // Digital Services Ethernet Podule
//device.option_add("ide_a3k_hccs", ARC_IDE_A3K_HCCS); // HCCS IDE A3000 Interface
//device.option_add("ide_castle", ARC_IDE_CASTLE); // Castle Technology A3000 IDE Expansion Card
diff --git a/src/devices/bus/archimedes/podule/slot.h b/src/devices/bus/archimedes/podule/slot.h
index eca2c54865f..b05425b9b70 100644
--- a/src/devices/bus/archimedes/podule/slot.h
+++ b/src/devices/bus/archimedes/podule/slot.h
@@ -44,7 +44,7 @@ public:
archimedes_podule_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_resolve_objects() override;
virtual void device_start() override;
@@ -91,12 +91,11 @@ public:
void pfiq_w(int state) { m_out_pfiq_cb(state); }
protected:
- // device-level overrides
- virtual void device_resolve_objects() override;
+ // device_t implementation
virtual void device_start() override;
virtual void device_reset() override;
- // device_memory_interface overrides
+ // device_memory_interface implementation
virtual space_config_vector memory_space_config() const override;
private:
diff --git a/src/devices/bus/astrocde/accessory.cpp b/src/devices/bus/astrocde/accessory.cpp
index fb047e660d8..b2e5fd6cf5c 100644
--- a/src/devices/bus/astrocde/accessory.cpp
+++ b/src/devices/bus/astrocde/accessory.cpp
@@ -66,8 +66,6 @@ void astrocade_accessory_port_device::device_resolve_objects()
m_device = get_card_device();
if (m_device)
m_device->set_screen(m_screen);
-
- m_ltpen_handler.resolve_safe();
}
void astrocade_accessory_port_device::device_start()
diff --git a/src/devices/bus/astrocde/accessory.h b/src/devices/bus/astrocde/accessory.h
index 5386cd1362a..dd4e0f4e50a 100644
--- a/src/devices/bus/astrocde/accessory.h
+++ b/src/devices/bus/astrocde/accessory.h
@@ -63,7 +63,7 @@ class device_astrocade_accessory_interface : public device_interface
public:
virtual ~device_astrocade_accessory_interface();
- DECLARE_WRITE_LINE_MEMBER( write_ltpen ) { m_port->m_ltpen = state; m_port->m_ltpen_handler(state); }
+ void write_ltpen(int state) { m_port->m_ltpen = state; m_port->m_ltpen_handler(state); }
protected:
device_astrocade_accessory_interface(machine_config const &mconfig, device_t &device);
diff --git a/src/devices/bus/astrocde/ctrl.cpp b/src/devices/bus/astrocde/ctrl.cpp
index b33c8aebb49..07aa620aba6 100644
--- a/src/devices/bus/astrocde/ctrl.cpp
+++ b/src/devices/bus/astrocde/ctrl.cpp
@@ -42,7 +42,7 @@ void device_astrocade_ctrl_interface::interface_pre_start()
throw device_missing_dependencies();
}
-WRITE_LINE_MEMBER( device_astrocade_ctrl_interface::write_ltpen )
+void device_astrocade_ctrl_interface::write_ltpen(int state)
{
if (m_port->m_ltpen != state)
{
@@ -72,8 +72,6 @@ astrocade_ctrl_port_device::~astrocade_ctrl_port_device()
void astrocade_ctrl_port_device::device_resolve_objects()
{
m_device = get_card_device();
-
- m_ltpen_handler.resolve_safe();
}
void astrocade_ctrl_port_device::device_start()
diff --git a/src/devices/bus/astrocde/ctrl.h b/src/devices/bus/astrocde/ctrl.h
index 0273b4a80fd..1e7a88396ee 100644
--- a/src/devices/bus/astrocde/ctrl.h
+++ b/src/devices/bus/astrocde/ctrl.h
@@ -34,7 +34,7 @@ protected:
virtual void interface_validity_check(validity_checker &valid) const override ATTR_COLD;
virtual void interface_pre_start() override;
- DECLARE_WRITE_LINE_MEMBER( write_ltpen );
+ void write_ltpen(int state);
private:
astrocade_ctrl_port_device *const m_port;
diff --git a/src/devices/bus/astrocde/slot.cpp b/src/devices/bus/astrocde/slot.cpp
index 6fcc2015160..3cc5ba6e8f5 100644
--- a/src/devices/bus/astrocde/slot.cpp
+++ b/src/devices/bus/astrocde/slot.cpp
@@ -44,11 +44,11 @@ device_astrocade_cart_interface::~device_astrocade_cart_interface()
// rom_alloc - alloc the space for the cart
//-------------------------------------------------
-void device_astrocade_cart_interface::rom_alloc(uint32_t size, const char *tag)
+void device_astrocade_cart_interface::rom_alloc(uint32_t size)
{
if (m_rom == nullptr)
{
- m_rom = device().machine().memory().region_alloc(std::string(tag).append(ASTROCADESLOT_ROM_REGION_TAG).c_str(), size, 1, ENDIANNESS_LITTLE)->base();
+ m_rom = device().machine().memory().region_alloc(device().subtag("^cart:rom"), size, 1, ENDIANNESS_LITTLE)->base();
m_rom_size = size;
}
}
@@ -134,12 +134,12 @@ static const char *astrocade_get_slot(int type)
call load
-------------------------------------------------*/
-image_init_result astrocade_cart_slot_device::call_load()
+std::pair<std::error_condition, std::string> astrocade_cart_slot_device::call_load()
{
if (m_cart)
{
- uint32_t size = !loaded_through_softlist() ? length() : get_software_region_length("rom");
- m_cart->rom_alloc(size, tag());
+ uint32_t const size = !loaded_through_softlist() ? length() : get_software_region_length("rom");
+ m_cart->rom_alloc(size);
if (!loaded_through_softlist())
fread(m_cart->get_rom_base(), size);
@@ -163,11 +163,9 @@ image_init_result astrocade_cart_slot_device::call_load()
}
//printf("Type: %s\n", astrocade_get_slot(m_type));
-
- return image_init_result::PASS;
}
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
diff --git a/src/devices/bus/astrocde/slot.h b/src/devices/bus/astrocde/slot.h
index a366b9dc518..1079133752b 100644
--- a/src/devices/bus/astrocde/slot.h
+++ b/src/devices/bus/astrocde/slot.h
@@ -12,8 +12,6 @@
TYPE DEFINITIONS
***************************************************************************/
-#define ASTROCADESLOT_ROM_REGION_TAG ":cart:rom"
-
/* PCB */
enum
{
@@ -35,8 +33,8 @@ public:
// reading and writing
virtual uint8_t read_rom(offs_t offset) { return 0xff; }
- void rom_alloc(uint32_t size, const char *tag);
- uint8_t* get_rom_base() { return m_rom; }
+ void rom_alloc(uint32_t size);
+ uint8_t *get_rom_base() { return m_rom; }
uint32_t get_rom_size() { return m_rom_size; }
protected:
@@ -68,15 +66,15 @@ public:
astrocade_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
virtual ~astrocade_cart_slot_device();
- // image-level overrides
- virtual image_init_result call_load() override;
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
virtual void call_unload() override {}
virtual bool is_reset_on_load() const noexcept override { return true; }
virtual const char *image_interface() const noexcept override { return "astrocde_cart"; }
virtual const char *file_extensions() const noexcept override { return "bin"; }
- // slot interface overrides
+ // device_slot_interface implementation
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
int get_type() { return m_type; }
@@ -85,11 +83,11 @@ public:
uint8_t read_rom(offs_t offset);
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
int m_type;
- device_astrocade_cart_interface* m_cart;
+ device_astrocade_cart_interface *m_cart;
};
// device type definition
diff --git a/src/devices/bus/ata/atadev.cpp b/src/devices/bus/ata/atadev.cpp
index d4e3e3cd3fa..2b1008eef33 100644
--- a/src/devices/bus/ata/atadev.cpp
+++ b/src/devices/bus/ata/atadev.cpp
@@ -10,8 +10,12 @@
#include "atadev.h"
#include "atapicdr.h"
-#include "idehd.h"
+#include "cp2024.h"
+#include "cr589.h"
+#include "hdd.h"
#include "px320a.h"
+#include "xm3301.h"
+#include "zip100.h"
//-------------------------------------------------
// device_ata_interface - constructor
@@ -19,10 +23,7 @@
device_ata_interface::device_ata_interface(const machine_config &mconfig, device_t &device) :
device_interface(device, "ata"),
- m_irq_handler(device),
- m_dmarq_handler(device),
- m_dasp_handler(device),
- m_pdiag_handler(device)
+ m_slot(dynamic_cast<ata_slot_device *>(device.owner()))
{
}
@@ -41,6 +42,10 @@ DEFINE_DEVICE_TYPE(ATA_SLOT, ata_slot_device, "ata_slot", "ATA Connector")
ata_slot_device::ata_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, ATA_SLOT, tag, owner, clock),
device_single_card_slot_interface<device_ata_interface>(mconfig, *this),
+ m_irq_handler(*this),
+ m_dmarq_handler(*this),
+ m_dasp_handler(*this),
+ m_pdiag_handler(*this),
m_dev(nullptr)
{
}
@@ -69,6 +74,11 @@ void ata_devices(device_slot_interface &device)
{
device.option_add("hdd", IDE_HARDDISK);
device.option_add("cdrom", ATAPI_CDROM);
- device.option_add("px320a", PX320A);
+
device.option_add("cf", ATA_CF);
+ device.option_add("cp2024", CP2024);
+ device.option_add("cr589", CR589);
+ device.option_add("px320a", PX320A);
+ device.option_add("xm3301", XM3301);
+ device.option_add("zip100", ZIP100_IDE);
}
diff --git a/src/devices/bus/ata/atadev.h b/src/devices/bus/ata/atadev.h
index 41832a8d22a..d052877349b 100644
--- a/src/devices/bus/ata/atadev.h
+++ b/src/devices/bus/ata/atadev.h
@@ -13,58 +13,71 @@
#pragma once
+class device_ata_interface;
-// ======================> device_ata_interface
-class ata_interface_device;
-
-class device_ata_interface : public device_interface
+class ata_slot_device :
+ public device_t,
+ public device_single_card_slot_interface<device_ata_interface>
{
- friend class abstract_ata_interface_device;
public:
- virtual uint16_t read_dma() = 0;
- virtual uint16_t read_cs0(offs_t offset, uint16_t mem_mask = 0xffff) = 0;
- virtual uint16_t read_cs1(offs_t offset, uint16_t mem_mask = 0xffff) = 0;
+ // construction/destruction
+ ata_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
- virtual void write_dma(uint16_t data) = 0;
- virtual void write_cs0(offs_t offset, uint16_t data, uint16_t mem_mask = 0xffff) = 0;
- virtual void write_cs1(offs_t offset, uint16_t data, uint16_t mem_mask = 0xffff) = 0;
+ auto irq_handler() { return m_irq_handler.bind(); }
+ auto dmarq_handler() { return m_dmarq_handler.bind(); }
+ auto dasp_handler() { return m_dasp_handler.bind(); }
+ auto pdiag_handler() { return m_pdiag_handler.bind(); }
- virtual DECLARE_WRITE_LINE_MEMBER(write_dmack) = 0;
- virtual DECLARE_WRITE_LINE_MEMBER(write_csel) = 0;
- virtual DECLARE_WRITE_LINE_MEMBER(write_dasp) = 0;
- virtual DECLARE_WRITE_LINE_MEMBER(write_pdiag) = 0;
+ device_ata_interface *dev() { return m_dev; }
protected:
- device_ata_interface(const machine_config &mconfig, device_t &device);
+ // device_t implementation
+ virtual void device_config_complete() override;
+ virtual void device_start() override;
+private:
devcb_write_line m_irq_handler;
devcb_write_line m_dmarq_handler;
devcb_write_line m_dasp_handler;
devcb_write_line m_pdiag_handler;
+
+ device_ata_interface *m_dev;
+
+ friend class device_ata_interface;
};
-// ======================> ata_slot_device
-class ata_slot_device : public device_t,
- public device_single_card_slot_interface<device_ata_interface>
+class device_ata_interface : public device_interface
{
public:
- // construction/destruction
- ata_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
+ virtual uint16_t read_dma() = 0;
+ virtual uint16_t read_cs0(offs_t offset, uint16_t mem_mask = 0xffff) = 0;
+ virtual uint16_t read_cs1(offs_t offset, uint16_t mem_mask = 0xffff) = 0;
- device_ata_interface *dev() { return m_dev; }
+ virtual void write_dma(uint16_t data) = 0;
+ virtual void write_cs0(offs_t offset, uint16_t data, uint16_t mem_mask = 0xffff) = 0;
+ virtual void write_cs1(offs_t offset, uint16_t data, uint16_t mem_mask = 0xffff) = 0;
+
+ virtual void write_dmack(int state) = 0;
+ virtual void write_csel(int state) = 0;
+ virtual void write_dasp(int state) = 0;
+ virtual void write_pdiag(int state) = 0;
protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_config_complete() override;
+ device_ata_interface(const machine_config &mconfig, device_t &device);
+
+ void set_irq(int state) { m_slot->m_irq_handler(state); }
+ void set_dmarq(int state) { m_slot->m_dmarq_handler(state); }
+ void set_dasp(int state) { m_slot->m_dasp_handler(state); }
+ void set_pdiag(int state) { m_slot->m_pdiag_handler(state); }
private:
- device_ata_interface *m_dev;
+ ata_slot_device *const m_slot;
};
-// device type definition
+
+// device type declaration
DECLARE_DEVICE_TYPE(ATA_SLOT, ata_slot_device)
void ata_devices(device_slot_interface &device);
diff --git a/src/devices/bus/ata/atahle.cpp b/src/devices/bus/ata/atahle.cpp
deleted file mode 100644
index 0ba22e2773b..00000000000
--- a/src/devices/bus/ata/atahle.cpp
+++ /dev/null
@@ -1,968 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:smf
-#include "emu.h"
-#include "atahle.h"
-
-#define VERBOSE 0
-#define PRINTF_IDE_COMMANDS 0
-
-#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
-#define LOGPRINT(x) do { if (VERBOSE) logerror x; if (PRINTF_IDE_COMMANDS) osd_printf_debug x; } while (0)
-
-enum
-{
- IDE_CS0_DATA_RW = 0,
- IDE_CS0_ERROR_R = 1,
- IDE_CS0_FEATURE_W = 1,
- IDE_CS0_SECTOR_COUNT_RW = 2,
- IDE_CS0_SECTOR_NUMBER_RW = 3,
- IDE_CS0_CYLINDER_LOW_RW = 4,
- IDE_CS0_CYLINDER_HIGH_RW = 5,
- IDE_CS0_DEVICE_HEAD_RW = 6,
- IDE_CS0_STATUS_R = 7,
- IDE_CS0_COMMAND_W = 7
-};
-
-enum
-{
- IDE_CS1_ALTERNATE_STATUS_R = 6,
- IDE_CS1_DEVICE_CONTROL_W = 6,
- IDE_CS1_ACTIVE_STATUS = 7
-};
-
-enum
-{
- IDE_DEVICE_CONTROL_NIEN = 0x02,
- IDE_DEVICE_CONTROL_SRST = 0x04
-};
-
-#define DETECT_DEVICE1_TIME (attotime::from_msec(2))
-#define DEVICE1_PDIAG_TIME (attotime::from_msec(2))
-#define DIAGNOSTIC_TIME (attotime::from_msec(2))
-
-ata_hle_device::ata_hle_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, type, tag, owner, clock),
- device_ata_interface(mconfig, *this),
- m_buffer_offset(0),
- m_buffer_size(0),
- m_error(0),
- m_feature(0),
- m_sector_count(0),
- m_sector_number(0),
- m_cylinder_low(0),
- m_cylinder_high(0),
- m_device_head(0),
- m_status(0),
- m_command(0),
- m_device_control(0),
- m_revert_to_defaults(true),
- m_8bit_data_transfers(false),
- m_csel(0),
- m_daspin(0),
- m_daspout(0),
- m_dmack(0),
- m_dmarq(0),
- m_irq(0),
- m_pdiagin(0),
- m_pdiagout(0),
- m_single_device(0),
- m_resetting(0), m_busy_timer(nullptr), m_buffer_empty_timer(nullptr)
-{
-}
-
-void ata_hle_device::device_start()
-{
- MINIMUM_COMMAND_TIME = attotime::from_usec(10);
-
- m_irq_handler.resolve_safe();
- m_dmarq_handler.resolve_safe();
- m_dasp_handler.resolve_safe();
- m_pdiag_handler.resolve_safe();
-
- m_buffer.resize(sector_length());
- save_item(NAME(m_buffer));
- save_item(NAME(m_buffer_offset));
- save_item(NAME(m_buffer_size));
- save_item(NAME(m_error));
- save_item(NAME(m_feature));
- save_item(NAME(m_sector_count));
- save_item(NAME(m_sector_number));
- save_item(NAME(m_cylinder_low));
- save_item(NAME(m_cylinder_high));
- save_item(NAME(m_device_head));
- save_item(NAME(m_status));
- save_item(NAME(m_command));
- save_item(NAME(m_device_control));
- save_item(NAME(m_revert_to_defaults));
- save_item(NAME(m_8bit_data_transfers));
-
- save_item(NAME(m_single_device));
- save_item(NAME(m_resetting));
-
- save_item(NAME(m_csel));
- save_item(NAME(m_daspin));
- save_item(NAME(m_daspout));
- save_item(NAME(m_dmack));
- save_item(NAME(m_dmarq));
- save_item(NAME(m_irq));
- save_item(NAME(m_pdiagin));
- save_item(NAME(m_pdiagout));
-
- save_item(NAME(m_identify_buffer));
-
- m_busy_timer = timer_alloc(FUNC(ata_hle_device::busy_tick), this);
- m_buffer_empty_timer = timer_alloc(FUNC(ata_hle_device::empty_tick), this);
-}
-
-void ata_hle_device::device_reset()
-{
- /* reset the drive state */
- set_dasp(CLEAR_LINE);
- set_dmarq(CLEAR_LINE);
- set_irq(CLEAR_LINE);
- set_pdiag(CLEAR_LINE);
-
- m_status = 0;
- m_device_control = 0;
- m_resetting = true;
-
- if (m_csel == 0)
- {
- start_busy(DETECT_DEVICE1_TIME, PARAM_DETECT_DEVICE1);
- }
- else
- {
- set_dasp(ASSERT_LINE);
- soft_reset();
- }
-}
-
-void ata_hle_device::soft_reset()
-{
- m_buffer_offset = 0;
- m_buffer_size = 0;
- m_status = 0;
-
- if (is_ready())
- {
- m_status |= IDE_STATUS_DRDY;
- }
-
- start_busy(DIAGNOSTIC_TIME, PARAM_DIAGNOSTIC);
-}
-
-TIMER_CALLBACK_MEMBER(ata_hle_device::busy_tick)
-{
- m_status &= ~IDE_STATUS_BSY;
- finished_busy(param);
-}
-
-TIMER_CALLBACK_MEMBER(ata_hle_device::empty_tick)
-{
- m_buffer_empty_timer->enable(false);
- fill_buffer();
-}
-
-void ata_hle_device::finished_busy(int param)
-{
- switch (param)
- {
- case PARAM_DETECT_DEVICE1:
- m_single_device = (m_daspin == CLEAR_LINE);
- soft_reset();
- break;
-
- case PARAM_DIAGNOSTIC:
- start_diagnostic();
- break;
-
- case PARAM_WAIT_FOR_PDIAG:
- m_error |= IDE_ERROR_DIAGNOSTIC_DEVICE1_FAILED;
- finished_diagnostic();
- break;
-
- case PARAM_COMMAND:
- finished_command();
- break;
- }
-}
-
-void ata_hle_device::process_command()
-{
- switch (m_command)
- {
- case IDE_COMMAND_DIAGNOSTIC:
- start_busy(DIAGNOSTIC_TIME, PARAM_COMMAND);
- break;
-
- case IDE_COMMAND_SET_FEATURES:
- start_busy(MINIMUM_COMMAND_TIME, PARAM_COMMAND);
- break;
-
- case IDE_COMMAND_CACHE_FLUSH:
- start_busy(MINIMUM_COMMAND_TIME, PARAM_COMMAND);
- break;
-
- default:
- LOGPRINT(("IDE unknown command (%02X)\n", m_command));
- m_status |= IDE_STATUS_ERR;
- m_error = IDE_ERROR_ABRT;
- set_irq(ASSERT_LINE);
- //machine().debug_break();
- break;
- }
-}
-
-void ata_hle_device::finished_command()
-{
- switch (m_command)
- {
- case IDE_COMMAND_DIAGNOSTIC:
- start_diagnostic();
-
- if (m_csel == 0)
- set_irq(ASSERT_LINE);
- break;
-
- case IDE_COMMAND_SET_FEATURES:
- if (!set_features())
- {
- LOGPRINT(("IDE Set features failed (%02X %02X %02X %02X %02X)\n", m_feature, m_sector_count & 0xff, m_sector_number, m_cylinder_low, m_cylinder_high));
-
- m_status |= IDE_STATUS_ERR;
- m_error = IDE_ERROR_ABRT;
- }
- set_irq(ASSERT_LINE);
- break;
-
- case IDE_COMMAND_CACHE_FLUSH:
- m_status |= IDE_STATUS_DRDY;
- break;
-
- default:
- logerror( "finished_command() unhandled command %02x\n", m_command );
- break;
- }
-}
-
-bool ata_hle_device::set_dma_mode(int word)
-{
- if ((m_identify_buffer[word] >> (m_sector_count & 7)) & 1)
- {
- m_identify_buffer[62] &= 0xff;
- m_identify_buffer[63] &= 0xff;
- m_identify_buffer[88] &= 0xff;
-
- m_identify_buffer[word] |= 0x100 << (m_sector_count & 7);
- return true;
- }
-
- return false;
-}
-
-bool ata_hle_device::set_features()
-{
- switch (m_feature)
- {
- case IDE_SET_FEATURES_ENABLE_8BIT_DATA_TRANSFERS:
- m_8bit_data_transfers = true;
- return true;
-
- case IDE_SET_FEATURES_TRANSFER_MODE:
- switch (m_sector_count & IDE_TRANSFER_TYPE_MASK)
- {
- case IDE_TRANSFER_TYPE_PIO_DEFAULT:
- switch (m_sector_count & 7)
- {
- case 0:
- case 1:
- return true;
- }
- break;
-
- case IDE_TRANSFER_TYPE_PIO_FLOW_CONTROL:
- switch (m_sector_count & 7)
- {
- case 0:
- case 1:
- case 2:
- return true;
-
- default:
- if ((m_identify_buffer[64] >> ((m_sector_count & 7) - 3)) & 1)
- {
- return true;
- }
- }
- break;
-
- case IDE_TRANSFER_TYPE_SINGLE_WORD_DMA:
- return set_dma_mode(62);
-
- case IDE_TRANSFER_TYPE_MULTI_WORD_DMA:
- return set_dma_mode(63);
-
- case IDE_TRANSFER_TYPE_ULTRA_DMA:
- return set_dma_mode(88);
- }
- break;
-
- case IDE_SET_FEATURES_DISABLE_REVERTING_TO_POWER_ON_DEFAULTS:
- m_revert_to_defaults = false;
- return true;
-
- case IDE_SET_FEATURES_DISABLE_8BIT_DATA_TRANSFERS:
- m_8bit_data_transfers = false;
- return true;
-
- case IDE_SET_FEATURES_ENABLE_REVERTING_TO_POWER_ON_DEFAULTS:
- m_revert_to_defaults = true;
- return true;
- }
-
- return false;
-}
-
-int ata_hle_device::bit_to_mode(uint16_t word)
-{
- switch (word>>8)
- {
- case 0x01:
- return 0;
- case 0x02:
- return 1;
- case 0x04:
- return 2;
- case 0x08:
- return 3;
- case 0x10:
- return 4;
- case 0x20:
- return 5;
- case 0x40:
- return 6;
- case 0x080:
- return 7;
- }
-
- return -1;
-}
-
-// Return the currently selected single word dma mode, -1 if none selected
-int ata_hle_device::single_word_dma_mode()
-{
- return bit_to_mode(m_identify_buffer[62]);
-}
-
-// Return the currently selected multi word dma mode, -1 if none selected
-int ata_hle_device::multi_word_dma_mode()
-{
- return bit_to_mode(m_identify_buffer[63]);
-}
-
-// Return the currently selected ultra dma mode, -1 if none selected
-int ata_hle_device::ultra_dma_mode()
-{
- return bit_to_mode(m_identify_buffer[88]);
-}
-
-uint16_t ata_hle_device::read_data()
-{
- /* fetch the correct amount of data */
- uint16_t result = m_buffer[m_buffer_offset++];
- if (!m_8bit_data_transfers)
- result |= m_buffer[m_buffer_offset++] << 8;
-
- /* if we're at the end of the buffer, handle it */
- if (m_buffer_offset >= m_buffer_size)
- {
- LOG(("%s:IDE completed PIO read\n", machine().describe_context()));
- read_buffer_empty();
- }
-
- return result;
-}
-
-void ata_hle_device::write_data(uint16_t data)
-{
- /* store the correct amount of data */
- m_buffer[m_buffer_offset++] = data;
- if (!m_8bit_data_transfers)
- m_buffer[m_buffer_offset++] = data >> 8;
-
- /* if we're at the end of the buffer, handle it */
- if (m_buffer_offset >= m_buffer_size)
- {
- LOG(("%s:IDE completed PIO write\n", machine().describe_context()));
- write_buffer_full();
- }
-}
-
-void ata_hle_device::update_irq()
-{
- if (device_selected() && (m_device_control & IDE_DEVICE_CONTROL_NIEN) == 0)
- m_irq_handler(m_irq);
- else
- m_irq_handler(CLEAR_LINE);
-}
-
-void ata_hle_device::set_irq(int state)
-{
- if (m_irq != state)
- {
- m_irq = state;
-
- update_irq();
- }
-}
-
-void ata_hle_device::set_dmarq(int state)
-{
- if (m_dmarq != state)
- {
- m_dmarq = state;
-
- m_dmarq_handler(state);
- }
-}
-
-void ata_hle_device::set_dasp(int state)
-{
- if (m_daspout != state)
- {
- m_daspout = state;
-
- m_dasp_handler(state);
- }
-}
-
-void ata_hle_device::set_pdiag(int state)
-{
- if (m_pdiagout != state)
- {
- m_pdiagout = state;
-
- m_pdiag_handler(state);
- }
-}
-
-void ata_hle_device::start_busy(const attotime &time, int param)
-{
- m_status |= IDE_STATUS_BSY;
- m_busy_timer->adjust(time, param);
-}
-
-void ata_hle_device::stop_busy()
-{
- m_status &= ~IDE_STATUS_BSY;
- m_busy_timer->adjust(attotime::never);
-}
-
-void ata_hle_device::read_buffer_empty()
-{
- m_buffer_offset = 0;
-
- m_status &= ~IDE_STATUS_DRQ;
-
- if ((multi_word_dma_mode() >= 0) || (ultra_dma_mode() >= 0))
- set_dmarq(CLEAR_LINE);
-
- if (ultra_dma_mode() >= 0) {
- m_buffer_empty_timer->enable(true);
- m_buffer_empty_timer->adjust(attotime::zero);
- }
- else
- fill_buffer();
-}
-
-void ata_hle_device::write_buffer_full()
-{
- m_buffer_offset = 0;
-
- m_status &= ~IDE_STATUS_DRQ;
-
- if ((multi_word_dma_mode() >= 0) || (ultra_dma_mode() >= 0))
- set_dmarq(CLEAR_LINE);
-
- process_buffer();
-}
-
-void ata_hle_device::start_diagnostic()
-{
- m_error = IDE_ERROR_DIAGNOSTIC_FAILED;
-
- perform_diagnostic();
-
- if (m_csel == 1 && m_error == IDE_ERROR_DIAGNOSTIC_PASSED)
- set_pdiag(ASSERT_LINE);
-
- if (m_csel == 0 && !m_single_device && m_pdiagin == CLEAR_LINE)
- start_busy(DEVICE1_PDIAG_TIME, PARAM_WAIT_FOR_PDIAG);
- else
- finished_diagnostic();
-}
-
-void ata_hle_device::finished_diagnostic()
-{
- m_resetting = false;
-
- signature();
-}
-
-
-WRITE_LINE_MEMBER( ata_hle_device::write_csel )
-{
- m_csel = state;
-}
-
-WRITE_LINE_MEMBER( ata_hle_device::write_dasp )
-{
- m_daspin = state;
-}
-
-WRITE_LINE_MEMBER( ata_hle_device::write_dmack )
-{
- if (state && !m_dmack && single_word_dma_mode() >= 0)
- set_dmarq(CLEAR_LINE);
-
- m_dmack = state;
-}
-
-WRITE_LINE_MEMBER( ata_hle_device::write_pdiag )
-{
- m_pdiagin = state;
-
- if (m_pdiagin == ASSERT_LINE && m_busy_timer->param() == PARAM_WAIT_FOR_PDIAG)
- {
- stop_busy();
- finished_diagnostic();
- }
-}
-
-uint16_t ata_hle_device::read_dma()
-{
- uint16_t result = 0xffff;
-
- if (device_selected())
- {
- if (!m_dmack)
- {
- logerror( "%s: %s dev %d read_dma ignored (!DMACK)\n", machine().describe_context(), tag(), dev() );
- }
- else if (m_dmarq && single_word_dma_mode() >= 0)
- {
- logerror( "%s: %s dev %d read_dma ignored (DMARQ)\n", machine().describe_context(), tag(), dev() );
- }
- else if (!m_dmarq && multi_word_dma_mode() >= 0)
- {
- logerror( "%s: %s dev %d read_dma ignored (!DMARQ)\n", machine().describe_context(), tag(), dev() );
- }
- else if (!m_dmarq && ultra_dma_mode() >= 0)
- {
- logerror("%s: %s dev %d read_dma ignored (!DMARQ)\n", machine().describe_context(), tag(), dev());
- }
- else if (m_status & IDE_STATUS_BSY)
- {
- logerror( "%s: %s dev %d read_dma ignored (BSY)\n", machine().describe_context(), tag(), dev() );
- }
- else if (!(m_status & IDE_STATUS_DRQ))
- {
- logerror( "%s: %s dev %d read_dma ignored (!DRQ)\n", machine().describe_context(), tag(), dev() );
- }
- else
- {
- result = read_data();
-
- if ((m_status & IDE_STATUS_DRQ) && single_word_dma_mode() >= 0)
- set_dmarq(ASSERT_LINE);
- }
- }
-
- return result;
-}
-
-uint16_t ata_hle_device::read_cs0(offs_t offset, uint16_t mem_mask)
-{
- /* logit */
-// if (offset != IDE_CS0_DATA_RW && offset != IDE_CS0_STATUS_R)
- LOG(("%s:IDE cs0 read at %X, mem_mask=%X\n", machine().describe_context(), offset, mem_mask));
-
- uint16_t result = 0xffff;
-
- if (device_selected() || m_single_device)
- {
- if (m_dmack)
- {
- logerror( "%s: %s dev %d read_cs0 %04x %04x ignored (DMACK)\n", machine().describe_context(), tag(), dev(), offset, mem_mask );
- }
- else if ((m_status & IDE_STATUS_BSY) && offset != IDE_CS0_STATUS_R)
- {
- // ATA5 spec says status reads should also go through here, but this breaks Primal Rage 2.
- // Real hardware might work due to read ahead in the vt83c461.
- if (device_selected())
- {
- switch (offset)
- {
- case IDE_CS0_DATA_RW:
- logerror( "%s: %s dev %d read_cs0 %04x %04x ignored (BSY)\n", machine().describe_context(), tag(), dev(), offset, mem_mask );
- break;
-
- default:
- result = calculate_status();
- break;
- }
- }
- else
- {
- result = 0;
- }
- }
- else
- {
- switch (offset)
- {
- /* read data if there's data to be read */
- case IDE_CS0_DATA_RW:
- if (device_selected())
- {
- if (!(m_status & IDE_STATUS_DRQ))
- {
- logerror( "%s: %s dev %d read_cs0 ignored (!DRQ)\n", machine().describe_context(), tag(), dev() );
- }
- else
- {
- result = read_data();
- }
- }
- else
- {
- result = 0;
- }
- break;
-
- /* return the current error */
- case IDE_CS0_ERROR_R:
- result = m_error;
- break;
-
- /* return the current sector count */
- case IDE_CS0_SECTOR_COUNT_RW:
- result = m_sector_count;
- break;
-
- /* return the current sector */
- case IDE_CS0_SECTOR_NUMBER_RW:
- result = m_sector_number;
- break;
-
- /* return the current cylinder LSB */
- case IDE_CS0_CYLINDER_LOW_RW:
- result = m_cylinder_low;
- break;
-
- /* return the current cylinder MSB */
- case IDE_CS0_CYLINDER_HIGH_RW:
- result = m_cylinder_high;
- break;
-
- /* return the current head */
- case IDE_CS0_DEVICE_HEAD_RW:
- result = m_device_head;
- break;
-
- /* return the current status and clear any pending interrupts */
- case IDE_CS0_STATUS_R:
- if (device_selected())
- {
- result = calculate_status();
-
- if (!(m_status & IDE_STATUS_DRDY) && is_ready())
- m_status |= IDE_STATUS_DRDY;
-
- set_irq(CLEAR_LINE);
- }
- else
- {
- result = 0;
- }
- break;
-
- /* log anything else */
- default:
- logerror("%s:unknown IDE cs0 read at %03X, mem_mask=%X\n", machine().describe_context(), offset, mem_mask);
- break;
- }
- }
- }
-
- /* return the result */
- return result;
-}
-
-
-uint16_t ata_hle_device::read_cs1(offs_t offset, uint16_t mem_mask)
-{
- /* logit */
-// if (offset != IDE_CS1_ALTERNATE_STATUS_R)
- LOG(("%s:IDE cs1 read at %X, mem_mask=%d\n", machine().describe_context(), offset, mem_mask));
-
- uint16_t result = 0xffff;
-
- if (device_selected() || m_single_device)
- {
- if (m_dmack)
- {
- logerror( "%s: %s dev %d read_cs1 %04x %04x ignored (DMACK)\n", machine().describe_context(), tag(), dev(), offset, mem_mask );
- }
- else
- {
- switch (offset)
- {
- case IDE_CS1_ALTERNATE_STATUS_R:
- if (device_selected())
- {
- result = calculate_status();
- }
- else
- {
- result = 0;
- }
- break;
-
- case IDE_CS1_ACTIVE_STATUS:
- /*
-
- bit description
-
- 0 master active
- 1 slave active
- 2 complement of active disk head bit 0
- 3 complement of active disk head bit 1
- 4 complement of active disk head bit 2
- 5 complement of active disk head bit 3
- 6 write in progress
- 7 floppy present (unused)
-
- */
- if (device_selected())
- {
- result = 0x01;
- }
- else
- {
- result = 0;
- }
- break;
-
- /* log anything else */
- default:
- logerror("%s:unknown IDE cs1 read at %03X, mem_mask=%d\n", machine().describe_context(), offset, mem_mask);
- break;
- }
- }
- }
-
- /* return the result */
- return result;
-}
-
-void ata_hle_device::write_dma( uint16_t data )
-{
- if (device_selected())
- {
- if (!m_dmack)
- {
- logerror( "%s: %s dev %d write_dma %04x ignored (!DMACK)\n", machine().describe_context(), tag(), dev(), data );
- }
- else if (m_dmarq && single_word_dma_mode() >= 0)
- {
- logerror( "%s: %s dev %d write_dma %04x ignored (DMARQ)\n", machine().describe_context(), tag(), dev(), data );
- }
- else if (!m_dmarq && multi_word_dma_mode() >= 0)
- {
- logerror( "%s: %s dev %d write_dma %04x ignored (!DMARQ)\n", machine().describe_context(), tag(), dev(), data );
- }
- else if (!m_dmarq && ultra_dma_mode() >= 0)
- {
- logerror("%s: %s dev %d write_dma %04x ignored (!DMARQ)\n", machine().describe_context(), tag(), dev(), data);
- }
- else if (m_status & IDE_STATUS_BSY)
- {
- logerror( "%s: %s dev %d write_dma %04x ignored (BSY)\n", machine().describe_context(), tag(), dev(), data );
- }
- else if (!(m_status & IDE_STATUS_DRQ))
- {
- logerror( "%s: %s dev %d write_dma %04x ignored (!DRQ)\n", machine().describe_context(), tag(), dev(), data );
- }
- else
- {
- write_data(data);
-
- if ((m_status & IDE_STATUS_DRQ) && single_word_dma_mode() >= 0)
- set_dmarq(ASSERT_LINE);
- }
- }
-}
-
-void ata_hle_device::write_cs0(offs_t offset, uint16_t data, uint16_t mem_mask)
-{
- /* logit */
- if (offset != IDE_CS0_DATA_RW)
- LOG(("%s:IDE cs0 write to %X = %08X, mem_mask=%d\n", machine().describe_context(), offset, data, mem_mask));
-
- if (m_dmack)
- {
- logerror( "%s: %s dev %d write_cs0 %04x %04x %04x ignored (DMACK)\n", machine().describe_context(), tag(), dev(), offset, data, mem_mask );
- }
- else if ((m_status & IDE_STATUS_BSY) && offset != IDE_CS0_COMMAND_W)
- {
- logerror( "%s: %s dev %d write_cs0 %04x %04x %04x ignored (BSY) command %02x\n", machine().describe_context(), tag(), dev(), offset, data, mem_mask, m_command );
- }
- else if ((m_status & IDE_STATUS_DRQ) && offset != IDE_CS0_DATA_RW && offset != IDE_CS0_COMMAND_W)
- {
- logerror( "%s: %s dev %d write_cs0 %04x %04x %04x ignored (DRQ) command %02x\n", machine().describe_context(), tag(), dev(), offset, data, mem_mask, m_command );
- }
- else
- {
- uint8_t old;
-
- switch (offset)
- {
- /* write data */
- case IDE_CS0_DATA_RW:
- if (device_selected())
- {
- if (!(m_status & IDE_STATUS_DRQ))
- {
- logerror( "%s: %s dev %d write_cs0 %04x %04x %04x ignored (!DRQ)\n", machine().describe_context(), tag(), dev(), offset, data, mem_mask );
- }
- else
- {
- write_data(data);
- }
- }
- break;
-
- case IDE_CS0_FEATURE_W:
- m_feature = data;
- break;
-
- /* sector count */
- case IDE_CS0_SECTOR_COUNT_RW:
- m_sector_count = (data & 0xff) ? (data & 0xff) : 0x100;
- break;
-
- /* current sector */
- case IDE_CS0_SECTOR_NUMBER_RW:
- m_sector_number = data;
- break;
-
- /* current cylinder LSB */
- case IDE_CS0_CYLINDER_LOW_RW:
- m_cylinder_low = data;
- break;
-
- /* current cylinder MSB */
- case IDE_CS0_CYLINDER_HIGH_RW:
- m_cylinder_high = data;
- break;
-
- /* current head */
- case IDE_CS0_DEVICE_HEAD_RW:
- old = m_device_head;
- m_device_head = data;
-
- if ((m_device_head ^ old) & IDE_DEVICE_HEAD_DRV)
- update_irq();
- break;
-
- /* command */
- case IDE_CS0_COMMAND_W:
- // Packet devices can accept DEVICE RESET when BSY or DRQ is set.
- if (m_status & IDE_STATUS_BSY)
- {
- logerror( "%s: %s dev %d write_cs0 %04x %04x %04x ignored (BSY) command %02x\n", machine().describe_context(), tag(), dev(), offset, data, mem_mask, m_command );
- }
- else if (m_status & IDE_STATUS_DRQ)
- {
- logerror( "%s: %s dev %d write_cs0 %04x %04x %04x ignored (DRQ) command %02x\n", machine().describe_context(), tag(), dev(), offset, data, mem_mask, m_command );
- }
- else if (device_selected() || m_command == IDE_COMMAND_DIAGNOSTIC)
- {
- m_command = data;
-
- /* implicitly clear interrupts & dmarq here */
- set_irq(CLEAR_LINE);
- set_dmarq(CLEAR_LINE);
-
- m_buffer_offset = 0;
-
- set_dasp(CLEAR_LINE);
- m_status &= ~IDE_STATUS_DRQ;
- m_status &= ~IDE_STATUS_ERR;
-
- process_command();
- }
- break;
-
- default:
- logerror("%s:unknown IDE cs0 write at %03X = %04x, mem_mask=%d\n", machine().describe_context(), offset, data, mem_mask);
- break;
- }
- }
-}
-
-void ata_hle_device::write_cs1(offs_t offset, uint16_t data, uint16_t mem_mask)
-{
- /* logit */
- LOG(("%s:IDE cs1 write to %X = %08X, mem_mask=%d\n", machine().describe_context(), offset, data, mem_mask));
-
- if (m_dmack)
- {
- logerror( "%s: %s dev %d write_cs1 %04x %04x %04x ignored (DMACK)\n", machine().describe_context(), tag(), dev(), offset, data, mem_mask );
- }
- else
- {
- uint8_t old;
-
- switch (offset)
- {
- /* adapter control */
- case IDE_CS1_DEVICE_CONTROL_W:
- old = m_device_control;
- m_device_control = data;
-
- if ((m_device_control ^ old) & IDE_DEVICE_CONTROL_NIEN)
- update_irq();
-
- if ((m_device_control ^ old) & IDE_DEVICE_CONTROL_SRST)
- {
- if (m_device_control & IDE_DEVICE_CONTROL_SRST)
- {
- if (m_resetting)
- {
- logerror( "%s: %s dev %d write_cs1 %04x %04x %04x ignored (RESET)\n", machine().describe_context(), tag(), dev(), offset, data, mem_mask );
- }
- else
- {
- set_dasp(CLEAR_LINE);
- set_dmarq(CLEAR_LINE);
- set_irq(CLEAR_LINE);
- set_pdiag(CLEAR_LINE);
-
- start_busy(attotime::never, PARAM_RESET);
- }
- }
- else if (m_busy_timer->param() == PARAM_RESET)
- {
- soft_reset();
- }
- }
- break;
-
- default:
- logerror("%s:unknown IDE cs1 write at %03X = %04x, mem_mask=%d\n", machine().describe_context(), offset, data, mem_mask);
- break;
- }
- }
-}
diff --git a/src/devices/bus/ata/atahle.h b/src/devices/bus/ata/atahle.h
deleted file mode 100644
index 5fcfa90c478..00000000000
--- a/src/devices/bus/ata/atahle.h
+++ /dev/null
@@ -1,221 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:smf
-/***************************************************************************
-
- atahle.h
-
- ATA Device HLE
-
-***************************************************************************/
-
-#ifndef MAME_BUS_ATA_ATAHLE_H
-#define MAME_BUS_ATA_ATAHLE_H
-
-#pragma once
-
-#include "atadev.h"
-
-class ata_hle_device : public device_t, public device_ata_interface
-{
-public:
- virtual uint16_t read_dma() override;
- virtual uint16_t read_cs0(offs_t offset, uint16_t mem_mask = 0xffff) override;
- virtual uint16_t read_cs1(offs_t offset, uint16_t mem_mask = 0xffff) override;
-
- virtual void write_dma(uint16_t data) override;
- virtual void write_cs0(offs_t offset, uint16_t data, uint16_t mem_mask = 0xffff) override;
- virtual void write_cs1(offs_t offset, uint16_t data, uint16_t mem_mask = 0xffff) override;
- virtual DECLARE_WRITE_LINE_MEMBER(write_csel) override;
- virtual DECLARE_WRITE_LINE_MEMBER(write_dasp) override;
- virtual DECLARE_WRITE_LINE_MEMBER(write_dmack) override;
- virtual DECLARE_WRITE_LINE_MEMBER(write_pdiag) override;
-
-protected:
- ata_hle_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void device_start() override;
- virtual void device_reset() override;
-
- TIMER_CALLBACK_MEMBER(busy_tick);
- TIMER_CALLBACK_MEMBER(empty_tick);
-
- void set_irq(int state);
- void set_dmarq(int state);
- void set_dasp(int state);
- void set_pdiag(int state);
-
- void start_busy(const attotime &time, int param);
- void stop_busy();
-
- int dev() { return (m_device_head & IDE_DEVICE_HEAD_DRV) >> 4; }
- bool device_selected() { return m_csel == dev(); }
-
- virtual uint8_t calculate_status() { return m_status; }
- virtual void soft_reset();
- virtual void process_command();
- virtual void finished_command();
- virtual bool set_features();
- virtual int sector_length() = 0;
- virtual void process_buffer() = 0;
- virtual void fill_buffer() = 0;
- virtual bool is_ready() = 0;
- virtual void perform_diagnostic() = 0;
- virtual void signature() = 0;
- virtual uint16_t read_data();
- virtual void write_data(uint16_t data);
-
- int bit_to_mode(uint16_t word);
- int single_word_dma_mode();
- int multi_word_dma_mode();
- int ultra_dma_mode();
-
- /// TODO: not sure this should be protected.
- void read_buffer_empty();
-
- enum
- {
- IDE_STATUS_ERR = 0x01, // Error
- IDE_STATUS_IDX = 0x02, // Index
- IDE_STATUS_CORR = 0x04, // Corrected Data
- IDE_STATUS_DRQ = 0x08, // Data Request
- IDE_STATUS_DSC = 0x10, // ATA Drive Seek Complete
- IDE_STATUS_SERV = 0x10, // ATAPI Service
- IDE_STATUS_DWF = 0x20, // ATA Drive Write Fault
- IDE_STATUS_DMRD = 0x20, // ATAPI DMA Ready
- IDE_STATUS_DRDY = 0x40, // Drive Ready
- IDE_STATUS_BSY = 0x80 // Busy
- };
-
- enum
- {
- IDE_ERROR_NONE = 0x00,
- IDE_ERROR_DIAGNOSTIC_OK = 0x01,
- IDE_ERROR_TRACK0_NOT_FOUND = 0x02,
- IDE_ERROR_ABRT = 0x04,
- IDE_ERROR_BAD_LOCATION = 0x10,
- IDE_ERROR_BAD_SECTOR = 0x80,
- IDE_ERROR_DIAGNOSTIC_FAILED = 0x00,
- IDE_ERROR_DIAGNOSTIC_PASSED = 0x01,
- IDE_ERROR_DIAGNOSTIC_DEVICE1_FAILED = 0x80
- };
-
- enum
- {
- IDE_COMMAND_NOP = 0x00,
- IDE_COMMAND_DEVICE_RESET = 0x08,
- IDE_COMMAND_RECALIBRATE = 0x10,
- IDE_COMMAND_READ_SECTORS = 0x20,
- IDE_COMMAND_READ_SECTORS_NORETRY = 0x21,
- IDE_COMMAND_WRITE_SECTORS = 0x30,
- IDE_COMMAND_WRITE_SECTORS_NORETRY = 0x31,
- IDE_COMMAND_VERIFY_SECTORS = 0x40,
- IDE_COMMAND_VERIFY_SECTORS_NORETRY = 0x41,
- IDE_COMMAND_SEEK = 0x70,
- IDE_COMMAND_DIAGNOSTIC = 0x90,
- IDE_COMMAND_SET_CONFIG = 0x91,
- IDE_COMMAND_PACKET = 0xa0,
- IDE_COMMAND_IDENTIFY_PACKET_DEVICE = 0xa1,
- IDE_COMMAND_READ_MULTIPLE = 0xc4,
- IDE_COMMAND_WRITE_MULTIPLE = 0xc5,
- IDE_COMMAND_SET_BLOCK_COUNT = 0xc6,
- IDE_COMMAND_READ_DMA = 0xc8,
- IDE_COMMAND_WRITE_DMA = 0xca,
- IDE_COMMAND_IDLE_IMMEDIATE = 0xe1,
- IDE_COMMAND_IDLE = 0xe3,
- IDE_COMMAND_CHECK_POWER_MODE = 0xe5,
- IDE_COMMAND_CACHE_FLUSH = 0xe7,
- IDE_COMMAND_IDENTIFY_DEVICE = 0xec,
- IDE_COMMAND_SET_FEATURES = 0xef,
- IDE_COMMAND_SECURITY_UNLOCK = 0xf2,
- IDE_COMMAND_SECURITY_DISABLE_PASSWORD = 0xf6,
- IDE_COMMAND_READ_NATIVE_MAX_ADDRESS = 0xf8,
- IDE_COMMAND_SET_MAX = 0xf9
- };
-
- enum
- {
- IDE_SET_FEATURES_ENABLE_8BIT_DATA_TRANSFERS = 0x01,
- IDE_SET_FEATURES_TRANSFER_MODE = 0x03,
- IDE_SET_FEATURES_DISABLE_REVERTING_TO_POWER_ON_DEFAULTS = 0x66,
- IDE_SET_FEATURES_DISABLE_8BIT_DATA_TRANSFERS = 0x81,
- IDE_SET_FEATURES_ENABLE_REVERTING_TO_POWER_ON_DEFAULTS = 0xcc
- };
-
- enum ide_transfer_type_t
- {
- IDE_TRANSFER_TYPE_PIO_DEFAULT = 0x00,
- IDE_TRANSFER_TYPE_PIO_FLOW_CONTROL = 0x08,
- IDE_TRANSFER_TYPE_SINGLE_WORD_DMA = 0x10,
- IDE_TRANSFER_TYPE_MULTI_WORD_DMA = 0x20,
- IDE_TRANSFER_TYPE_ULTRA_DMA = 0x40,
- IDE_TRANSFER_TYPE_MASK = 0xf8
- };
-
- enum
- {
- IDE_DEVICE_HEAD_HS = 0x0f,
- IDE_DEVICE_HEAD_DRV = 0x10,
- IDE_DEVICE_HEAD_L = 0x40,
- IDE_DEVICE_HEAD_OBSOLETE = 0x80 | 0x20
- };
-
- enum
- {
- TID_BUSY,
- TID_BUFFER_EMPTY
- };
-
- enum
- {
- PARAM_RESET,
- PARAM_DETECT_DEVICE1,
- PARAM_DIAGNOSTIC,
- PARAM_WAIT_FOR_PDIAG,
- PARAM_COMMAND
- };
-
- attotime MINIMUM_COMMAND_TIME;
-
- std::vector<uint8_t> m_buffer;
- uint16_t m_buffer_offset;
- uint16_t m_buffer_size;
- uint8_t m_error;
- uint8_t m_feature;
- uint16_t m_sector_count;
- uint8_t m_sector_number;
- uint8_t m_cylinder_low;
- uint8_t m_cylinder_high;
- uint8_t m_device_head;
- uint8_t m_status;
- uint8_t m_command;
- uint8_t m_device_control;
-
- uint16_t m_identify_buffer[256];
- bool m_revert_to_defaults;
- bool m_8bit_data_transfers;
-
-private:
- void update_irq();
- void write_buffer_full();
- void start_diagnostic();
- void finished_diagnostic();
- void finished_busy(int param);
- bool set_dma_mode(int word);
-
- int m_csel;
- int m_daspin;
- int m_daspout;
- int m_dmack;
- int m_dmarq;
- int m_irq;
- int m_pdiagin;
- int m_pdiagout;
-
- bool m_single_device;
- bool m_resetting;
-
- emu_timer *m_busy_timer;
- emu_timer *m_buffer_empty_timer;
-};
-
-#endif // MAME_BUS_ATA_ATAHLE_H
diff --git a/src/devices/bus/ata/ataintf.cpp b/src/devices/bus/ata/ataintf.cpp
index d2a09e7a689..bd6753ee237 100644
--- a/src/devices/bus/ata/ataintf.cpp
+++ b/src/devices/bus/ata/ataintf.cpp
@@ -40,7 +40,7 @@ void abstract_ata_interface_device::set_dasp(int state)
m_dasp_handler(state);
}
-WRITE_LINE_MEMBER( abstract_ata_interface_device::irq0_write_line )
+void abstract_ata_interface_device::irq0_write_line(int state)
{
if (m_irq[0] != state)
{
@@ -50,7 +50,7 @@ WRITE_LINE_MEMBER( abstract_ata_interface_device::irq0_write_line )
}
}
-WRITE_LINE_MEMBER( abstract_ata_interface_device::irq1_write_line )
+void abstract_ata_interface_device::irq1_write_line(int state)
{
if (m_irq[1] != state)
{
@@ -60,7 +60,7 @@ WRITE_LINE_MEMBER( abstract_ata_interface_device::irq1_write_line )
}
}
-WRITE_LINE_MEMBER( abstract_ata_interface_device::dasp0_write_line )
+void abstract_ata_interface_device::dasp0_write_line(int state)
{
if (m_dasp[0] != state)
{
@@ -70,7 +70,7 @@ WRITE_LINE_MEMBER( abstract_ata_interface_device::dasp0_write_line )
}
}
-WRITE_LINE_MEMBER( abstract_ata_interface_device::dasp1_write_line )
+void abstract_ata_interface_device::dasp1_write_line(int state)
{
if (m_dasp[1] != state)
{
@@ -84,7 +84,7 @@ WRITE_LINE_MEMBER( abstract_ata_interface_device::dasp1_write_line )
}
}
-WRITE_LINE_MEMBER( abstract_ata_interface_device::dmarq0_write_line )
+void abstract_ata_interface_device::dmarq0_write_line(int state)
{
if (m_dmarq[0] != state)
{
@@ -94,7 +94,7 @@ WRITE_LINE_MEMBER( abstract_ata_interface_device::dmarq0_write_line )
}
}
-WRITE_LINE_MEMBER( abstract_ata_interface_device::dmarq1_write_line )
+void abstract_ata_interface_device::dmarq1_write_line(int state)
{
if (m_dmarq[1] != state)
{
@@ -104,12 +104,12 @@ WRITE_LINE_MEMBER( abstract_ata_interface_device::dmarq1_write_line )
}
}
-WRITE_LINE_MEMBER( abstract_ata_interface_device::pdiag0_write_line )
+void abstract_ata_interface_device::pdiag0_write_line(int state)
{
m_pdiag[0] = state;
}
-WRITE_LINE_MEMBER( abstract_ata_interface_device::pdiag1_write_line )
+void abstract_ata_interface_device::pdiag1_write_line(int state)
{
if (m_pdiag[1] != state)
{
@@ -197,7 +197,7 @@ void abstract_ata_interface_device::internal_write_cs1(offs_t offset, uint16_t d
elem->dev()->write_cs1(offset, data, mem_mask);
}
-WRITE_LINE_MEMBER( abstract_ata_interface_device::write_dmack )
+void abstract_ata_interface_device::write_dmack(int state)
{
// logerror( "%s: write_dmack %04x\n", machine().describe_context(), state );
@@ -230,10 +230,6 @@ ata_interface_device::ata_interface_device(const machine_config &mconfig, const
void abstract_ata_interface_device::device_start()
{
- m_irq_handler.resolve_safe();
- m_dmarq_handler.resolve_safe();
- m_dasp_handler.resolve_safe();
-
for (int i = 0; i < 2; i++)
{
m_irq[i] = 0;
@@ -241,26 +237,9 @@ void abstract_ata_interface_device::device_start()
m_dasp[i] = 0;
m_pdiag[i] = 0;
- device_ata_interface *dev = m_slot[i]->dev();
+ device_ata_interface *const dev = m_slot[i]->dev();
if (dev)
- {
- if (i == 0)
- {
- dev->m_irq_handler.bind().set(*this, FUNC(abstract_ata_interface_device::irq0_write_line));
- dev->m_dmarq_handler.bind().set(*this, FUNC(abstract_ata_interface_device::dmarq0_write_line));
- dev->m_dasp_handler.bind().set(*this, FUNC(abstract_ata_interface_device::dasp0_write_line));
- dev->m_pdiag_handler.bind().set(*this, FUNC(abstract_ata_interface_device::pdiag0_write_line));
- }
- else
- {
- dev->m_irq_handler.bind().set(*this, FUNC(abstract_ata_interface_device::irq1_write_line));
- dev->m_dmarq_handler.bind().set(*this, FUNC(abstract_ata_interface_device::dmarq1_write_line));
- dev->m_dasp_handler.bind().set(*this, FUNC(abstract_ata_interface_device::dasp1_write_line));
- dev->m_pdiag_handler.bind().set(*this, FUNC(abstract_ata_interface_device::pdiag1_write_line));
- }
-
dev->write_csel(i);
- }
}
}
@@ -271,6 +250,15 @@ void abstract_ata_interface_device::device_start()
void abstract_ata_interface_device::device_add_mconfig(machine_config &config)
{
- for (size_t slot = 0; slot < SLOT_COUNT; slot++)
- ATA_SLOT(config, m_slot[slot]);
+ ATA_SLOT(config, m_slot[0]);
+ m_slot[0]->irq_handler().set(FUNC(abstract_ata_interface_device::irq0_write_line));
+ m_slot[0]->dmarq_handler().set(FUNC(abstract_ata_interface_device::dmarq0_write_line));
+ m_slot[0]->dasp_handler().set(FUNC(abstract_ata_interface_device::dasp0_write_line));
+ m_slot[0]->pdiag_handler().set(FUNC(abstract_ata_interface_device::pdiag0_write_line));
+
+ ATA_SLOT(config, m_slot[1]);
+ m_slot[1]->irq_handler().set(FUNC(abstract_ata_interface_device::irq1_write_line));
+ m_slot[1]->dmarq_handler().set(FUNC(abstract_ata_interface_device::dmarq1_write_line));
+ m_slot[1]->dasp_handler().set(FUNC(abstract_ata_interface_device::dasp1_write_line));
+ m_slot[1]->pdiag_handler().set(FUNC(abstract_ata_interface_device::pdiag1_write_line));
}
diff --git a/src/devices/bus/ata/ataintf.h b/src/devices/bus/ata/ataintf.h
index 423a8165d35..45819c53436 100644
--- a/src/devices/bus/ata/ataintf.h
+++ b/src/devices/bus/ata/ataintf.h
@@ -59,7 +59,7 @@ public:
uint16_t read_dma();
void write_dma(uint16_t data);
- DECLARE_WRITE_LINE_MEMBER(write_dmack);
+ void write_dmack(int state);
protected:
abstract_ata_interface_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
@@ -86,15 +86,15 @@ protected:
};
private:
- DECLARE_WRITE_LINE_MEMBER(irq0_write_line);
- DECLARE_WRITE_LINE_MEMBER(dmarq0_write_line);
- DECLARE_WRITE_LINE_MEMBER(dasp0_write_line);
- DECLARE_WRITE_LINE_MEMBER(pdiag0_write_line);
+ void irq0_write_line(int state);
+ void dmarq0_write_line(int state);
+ void dasp0_write_line(int state);
+ void pdiag0_write_line(int state);
- DECLARE_WRITE_LINE_MEMBER(irq1_write_line);
- DECLARE_WRITE_LINE_MEMBER(dmarq1_write_line);
- DECLARE_WRITE_LINE_MEMBER(dasp1_write_line);
- DECLARE_WRITE_LINE_MEMBER(pdiag1_write_line);
+ void irq1_write_line(int state);
+ void dmarq1_write_line(int state);
+ void dasp1_write_line(int state);
+ void pdiag1_write_line(int state);
required_device_array<ata_slot_device, SLOT_COUNT> m_slot;
int m_irq[SLOT_COUNT];
@@ -137,6 +137,11 @@ public:
uint16_t cs1_r(offs_t offset, uint16_t mem_mask = 0xffff) { return internal_read_cs1(offset, mem_mask); }
void cs0_w(offs_t offset, uint16_t data, uint16_t mem_mask = 0xffff) { internal_write_cs0(offset, data, mem_mask); }
void cs1_w(offs_t offset, uint16_t data, uint16_t mem_mask = 0xffff) { internal_write_cs1(offset, data, mem_mask); }
+
+ uint16_t cs0_swap_r(offs_t offset, uint16_t mem_mask = 0xffff) { return swapendian_int16(internal_read_cs0(offset, swapendian_int16(mem_mask))); }
+ uint16_t cs1_swap_r(offs_t offset, uint16_t mem_mask = 0xffff) { return swapendian_int16(internal_read_cs1(offset, swapendian_int16(mem_mask))); }
+ void cs0_swap_w(offs_t offset, uint16_t data, uint16_t mem_mask = 0xffff) { internal_write_cs0(offset, swapendian_int16(data), swapendian_int16(mem_mask)); }
+ void cs1_swap_w(offs_t offset, uint16_t data, uint16_t mem_mask = 0xffff) { internal_write_cs1(offset, swapendian_int16(data), swapendian_int16(mem_mask)); }
};
DECLARE_DEVICE_TYPE(ATA_INTERFACE, ata_interface_device)
diff --git a/src/devices/bus/ata/atapicdr.cpp b/src/devices/bus/ata/atapicdr.cpp
index fd3003f58d3..aa32806913f 100644
--- a/src/devices/bus/ata/atapicdr.cpp
+++ b/src/devices/bus/ata/atapicdr.cpp
@@ -2,14 +2,17 @@
// copyright-holders:smf
#include "emu.h"
#include "atapicdr.h"
+#include "gdrom.h"
#define SCSI_SENSE_ASC_MEDIUM_NOT_PRESENT 0x3a
#define SCSI_SENSE_ASC_NOT_READY_TO_READY_TRANSITION 0x28
#define T10MMC_GET_EVENT_STATUS_NOTIFICATION 0x4a
// device type definition
-DEFINE_DEVICE_TYPE(ATAPI_CDROM, atapi_cdrom_device, "cdrom", "ATAPI CD-ROM")
-DEFINE_DEVICE_TYPE(ATAPI_FIXED_CDROM, atapi_fixed_cdrom_device, "cdrom_fixed", "ATAPI fixed CD-ROM")
+DEFINE_DEVICE_TYPE(ATAPI_CDROM, atapi_cdrom_device, "cdrom", "ATAPI CD-ROM")
+DEFINE_DEVICE_TYPE(ATAPI_FIXED_CDROM, atapi_fixed_cdrom_device, "cdrom_fixed", "ATAPI fixed CD-ROM")
+DEFINE_DEVICE_TYPE(ATAPI_DVDROM, atapi_dvdrom_device, "dvdrom", "ATAPI CD/DVD-ROM")
+DEFINE_DEVICE_TYPE(ATAPI_FIXED_DVDROM, atapi_fixed_dvdrom_device, "dvdrom_fixed", "ATAPI fixed CD/DVD-ROM")
atapi_cdrom_device::atapi_cdrom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
atapi_cdrom_device(mconfig, ATAPI_CDROM, tag, owner, clock)
@@ -18,12 +21,28 @@ atapi_cdrom_device::atapi_cdrom_device(const machine_config &mconfig, const char
atapi_cdrom_device::atapi_cdrom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
atapi_hle_device(mconfig, type, tag, owner, clock),
- ultra_dma_mode(0)
+ device_ata_interface(mconfig, *this),
+ m_ultra_dma_mode(0)
+{
+}
+
+atapi_fixed_cdrom_device::atapi_fixed_cdrom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
+ atapi_cdrom_device(mconfig, type, tag, owner, clock)
{
}
atapi_fixed_cdrom_device::atapi_fixed_cdrom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- atapi_cdrom_device(mconfig, ATAPI_FIXED_CDROM, tag, owner, clock)
+ atapi_fixed_cdrom_device(mconfig, ATAPI_FIXED_CDROM, tag, owner, clock)
+{
+}
+
+atapi_dvdrom_device::atapi_dvdrom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ atapi_cdrom_device(mconfig, ATAPI_DVDROM, tag, owner, clock)
+{
+}
+
+atapi_fixed_dvdrom_device::atapi_fixed_dvdrom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ atapi_cdrom_device(mconfig, ATAPI_FIXED_DVDROM, tag, owner, clock)
{
}
@@ -33,8 +52,13 @@ atapi_fixed_cdrom_device::atapi_fixed_cdrom_device(const machine_config &mconfig
void atapi_cdrom_device::device_add_mconfig(machine_config &config)
{
- CDROM(config, "image").set_interface("cdrom");
- CDDA(config, "cdda");
+ if(type() == ATAPI_DVDROM || type() == ATAPI_FIXED_DVDROM)
+ DVDROM(config, "image").set_interface("cdrom");
+ else if(type() == ATAPI_GDROM)
+ GDROM(config, "image").set_interface("cdrom");
+ else
+ CDROM(config, "image").set_interface("cdrom");
+ CDDA(config, "cdda").set_cdrom_tag("image");
}
void atapi_cdrom_device::device_start()
@@ -44,65 +68,80 @@ void atapi_cdrom_device::device_start()
memset(m_identify_buffer, 0, sizeof(m_identify_buffer));
- m_identify_buffer[ 0 ] = 0x8500; // ATAPI device, cmd set 5 compliant, DRQ within 3 ms of PACKET command
-
- m_identify_buffer[ 23 ] = ('1' << 8) | '.';
- m_identify_buffer[ 24 ] = ('0' << 8) | ' ';
- m_identify_buffer[ 25 ] = (' ' << 8) | ' ';
- m_identify_buffer[ 26 ] = (' ' << 8) | ' ';
-
- m_identify_buffer[ 27 ] = ('M' << 8) | 'A';
- m_identify_buffer[ 28 ] = ('M' << 8) | 'E';
- m_identify_buffer[ 29 ] = (' ' << 8) | ' ';
- m_identify_buffer[ 30 ] = (' ' << 8) | ' ';
- m_identify_buffer[ 31 ] = ('V' << 8) | 'i';
- m_identify_buffer[ 32 ] = ('r' << 8) | 't';
- m_identify_buffer[ 33 ] = ('u' << 8) | 'a';
- m_identify_buffer[ 34 ] = ('l' << 8) | ' ';
- m_identify_buffer[ 35 ] = ('C' << 8) | 'D';
- m_identify_buffer[ 36 ] = ('R' << 8) | 'O';
- m_identify_buffer[ 37 ] = ('M' << 8) | ' ';
- m_identify_buffer[ 38 ] = (' ' << 8) | ' ';
- m_identify_buffer[ 39 ] = (' ' << 8) | ' ';
- m_identify_buffer[ 40 ] = (' ' << 8) | ' ';
- m_identify_buffer[ 41 ] = (' ' << 8) | ' ';
- m_identify_buffer[ 42 ] = (' ' << 8) | ' ';
- m_identify_buffer[ 43 ] = (' ' << 8) | ' ';
- m_identify_buffer[ 44 ] = (' ' << 8) | ' ';
- m_identify_buffer[ 45 ] = (' ' << 8) | ' ';
- m_identify_buffer[ 46 ] = (' ' << 8) | ' ';
-
- m_identify_buffer[ 49 ] = 0x0600; // Word 49=Capabilities, IORDY may be disabled (bit_10), LBA Supported mandatory (bit_9)
-
- m_identify_buffer[ 88 ] = ultra_dma_mode;
+ m_identify_buffer[0] = 0x8500; // ATAPI device, cmd set 5 compliant, DRQ within 3 ms of PACKET command
+
+ m_identify_buffer[23] = ('1' << 8) | '.';
+ m_identify_buffer[24] = ('0' << 8) | ' ';
+ m_identify_buffer[25] = (' ' << 8) | ' ';
+ m_identify_buffer[26] = (' ' << 8) | ' ';
+
+ m_identify_buffer[27] = ('M' << 8) | 'A';
+ m_identify_buffer[28] = ('M' << 8) | 'E';
+ m_identify_buffer[29] = (' ' << 8) | ' ';
+ m_identify_buffer[30] = (' ' << 8) | ' ';
+ m_identify_buffer[31] = ('V' << 8) | 'i';
+ m_identify_buffer[32] = ('r' << 8) | 't';
+ m_identify_buffer[33] = ('u' << 8) | 'a';
+ m_identify_buffer[34] = ('l' << 8) | ' ';
+ m_identify_buffer[35] = ('C' << 8) | 'D';
+ m_identify_buffer[36] = ('R' << 8) | 'O';
+ m_identify_buffer[37] = ('M' << 8) | ' ';
+ m_identify_buffer[38] = (' ' << 8) | ' ';
+ m_identify_buffer[39] = (' ' << 8) | ' ';
+ m_identify_buffer[40] = (' ' << 8) | ' ';
+ m_identify_buffer[41] = (' ' << 8) | ' ';
+ m_identify_buffer[42] = (' ' << 8) | ' ';
+ m_identify_buffer[43] = (' ' << 8) | ' ';
+ m_identify_buffer[44] = (' ' << 8) | ' ';
+ m_identify_buffer[45] = (' ' << 8) | ' ';
+ m_identify_buffer[46] = (' ' << 8) | ' ';
+
+ m_identify_buffer[49] = 0x0600; // Word 49=Capabilities, IORDY may be disabled (bit_10), LBA Supported mandatory (bit_9)
+
+ m_identify_buffer[88] = m_ultra_dma_mode;
atapi_hle_device::device_start();
}
void atapi_cdrom_device::set_ultra_dma_mode(uint16_t mode)
{
- ultra_dma_mode = mode;
+ m_ultra_dma_mode = mode;
}
void atapi_cdrom_device::device_reset()
{
atapi_hle_device::device_reset();
m_media_change = true;
+ m_sequence_counter = m_image->sequence_counter();
}
void atapi_fixed_cdrom_device::device_reset()
{
atapi_hle_device::device_reset();
- m_cdrom = m_image->get_cdrom_file();
m_media_change = false;
+ m_sequence_counter = m_image->sequence_counter();
+}
+
+void atapi_dvdrom_device::device_reset()
+{
+ atapi_hle_device::device_reset();
+ m_media_change = true;
+ m_sequence_counter = m_image->sequence_counter();
+}
+
+void atapi_fixed_dvdrom_device::device_reset()
+{
+ atapi_hle_device::device_reset();
+ m_media_change = false;
+ m_sequence_counter = m_image->sequence_counter();
}
void atapi_cdrom_device::process_buffer()
{
- if(m_cdrom != m_image->get_cdrom_file())
+ if( m_sequence_counter != m_image->sequence_counter() )
{
m_media_change = true;
- SetDevice(m_image->get_cdrom_file());
+ m_sequence_counter = m_image->sequence_counter();
}
atapi_hle_device::process_buffer();
}
@@ -128,8 +167,10 @@ void atapi_cdrom_device::ExecCommand()
case T10MMC_CMD_PLAY_AUDIO_TRACK_INDEX:
case T10MMC_CMD_PAUSE_RESUME:
case T10MMC_CMD_PLAY_AUDIO_12:
+ case T10MMC_CMD_READ_CD:
case T10SBC_CMD_READ_12:
- if(!m_cdrom)
+ case T10SBC_CMD_SEEK_10:
+ if(!m_image->exists())
{
m_phase = SCSI_PHASE_STATUS;
m_sense_key = SCSI_SENSE_KEY_MEDIUM_ERROR;
@@ -157,4 +198,10 @@ void atapi_cdrom_device::ExecCommand()
break;
}
t10mmc::ExecCommand();
+
+ // truckk requires seek complete flag to be set after calling the SEEK command
+ // so set the seek complete status flag after a successful request to emulate
+ // having asked the device itself to seek
+ if (command[0] == T10SBC_CMD_SEEK_10 && m_status_code == SCSI_STATUS_CODE_GOOD)
+ m_status |= IDE_STATUS_DSC;
}
diff --git a/src/devices/bus/ata/atapicdr.h b/src/devices/bus/ata/atapicdr.h
index c2ffbb92fee..16c4a171517 100644
--- a/src/devices/bus/ata/atapicdr.h
+++ b/src/devices/bus/ata/atapicdr.h
@@ -4,7 +4,7 @@
atapicdr.h
- ATAPI CDROM
+ ATAPI CDROM/DVDROM
***************************************************************************/
@@ -13,10 +13,13 @@
#pragma once
+#include "atadev.h"
#include "atapihle.h"
+
#include "machine/t10mmc.h"
-class atapi_cdrom_device : public atapi_hle_device, public t10mmc
+
+class atapi_cdrom_device : public atapi_hle_device, public device_ata_interface, public t10mmc
{
public:
atapi_cdrom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
@@ -25,6 +28,20 @@ public:
uint16_t *identify_device_buffer() { return m_identify_buffer; }
+ // device_ata_interface implementation
+ virtual uint16_t read_dma() override { return dma_r(); }
+ virtual uint16_t read_cs0(offs_t offset, uint16_t mem_mask) override { return command_r(offset); }
+ virtual uint16_t read_cs1(offs_t offset, uint16_t mem_mask) override { return control_r(offset); }
+
+ virtual void write_dma(uint16_t data) override { dma_w(data); }
+ virtual void write_cs0(offs_t offset, uint16_t data, uint16_t mem_mask) override { command_w(offset, data); }
+ virtual void write_cs1(offs_t offset, uint16_t data, uint16_t mem_mask) override { control_w(offset, data); }
+
+ virtual void write_dmack(int state) override { set_dmack_in(state); }
+ virtual void write_csel(int state) override { set_csel_in(state); }
+ virtual void write_dasp(int state) override { set_dasp_in(state); }
+ virtual void write_pdiag(int state) override { set_pdiag_in(state); }
+
protected:
atapi_cdrom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
@@ -37,8 +54,16 @@ protected:
virtual void identify_packet_device() override;
virtual void process_buffer() override;
virtual void ExecCommand() override;
+ u32 m_sequence_counter;
bool m_media_change;
- uint16_t ultra_dma_mode;
+ uint16_t m_ultra_dma_mode;
+
+private:
+ // ata_hle_device_base implementation
+ virtual void set_irq_out(int state) override { device_ata_interface::set_irq(state); }
+ virtual void set_dmarq_out(int state) override { device_ata_interface::set_dmarq(state); }
+ virtual void set_dasp_out(int state) override { device_ata_interface::set_dasp(state); }
+ virtual void set_pdiag_out(int state) override { device_ata_interface::set_pdiag(state); }
};
class atapi_fixed_cdrom_device : public atapi_cdrom_device
@@ -47,11 +72,32 @@ public:
atapi_fixed_cdrom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
+ atapi_fixed_cdrom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+ virtual void device_reset() override;
+};
+
+class atapi_dvdrom_device : public atapi_cdrom_device
+{
+public:
+ atapi_dvdrom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual void device_reset() override;
+};
+
+class atapi_fixed_dvdrom_device : public atapi_cdrom_device
+{
+public:
+ atapi_fixed_dvdrom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
virtual void device_reset() override;
};
// device type definition
-DECLARE_DEVICE_TYPE(ATAPI_CDROM, atapi_cdrom_device)
-DECLARE_DEVICE_TYPE(ATAPI_FIXED_CDROM, atapi_fixed_cdrom_device)
+DECLARE_DEVICE_TYPE(ATAPI_CDROM, atapi_cdrom_device)
+DECLARE_DEVICE_TYPE(ATAPI_FIXED_CDROM, atapi_fixed_cdrom_device)
+DECLARE_DEVICE_TYPE(ATAPI_DVDROM, atapi_dvdrom_device)
+DECLARE_DEVICE_TYPE(ATAPI_FIXED_DVDROM, atapi_fixed_dvdrom_device)
#endif // MAME_BUS_ATA_ATAPICDR_H
diff --git a/src/devices/bus/ata/atapihle.cpp b/src/devices/bus/ata/atapihle.cpp
index b416cdf1e94..0161084fe1d 100644
--- a/src/devices/bus/ata/atapihle.cpp
+++ b/src/devices/bus/ata/atapihle.cpp
@@ -3,23 +3,32 @@
#include "emu.h"
#include "atapihle.h"
-atapi_hle_device::atapi_hle_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
- : ata_hle_device(mconfig, type, tag, owner, clock),
+atapi_hle_device::atapi_hle_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
+ ata_hle_device_base(mconfig, type, tag, owner, clock),
m_packet(0),
- m_data_size(0)
+ m_data_size(0),
+ m_is_ready(false)
{
}
void atapi_hle_device::device_start()
{
t10_start(*this);
- ata_hle_device::device_start();
+ ata_hle_device_base::device_start();
}
void atapi_hle_device::device_reset()
{
t10_reset();
- ata_hle_device::device_reset();
+ ata_hle_device_base::device_reset();
+}
+
+void atapi_hle_device::set_is_ready(bool state)
+{
+ if (has_running_machine() && (machine().phase() >= machine_phase::RESET))
+ throw emu_fatalerror("Static ready state should only be set during configuration");
+
+ m_is_ready = state;
}
void atapi_hle_device::process_buffer()
@@ -227,8 +236,8 @@ void atapi_hle_device::process_command()
for( int w = 0; w < 256; w++ )
{
- m_buffer[w * 2] = m_identify_buffer[ w ] & 0xff;
- m_buffer[(w * 2) + 1] = m_identify_buffer[ w ] >> 8;
+ m_buffer[w * 2] = m_identify_buffer[w] & 0xff;
+ m_buffer[(w * 2) + 1] = m_identify_buffer[w] >> 8;
}
m_buffer_size = 512;
@@ -257,7 +266,7 @@ void atapi_hle_device::process_command()
break;
default:
- ata_hle_device::process_command();
+ ata_hle_device_base::process_command();
break;
}
}
@@ -267,7 +276,7 @@ void atapi_hle_device::finished_command()
switch (m_command)
{
default:
- ata_hle_device::finished_command();
+ ata_hle_device_base::finished_command();
break;
}
}
diff --git a/src/devices/bus/ata/atapihle.h b/src/devices/bus/ata/atapihle.h
index 8d1bb95eec4..8cfe47710f5 100644
--- a/src/devices/bus/ata/atapihle.h
+++ b/src/devices/bus/ata/atapihle.h
@@ -13,10 +13,10 @@
#pragma once
-#include "atahle.h"
+#include "machine/atahle.h"
#include "machine/t10spc.h"
-class atapi_hle_device : public ata_hle_device, public virtual t10spc
+class atapi_hle_device : public ata_hle_device_base, public virtual t10spc
{
public:
enum atapi_features_flag_t
@@ -46,6 +46,8 @@ public:
PACKET_COMMAND_RESPONSE_DRQ_50US
};
+ void set_is_ready(bool state);
+
protected:
atapi_hle_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
@@ -55,7 +57,7 @@ protected:
virtual int sector_length() override { return ATAPI_BUFFER_LENGTH; }
virtual void process_buffer() override;
virtual void fill_buffer() override;
- virtual bool is_ready() override { return false; }
+ virtual bool is_ready() override { return m_is_ready; }
virtual void signature() override;
virtual void process_command() override;
virtual void finished_command() override;
@@ -70,6 +72,7 @@ private:
int m_packet;
int m_data_size;
+ bool m_is_ready;
static constexpr int ATAPI_BUFFER_LENGTH = 0xf800;
};
diff --git a/src/devices/bus/ata/cp2024.cpp b/src/devices/bus/ata/cp2024.cpp
new file mode 100644
index 00000000000..15dc652341f
--- /dev/null
+++ b/src/devices/bus/ata/cp2024.cpp
@@ -0,0 +1,101 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/*******************************************************************************
+
+ Skeleton device for Conner Peripherals CP-2024 2.5″ IDE hard disk drive.
+
+ Codename: "Kato"
+ ICs: Linear Technology LT1072 (DIP8)
+ Cirrus Logic SH110-00PC (PLCC28)
+ Cirrus Logic CL-SH265-25QC-C (QFP100)
+ Microchip 27C256-20/L (PLCC32)
+ Motorola SC80566FN (PLCC52)
+ Texas Instruments LS01 (SOP14)
+ S-MOS 61100-003 (QFP64)
+ Cirrus Logic 61094-4 (PLCC44)
+ LSI Logic(?) 61089-003 (PLCC52)
+
+*******************************************************************************/
+
+#include "emu.h"
+#include "cp2024.h"
+#include "cpu/mc68hc11/mc68hc11.h"
+
+DEFINE_DEVICE_TYPE(CP2024, cp2024_device, "cp2024", "Conner Peripherals CP-2024 hard disk")
+
+cp2024_device::cp2024_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, CP2024, tag, owner, clock)
+ , device_ata_interface(mconfig, *this)
+{
+}
+
+void cp2024_device::device_start()
+{
+}
+
+
+u16 cp2024_device::read_dma()
+{
+ return 0;
+}
+
+u16 cp2024_device::read_cs0(offs_t offset, u16 mem_mask)
+{
+ return 0;
+}
+
+u16 cp2024_device::read_cs1(offs_t offset, u16 mem_mask)
+{
+ return 0;
+}
+
+void cp2024_device::write_dma(u16 data)
+{
+}
+
+void cp2024_device::write_cs0(offs_t offset, u16 data, u16 mem_mask)
+{
+}
+
+void cp2024_device::write_cs1(offs_t offset, u16 data, u16 mem_mask)
+{
+}
+
+void cp2024_device::write_dmack(int state)
+{
+}
+
+void cp2024_device::write_csel(int state)
+{
+}
+
+void cp2024_device::write_dasp(int state)
+{
+}
+
+void cp2024_device::write_pdiag(int state)
+{
+}
+
+
+void cp2024_device::mcu_map(address_map &map)
+{
+ //map(0x0000, 0x00ff).m("sh265", FUNC(cl_sh265_device::map));
+ map(0x8000, 0xffff).rom().region("eprom", 0);
+}
+
+void cp2024_device::device_add_mconfig(machine_config &config)
+{
+ mc68hc11a1_device &mcu(MC68HC11A1(config, "mcu", 10'000'000)); // clock unknown
+ mcu.set_addrmap(AS_PROGRAM, &cp2024_device::mcu_map);
+}
+
+ROM_START(cp2024)
+ ROM_REGION(0x8000, "eprom", 0)
+ ROM_LOAD("27c256.bin", 0x0000, 0x8000, CRC(574b5904) SHA1(79bccc33835ba01fc4eb33fb4d412a691e7790c2))
+ROM_END
+
+const tiny_rom_entry *cp2024_device::device_rom_region() const
+{
+ return ROM_NAME(cp2024);
+}
diff --git a/src/devices/bus/ata/cp2024.h b/src/devices/bus/ata/cp2024.h
new file mode 100644
index 00000000000..5b0182a5012
--- /dev/null
+++ b/src/devices/bus/ata/cp2024.h
@@ -0,0 +1,40 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+
+#ifndef MAME_BUS_ATA_CP2024_H
+#define MAME_BUS_ATA_CP2024_H
+
+#pragma once
+
+#include "atadev.h"
+
+class cp2024_device : public device_t, public device_ata_interface
+{
+public:
+ cp2024_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ static constexpr feature_type unemulated_features() { return feature::DISK; }
+
+protected:
+ virtual void device_start() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+ virtual u16 read_dma() override;
+ virtual u16 read_cs0(offs_t offset, u16 mem_mask = 0xffff) override;
+ virtual u16 read_cs1(offs_t offset, u16 mem_mask = 0xffff) override;
+ virtual void write_dma(u16 data) override;
+ virtual void write_cs0(offs_t offset, u16 data, u16 mem_mask = 0xffff) override;
+ virtual void write_cs1(offs_t offset, u16 data, u16 mem_mask = 0xffff) override;
+ virtual void write_dmack(int state) override;
+ virtual void write_csel(int state) override;
+ virtual void write_dasp(int state) override;
+ virtual void write_pdiag(int state) override;
+
+private:
+ void mcu_map(address_map &map);
+};
+
+DECLARE_DEVICE_TYPE(CP2024, cp2024_device)
+
+#endif // MAME_BUS_ATA_CP2024_H
diff --git a/src/devices/bus/ata/cr589.cpp b/src/devices/bus/ata/cr589.cpp
index 5905a54bd54..15309f6e41e 100644
--- a/src/devices/bus/ata/cr589.cpp
+++ b/src/devices/bus/ata/cr589.cpp
@@ -3,6 +3,8 @@
#include "emu.h"
#include "cr589.h"
+#include "multibyte.h"
+
static constexpr int identity_offset = 0x3ab;
static constexpr char download_identity[] = "MATSHITA CD98Q4 DOWNLOADGS0N";
@@ -14,8 +16,8 @@ static constexpr char download_identity[] = "MATSHITA CD98Q4 DOWNLOADGS0N";
void matsushita_cr589_device::nvram_default()
{
- memset( buffer, 0, sizeof(buffer));
- memcpy( &buffer[ identity_offset ], "MATSHITACD-ROM CR-589 GS0N", 28 );
+ memset(buffer, 0, sizeof(buffer));
+ memcpy(&buffer[identity_offset], "MATSHITACD-ROM CR-589 GS0N", 28);
}
@@ -27,8 +29,8 @@ void matsushita_cr589_device::nvram_default()
bool matsushita_cr589_device::nvram_read(util::read_stream &file)
{
- size_t actual;
- return !file.read(buffer, sizeof(buffer), actual) && actual == sizeof(buffer);
+ auto const [err, actual] = read(file, buffer, sizeof(buffer));
+ return !err && (actual == sizeof(buffer));
}
@@ -40,35 +42,35 @@ bool matsushita_cr589_device::nvram_read(util::read_stream &file)
bool matsushita_cr589_device::nvram_write(util::write_stream &file)
{
- size_t actual;
- return !file.write(buffer, sizeof(buffer), actual) && actual == sizeof(buffer);
+ auto const [err, actual] = write(file, buffer, sizeof(buffer));
+ return !err;
}
void matsushita_cr589_device::ExecCommand()
{
- switch( command[ 0 ] )
+ switch( command[0] )
{
case T10SPC_CMD_INQUIRY:
logerror("T10MMC: INQUIRY\n");
m_phase = SCSI_PHASE_DATAIN;
m_status_code = SCSI_STATUS_CODE_GOOD;
- m_transfer_length = SCSILengthFromUINT8( &command[ 4 ] );
+ m_transfer_length = SCSILengthFromUINT8( &command[4] );
break;
case 0x3b: // WRITE BUFFER
- bufferOffset = ( command[ 3 ] << 16 ) | ( command[ 4 ] << 8 ) | command[ 5 ];
+ bufferOffset = get_u24be( &command[3] );
m_phase = SCSI_PHASE_DATAOUT;
m_status_code = SCSI_STATUS_CODE_GOOD;
- m_transfer_length = ( command[ 6 ] << 16 ) | ( command[ 7 ] << 8 ) | command[ 8 ];
+ m_transfer_length = get_u24be( &command[6] );
break;
case 0x3c: // READ BUFFER
- bufferOffset = ( command[ 3 ] << 16 ) | ( command[ 4 ] << 8 ) | command[ 5 ];
+ bufferOffset = get_u24be( &command[3] );
m_phase = SCSI_PHASE_DATAIN;
m_status_code = SCSI_STATUS_CODE_GOOD;
- m_transfer_length = ( command[ 6 ] << 16 ) | ( command[ 7 ] << 8 ) | command[ 8 ];
+ m_transfer_length = get_u24be( &command[6] );
break;
case 0xcc: // FIRMWARE DOWNLOAD ENABLE
@@ -85,7 +87,7 @@ void matsushita_cr589_device::ExecCommand()
void matsushita_cr589_device::ReadData( uint8_t *data, int dataLength )
{
- switch( command[ 0 ] )
+ switch( command[0] )
{
case T10SPC_CMD_INQUIRY:
memset(data, 0, dataLength);
@@ -94,16 +96,16 @@ void matsushita_cr589_device::ReadData( uint8_t *data, int dataLength )
if( download )
{
- memcpy( &data[ 8 ], download_identity, 28 );
+ memcpy( &data[8], download_identity, 28 );
}
else
{
- memcpy( &data[ 8 ], &buffer[ identity_offset ], 28 );
+ memcpy( &data[8], &buffer[identity_offset], 28 );
}
break;
case 0x3c: // READ BUFFER
- memcpy( data, &buffer[ bufferOffset ], dataLength );
+ memcpy( data, &buffer[bufferOffset], dataLength );
bufferOffset += dataLength;
break;
@@ -115,15 +117,15 @@ void matsushita_cr589_device::ReadData( uint8_t *data, int dataLength )
void matsushita_cr589_device::WriteData( uint8_t *data, int dataLength )
{
- switch( command[ 0 ] )
+ switch( command[0] )
{
case 0x3b: // WRITE BUFFER
- memcpy( &buffer[ bufferOffset ], data + 32, dataLength - 32 );
+ memcpy( &buffer[bufferOffset], data + 32, dataLength - 32 );
bufferOffset += dataLength;
break;
case 0xcc: // FIRMWARE DOWNLOAD ENABLE
- if( memcmp( data, &buffer[ identity_offset ], 28 ) == 0 )
+ if( memcmp( data, &buffer[identity_offset], 28 ) == 0 )
{
download = 1;
}
@@ -159,35 +161,35 @@ void matsushita_cr589_device::device_start()
/// TODO: split identify buffer into another method as device_start() should be called after it's filled in, but the atapi_cdrom_device has it's own.
memset(m_identify_buffer, 0, sizeof(m_identify_buffer));
- m_identify_buffer[ 0 ] = 0x8500; // ATAPI device, cmd set 5 compliant, DRQ within 3 ms of PACKET command
-
- m_identify_buffer[ 23 ] = ('1' << 8) | '.';
- m_identify_buffer[ 24 ] = ('0' << 8) | ' ';
- m_identify_buffer[ 25 ] = (' ' << 8) | ' ';
- m_identify_buffer[ 26 ] = (' ' << 8) | ' ';
-
- m_identify_buffer[ 27 ] = ('M' << 8) | 'A';
- m_identify_buffer[ 28 ] = ('T' << 8) | 'S';
- m_identify_buffer[ 29 ] = ('H' << 8) | 'I';
- m_identify_buffer[ 30 ] = ('T' << 8) | 'A';
- m_identify_buffer[ 31 ] = (' ' << 8) | 'C';
- m_identify_buffer[ 32 ] = ('R' << 8) | '-';
- m_identify_buffer[ 33 ] = ('5' << 8) | '8';
- m_identify_buffer[ 34 ] = ('9' << 8) | ' ';
- m_identify_buffer[ 35 ] = (' ' << 8) | ' ';
- m_identify_buffer[ 36 ] = (' ' << 8) | ' ';
- m_identify_buffer[ 37 ] = (' ' << 8) | ' ';
- m_identify_buffer[ 38 ] = (' ' << 8) | ' ';
- m_identify_buffer[ 39 ] = (' ' << 8) | ' ';
- m_identify_buffer[ 40 ] = (' ' << 8) | ' ';
- m_identify_buffer[ 41 ] = (' ' << 8) | ' ';
- m_identify_buffer[ 42 ] = (' ' << 8) | ' ';
- m_identify_buffer[ 43 ] = (' ' << 8) | ' ';
- m_identify_buffer[ 44 ] = (' ' << 8) | ' ';
- m_identify_buffer[ 45 ] = (' ' << 8) | ' ';
- m_identify_buffer[ 46 ] = (' ' << 8) | ' ';
-
- m_identify_buffer[ 49 ] = 0x0400; // IORDY may be disabled
+ m_identify_buffer[0] = 0x8500; // ATAPI device, cmd set 5 compliant, DRQ within 3 ms of PACKET command
+
+ m_identify_buffer[23] = ('1' << 8) | '.';
+ m_identify_buffer[24] = ('0' << 8) | ' ';
+ m_identify_buffer[25] = (' ' << 8) | ' ';
+ m_identify_buffer[26] = (' ' << 8) | ' ';
+
+ m_identify_buffer[27] = ('M' << 8) | 'A';
+ m_identify_buffer[28] = ('T' << 8) | 'S';
+ m_identify_buffer[29] = ('H' << 8) | 'I';
+ m_identify_buffer[30] = ('T' << 8) | 'A';
+ m_identify_buffer[31] = (' ' << 8) | 'C';
+ m_identify_buffer[32] = ('R' << 8) | '-';
+ m_identify_buffer[33] = ('5' << 8) | '8';
+ m_identify_buffer[34] = ('9' << 8) | ' ';
+ m_identify_buffer[35] = (' ' << 8) | ' ';
+ m_identify_buffer[36] = (' ' << 8) | ' ';
+ m_identify_buffer[37] = (' ' << 8) | ' ';
+ m_identify_buffer[38] = (' ' << 8) | ' ';
+ m_identify_buffer[39] = (' ' << 8) | ' ';
+ m_identify_buffer[40] = (' ' << 8) | ' ';
+ m_identify_buffer[41] = (' ' << 8) | ' ';
+ m_identify_buffer[42] = (' ' << 8) | ' ';
+ m_identify_buffer[43] = (' ' << 8) | ' ';
+ m_identify_buffer[44] = (' ' << 8) | ' ';
+ m_identify_buffer[45] = (' ' << 8) | ' ';
+ m_identify_buffer[46] = (' ' << 8) | ' ';
+
+ m_identify_buffer[49] = 0x0400; // IORDY may be disabled
}
void matsushita_cr589_device::device_reset()
diff --git a/src/devices/bus/ata/cr589.h b/src/devices/bus/ata/cr589.h
index 9b2f89d172c..a68eab7c2be 100644
--- a/src/devices/bus/ata/cr589.h
+++ b/src/devices/bus/ata/cr589.h
@@ -39,7 +39,7 @@ protected:
private:
int download;
- uint8_t buffer[ 65536 ];
+ uint8_t buffer[65536];
int bufferOffset;
};
diff --git a/src/devices/bus/ata/gdrom.cpp b/src/devices/bus/ata/gdrom.cpp
index 59a7d154d56..621710a49a6 100644
--- a/src/devices/bus/ata/gdrom.cpp
+++ b/src/devices/bus/ata/gdrom.cpp
@@ -8,18 +8,25 @@
#include "emu.h"
#include "gdrom.h"
+#include "coreutil.h"
+
+#include <iostream>
#define LOG_WARN (1U << 1)
#define LOG_CMD (1U << 2)
-#define LOG_XFER (1U << 3)
+#define LOG_CMD_RAW (1U << 3) // bare command IDs (temp until all commands are in)
+#define LOG_XFER (1U << 4)
+#define LOG_TOC (1U << 5) // TOC frame offsets
-#define VERBOSE (LOG_WARN | LOG_CMD)
+#define VERBOSE (LOG_GENERAL | LOG_WARN | LOG_CMD | LOG_TOC)
//#define LOG_OUTPUT_STREAM std::cout
#include "logmacro.h"
#define LOGWARN(...) LOGMASKED(LOG_WARN, __VA_ARGS__)
#define LOGCMD(...) LOGMASKED(LOG_CMD, __VA_ARGS__)
+#define LOGCMDRAW(...) LOGMASKED(LOG_CMD_RAW, __VA_ARGS__)
#define LOGXFER(...) LOGMASKED(LOG_XFER, __VA_ARGS__)
+#define LOGTOC(...) LOGMASKED(LOG_TOC, __VA_ARGS__)
#define GDROM_BUSY_STATE 0x00
#define GDROM_PAUSE_STATE 0x01
@@ -32,6 +39,8 @@
#define GDROM_RETRY_STATE 0x08
#define GDROM_ERROR_STATE 0x09
+// CD status readback/subchannel Q
+#define LIVE_REQ_STAT 0
/*
Officially not documented security-related packet commands:
@@ -169,28 +178,200 @@ void gdrom_device::device_reset()
void gdrom_device::ExecCommand()
{
+ LOGCMDRAW("%02x\n", command[0]);
switch ( command[0] )
{
- case 0x11: // REQ_MODE
+ case 0x00:
+ // TEST_UNIT
+ // TODO: verify if t10mmc use is enough
+ // loopchk returns OK in Packet cmnd (0201)
+ t10mmc::ExecCommand();
+ break;
+
+ case 0x10:
+ {
+ transferOffset = command[2];
+ u8 allocation_length = SCSILengthFromUINT8( &command[4] );
+ // any game that enables [redbook]
+ LOGCMD("REQ_STAT 10h offset %02x length %02x\n", transferOffset, allocation_length);
+
+ if (transferOffset || allocation_length != 0xa)
+ throw emu_fatalerror("GDROM: REQ_STAT with unsupported offset %02x length %02x", transferOffset, allocation_length);
+
m_phase = SCSI_PHASE_DATAIN;
m_status_code = SCSI_STATUS_CODE_GOOD;
- LOGCMD("REQ_MODE %02x %02x %02x %02x %02x %02x\n",
- command[0], command[1],
- command[2], command[3],
- command[4], command[5]
- );
-// if (SCSILengthFromUINT8( &command[ 4 ] ) < 32) return -1;
+ m_transfer_length = allocation_length;
+ break;
+ }
+
+ case 0x11:
+ LOGCMD("REQ_MODE 11h %02x %02x\n", command[2], command[4]);
+ m_phase = SCSI_PHASE_DATAIN;
+ m_status_code = SCSI_STATUS_CODE_GOOD;
+
+// if (SCSILengthFromUINT8( &command[4] ) < 32) return -1;
transferOffset = command[2];
- m_transfer_length = SCSILengthFromUINT8( &command[ 4 ] );
+ m_transfer_length = SCSILengthFromUINT8( &command[4] );
+ if (transferOffset & 1)
+ throw emu_fatalerror("GDROM: REQ_MODE with odd offset %02x %02x", transferOffset, m_transfer_length);
break;
case 0x12: // SET_MODE
+ LOGCMD("SET_MODE 12h %02x %02x\n", command[2], command[4]);
+
m_phase = SCSI_PHASE_DATAOUT;
m_status_code = SCSI_STATUS_CODE_GOOD;
//transferOffset = command[2];
- m_transfer_length = SCSILengthFromUINT8( &command[ 4 ] );
- LOGCMD("SET_MODE %02x %02x\n", command[2], command[4]);
+ m_transfer_length = SCSILengthFromUINT8( &command[4] );
+ if (command[2])
+ throw emu_fatalerror("GDROM: SET_MODE with offset %02x %02x", transferOffset, m_transfer_length);
+
+ if (m_transfer_length > 0xa)
+ {
+ LOGWARN("SET_MODE attempt to write on read only regs %02x\n", command[4]);
+ m_transfer_length = 0xa;
+ }
+ break;
+
+ case 0x14:
+ {
+ if (!m_image->exists())
+ {
+ m_phase = SCSI_PHASE_STATUS;
+ m_status_code = SCSI_STATUS_CODE_CHECK_CONDITION;
+ m_transfer_length = 0;
+ break;
+ }
+
+ // TODO: it's supposed to write a single and a double density TOC request
+ //if (command[1])
+ // throw emu_fatalerror("Double density unsupported");
+ u16 allocation_length = SCSILengthFromUINT16( &command[3] );
+ LOGCMD("READ_TOC 14h %02x %02x %d\n",
+ command[1], command[2], allocation_length
+ );
+
+ if (allocation_length != 408)
+ throw emu_fatalerror("TOC with allocation length != 408 (%d)", allocation_length);
+
+ if (m_cdda != nullptr)
+ {
+ m_cdda->stop_audio();
+ m_sector_number = (m_sector_number & 0xf0) | GDROM_STANDBY_STATE;
+ }
+
+ m_phase = SCSI_PHASE_DATAIN;
+ m_status_code = SCSI_STATUS_CODE_GOOD;
+ m_transfer_length = allocation_length;
break;
+ }
+
+ // accessed for audio CDs
+ // TODO: needed for Mil CD support
+ case 0x15:
+ {
+ m_phase = SCSI_PHASE_DATAIN;
+ m_status_code = SCSI_STATUS_CODE_GOOD;
+ m_transfer_length = SCSILengthFromUINT8( &command[4] );
+ LOGCMD("REQ_SES 15h %02x %02x\n", command[2], m_transfer_length);
+ break;
+ }
+
+ case 0x20: // CD_PLAY
+ {
+ if (!m_image->exists())
+ {
+ m_phase = SCSI_PHASE_STATUS;
+ m_status_code = SCSI_STATUS_CODE_CHECK_CONDITION;
+ m_transfer_length = 0;
+ break;
+ }
+
+ const u32 start_offs = (command[2]<<16 | command[3]<<8 | command[4]);
+ const u32 end_offs = (command[8]<<16 | command[9]<<8 | command[10]);
+ //(command[8] % 75) + ((command[7] * 75) % (60*75)) + (command[6] * (75*60)) - m_lba;
+
+ const u8 play_mode = command[1] & 7;
+
+ auto trk = m_image->get_track(start_offs);
+ const u8 repeat = command[6] & 0xf;
+ LOGCMD("CD_PLAY 20h track %d FAD %d blocks %d type %02x repeat %01x\n"
+ , trk + 1
+ , start_offs
+ , end_offs - start_offs
+ , play_mode
+ , repeat
+ );
+
+ if (play_mode == 7 && m_audio_sense == SCSI_SENSE_ASC_ASCQ_AUDIO_PLAY_OPERATION_PAUSED)
+ {
+ m_cdda->pause_audio(0);
+ m_audio_sense = SCSI_SENSE_ASC_ASCQ_AUDIO_PLAY_OPERATION_IN_PROGRESS;
+ LOGCMD("\tPlayback resume\n");
+ m_sector_number = (m_sector_number & 0xf0) | GDROM_PLAY_STATE;
+ }
+ else if (m_image->get_track_type(trk) == cdrom_file::CD_TRACK_AUDIO && end_offs > start_offs)
+ {
+ // TODO: check end > start assertion
+ m_cd_status.cdda_fad = start_offs - 150;
+ m_cd_status.cdda_blocks = (end_offs - start_offs);
+
+ m_cdda->start_audio(m_cd_status.cdda_fad, m_cd_status.cdda_blocks);
+ m_audio_sense = SCSI_SENSE_ASC_ASCQ_AUDIO_PLAY_OPERATION_IN_PROGRESS;
+ m_cd_status.repeat_current = 0;
+ m_cd_status.repeat_count = repeat;
+ m_sector_number = (m_sector_number & 0xf0) | GDROM_PLAY_STATE;
+
+ LOGCMD("\tPlayback started\n");
+ }
+ else
+ {
+ LOGWARN("track is NOT audio!\n");
+ set_sense(SCSI_SENSE_KEY_ILLEGAL_REQUEST, SCSI_SENSE_ASC_ASCQ_ILLEGAL_MODE_FOR_THIS_TRACK);
+ // TODO: unconfirmed state
+ m_sector_number = (m_sector_number & 0xf0) | GDROM_ERROR_STATE;
+ return;
+ }
+
+ m_phase = SCSI_PHASE_STATUS;
+ m_status_code = SCSI_STATUS_CODE_GOOD;
+ m_transfer_length = 0;
+ break;
+ }
+
+ case 0x21:
+ {
+ if (!m_image->exists())
+ {
+ m_phase = SCSI_PHASE_STATUS;
+ m_status_code = SCSI_STATUS_CODE_CHECK_CONDITION;
+ m_transfer_length = 0;
+ break;
+ }
+
+ const u32 start_seek = (command[2]<<16 | command[3]<<8 | command[4]);
+ const u8 seek_mode = command[1] & 0xf;
+ LOGCMD("CD_SEEK 21h FAD %d type %02x\n", start_seek + 150, seek_mode);
+ switch(seek_mode)
+ {
+ // TODO: implement SEEK & standby
+ // 1 FAD seek
+ // 2 MSF seek
+ // 3 stop audio, go to Home FAD
+ case 4:
+ // 4 pause audio
+ LOGCMD("\tPlayback paused\n");
+ m_cdda->pause_audio(1);
+ m_audio_sense = SCSI_SENSE_ASC_ASCQ_AUDIO_PLAY_OPERATION_PAUSED;
+ m_sector_number = (m_sector_number & 0xf0) | GDROM_PAUSE_STATE;
+ break;
+ }
+
+ m_phase = SCSI_PHASE_STATUS;
+ m_status_code = SCSI_STATUS_CODE_GOOD;
+ m_transfer_length = 0;
+ break;
+ }
case 0x30: // CD_READ
if (command[1] & 1)
@@ -204,9 +385,11 @@ void gdrom_device::ExecCommand()
m_blocks = command[8]<<16 | command[9]<<8 | command[10];
read_type = (command[1] >> 1) & 7;
- data_select = (command[1]>>4) & 0xf;
+ data_select = (command[1] >> 4) & 0xf;
+ //m_status |= IDE_STATUS_DSC;
- if (read_type != 2) // mode 1
+ // TODO: any other value is a non-Mode 1 attempt basically
+ if (read_type != 0 && read_type != 2)
{
throw emu_fatalerror("GDROM: Unhandled read_type %d", read_type);
}
@@ -216,9 +399,10 @@ void gdrom_device::ExecCommand()
throw emu_fatalerror("GDROM: Unhandled data_select %d", data_select);
}
- LOGCMD("CD_READ %02x %02x\n", command[2], command[4]);
- LOGCMD(" LBA %x for %d blocks (%d bytes, read type %d, data select %d)\n",
- m_lba, m_blocks,
+ // LBA 45000 is start of double density GD-ROM
+ LOGCMD("CD_READ 30h %02x %02x\n", command[2], command[4]);
+ LOGCMD(" LBA %d (%x) for %d blocks (%d bytes, read type %d, data select %d)\n",
+ m_lba + 150, m_lba, m_blocks,
m_blocks * m_sector_bytes, read_type, data_select
);
@@ -235,6 +419,8 @@ void gdrom_device::ExecCommand()
if (m_cdda != nullptr)
{
m_cdda->stop_audio();
+ m_audio_sense = SCSI_SENSE_ASC_ASCQ_NO_SENSE;
+ m_sector_number = (m_sector_number & 0xf0) | GDROM_STANDBY_STATE;
}
m_phase = SCSI_PHASE_DATAIN;
@@ -243,54 +429,32 @@ void gdrom_device::ExecCommand()
}
break;
- // READ TOC (GD-ROM ver.)
- case 0x14:
+ case 0x40:
{
- if (m_cdrom == nullptr)
- {
- m_phase = SCSI_PHASE_STATUS;
- m_status_code = SCSI_STATUS_CODE_CHECK_CONDITION;
- m_transfer_length = 0;
- break;
- }
-
- // TODO: is this correct?
- int start_trk = command[2];
- int end_trk = m_cdrom->get_last_track();
- int length;
- int allocation_length = SCSILengthFromUINT16( &command[ 3 ] );
-
- if( start_trk == 0 )
- {
- start_trk = 1;
- }
- if( start_trk == 0xaa )
- {
- end_trk = start_trk;
- }
+ m_transfer_length = SCSILengthFromUINT8( &command[4] );
+ //LOGCMD("CD_SCD 40h %02x %d\n", command[1] & 0xf, m_transfer_length);
- length = 4 + ( 8 * ( ( end_trk - start_trk ) + 1 ) );
- if( length > allocation_length )
+ switch(command[1] & 0xf)
{
- length = allocation_length;
- }
- else if( length < 4 )
- {
- length = 4;
- }
-
- if (m_cdda != nullptr)
- {
- m_cdda->stop_audio();
+ case 0x00:
+ m_phase = SCSI_PHASE_DATAIN;
+ m_status_code = SCSI_STATUS_CODE_GOOD;
+ m_transfer_length = SCSILengthFromUINT8( &command[4] );
+ break;
+ case 0x01:
+ m_phase = SCSI_PHASE_DATAIN;
+ m_status_code = SCSI_STATUS_CODE_GOOD;
+ m_transfer_length = 0xe;
+ break;
+ default:
+ LOGWARN("command 0x40: unhandled subchannel request\n");
+ break;
}
-
- m_phase = SCSI_PHASE_DATAIN;
- m_status_code = SCSI_STATUS_CODE_GOOD;
- m_transfer_length = length;
break;
}
- case 0x70: // security check, return no data, always followed by cmd 0x71, command[1] parameter can be 0x1f or 0x9f
+ // security check, return no data, always followed by cmd 0x71, command[1] parameter can be 0x1f or 0x9f
+ case 0x70:
m_phase = SCSI_PHASE_STATUS;
m_status_code = SCSI_STATUS_CODE_GOOD;
m_transfer_length = 0;
@@ -302,22 +466,16 @@ void gdrom_device::ExecCommand()
m_transfer_length = sizeof(GDROM_Cmd71_Reply);
break;
- case 0x40:
- if(command[1] & 0xf)
- {
- m_phase = SCSI_PHASE_DATAIN;
- m_status_code = SCSI_STATUS_CODE_GOOD;
- m_transfer_length = 0xe;
- }
- else
- {
- LOGWARN("command 0x40: unhandled subchannel request\n");
- }
- break;
+ // case 0x22: CD_SCAN
+ // case 0x31: CD_READ2
+ // case 0x13: REQ_ERROR
+ // case 0x16: CD_OPEN [Tray]
+
+ // case 0x08: ??? loopchk uses it in one of the Packet cmnd tests
+ // (check for unsupported command?)
default:
- t10mmc::ExecCommand();
- break;
+ throw emu_fatalerror("GDROM: unhandled command %02x", command[0]);
}
}
@@ -332,20 +490,159 @@ void gdrom_device::ReadData( uint8_t *data, int dataLength )
switch ( command[0] )
{
+ case 0x10: // REQ_STAT
+ {
+ data[0] = m_sector_number & 0xf; // CD status
+ data[1] = (m_sector_number & 0xf0) | (m_cd_status.repeat_current & 0xf);
+ auto fad = m_cdda->get_audio_lba();
+ auto trk = m_image->get_track(fad);
+ data[2] = m_image->get_adr_control(trk - 1);
+ data[3] = trk;
+ // TODO: index
+ data[4] = 1;
+ // FAD, in binary format
+ data[5] = (fad >> 16) & 0xff;
+ data[6] = (fad >> 8) & 0xff;
+ data[7] = fad & 0xff;
+ // Max Read Error Retry Times
+ data[8] = 0;
+ // <reserved>
+ data[9] = 0;
+ if (LIVE_REQ_STAT)
+ {
+ popmessage("REQ_STAT STATUS %02x track %d index %d adr %02x fad %06d"
+ , m_sector_number
+ , data[3]
+ , data[4]
+ , data[2]
+ , fad
+ );
+ }
+ break;
+ }
+
case 0x11: // REQ_MODE
- LOGCMD("REQ_MODE dataLength %d\n", dataLength);
+ //LOGCMD("REQ_MODE dataLength %d\n", dataLength);
memcpy(data, &GDROM_Cmd11_Reply[transferOffset], (dataLength >= 32-transferOffset) ? 32-transferOffset : dataLength);
+ // TODO: reading this while playing a redbook likely hardwires CD speed to 75 Hz
+ //data[1] = 0x01;
break;
+ case 0x13: // REQ_ERROR
+ // cfr. Appendix I for possible error types
+ data[0] = 0xf0; // fixed?
+ data[1] = 0;
+ data[2] = 6; // Sense Key
+ data[3] = 0;
+ // 4-7 "specific command details" (?) or FAD
+ data[4] = 0;
+ data[5] = 0;
+ data[6] = 0;
+ data[7] = 0;
+ data[8] = 0x29; // ASC
+ data[9] = 0; // ASCQ
+ break;
+
+ case 0x14: // READ TOC (GD-ROM ver.)
+ /*
+ Track numbers are problematic here: 0 = lead-in, 0xaa = lead-out.
+ That makes sense in terms of how real-world CDs are referred to, but
+ our internal routines for tracks use "0" as track 1. That probably
+ should be fixed...
+ */
+ LOGCMD("READ_TOC format %d time %d\n",
+ command[2] & 0xf, (command[1] >> 1) & 1
+ );
+ switch (command[2] & 0x0f)
+ {
+ case 0: // normal
+ {
+ int start_trk = 1;
+ int end_trk = m_image->get_last_track();
+ int len = 408;
+ //int in_len;
+ int dptr = 0;
+ uint32_t tstart;
+
+ // Non-standard, doesn't want in_len readback
+ //dptr = 0;
+ //data[dptr++] = (len>>8) & 0xff;
+ //data[dptr++] = (len & 0xff);
+
+ // pre-fill with 0xffs, audio CD player counts number of tracks by checking the
+ // first EOF it encounters (and don't care about the 396-407 dataset below)
+ memset(data, 0xff, len);
+ dptr = 0;
+ LOGTOC("TOC: Start track %d end track %d\n", start_trk, end_trk);
+ for (i = start_trk; i <= end_trk; i++)
+ {
+ u8 adr = m_image->get_adr_control(i - 1) | 1;
+ data[dptr++] = adr;
+
+ tstart = m_image->get_track_start(i - 1) + 150;
+ //if ((command[1]&2)>>1)
+ // tstart = cdrom_file::lba_to_msf(tstart);
+ data[dptr++] = (tstart>>16) & 0xff;
+ data[dptr++] = (tstart>>8) & 0xff;
+ data[dptr++] = (tstart & 0xff);
+ LOGTOC("\t%d: FAD %d %02x\n", i, tstart, adr);
+ }
+
+ dptr = 396;
+ data[dptr++] = m_image->get_adr_control(0) | 1;
+ data[dptr++] = start_trk;
+ data[dptr++] = 0;
+ data[dptr++] = 0;
+ data[dptr++] = m_image->get_adr_control(end_trk) | 1;
+ data[dptr++] = end_trk;
+ data[dptr++] = 0;
+ data[dptr++] = 0;
+ const u32 tend = m_image->get_track_start(0xaa) + 150;
+ //if ((command[1]&2)>>1)
+ // tstart = cdrom_file::lba_to_msf(tstart);
+ data[dptr++] = m_image->get_adr_control(0xaa) | 1;
+ data[dptr++] = (tend>>16) & 0xff;
+ data[dptr++] = (tend>>8) & 0xff;
+ data[dptr++] = (tend & 0xff);
+ LOGTOC("\t0xaa: FAD %d\n", tstart);
+ break;
+ }
+ default:
+ LOGWARN("Unhandled READ_TOC format %d\n", command[2]&0xf);
+ break;
+ }
+ break;
+
+ case 0x15:
+ {
+ // REQ_SES
+ data[0] = m_sector_number & 0xf; // CD status, stripped by type?
+ data[1] = 0; // <reserved>, zeroed
+ data[2] = 1; // number of sessions
+
+ const u8 session_num = command[2] & 0xff;
+ u32 fad;
+ if (session_num == 0)
+ fad = m_image->get_track_start(0xaa) + 150;
+ else
+ fad = m_image->get_track_start(0) + 150;
+ LOGTOC("SESSION %d: %06d\n", session_num, fad);
+ data[3] = (fad >> 16) & 0xff;
+ data[4] = (fad >> 8) & 0xff;
+ data[5] = fad & 0xff;
+ break;
+ }
+
case 0x30: // CD_READ
- LOGCMD("CD_READ read %x dataLength,\n", dataLength);
- if ((m_cdrom) && (m_blocks))
+ LOGXFER("CD_READ read %x dataLength,\n", dataLength);
+ if ((m_image->exists()) && (m_blocks))
{
while (dataLength > 0)
{
- if (!m_cdrom->read_data(m_lba, tmp_buffer, cdrom_file::CD_TRACK_MODE1))
+ if (!m_image->read_data(m_lba, tmp_buffer, cdrom_file::CD_TRACK_MODE1))
{
LOGWARN("CD read error!\n");
+ return;
}
LOGXFER("True LBA: %d, buffer half: %d\n", m_lba, m_cur_subblock * m_sector_bytes);
@@ -368,82 +665,71 @@ void gdrom_device::ReadData( uint8_t *data, int dataLength )
}
break;
- case 0x14: // READ TOC (GD-ROM ver.)
- /*
- Track numbers are problematic here: 0 = lead-in, 0xaa = lead-out.
- That makes sense in terms of how real-world CDs are referred to, but
- our internal routines for tracks use "0" as track 1. That probably
- should be fixed...
- */
- LOGCMD("READ TOC format = %d time=%d\n",
- command[2] & 0xf, (command[1] >> 1) & 1
- );
+ case 0x40: // Get Subchannel status
switch (command[2] & 0x0f)
{
- case 0: // normal
+ case 0: // Subcode P-W
{
- int start_trk;
- int end_trk;
- int len;
- int in_len;
- int dptr;
- uint32_t tstart;
-
- start_trk = command[2];
- if( start_trk == 0 )
- {
- start_trk = 1;
- }
-
- end_trk = m_cdrom->get_last_track();
- len = (end_trk * 8) + 2;
-
- // the returned TOC DATA LENGTH must be the full amount,
- // regardless of how much we're able to pass back due to in_len
- dptr = 0;
- data[dptr++] = (len>>8) & 0xff;
- data[dptr++] = (len & 0xff);
- data[dptr++] = 1;
- data[dptr++] = end_trk;
-
- if( start_trk == 0xaa )
+ data[0] = 0; // Reserved
+ data[1] = m_audio_sense;
+ data[2] = 0;
+ data[3] = m_transfer_length; // header size
+ auto fad = m_cdda->get_audio_lba();
+ if (!m_image->read_subcode( fad, &data[4 + m_transfer_length]))
{
- end_trk = 0xaa;
- }
-
- in_len = command[3]<<8 | command[4];
-
- for (i = start_trk; i <= end_trk; i++)
- {
- int cdrom_track = i;
- if( cdrom_track != 0xaa )
- {
- cdrom_track--;
- }
-
- if( dptr >= in_len )
+ // attempt to provide Q channel
+ // TODO: audio CD player definitely reads here but never updates GFXs?
+ u8 subqbuf[12]{};
+ const u32 msf_abs = cdrom_file::lba_to_msf_alt( fad );
+ const auto trk = m_image->get_track( fad );
+ const u32 msf_rel = cdrom_file::lba_to_msf_alt( fad - m_image->get_track_start( trk ) );
+
+ subqbuf[0] = 0x01 | ((m_image->get_track_type(m_image->get_track(trk + 1)) == cdrom_file::CD_TRACK_AUDIO) ? 0x00 : 0x40);
+ subqbuf[1] = dec_2_bcd(trk + 1);
+ subqbuf[2] = 1;
+ subqbuf[3] = dec_2_bcd((msf_rel >> 16) & 0xff);
+ subqbuf[4] = dec_2_bcd((msf_rel >> 8) & 0xff);
+ subqbuf[5] = dec_2_bcd((msf_rel >> 0) & 0xff);
+ subqbuf[6] = 0;
+ subqbuf[7] = dec_2_bcd((msf_abs >> 16) & 0xff);
+ subqbuf[8] = dec_2_bcd((msf_abs >> 8) & 0xff);
+ subqbuf[9] = dec_2_bcd((msf_abs >> 0) & 0xff);
+ subqbuf[10] = 0xff; //machine().rand(); // CRC
+ subqbuf[11] = 0xff; //machine().rand();
+
+ if (LIVE_REQ_STAT)
{
- break;
+ popmessage("Qchan STATUS %02x TRACK %d ABS %02x:%02x:%02x REL %02x:%02x:%02x"
+ , subqbuf[0]
+ , subqbuf[1]
+ , subqbuf[7], subqbuf[8], subqbuf[9]
+ , subqbuf[3], subqbuf[4], subqbuf[5]
+ );
}
- data[dptr++] = 0;
- data[dptr++] = m_cdrom->get_adr_control(cdrom_track);
- data[dptr++] = i;
- data[dptr++] = 0;
-
- tstart = m_cdrom->get_track_start(cdrom_track);
- if ((command[1]&2)>>1)
- tstart = cdrom_file::lba_to_msf(tstart);
- data[dptr++] = (tstart>>24) & 0xff;
- data[dptr++] = (tstart>>16) & 0xff;
- data[dptr++] = (tstart>>8) & 0xff;
- data[dptr++] = (tstart & 0xff);
+ for (int i = 0; i < m_transfer_length - 4; i++)
+ data[i + 4] = BIT(subqbuf[i >> 3], 7 - (i & 7)) ? 0x40 : 0x00;
}
break;
}
- default:
- LOGWARN("Unhandled READ TOC format %d\n", command[2]&0xf);
+ case 1: // Subcode Q
+ // TODO: unread by audio CD player (?)
+ LOGWARN("CD_SCD: unhandled Subcode Q path\n");
+ data[0] = 0; // Reserved
+ data[1] = m_audio_sense;
+ data[2] = 0;
+ data[3] = m_transfer_length; // header size
+ data[4] = 0; // ADR
+ data[5] = 1; // Track Number
+ data[6] = 1; // index #1
+ data[7] = 0; // ?
+ data[8] = 0; // ?
+ data[9] = 0; // elapsed FAD
+ data[0xa] = 0; // <reserved>, zeroed
+ data[0xb] = 0; // FAD >> 16
+ data[0xc] = 0; // FAD >> 8
+ data[0xd] = 0x96; // FAD >> 0
break;
}
break;
@@ -451,27 +737,10 @@ void gdrom_device::ReadData( uint8_t *data, int dataLength )
case 0x71:
LOGCMD("SYS_REQ_SECU\n");
memcpy(data, &GDROM_Cmd71_Reply[0], sizeof(GDROM_Cmd71_Reply));
- if (is_real_gdrom_disc)
+ if (m_image->is_gd())
data[10] = 0x1f; // needed by dimm board firmware
break;
- case 0x40: // Get Subchannel status
- data[0] = 0; // Reserved
- data[1] = 0x15; // Audio Playback status (todo)
- data[2] = 0;
- data[3] = 0x0e; // header size
- data[4] = 0; // ?
- data[5] = 1; // Track Number
- data[6] = 1; // gap #1
- data[7] = 0; // ?
- data[8] = 0; // ?
- data[9] = 0; // ?
- data[0xa] = 0; // ?
- data[0xb] = 0; // FAD >> 16
- data[0xc] = 0; // FAD >> 8
- data[0xd] = 0x96; // FAD >> 0
- break;
-
default:
t10mmc::ReadData( data, dataLength );
break;
@@ -484,10 +753,26 @@ void gdrom_device::ReadData( uint8_t *data, int dataLength )
void gdrom_device::WriteData( uint8_t *data, int dataLength )
{
- switch (command[ 0 ])
+ switch (command[0])
{
case 0x12: // SET_MODE
memcpy(&GDROM_Cmd11_Reply[transferOffset], data, (dataLength >= 32-transferOffset) ? 32-transferOffset : dataLength);
+ if (data[2] != 0 && data[2] != 7)
+ throw emu_fatalerror("GDROM: Unsupported CD speed setting %02x\n", data[2]);
+ // ---- -000 Max speed (x12)
+ // ---- -xxx [x1 (75 Hz), x2, x4, x6, x8, x10, x12]
+ LOGCMD("\tCD speed: %02x\n", data[2]);
+ // Standby Time:
+ // - 0 = no standby
+ // any other value = number of seconds for pause -> standby transition
+ LOGCMD("\tStandby Time: %02x%02x\n", data[4], data[5]);
+
+ LOGCMD("\tRead Continous: %s\n", BIT(data[6], 5) ? "enable" : "disable");
+ LOGCMD("\tECC: %s\n", BIT(data[6], 4) ? "enable" : "disable");
+ LOGCMD("\tRead Retry: %s\n", BIT(data[6], 3) ? "enable" : "disable");
+ LOGCMD("\tForm 2 Read Retry: %s\n", BIT(data[6], 0) ? "enable" : "disable");
+
+ LOGCMD("\tRead Retry Times %d\n", data[9]);
break;
default:
@@ -496,22 +781,11 @@ void gdrom_device::WriteData( uint8_t *data, int dataLength )
}
}
-void gdrom_device::SetDevice(void *device)
-{
- t10mmc::SetDevice(device);
-
- // try to find if the mounted chd is from an actual gd-rom disc
- if (m_cdrom)
- if (m_cdrom->get_toc().flags & cdrom_file::CD_FLAG_GDROM)
- is_real_gdrom_disc = true;
-}
-
// device type definition
-DEFINE_DEVICE_TYPE(GDROM, gdrom_device, "gdrom", "GD-ROM")
+DEFINE_DEVICE_TYPE(ATAPI_GDROM, gdrom_device, "gdrom", "GD-ROM")
gdrom_device::gdrom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- atapi_cdrom_device(mconfig, GDROM, tag, owner, clock),
- is_real_gdrom_disc(false)
+ atapi_cdrom_device(mconfig, ATAPI_GDROM, tag, owner, clock)
{
}
@@ -528,31 +802,33 @@ void gdrom_device::device_start()
m_identify_buffer[0] = 0x8600; // ATAPI device, cmd set 6 compliant, DRQ within 3 ms of PACKET command
- m_identify_buffer[23] = ('S' << 8) | 'E';
- m_identify_buffer[24] = (' ' << 8) | ' ';
- m_identify_buffer[25] = (' ' << 8) | ' ';
- m_identify_buffer[26] = (' ' << 8) | ' ';
-
- m_identify_buffer[27] = ('C' << 8) | 'D';
- m_identify_buffer[28] = ('-' << 8) | 'R';
- m_identify_buffer[29] = ('O' << 8) | 'M';
- m_identify_buffer[30] = (' ' << 8) | 'D';
- m_identify_buffer[31] = ('R' << 8) | 'I';
- m_identify_buffer[32] = ('V' << 8) | 'E';
- m_identify_buffer[33] = (' ' << 8) | ' ';
- m_identify_buffer[34] = (' ' << 8) | ' ';
- m_identify_buffer[35] = ('6' << 8) | '.';
- m_identify_buffer[36] = ('4' << 8) | '2';
- m_identify_buffer[37] = (' ' << 8) | ' ';
- m_identify_buffer[38] = (' ' << 8) | ' ';
- m_identify_buffer[39] = (' ' << 8) | ' ';
- m_identify_buffer[40] = (' ' << 8) | ' ';
- m_identify_buffer[41] = (' ' << 8) | ' ';
- m_identify_buffer[42] = (' ' << 8) | ' ';
- m_identify_buffer[43] = (' ' << 8) | ' ';
- m_identify_buffer[44] = (' ' << 8) | ' ';
- m_identify_buffer[45] = (' ' << 8) | ' ';
- m_identify_buffer[46] = (' ' << 8) | ' ';
+ // non-standard identify returns
+ // TODO: should be centralized in command 11h
+ // loopchk: identify device Maker test (0104) PC=c04694a
+ // Was 23
+ int dptr = 8;
+ m_identify_buffer[dptr++] = 'S' | ('E' << 8);
+ m_identify_buffer[dptr++] = ' ' | (' ' << 8);
+ m_identify_buffer[dptr++] = ' ' | (' ' << 8);
+ m_identify_buffer[dptr++] = ' ' | (' ' << 8);
+
+ // loopchk: identify device Model test (0104) PC=c046acc
+ // Was 27
+ dptr = 16;
+ m_identify_buffer[dptr++] = 'C' | ('D' << 8);
+ m_identify_buffer[dptr++] = '-' | ('R' << 8);
+ m_identify_buffer[dptr++] = 'O' | ('M' << 8);
+ m_identify_buffer[dptr++] = ' ' | ('D' << 8);
+ m_identify_buffer[dptr++] = 'R' | ('I' << 8);
+ m_identify_buffer[dptr++] = 'V' | ('E' << 8);
+ m_identify_buffer[dptr++] = ' ' | (' ' << 8);
+ m_identify_buffer[dptr++] = ' ' | (' ' << 8);
+ // TODO: versioning is unchecked by loopchk
+ m_identify_buffer[dptr++] = '6' | ('.' << 8);
+ m_identify_buffer[dptr++] = '4' | ('2' << 8);
+ // FIXME: doc mentions a "System Date" readback
+ for (; dptr < 47; dptr ++)
+ m_identify_buffer[dptr] = ' ' | (' ' << 8);
m_identify_buffer[49] = 0x0400; // IORDY may be disabled
@@ -564,14 +840,57 @@ void gdrom_device::process_buffer()
{
atapi_hle_device::process_buffer();
// HACK: find out when this should be updated
- m_sector_number = 0x80 | GDROM_PAUSE_STATE;
+ // TODO: upper byte is CD type detection
+ // 0000 CD-DA
+ // 0001 CD-ROM
+ // 0010 CD-ROM XA / CD Extra
+ // 0011 CD-I
+ // 1000 GD-ROM
+ const u8 cd_type = m_image->is_gd() ? 0x80 : 0x00;
+ m_sector_number = cd_type | (m_image->exists() ? m_sector_number & 0xf : GDROM_NODISC_STATE);
}
void gdrom_device::signature()
{
atapi_hle_device::signature();
+ const u8 cd_type = m_image->is_gd() ? 0x80 : 0x00;
+
// naomi dimm board firmware needs the upper nibble to be 8 at the beginning
- if (is_real_gdrom_disc)
- m_sector_number = 0x81;
+ m_sector_number = cd_type | (m_image->exists() ? m_sector_number & 0xf : GDROM_NODISC_STATE);
+}
+
+//bool gdrom_device::set_features()
+//{
+ // TODO: DSC, likely tested by Check-GD programs
+// m_status |= IDE_STATUS_DSC;
+// return atapi_cdrom_device::set_features();
+//}
+
+void gdrom_device::cdda_end_mark_cb(int state)
+{
+ if (state != ASSERT_LINE)
+ return;
+
+ m_cd_status.repeat_current ++;
+ m_cd_status.repeat_current &= 0xf;
+ LOG("end marker %d %d\n", m_cd_status.repeat_current, m_cd_status.repeat_count);
+
+ // repeat_count = 0xf: infinite, not unlike Saturn CD Block
+ // - ggx sound test track #20 (opening) is a good testing scenario.
+ // - audio cd player don't care about this:
+ // it manually handle repeat modes depending on GD state alone.
+ if (m_cd_status.repeat_current > m_cd_status.repeat_count)
+ {
+ m_cdda->pause_audio(1);
+ m_audio_sense = SCSI_SENSE_ASC_ASCQ_AUDIO_PLAY_OPERATION_SUCCESSFULLY_COMPLETED;
+ LOG("\tCompleted\n");
+ m_sector_number = (m_sector_number & 0xf0) | GDROM_PAUSE_STATE;
+ }
+ else
+ {
+ m_cdda->start_audio(m_cd_status.cdda_fad, m_cd_status.cdda_blocks);
+ LOG("\tRestart playback\n");
+ m_sector_number = (m_sector_number & 0xf0) | GDROM_PLAY_STATE;
+ }
}
diff --git a/src/devices/bus/ata/gdrom.h b/src/devices/bus/ata/gdrom.h
index 66565e7160b..45a4a8b52a0 100644
--- a/src/devices/bus/ata/gdrom.h
+++ b/src/devices/bus/ata/gdrom.h
@@ -23,24 +23,37 @@ public:
virtual void ExecCommand() override;
virtual void WriteData( uint8_t *data, int dataLength ) override;
virtual void ReadData( uint8_t *data, int dataLength ) override;
+ void cdda_end_mark_cb(int state);
protected:
virtual void process_buffer() override;
virtual void signature() override;
- virtual void SetDevice(void *device) override;
// device-level overrides
virtual void device_start() override;
virtual void device_reset() override;
+// virtual bool set_features() override;
+ // TODO: how GDROM determines ready flag?
+ // cfr. dc.xml [GDROM READY] for a list of SW that wants this on.
+ virtual bool is_ready() override { return true; }
private:
- uint8_t GDROM_Cmd11_Reply[32];
+ uint8_t GDROM_Cmd11_Reply[32]{};
uint32_t read_type = 0; // for command 0x30 only
uint32_t data_select = 0; // for command 0x30 only
uint32_t transferOffset = 0;
- bool is_real_gdrom_disc;
+
+ struct cd_status
+ {
+ u8 repeat_count = 0;
+ u8 repeat_current = 0;
+ u32 cdda_fad = 0;
+ u32 cdda_blocks = 0;
+ };
+
+ cd_status m_cd_status;
};
-DECLARE_DEVICE_TYPE(GDROM, gdrom_device)
+DECLARE_DEVICE_TYPE(ATAPI_GDROM, gdrom_device)
#endif // MAME_BUS_ATA_GDROM_H
diff --git a/src/devices/bus/ata/hdd.cpp b/src/devices/bus/ata/hdd.cpp
new file mode 100644
index 00000000000..8eac9aa9163
--- /dev/null
+++ b/src/devices/bus/ata/hdd.cpp
@@ -0,0 +1,45 @@
+// license:BSD-3-Clause
+// copyright-holders:smf
+#include "emu.h"
+#include "hdd.h"
+
+
+//**************************************************************************
+// IDE HARD DISK DEVICE
+//**************************************************************************
+
+// device type definition
+DEFINE_DEVICE_TYPE(IDE_HARDDISK, ide_hdd_device, "idehd", "IDE Hard Disk")
+
+//-------------------------------------------------
+// ide_hdd_device - constructor
+//-------------------------------------------------
+
+ide_hdd_device::ide_hdd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ ide_hdd_device(mconfig, IDE_HARDDISK, tag, owner, clock)
+{
+}
+
+ide_hdd_device::ide_hdd_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
+ ide_hdd_device_base(mconfig, type, tag, owner, clock),
+ device_ata_interface(mconfig, *this)
+{
+}
+
+
+//**************************************************************************
+// ATA COMPACTFLASH CARD DEVICE
+//**************************************************************************
+
+// device type definition
+DEFINE_DEVICE_TYPE(ATA_CF, ata_cf_device, "atacf", "ATA CompactFlash Card")
+
+//-------------------------------------------------
+// ata_cf_device - constructor
+//-------------------------------------------------
+
+ata_cf_device::ata_cf_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ cf_device_base(mconfig, ATA_CF, tag, owner, clock),
+ device_ata_interface(mconfig, *this)
+{
+}
diff --git a/src/devices/bus/ata/hdd.h b/src/devices/bus/ata/hdd.h
new file mode 100644
index 00000000000..345b6c77115
--- /dev/null
+++ b/src/devices/bus/ata/hdd.h
@@ -0,0 +1,92 @@
+// license:BSD-3-Clause
+// copyright-holders:smf
+/***************************************************************************
+
+ hdd.h
+
+ IDE hard disk on ATA bus
+
+***************************************************************************/
+
+#ifndef MAME_BUS_ATA_IDEHD_H
+#define MAME_BUS_ATA_IDEHD_H
+
+#pragma once
+
+#include "atadev.h"
+
+#include "machine/atastorage.h"
+#include "imagedev/harddriv.h"
+
+#include "harddisk.h"
+
+
+// ======================> ide_hdd_device
+
+class ide_hdd_device : public ide_hdd_device_base, public device_ata_interface
+{
+public:
+ // construction/destruction
+ ide_hdd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ // device_ata_interface implementation
+ virtual uint16_t read_dma() override { return dma_r(); }
+ virtual uint16_t read_cs0(offs_t offset, uint16_t mem_mask) override { return command_r(offset); }
+ virtual uint16_t read_cs1(offs_t offset, uint16_t mem_mask) override { return control_r(offset); }
+
+ virtual void write_dma(uint16_t data) override { dma_w(data); }
+ virtual void write_cs0(offs_t offset, uint16_t data, uint16_t mem_mask) override { command_w(offset, data); }
+ virtual void write_cs1(offs_t offset, uint16_t data, uint16_t mem_mask) override { control_w(offset, data); }
+
+ virtual void write_dmack(int state) override { set_dmack_in(state); }
+ virtual void write_csel(int state) override { set_csel_in(state); }
+ virtual void write_dasp(int state) override { set_dasp_in(state); }
+ virtual void write_pdiag(int state) override { set_pdiag_in(state); }
+
+protected:
+ ide_hdd_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+private:
+ // ata_hle_device_base implementation
+ virtual void set_irq_out(int state) override { device_ata_interface::set_irq(state); }
+ virtual void set_dmarq_out(int state) override { device_ata_interface::set_dmarq(state); }
+ virtual void set_dasp_out(int state) override { device_ata_interface::set_dasp(state); }
+ virtual void set_pdiag_out(int state) override { device_ata_interface::set_pdiag(state); }
+};
+
+
+// ======================> ata_cf_device
+
+class ata_cf_device : public cf_device_base, public device_ata_interface
+{
+public:
+ // construction/destruction
+ ata_cf_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ // device_ata_interface implementation
+ virtual uint16_t read_dma() override { return dma_r(); }
+ virtual uint16_t read_cs0(offs_t offset, uint16_t mem_mask) override { return command_r(offset); }
+ virtual uint16_t read_cs1(offs_t offset, uint16_t mem_mask) override { return control_r(offset); }
+
+ virtual void write_dma(uint16_t data) override { dma_w(data); }
+ virtual void write_cs0(offs_t offset, uint16_t data, uint16_t mem_mask) override { command_w(offset, data); }
+ virtual void write_cs1(offs_t offset, uint16_t data, uint16_t mem_mask) override { control_w(offset, data); }
+
+ virtual void write_dmack(int state) override { set_dmack_in(state); }
+ virtual void write_csel(int state) override { set_csel_in(state); }
+ virtual void write_dasp(int state) override { set_dasp_in(state); }
+ virtual void write_pdiag(int state) override { set_pdiag_in(state); }
+
+private:
+ // ata_hle_device_base implementation
+ virtual void set_irq_out(int state) override { device_ata_interface::set_irq(state); }
+ virtual void set_dmarq_out(int state) override { device_ata_interface::set_dmarq(state); }
+ virtual void set_dasp_out(int state) override { device_ata_interface::set_dasp(state); }
+ virtual void set_pdiag_out(int state) override { device_ata_interface::set_pdiag(state); }
+};
+
+// device type declaration
+DECLARE_DEVICE_TYPE(IDE_HARDDISK, ide_hdd_device)
+DECLARE_DEVICE_TYPE(ATA_CF, ata_cf_device)
+
+#endif // MAME_BUS_ATA_IDEHD_H
diff --git a/src/devices/bus/ata/idehd.cpp b/src/devices/bus/ata/idehd.cpp
deleted file mode 100644
index 38ea6c21c6c..00000000000
--- a/src/devices/bus/ata/idehd.cpp
+++ /dev/null
@@ -1,955 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:smf
-#include "emu.h"
-#include "idehd.h"
-
-/***************************************************************************
- DEBUGGING
-***************************************************************************/
-
-#define VERBOSE 0
-#define PRINTF_IDE_COMMANDS 0
-#define PRINTF_IDE_PASSWORD 0
-
-#define LOGPRINT(x) do { if (VERBOSE) logerror x; if (PRINTF_IDE_COMMANDS) osd_printf_debug x; } while (0)
-
-#define TIME_PER_SECTOR_WRITE (attotime::from_usec(100))
-#define TIME_PER_ROTATION (attotime::from_hz(5400/60))
-#define TIME_BETWEEN_SECTORS (attotime::from_nsec(400))
-
-#define TIME_FULL_STROKE_SEEK (attotime::from_usec(13000))
-#define TIME_AVERAGE_ROTATIONAL_LATENCY (attotime::from_usec(1300))
-
-ata_mass_storage_device::ata_mass_storage_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
- : ata_hle_device(mconfig, type, tag, owner, clock),
- m_can_identify_device(0),
- m_num_cylinders(0),
- m_num_sectors(0),
- m_num_heads(0), m_cur_lba(0), m_block_count(0), m_sectors_until_int(0), m_master_password_enable(0), m_user_password_enable(0),
- m_master_password(nullptr),
- m_user_password(nullptr),
- m_dma_transfer_time(attotime::zero)
-{
-}
-
-/*************************************
- *
- * Compute the LBA address
- *
- *************************************/
-
-uint32_t ata_mass_storage_device::lba_address()
-{
- /* LBA direct? */
- if (m_device_head & IDE_DEVICE_HEAD_L)
- return ((m_device_head & IDE_DEVICE_HEAD_HS) << 24) | (m_cylinder_high << 16) | (m_cylinder_low << 8) | m_sector_number;
-
- /* standard CHS */
- else
- return (((((m_cylinder_high << 8) | m_cylinder_low) * m_num_heads) + (m_device_head & IDE_DEVICE_HEAD_HS)) * m_num_sectors) + m_sector_number - 1;
-}
-
-
-/*************************************
- *
- * Build a features page
- *
- *************************************/
-
-static void swap_strncpy(uint16_t *dst, const char *src, int field_size_in_words)
-{
- for (int i = 0; i < field_size_in_words; i++)
- {
- uint16_t d;
-
- if (*src)
- {
- d = *(src++) << 8;
- }
- else
- {
- d = ' ' << 8;
- }
-
- if (*src)
- {
- d |= *(src++);
- }
- else
- {
- d |= ' ';
- }
-
- dst[i] = d;
- }
-
- assert(*(src) == 0);
-}
-
-
-void ata_mass_storage_device::ide_build_identify_device()
-{
- memset(m_identify_buffer, 0, sizeof(m_identify_buffer));
- int total_sectors = m_num_cylinders * m_num_heads * m_num_sectors;
-
- /* basic geometry */
- m_identify_buffer[0] = 0x045a; /* 0: configuration bits */
- m_identify_buffer[1] = m_num_cylinders; /* 1: logical cylinders */
- m_identify_buffer[2] = 0; /* 2: reserved */
- m_identify_buffer[3] = m_num_heads; /* 3: logical heads */
- m_identify_buffer[4] = 0; /* 4: vendor specific (obsolete) */
- m_identify_buffer[5] = 0; /* 5: vendor specific (obsolete) */
- m_identify_buffer[6] = m_num_sectors; /* 6: logical sectors per logical track */
- m_identify_buffer[7] = 0; /* 7: vendor-specific */
- m_identify_buffer[8] = 0; /* 8: vendor-specific */
- m_identify_buffer[9] = 0; /* 9: vendor-specific */
- swap_strncpy(&m_identify_buffer[10], /* 10-19: serial number */
- "00000000000000000000", 10);
- m_identify_buffer[20] = 0; /* 20: vendor-specific */
- m_identify_buffer[21] = 0; /* 21: vendor-specific */
- m_identify_buffer[22] = 4; /* 22: # of vendor-specific bytes on read/write long commands */
- swap_strncpy(&m_identify_buffer[23], /* 23-26: firmware revision */
- "1.0", 4);
- swap_strncpy(&m_identify_buffer[27], /* 27-46: model number */
- "MAME Compressed Hard Disk", 20);
- m_identify_buffer[47] = 0x8010; /* 47: read/write multiple support, value from Seagate Quantum Fireball */
- m_identify_buffer[48] = 0; /* 48: reserved */
- m_identify_buffer[49] = 0x0f03; /* 49: capabilities */
- m_identify_buffer[50] = 0; /* 50: reserved */
- m_identify_buffer[51] = 2; /* 51: PIO data transfer cycle timing mode */
- m_identify_buffer[52] = 2; /* 52: single word DMA transfer cycle timing mode */
- m_identify_buffer[53] = 3; /* 53: field validity */
- m_identify_buffer[54] = m_num_cylinders; /* 54: number of current logical cylinders */
- m_identify_buffer[55] = m_num_heads; /* 55: number of current logical heads */
- m_identify_buffer[56] = m_num_sectors; /* 56: number of current logical sectors per track */
- m_identify_buffer[57] = total_sectors & 0xffff; /* 57-58: current capacity in sectors (ATA-1 through ATA-5; obsoleted in ATA-6) */
- m_identify_buffer[58] = total_sectors >> 16;
- m_identify_buffer[59] = 0; /* 59: multiple sector timing */
- m_identify_buffer[60] = total_sectors & 0xffff; /* 60-61: total user addressable sectors for LBA mode (ATA-1 through ATA-7) */
- m_identify_buffer[61] = total_sectors >> 16;
- m_identify_buffer[62] = 0x0007; /* 62: single word dma transfer */
- m_identify_buffer[63] = 0x0407; /* 63: multiword DMA transfer */
- m_identify_buffer[64] = 0x0003; /* 64: flow control PIO transfer modes supported */
- m_identify_buffer[65] = 0x78; /* 65: minimum multiword DMA transfer cycle time per word */
- m_identify_buffer[66] = 0x78; /* 66: mfr's recommended multiword DMA transfer cycle time */
- m_identify_buffer[67] = 0x014d; /* 67: minimum PIO transfer cycle time without flow control */
- m_identify_buffer[68] = 0x78; /* 68: minimum PIO transfer cycle time with IORDY */
- m_identify_buffer[69] = 0x00; /* 69-70: reserved */
- m_identify_buffer[71] = 0x00; /* 71: reserved for IDENTIFY PACKET command */
- m_identify_buffer[72] = 0x00; /* 72: reserved for IDENTIFY PACKET command */
- m_identify_buffer[73] = 0x00; /* 73: reserved for IDENTIFY PACKET command */
- m_identify_buffer[74] = 0x00; /* 74: reserved for IDENTIFY PACKET command */
- m_identify_buffer[75] = 0x00; /* 75: queue depth */
- m_identify_buffer[76] = 0x00; /* 76-79: reserved */
- m_identify_buffer[80] = 0x00; /* 80: major version number */
- m_identify_buffer[81] = 0x00; /* 81: minor version number */
- m_identify_buffer[82] = 0x00; /* 82: command set supported */
- m_identify_buffer[83] = 0x00; /* 83: command sets supported */
- m_identify_buffer[84] = 0x00; /* 84: command set/feature supported extension */
- m_identify_buffer[85] = 0x00; /* 85: command set/feature enabled */
- m_identify_buffer[86] = 0x00; /* 86: command set/feature enabled */
- m_identify_buffer[87] = 0x00; /* 87: command set/feature default */
- m_identify_buffer[88] = 0x00; /* 88: additional DMA modes (ultra dma) */
- m_identify_buffer[89] = 0x00; /* 89: time required for security erase unit completion */
- m_identify_buffer[90] = 0x00; /* 90: time required for enhanced security erase unit completion */
- m_identify_buffer[91] = 0x00; /* 91: current advanced power management value */
- m_identify_buffer[92] = 0x00; /* 92: master password revision code */
- m_identify_buffer[93] = 0x00; /* 93: hardware reset result */
- m_identify_buffer[94] = 0x00; /* 94: acoustic management values */
- m_identify_buffer[95] = 0x00; /* 95-99: reserved */
- m_identify_buffer[100] = total_sectors & 0xffff; /* 100-103: maximum 48-bit LBA */
- m_identify_buffer[101] = total_sectors >> 16;
- m_identify_buffer[102] = 0x00;
- m_identify_buffer[103] = 0x00;
- m_identify_buffer[104] = 0x00; /* 104-126: reserved */
- m_identify_buffer[127] = 0x00; /* 127: removable media status notification */
- m_identify_buffer[128] = 0x00; /* 128: security status */
- m_identify_buffer[129] = 0x00; /* 129-159: vendor specific */
- m_identify_buffer[160] = 0x00; /* 160: CFA power mode 1 */
- m_identify_buffer[161] = 0x00; /* 161-175: reserved for CompactFlash */
- m_identify_buffer[176] = 0x00; /* 176-205: current media serial number */
- m_identify_buffer[206] = 0x00; /* 206-254: reserved */
- m_identify_buffer[255] = 0x00; /* 255: integrity word */
-
- if (total_sectors >= 16514064)
- {
- /// CHS limit
- m_identify_buffer[1] = 16383; /* 1: logical cylinders */
- m_identify_buffer[3] = 16; /* 3: logical heads */
- m_identify_buffer[6] = 63; /* 6: logical sectors per logical track */
- m_identify_buffer[54] = 16383; /* 54: number of current logical cylinders */
- m_identify_buffer[55] = 16; /* 55: number of current logical heads */
- m_identify_buffer[56] = 63; /* 56: number of current logical sectors per track */
- m_identify_buffer[57] = 16514064 & 0xffff; /* 57-58: current capacity in sectors (ATA-1 through ATA-5; obsoleted in ATA-6) */
- m_identify_buffer[58] = 16514064 >> 16;
- }
-
- if (total_sectors > 268435455)
- {
- /// LBA limit
- m_identify_buffer[60] = 268435455 & 0xffff; /* 60-61: total user addressable sectors for LBA mode (ATA-1 through ATA-7) */
- m_identify_buffer[61] = 268435455 >> 16;
- }
-}
-
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-
-void ata_mass_storage_device::device_start()
-{
- ata_hle_device::device_start();
-
- save_item(NAME(m_can_identify_device));
- save_item(NAME(m_num_cylinders));
- save_item(NAME(m_num_sectors));
- save_item(NAME(m_num_heads));
-
- save_item(NAME(m_cur_lba));
- save_item(NAME(m_sectors_until_int));
- save_item(NAME(m_master_password_enable));
- save_item(NAME(m_user_password_enable));
- save_item(NAME(m_block_count));
-}
-
-void ata_mass_storage_device::soft_reset()
-{
- ata_hle_device::soft_reset();
-
- m_cur_lba = 0;
- m_status |= IDE_STATUS_DSC;
-
- m_master_password_enable = (m_master_password != nullptr);
- m_user_password_enable = (m_user_password != nullptr);
-}
-
-void ata_mass_storage_device::perform_diagnostic()
-{
- if (m_can_identify_device)
- m_error = IDE_ERROR_DIAGNOSTIC_PASSED;
-}
-
-void ata_mass_storage_device::signature()
-{
- m_sector_count = 1;
- m_sector_number = 1;
- m_cylinder_low = 0;
- m_cylinder_high = 0;
- m_device_head = 0;
-}
-
-void ata_mass_storage_device::finished_command()
-{
- int total_sectors = m_num_cylinders * m_num_heads * m_num_sectors;
-
- switch (m_command)
- {
- case IDE_COMMAND_IDENTIFY_DEVICE:
- if (m_can_identify_device)
- {
- for( int w = 0; w < 256; w++ )
- {
- m_buffer[w * 2] = m_identify_buffer[ w ] & 0xff;
- m_buffer[(w * 2) + 1] = m_identify_buffer[ w ] >> 8;
- }
-
- m_status |= IDE_STATUS_DRQ;
- }
- else
- {
- m_status |= IDE_STATUS_ERR;
- m_error = IDE_ERROR_NONE;
- }
-
- set_irq(ASSERT_LINE);
- break;
-
- case IDE_COMMAND_SET_CONFIG:
- set_geometry(m_sector_count,(m_device_head & IDE_DEVICE_HEAD_HS) + 1);
- set_irq(ASSERT_LINE);
- break;
-
- case IDE_COMMAND_READ_SECTORS:
- case IDE_COMMAND_READ_SECTORS_NORETRY:
- case IDE_COMMAND_READ_MULTIPLE:
- case IDE_COMMAND_VERIFY_SECTORS:
- case IDE_COMMAND_VERIFY_SECTORS_NORETRY:
- case IDE_COMMAND_READ_DMA:
- finished_read();
- break;
-
- case IDE_COMMAND_WRITE_SECTORS:
- case IDE_COMMAND_WRITE_SECTORS_NORETRY:
- case IDE_COMMAND_WRITE_MULTIPLE:
- case IDE_COMMAND_WRITE_DMA:
- finished_write();
- break;
-
- case IDE_COMMAND_RECALIBRATE:
- set_irq(ASSERT_LINE);
- break;
-
- case IDE_COMMAND_READ_NATIVE_MAX_ADDRESS:
- m_buffer[0] = (total_sectors & 0xff000000) >> 24;
- m_buffer[1] = (total_sectors & 0x00ff0000) >> 16;
- m_buffer[2] = (total_sectors & 0x0000ff00) >> 8;
- m_buffer[3] = (total_sectors & 0x000000ff);
- set_irq(ASSERT_LINE);
- break;
-
- default:
- ata_hle_device::finished_command();
- break;
- }
-}
-
-/*************************************
- *
- * Advance to the next sector
- *
- *************************************/
-
-void ata_mass_storage_device::next_sector()
-{
- uint8_t cur_head = m_device_head & IDE_DEVICE_HEAD_HS;
-
- /* LBA direct? */
- if (m_device_head & IDE_DEVICE_HEAD_L)
- {
- m_sector_number++;
- if (m_sector_number == 0)
- {
- m_cylinder_low++;
- if (m_cylinder_low == 0)
- {
- m_cylinder_high++;
- if (m_cylinder_high == 0)
- cur_head++;
- }
- }
- }
-
- /* standard CHS */
- else
- {
- /* sectors are 1-based */
- m_sector_number++;
- if (m_sector_number > m_num_sectors)
- {
- /* heads are 0 based */
- m_sector_number = 1;
- cur_head++;
- if (cur_head >= m_num_heads)
- {
- cur_head = 0;
- m_cylinder_low++;
- if (m_cylinder_low == 0)
- m_cylinder_high++;
- }
- }
- }
-
- m_device_head = (m_device_head & ~IDE_DEVICE_HEAD_HS) | cur_head;
-
- m_cur_lba = lba_address();
-}
-
-
-
-/*************************************
- *
- * security error handling
- *
- *************************************/
-
-void ata_mass_storage_device::security_error()
-{
- /* set error state */
- m_status |= IDE_STATUS_ERR;
- m_error = IDE_ERROR_NONE;
- m_status &= ~IDE_STATUS_DRDY;
-}
-
-
-
-/*************************************
- *
- * Sector reading
- *
- *************************************/
-
-attotime ata_mass_storage_device::seek_time()
-{
- int sectors_per_cylinder = m_num_heads * m_num_sectors;
-
- if (sectors_per_cylinder == 0 || m_num_cylinders == 0)
- return attotime::zero;
-
- int new_lba = lba_address();
- int old_cylinder = m_cur_lba / sectors_per_cylinder;
- int new_cylinder = new_lba / sectors_per_cylinder;
- int diff = abs(old_cylinder - new_cylinder);
-
- m_cur_lba = new_lba;
-
- if (diff == 0)
- return TIME_BETWEEN_SECTORS;
-
- attotime seek_time = (TIME_FULL_STROKE_SEEK * diff) / m_num_cylinders;
-
- return seek_time + TIME_AVERAGE_ROTATIONAL_LATENCY;
-}
-
-void ata_mass_storage_device::fill_buffer()
-{
- switch (m_command)
- {
- case IDE_COMMAND_IDENTIFY_DEVICE:
- break;
-
- case IDE_COMMAND_READ_MULTIPLE:
- /* if there is more data to read, keep going */
- if (m_sector_count > 0)
- m_sector_count--;
-
- if (m_sector_count > 0)
- {
- // Read the next sector with no delay
- finished_read();
- }
- break;
-
- default:
- /* if there is more data to read, keep going */
- if (m_sector_count > 0)
- m_sector_count--;
-
- if (m_sector_count > 0)
- {
- set_dasp(ASSERT_LINE);
- if (m_command == IDE_COMMAND_READ_DMA)
- start_busy(TIME_BETWEEN_SECTORS + m_dma_transfer_time, PARAM_COMMAND);
- else
- start_busy(TIME_BETWEEN_SECTORS, PARAM_COMMAND);
- }
- break;
- }
-}
-
-
-void ata_mass_storage_device::finished_read()
-{
- int lba = lba_address(), read_status;
-
- set_dasp(CLEAR_LINE);
-
- /* now do the read */
- read_status = read_sector(lba, &m_buffer[0]);
-
- /* if we succeeded, advance to the next sector and set the nice bits */
- if (read_status)
- {
- /* advance the pointers, unless this is the last sector */
- /* Gauntlet: Dark Legacy checks to make sure we stop on the last sector */
- if (m_sector_count != 1)
- next_sector();
-
- /* signal an interrupt, IDE_COMMAND_READ_MULTIPLE sets the interrupt at the start the block */
- if (--m_sectors_until_int == 0 || (m_sector_count == 1 && m_command != IDE_COMMAND_READ_MULTIPLE))
- {
- m_sectors_until_int = ((m_command == IDE_COMMAND_READ_MULTIPLE) ? m_block_count : 1);
- set_irq(ASSERT_LINE);
- }
-
- /* if we're just verifying we can read the next sector */
- if (m_command == IDE_COMMAND_VERIFY_SECTORS ||
- m_command == IDE_COMMAND_VERIFY_SECTORS_NORETRY )
- {
- read_buffer_empty();
- }
- else
- {
- m_status |= IDE_STATUS_DRQ;
-
- if (m_command == IDE_COMMAND_READ_DMA)
- set_dmarq(ASSERT_LINE);
- }
- }
-
- /* if we got an error, we need to report it */
- else
- {
- /* set the error flag and the error */
- m_status |= IDE_STATUS_ERR;
- m_error = IDE_ERROR_BAD_SECTOR;
-
- /* signal an interrupt */
- set_irq(ASSERT_LINE);
- }
-}
-
-
-void ata_mass_storage_device::read_first_sector()
-{
- if (m_master_password_enable || m_user_password_enable)
- {
- security_error();
- }
- else
- {
- set_dasp(ASSERT_LINE);
-
- start_busy(seek_time(), PARAM_COMMAND);
- }
-}
-
-/*************************************
- *
- * Sector writing
- *
- *************************************/
-
-void ata_mass_storage_device::process_buffer()
-{
- if (m_command == IDE_COMMAND_SECURITY_UNLOCK)
- {
- if (m_user_password_enable && memcmp(&m_buffer[0], m_user_password, 2 + 32) == 0)
- {
- LOGPRINT(("IDE Unlocked user password\n"));
- m_user_password_enable = 0;
- }
- if (m_master_password_enable && memcmp(&m_buffer[0], m_master_password, 2 + 32) == 0)
- {
- LOGPRINT(("IDE Unlocked master password\n"));
- m_master_password_enable = 0;
- }
- if (PRINTF_IDE_PASSWORD)
- {
- int i;
-
- for (i = 0; i < 34; i += 2)
- {
- if (i % 8 == 2)
- osd_printf_debug("\n");
-
- osd_printf_debug("0x%02x, 0x%02x, ", m_buffer[i], m_buffer[i + 1]);
- //osd_printf_debug("0x%02x%02x, ", m_buffer[i], m_buffer[i + 1]);
- }
- osd_printf_debug("\n");
- }
-
- if (m_master_password_enable || m_user_password_enable)
- security_error();
- }
- else if (m_command == IDE_COMMAND_SECURITY_DISABLE_PASSWORD)
- {
- LOGPRINT(("IDE Done unimplemented SECURITY_DISABLE_PASSWORD command\n"));
- }
- else
- {
- set_dasp(ASSERT_LINE);
-
- if (m_command == IDE_COMMAND_WRITE_MULTIPLE)
- {
- if (m_sectors_until_int != 1)
- {
- /* ready to write now */
- finished_write();
- }
- else
- {
- /* set a timer to do the write */
- start_busy(TIME_PER_SECTOR_WRITE, PARAM_COMMAND);
- }
- }
- else
- {
- /* set a timer to do the write */
- start_busy(TIME_PER_SECTOR_WRITE, PARAM_COMMAND);
- }
- }
-}
-
-
-void ata_mass_storage_device::finished_write()
-{
- int lba = lba_address(), count;
-
- set_dasp(CLEAR_LINE);
-
- /* now do the write */
- count = write_sector(lba, &m_buffer[0]);
-
- /* if we succeeded, advance to the next sector and set the nice bits */
- if (count == 1)
- {
- /* advance the pointers, unless this is the last sector */
- /* Gauntlet: Dark Legacy checks to make sure we stop on the last sector */
- if (m_sector_count != 1)
- next_sector();
-
- /* signal an interrupt */
- if (--m_sectors_until_int == 0 || m_sector_count == 1)
- {
- m_sectors_until_int = ((m_command == IDE_COMMAND_WRITE_MULTIPLE) ? m_block_count : 1);
- set_irq(ASSERT_LINE);
- }
-
- /* signal an interrupt if there's more data needed */
- if (m_sector_count > 0)
- m_sector_count--;
-
- if (m_sector_count > 0)
- {
- m_status |= IDE_STATUS_DRQ;
-
- if (m_command == IDE_COMMAND_WRITE_DMA)
- set_dmarq(ASSERT_LINE);
- }
- }
-
- /* if we got an error, we need to report it */
- else
- {
- /* set the error flag and the error */
- m_status |= IDE_STATUS_ERR;
- m_error = IDE_ERROR_BAD_SECTOR;
-
- /* signal an interrupt */
- set_irq(ASSERT_LINE);
- }
-}
-
-
-/*************************************
- *
- * Handle IDE commands
- *
- *************************************/
-
-void ata_mass_storage_device::process_command()
-{
- m_sectors_until_int = 0;
- m_buffer_size = IDE_DISK_SECTOR_SIZE;
-
- switch (m_command)
- {
- case IDE_COMMAND_READ_SECTORS:
- case IDE_COMMAND_READ_SECTORS_NORETRY:
- LOGPRINT(("IDE Read multiple: C=%u H=%d S=%u LBA=%u count=%u\n",
- (m_cylinder_high << 8) | m_cylinder_low, m_device_head & IDE_DEVICE_HEAD_HS, m_sector_number, lba_address(), m_sector_count));
-
- m_sectors_until_int = 1;
-
- /* start the read going */
- read_first_sector();
- break;
-
- case IDE_COMMAND_READ_MULTIPLE:
- LOGPRINT(("IDE Read multiple block: C=%u H=%u S=%u LBA=%u count=%u\n",
- (m_cylinder_high << 8) | m_cylinder_low, m_device_head & IDE_DEVICE_HEAD_HS, m_sector_number, lba_address(), m_sector_count));
-
- m_sectors_until_int = 1;
-
- /* start the read going */
- read_first_sector();
- break;
-
- case IDE_COMMAND_VERIFY_SECTORS:
- case IDE_COMMAND_VERIFY_SECTORS_NORETRY:
- LOGPRINT(("IDE Read verify multiple with/without retries: C=%u H=%u S=%u LBA=%u count=%u\n",
- (m_cylinder_high << 8) | m_cylinder_low, m_device_head & IDE_DEVICE_HEAD_HS, m_sector_number, lba_address(), m_sector_count));
-
- /* reset the buffer */
- m_sectors_until_int = m_sector_count;
-
- /* start the read going */
- read_first_sector();
- break;
-
- case IDE_COMMAND_READ_DMA:
- LOGPRINT(("IDE Read multiple DMA: C=%u H=%u S=%u LBA=%u count=%u\n",
- (m_cylinder_high << 8) | m_cylinder_low, m_device_head & IDE_DEVICE_HEAD_HS, m_sector_number, lba_address(), m_sector_count));
-
- /* reset the buffer */
- m_sectors_until_int = m_sector_count;
-
- /* start the read going */
- read_first_sector();
- break;
-
- case IDE_COMMAND_WRITE_SECTORS:
- case IDE_COMMAND_WRITE_SECTORS_NORETRY:
- LOGPRINT(("IDE Write multiple: C=%u H=%u S=%u LBA=%u count=%u\n",
- (m_cylinder_high << 8) | m_cylinder_low, m_device_head & IDE_DEVICE_HEAD_HS, m_sector_number, lba_address(), m_sector_count));
-
- /* reset the buffer */
- m_sectors_until_int = 1;
-
- /* mark the buffer ready */
- m_status |= IDE_STATUS_DRQ;
- break;
-
- case IDE_COMMAND_WRITE_MULTIPLE:
- LOGPRINT(("IDE Write multiple block: C=%u H=%u S=%u LBA=%u count=%u\n",
- (m_cylinder_high << 8) | m_cylinder_low, m_device_head & IDE_DEVICE_HEAD_HS, m_sector_number, lba_address(), m_sector_count));
-
- /* reset the buffer */
- m_sectors_until_int = m_block_count;
-
- /* mark the buffer ready */
- m_status |= IDE_STATUS_DRQ;
- break;
-
- case IDE_COMMAND_WRITE_DMA:
- LOGPRINT(("IDE Write multiple DMA: C=%u H=%u S=%u LBA=%u count=%u\n",
- (m_cylinder_high << 8) | m_cylinder_low, m_device_head & IDE_DEVICE_HEAD_HS, m_sector_number, lba_address(), m_sector_count));
-
- /* reset the buffer */
- m_sectors_until_int = m_sector_count;
-
- /* mark the buffer ready */
- m_status |= IDE_STATUS_DRQ;
-
- /* start the read going */
- set_dmarq(ASSERT_LINE);
- break;
-
- case IDE_COMMAND_SECURITY_UNLOCK:
- LOGPRINT(("IDE Security Unlock\n"));
-
- /* mark the buffer ready */
- m_status |= IDE_STATUS_DRQ;
-
- set_irq(ASSERT_LINE);
- break;
-
- case IDE_COMMAND_SECURITY_DISABLE_PASSWORD:
- LOGPRINT(("IDE Unimplemented SECURITY DISABLE PASSWORD command\n"));
-
- /* mark the buffer ready */
- m_status |= IDE_STATUS_DRQ;
-
- set_irq(ASSERT_LINE);
- break;
-
- case IDE_COMMAND_IDENTIFY_DEVICE:
- LOGPRINT(("IDE Identify device\n"));
-
- start_busy(MINIMUM_COMMAND_TIME, PARAM_COMMAND);
- break;
-
- case IDE_COMMAND_RECALIBRATE:
- start_busy(MINIMUM_COMMAND_TIME, PARAM_COMMAND);
- break;
-
- case IDE_COMMAND_IDLE:
- /* signal an interrupt */
- set_irq(ASSERT_LINE);
- break;
-
- case IDE_COMMAND_SET_CONFIG:
- LOGPRINT(("IDE Set configuration (%u heads, %u sectors)\n", (m_device_head & IDE_DEVICE_HEAD_HS) + 1, m_sector_count));
-
- start_busy(MINIMUM_COMMAND_TIME, PARAM_COMMAND);
- break;
-
- case IDE_COMMAND_SET_MAX:
- LOGPRINT(("IDE Set max (%02X %02X %02X %02X %02X)\n", m_feature, m_sector_count & 0xff, m_sector_number, m_cylinder_low, m_cylinder_high));
-
- /* signal an interrupt */
- set_irq(ASSERT_LINE);
- break;
-
- case IDE_COMMAND_SET_BLOCK_COUNT:
- LOGPRINT(("IDE Set block count (%u)\n", m_sector_count));
-
- m_block_count = m_sector_count;
-
- /* signal an interrupt */
- set_irq(ASSERT_LINE);
- break;
-
- case IDE_COMMAND_SEEK:
- /* signal an interrupt */
- set_irq(ASSERT_LINE);
- break;
-
- case IDE_COMMAND_READ_NATIVE_MAX_ADDRESS:
- start_busy(MINIMUM_COMMAND_TIME, PARAM_COMMAND);
- break;
-
- default:
- ata_hle_device::process_command();
- break;
- }
-}
-
-//**************************************************************************
-// IDE HARD DISK DEVICE
-//**************************************************************************
-
-// device type definition
-DEFINE_DEVICE_TYPE(IDE_HARDDISK, ide_hdd_device, "idehd", "IDE Hard Disk")
-
-//-------------------------------------------------
-// ide_hdd_device - constructor
-//-------------------------------------------------
-
-ide_hdd_device::ide_hdd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : ide_hdd_device(mconfig, IDE_HARDDISK, tag, owner, clock)
-{
-}
-
-ide_hdd_device::ide_hdd_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
- : ata_mass_storage_device(mconfig, type, tag, owner, clock),
- m_image(*this, "image")
-{
-}
-
-void ide_hdd_device::device_start()
-{
- ata_mass_storage_device::device_start();
-
- /* create a timer for timing status */
- m_last_status_timer = machine().scheduler().timer_alloc(timer_expired_delegate());
-}
-
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
-void ide_hdd_device::device_reset()
-{
- m_disk = m_image->get_hard_disk_file();
-
- if (m_disk != nullptr && !m_can_identify_device)
- {
- const auto &hdinfo = m_disk->get_info();
- if (hdinfo.sectorbytes == IDE_DISK_SECTOR_SIZE)
- {
- m_num_cylinders = hdinfo.cylinders;
- m_num_sectors = hdinfo.sectors;
- m_num_heads = hdinfo.heads;
- if (PRINTF_IDE_COMMANDS) osd_printf_debug("CHS: %u %u %u\n", m_num_cylinders, m_num_heads, m_num_sectors);
- osd_printf_debug("CHS: %u %u %u\n", m_num_cylinders, m_num_heads, m_num_sectors);
- }
-
- // build the features page
- std::vector<u8> ident;
- m_disk->get_inquiry_data(ident);
- if (ident.size() == 512)
- {
- for( int w = 0; w < 256; w++ )
- {
- m_identify_buffer[w] = (ident[(w * 2) + 1] << 8) | ident[w * 2];
- }
- }
- else
- {
- ide_build_identify_device();
- }
-
- m_can_identify_device = 1;
- }
-
- ata_mass_storage_device::device_reset();
-}
-
-uint8_t ide_hdd_device::calculate_status()
-{
- uint8_t result = ata_hle_device::calculate_status();
-
- if (m_last_status_timer->elapsed() > TIME_PER_ROTATION)
- {
- result |= IDE_STATUS_IDX;
- m_last_status_timer->adjust(attotime::never);
- }
-
- return result;
-}
-
-//-------------------------------------------------
-// device_add_mconfig - add device configuration
-//-------------------------------------------------
-
-void ide_hdd_device::device_add_mconfig(machine_config &config)
-{
- HARDDISK(config, "image", "ide_hdd");
-}
-
-//**************************************************************************
-// ATA COMPACTFLASH CARD DEVICE
-//**************************************************************************
-
-// device type definition
-DEFINE_DEVICE_TYPE(ATA_CF, ide_cf_device, "atacf", "ATA CompactFlash Card")
-
-//-------------------------------------------------
-// ide_cf_device - constructor
-//-------------------------------------------------
-
-ide_cf_device::ide_cf_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : ide_hdd_device(mconfig, ATA_CF, tag, owner, clock)
-{
-}
-
-//-------------------------------------------------
-// device_add_mconfig - add device configuration
-//-------------------------------------------------
-
-void ide_cf_device::device_add_mconfig(machine_config &config)
-{
- HARDDISK(config, "image", "ata_cf");
-}
-
-//-------------------------------------------------
-// ide_build_identify_device
-//-------------------------------------------------
-
-void ide_cf_device::ide_build_identify_device()
-{
- memset(m_identify_buffer, 0, sizeof(m_identify_buffer));
- int total_sectors = m_num_cylinders * m_num_heads * m_num_sectors;
-
- /* basic geometry */
- m_identify_buffer[0] = 0x848a; /* 0: configuration bits */
- m_identify_buffer[1] = m_num_cylinders; /* 1: logical cylinders */
- m_identify_buffer[2] = 0; /* 2: reserved */
- m_identify_buffer[3] = m_num_heads; /* 3: logical heads */
- m_identify_buffer[4] = 0; /* 4: number of unformatted bytes per track */
- m_identify_buffer[5] = 0; /* 5: number of unformatted bytes per sector */
- m_identify_buffer[6] = m_num_sectors; /* 6: logical sectors per logical track */
- m_identify_buffer[7] = total_sectors >> 16; /* 7: number of sectors per card MSW */
- m_identify_buffer[8] = total_sectors & 0xffff; /* 8: number of sectors per card LSW */
- m_identify_buffer[9] = 0; /* 9: vendor-specific */
- swap_strncpy(&m_identify_buffer[10], /* 10-19: serial number */
- "00000000000000000000", 10);
- m_identify_buffer[20] = 0; /* 20: buffer type */
- m_identify_buffer[21] = 0; /* 21: buffer size in 512 byte increments */
- m_identify_buffer[22] = 4; /* 22: # of vendor-specific bytes on read/write long commands */
- swap_strncpy(&m_identify_buffer[23], /* 23-26: firmware revision */
- "1.0", 4);
- swap_strncpy(&m_identify_buffer[27], /* 27-46: model number */
- "MAME Compressed CompactFlash", 20);
- m_identify_buffer[47] = 0x0001; /* 47: read/write multiple support */
- m_identify_buffer[48] = 0; /* 48: double word not supported */
- m_identify_buffer[49] = 0x0200; /* 49: capabilities */
- m_identify_buffer[50] = 0; /* 50: reserved */
- m_identify_buffer[51] = 0x0200; /* 51: PIO data transfer cycle timing mode */
- m_identify_buffer[52] = 0x0000; /* 52: single word DMA transfer cycle timing mode */
- m_identify_buffer[53] = 0x0003; /* 53: translation parameters are valid */
- m_identify_buffer[54] = m_num_cylinders; /* 54: number of current logical cylinders */
- m_identify_buffer[55] = m_num_heads; /* 55: number of current logical heads */
- m_identify_buffer[56] = m_num_sectors; /* 56: number of current logical sectors per track */
- m_identify_buffer[57] = total_sectors & 0xffff; /* 57-58: current capacity in sectors */
- m_identify_buffer[58] = total_sectors >> 16;
- m_identify_buffer[59] = 0; /* 59: multiple sector timing */
- m_identify_buffer[60] = total_sectors & 0xffff; /* 60-61: total user addressable sectors for LBA mode */
- m_identify_buffer[61] = total_sectors >> 16;
- m_identify_buffer[62] = 0x00; /* 62-127: reserved */
- m_identify_buffer[128] = 0x00; /* 128: security status */
- m_identify_buffer[129] = 0x00; /* 129-159: vendor specific */
- m_identify_buffer[160] = 0x00; /* 160: Power requirement description*/
- m_identify_buffer[161] = 0x00; /* 161-255: reserved */
-}
diff --git a/src/devices/bus/ata/idehd.h b/src/devices/bus/ata/idehd.h
deleted file mode 100644
index 0d7a999a412..00000000000
--- a/src/devices/bus/ata/idehd.h
+++ /dev/null
@@ -1,141 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:smf
-/***************************************************************************
-
- idehd.h
-
- IDE Harddisk
-
-***************************************************************************/
-
-#ifndef MAME_BUS_ATA_IDEHD_H
-#define MAME_BUS_ATA_IDEHD_H
-
-#pragma once
-
-#include "atahle.h"
-#include "harddisk.h"
-#include "imagedev/harddriv.h"
-
-class ata_mass_storage_device : public ata_hle_device
-{
-public:
- uint16_t *identify_device_buffer() { return m_identify_buffer; }
-
- void set_master_password(const uint8_t *password)
- {
- m_master_password = password;
- m_master_password_enable = (password != nullptr);
- }
-
- void set_user_password(const uint8_t *password)
- {
- m_user_password = password;
- m_user_password_enable = (password != nullptr);
- }
-
- void set_dma_transfer_time(const attotime time) { m_dma_transfer_time = time; }
-protected:
- ata_mass_storage_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void device_start() override;
-
- virtual int read_sector(uint32_t lba, void *buffer) = 0;
- virtual int write_sector(uint32_t lba, const void *buffer) = 0;
- virtual attotime seek_time();
-
- virtual void ide_build_identify_device();
-
- static const int IDE_DISK_SECTOR_SIZE = 512;
- virtual int sector_length() override { return IDE_DISK_SECTOR_SIZE; }
- virtual void process_buffer() override;
- virtual void fill_buffer() override;
- virtual bool is_ready() override { return true; }
- virtual void process_command() override;
- virtual void finished_command() override;
- virtual void perform_diagnostic() override;
- virtual void signature() override;
-
- int m_can_identify_device;
- uint16_t m_num_cylinders;
- uint8_t m_num_sectors;
- uint8_t m_num_heads;
-
- virtual uint32_t lba_address();
-
-private:
- void set_geometry(uint8_t sectors, uint8_t heads) { m_num_sectors = sectors; m_num_heads = heads; }
- void finished_read();
- void finished_write();
- void next_sector();
- void security_error();
- void read_first_sector();
- void soft_reset() override;
-
- uint32_t m_cur_lba;
- uint16_t m_block_count;
- uint16_t m_sectors_until_int;
-
- uint8_t m_master_password_enable;
- uint8_t m_user_password_enable;
- const uint8_t * m_master_password;
- const uint8_t * m_user_password;
- // DMA data transfer time for 1 sector
- attotime m_dma_transfer_time;
-};
-
-// ======================> ide_hdd_device
-
-class ide_hdd_device : public ata_mass_storage_device
-{
-public:
- // construction/destruction
- ide_hdd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- ide_hdd_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
-
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
-
- // optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
-
- virtual int read_sector(uint32_t lba, void *buffer) override { return !m_disk ? 0 : m_disk->read(lba, buffer); }
- virtual int write_sector(uint32_t lba, const void *buffer) override { return !m_disk ? 0 : m_disk->write(lba, buffer); }
- virtual uint8_t calculate_status() override;
-
- hard_disk_file *m_disk;
-
- enum
- {
- TID_NULL = TID_BUSY + 1
- };
-
-private:
- required_device<harddisk_image_device> m_image;
-
- emu_timer * m_last_status_timer;
-};
-
-// ======================> ide_cf_device
-
-class ide_cf_device : public ide_hdd_device
-{
-public:
- // construction/destruction
- ide_cf_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- // optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
-
- void ide_build_identify_device() override;
-};
-
-// device type definition
-DECLARE_DEVICE_TYPE(IDE_HARDDISK, ide_hdd_device)
-DECLARE_DEVICE_TYPE(ATA_CF, ide_cf_device)
-
-#endif // MAME_BUS_ATA_IDEHD_H
diff --git a/src/devices/bus/ata/px320a.cpp b/src/devices/bus/ata/px320a.cpp
index fabad11e967..b7414df264a 100644
--- a/src/devices/bus/ata/px320a.cpp
+++ b/src/devices/bus/ata/px320a.cpp
@@ -51,19 +51,19 @@ void px320a_device::write_cs1(offs_t offset, u16 data, u16 mem_mask)
{
}
-WRITE_LINE_MEMBER(px320a_device::write_dmack)
+void px320a_device::write_dmack(int state)
{
}
-WRITE_LINE_MEMBER(px320a_device::write_csel)
+void px320a_device::write_csel(int state)
{
}
-WRITE_LINE_MEMBER(px320a_device::write_dasp)
+void px320a_device::write_dasp(int state)
{
}
-WRITE_LINE_MEMBER(px320a_device::write_pdiag)
+void px320a_device::write_pdiag(int state)
{
}
diff --git a/src/devices/bus/ata/px320a.h b/src/devices/bus/ata/px320a.h
index 938fc3a580b..553475ddafc 100644
--- a/src/devices/bus/ata/px320a.h
+++ b/src/devices/bus/ata/px320a.h
@@ -26,10 +26,10 @@ protected:
virtual void write_dma(u16 data) override;
virtual void write_cs0(offs_t offset, u16 data, u16 mem_mask = 0xffff) override;
virtual void write_cs1(offs_t offset, u16 data, u16 mem_mask = 0xffff) override;
- virtual DECLARE_WRITE_LINE_MEMBER(write_dmack) override;
- virtual DECLARE_WRITE_LINE_MEMBER(write_csel) override;
- virtual DECLARE_WRITE_LINE_MEMBER(write_dasp) override;
- virtual DECLARE_WRITE_LINE_MEMBER(write_pdiag) override;
+ virtual void write_dmack(int state) override;
+ virtual void write_csel(int state) override;
+ virtual void write_dasp(int state) override;
+ virtual void write_pdiag(int state) override;
private:
void frcpu_map(address_map &map);
diff --git a/src/devices/bus/ata/xm3301.cpp b/src/devices/bus/ata/xm3301.cpp
new file mode 100644
index 00000000000..dabcac41d9e
--- /dev/null
+++ b/src/devices/bus/ata/xm3301.cpp
@@ -0,0 +1,82 @@
+// license:BSD-3-Clause
+// copyright-holders: Angelo Salese, Grull Osgo
+/**************************************************************************************************
+
+Toshiba TAISATAP.SYS support / CD_BALLY.SYS (gammagic)
+
+TODO:
+- XM-3301 on its own is a SCSI-2 drive, the ATAPI variants must be higher number(s)?
+
+**************************************************************************************************/
+
+#include "emu.h"
+#include "xm3301.h"
+
+DEFINE_DEVICE_TYPE(XM3301, toshiba_xm3301_device, "xm3301", "Toshiba XM-3301 CD-ROM Drive")
+
+toshiba_xm3301_device::toshiba_xm3301_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : atapi_cdrom_device(mconfig, XM3301, tag, owner, clock)
+{
+}
+
+void toshiba_xm3301_device::device_start()
+{
+ atapi_cdrom_device::device_start();
+
+ memset(m_identify_buffer, 0, sizeof(m_identify_buffer));
+
+ // From a XM-5401 SCSI dump string $7f08
+ // [5401] will be printed as Master Model
+ // [3605] as Rev number
+ // Both TAISATAP.SYS and CD_BALLY.SYS tests against one of these strings:
+ // "TOSHIBA CD-ROM"
+ // "TOSHIBA CD-ROM XM-3301"
+ // "TOSHIBA CD-ROM DRIVE:XM"
+ // "TOSHIBA DVD" (CD_BALLY.SYS only)
+ t10mmc::set_model("TOSHIBA CD-ROM XM-5401TA3605");
+
+ // xx20 is the only confirmed part (wants IRQ for command $a0)
+ m_identify_buffer[0] = 0x8520;
+
+ // TODO: everything below here is unconfirmed
+ m_identify_buffer[23] = ('1' << 8) | '.';
+ m_identify_buffer[24] = ('0' << 8) | ' ';
+ m_identify_buffer[25] = (' ' << 8) | ' ';
+ m_identify_buffer[26] = (' ' << 8) | ' ';
+
+ m_identify_buffer[27] = ('T' << 8) | 'O';
+ m_identify_buffer[28] = ('S' << 8) | 'H';
+ m_identify_buffer[29] = ('I' << 8) | 'B';
+ m_identify_buffer[30] = ('A' << 8) | ' ';
+ m_identify_buffer[31] = ('X' << 8) | 'M';
+ m_identify_buffer[32] = ('-' << 8) | '3';
+ m_identify_buffer[33] = ('3' << 8) | '0';
+ m_identify_buffer[34] = ('1' << 8) | ' ';
+ m_identify_buffer[35] = (' ' << 8) | ' ';
+ m_identify_buffer[36] = (' ' << 8) | ' ';
+ m_identify_buffer[37] = (' ' << 8) | ' ';
+ m_identify_buffer[38] = (' ' << 8) | ' ';
+ m_identify_buffer[39] = (' ' << 8) | ' ';
+ m_identify_buffer[40] = (' ' << 8) | ' ';
+ m_identify_buffer[41] = (' ' << 8) | ' ';
+ m_identify_buffer[42] = (' ' << 8) | ' ';
+ m_identify_buffer[43] = (' ' << 8) | ' ';
+ m_identify_buffer[44] = (' ' << 8) | ' ';
+ m_identify_buffer[45] = (' ' << 8) | ' ';
+ m_identify_buffer[46] = (' ' << 8) | ' ';
+
+ m_identify_buffer[49] = 0x0400; // IORDY may be disabled
+}
+
+void toshiba_xm3301_device::device_reset()
+{
+ atapi_cdrom_device::device_reset();
+
+}
+
+void toshiba_xm3301_device::identify_packet_device()
+{
+ // gammagic CD_BALLY.SYS doesn't care about $a1 contents but wants these two to be high
+ // when command is issued.
+ m_status |= IDE_STATUS_DSC | IDE_STATUS_DRDY;
+}
diff --git a/src/devices/bus/ata/xm3301.h b/src/devices/bus/ata/xm3301.h
new file mode 100644
index 00000000000..b730502b241
--- /dev/null
+++ b/src/devices/bus/ata/xm3301.h
@@ -0,0 +1,31 @@
+// license:BSD-3-Clause
+// copyright-holders:Angelo Salese, Grull Osgo
+
+#ifndef MAME_BUS_ATA_XM3301_H
+#define MAME_BUS_ATA_XM3301_H
+
+#pragma once
+
+#include "atapicdr.h"
+
+class toshiba_xm3301_device : public atapi_cdrom_device
+{
+public:
+ toshiba_xm3301_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ static constexpr feature_type unemulated_features() { return feature::DISK; }
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ virtual void identify_packet_device() override;
+private:
+
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(XM3301, toshiba_xm3301_device)
+
+#endif // MAME_BUS_ATA_XM3301_H
diff --git a/src/devices/bus/ata/zip100.cpp b/src/devices/bus/ata/zip100.cpp
new file mode 100644
index 00000000000..53a12eeda1b
--- /dev/null
+++ b/src/devices/bus/ata/zip100.cpp
@@ -0,0 +1,100 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/*******************************************************************************
+
+ Skeleton device for Iomega Zip 100MB IDE drive.
+
+ Main IC is a 100-pin QFP system-on-a-chip bearing the manufacturer logo.
+ The SoC seems to be named "Rucify", which appears both on its silkscreened
+ label and in its firmware EPROM.
+
+*******************************************************************************/
+
+#include "emu.h"
+#include "zip100.h"
+#include "cpu/mcs51/mcs51.h"
+
+DEFINE_DEVICE_TYPE(ZIP100_IDE, zip100_ide_device, "zip100_ide", "Iomega Zip 100MB IDE Drive")
+
+zip100_ide_device::zip100_ide_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, ZIP100_IDE, tag, owner, clock)
+ , device_ata_interface(mconfig, *this)
+{
+}
+
+void zip100_ide_device::device_start()
+{
+}
+
+
+u16 zip100_ide_device::read_dma()
+{
+ return 0;
+}
+
+u16 zip100_ide_device::read_cs0(offs_t offset, u16 mem_mask)
+{
+ return 0;
+}
+
+u16 zip100_ide_device::read_cs1(offs_t offset, u16 mem_mask)
+{
+ return 0;
+}
+
+void zip100_ide_device::write_dma(u16 data)
+{
+}
+
+void zip100_ide_device::write_cs0(offs_t offset, u16 data, u16 mem_mask)
+{
+}
+
+void zip100_ide_device::write_cs1(offs_t offset, u16 data, u16 mem_mask)
+{
+}
+
+void zip100_ide_device::write_dmack(int state)
+{
+}
+
+void zip100_ide_device::write_csel(int state)
+{
+}
+
+void zip100_ide_device::write_dasp(int state)
+{
+}
+
+void zip100_ide_device::write_pdiag(int state)
+{
+}
+
+
+void zip100_ide_device::mem_map(address_map &map)
+{
+ map(0x0000, 0xffff).rom().region("eprom", 0);
+}
+
+void zip100_ide_device::ext_map(address_map &map)
+{
+ // TODO
+}
+
+void zip100_ide_device::device_add_mconfig(machine_config &config)
+{
+ i80c32_device &mcu(I80C32(config, "mcu", 12'000'000)); // custom SoC; clock unknown
+ mcu.set_addrmap(AS_PROGRAM, &zip100_ide_device::mem_map);
+ mcu.set_addrmap(AS_IO, &zip100_ide_device::ext_map);
+}
+
+ROM_START(zip100_ide)
+ ROM_REGION(0x10000, "eprom", 0)
+ // "IOMEGA ZIP 100 14.A09/04/98"
+ ROM_LOAD("nm27c520m.u1", 0x00000, 0x10000, CRC(67a04459) SHA1(b8df2a733838db5116982a7295484b77b272287c)) // 20-pin address-latched device
+ROM_END
+
+const tiny_rom_entry *zip100_ide_device::device_rom_region() const
+{
+ return ROM_NAME(zip100_ide);
+}
diff --git a/src/devices/bus/ata/zip100.h b/src/devices/bus/ata/zip100.h
new file mode 100644
index 00000000000..8b90a62533f
--- /dev/null
+++ b/src/devices/bus/ata/zip100.h
@@ -0,0 +1,41 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+
+#ifndef MAME_BUS_ATA_ZIP100_H
+#define MAME_BUS_ATA_ZIP100_H
+
+#pragma once
+
+#include "atadev.h"
+
+class zip100_ide_device : public device_t, public device_ata_interface
+{
+public:
+ zip100_ide_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ static constexpr feature_type unemulated_features() { return feature::DISK; }
+
+protected:
+ virtual void device_start() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+ virtual u16 read_dma() override;
+ virtual u16 read_cs0(offs_t offset, u16 mem_mask = 0xffff) override;
+ virtual u16 read_cs1(offs_t offset, u16 mem_mask = 0xffff) override;
+ virtual void write_dma(u16 data) override;
+ virtual void write_cs0(offs_t offset, u16 data, u16 mem_mask = 0xffff) override;
+ virtual void write_cs1(offs_t offset, u16 data, u16 mem_mask = 0xffff) override;
+ virtual void write_dmack(int state) override;
+ virtual void write_csel(int state) override;
+ virtual void write_dasp(int state) override;
+ virtual void write_pdiag(int state) override;
+
+private:
+ void mem_map(address_map &map);
+ void ext_map(address_map &map);
+};
+
+DECLARE_DEVICE_TYPE(ZIP100_IDE, zip100_ide_device)
+
+#endif // MAME_BUS_ATA_ZIP100_H
diff --git a/src/devices/bus/bbc/1mhzbus/1mhzbus.cpp b/src/devices/bus/bbc/1mhzbus/1mhzbus.cpp
index 0af231e4eb3..502952bc185 100644
--- a/src/devices/bus/bbc/1mhzbus/1mhzbus.cpp
+++ b/src/devices/bus/bbc/1mhzbus/1mhzbus.cpp
@@ -26,10 +26,10 @@ DEFINE_DEVICE_TYPE(BBC_1MHZBUS_SLOT, bbc_1mhzbus_slot_device, "bbc_1mhzbus_slot"
// device_bbc_1mhzbus_interface - constructor
//-------------------------------------------------
-device_bbc_1mhzbus_interface::device_bbc_1mhzbus_interface(const machine_config &mconfig, device_t &device) :
- device_interface(device, "bbc1mhzbus")
+device_bbc_1mhzbus_interface::device_bbc_1mhzbus_interface(const machine_config &mconfig, device_t &device)
+ : device_interface(device, "bbc1mhzbus")
+ , m_slot(dynamic_cast<bbc_1mhzbus_slot_device*>(device.owner()))
{
- m_slot = dynamic_cast<bbc_1mhzbus_slot_device *>(device.owner());
}
@@ -58,10 +58,6 @@ bbc_1mhzbus_slot_device::bbc_1mhzbus_slot_device(const machine_config &mconfig,
void bbc_1mhzbus_slot_device::device_start()
{
m_card = get_card_device();
-
- // resolve callbacks
- m_irq_handler.resolve_safe();
- m_nmi_handler.resolve_safe();
}
@@ -107,7 +103,10 @@ void bbc_1mhzbus_slot_device::jim_w(offs_t offset, uint8_t data)
// slot devices
+#include "24bbc.h"
+#include "2ndserial.h"
#include "autoprom.h"
+#include "barrybox.h"
#include "cc500.h"
#include "cisco.h"
//#include "beebscan.h"
@@ -141,13 +140,15 @@ void bbc_1mhzbus_devices(device_slot_interface &device)
device.option_add("m500", BBC_M500); /* Acorn ANV02 Music 500 */
device.option_add("awhd", BBC_AWHD); /* Acorn Winchester Disc */
device.option_add("autoprom", BBC_AUTOPROM); /* ATPL AutoPrommer */
+ device.option_add("barrybox", BBC_BARRYBOX); /* The Barry-Box */
+ device.option_add("24bbc", BBC_24BBC); /* Sprow 24bBC/RAM Disc */
+ device.option_add("2ndserial", BBC_2NDSERIAL); /* Sprow 2nd Serial Port */
device.option_add("beebide", BBC_BEEBIDE); /* Sprow BeebIDE 16-bit */
device.option_add("ide8", BBC_IDE8); /* RetroClinic BBC 8-bit IDE */
//device.option_add("beebscan", BBC_BEEBSCAN); /* Beeb HandScan */
device.option_add("b488", BBC_B488); /* Aries B488 */
- device.option_add("cisco", BBC_CISCO); /* Cisco Terminal */
//device.option_add("videodig", BBC_VIDEODIG); /* Video Digitiser (RH Electronics) */
- device.option_add("emrmidi", BBC_EMRMIDI); /* EMR Midi Interface */
+ device.option_add("emrmidi", BBC_EMRMIDI); /* EMR MIDI Interface */
//device.option_add("procyon", BBC_PROCYON); /* CST Procyon IEEE Interface */
device.option_add("m2000", BBC_M2000); /* Hybrid Music 2000 Interface */
device.option_add("m3000", BBC_M3000); /* Hybrid Music 3000 Expander */
@@ -167,6 +168,7 @@ void bbc_1mhzbus_devices(device_slot_interface &device)
//device.option_add("prisma3", BBC_PRISMA3); /* PRISMA-3 - Millipede 1989 */
device.option_add("sprite", BBC_SPRITE); /* Logotron Sprite Board */
device.option_add_internal("cfa3000opt", CFA3000_OPT);/* Henson CFA 3000 Option Board */
+ device.option_add_internal("cisco", BBC_CISCO); /* Cisco Terminal */
}
void bbcm_1mhzbus_devices(device_slot_interface &device)
@@ -174,11 +176,14 @@ void bbcm_1mhzbus_devices(device_slot_interface &device)
//device.option_add("teletext", BBC_TELETEXT); /* Acorn ANE01 Teletext Adapter */
device.option_add("ieee488", BBC_IEEE488); /* Acorn ANK01 IEEE488 Interface */
device.option_add("awhd", BBC_AWHD); /* Acorn Winchester Disc */
+ device.option_add("barrybox", BBC_BARRYBOX); /* The Barry-Box */
+ device.option_add("24bbc", BBC_24BBC); /* Sprow 24bBC/RAM Disc */
+ device.option_add("2ndserial", BBC_2NDSERIAL); /* Sprow 2nd Serial Port */
device.option_add("beebide", BBC_BEEBIDE); /* Sprow BeebIDE 16-bit */
device.option_add("ide8", BBC_IDE8); /* RetroClinic BBC 8-bit IDE */
device.option_add("b488", BBC_B488); /* Aries B488 */
//device.option_add("videodig", BBC_VIDEODIG); /* Video Digitiser (RH Electronics) */
- device.option_add("emrmidi", BBC_EMRMIDI); /* EMR Midi Interface */
+ device.option_add("emrmidi", BBC_EMRMIDI); /* EMR MIDI Interface */
//device.option_add("procyon", BBC_PROCYON); /* CST Procyon IEEE Interface */
device.option_add("m2000", BBC_M2000); /* Hybrid Music 2000 Interface */
device.option_add("m3000", BBC_M3000); /* Hybrid Music 3000 Expander */
diff --git a/src/devices/bus/bbc/1mhzbus/1mhzbus.h b/src/devices/bus/bbc/1mhzbus/1mhzbus.h
index 302348b6822..c1885535645 100644
--- a/src/devices/bus/bbc/1mhzbus/1mhzbus.h
+++ b/src/devices/bus/bbc/1mhzbus/1mhzbus.h
@@ -112,11 +112,11 @@ public:
virtual uint8_t jim_r(offs_t offset);
virtual void jim_w(offs_t offset, uint8_t data);
- DECLARE_WRITE_LINE_MEMBER( irq_w ) { m_irq_handler(state); }
- DECLARE_WRITE_LINE_MEMBER( nmi_w ) { m_nmi_handler(state); }
+ void irq_w(int state) { m_irq_handler(state); }
+ void nmi_w(int state) { m_nmi_handler(state); }
protected:
- // device-level overrides
+ // device_t overrides
virtual void device_start() override;
device_bbc_1mhzbus_interface *m_card;
@@ -140,7 +140,7 @@ public:
protected:
device_bbc_1mhzbus_interface(const machine_config &mconfig, device_t &device);
- bbc_1mhzbus_slot_device *m_slot;
+ bbc_1mhzbus_slot_device *const m_slot;
};
diff --git a/src/devices/bus/bbc/1mhzbus/24bbc.cpp b/src/devices/bus/bbc/1mhzbus/24bbc.cpp
new file mode 100644
index 00000000000..2cc14a83f26
--- /dev/null
+++ b/src/devices/bus/bbc/1mhzbus/24bbc.cpp
@@ -0,0 +1,142 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Sprow 24bBC/RAM Disc Board
+
+ http://www.sprow.co.uk/bbc/ramdisc.htm
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "24bbc.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_24BBC, bbc_24bbc_device, "bbc_24bbc", "Sprow 24bBC/RAM Disc Board");
+
+
+//-------------------------------------------------
+// ROM( ramfs )
+//-------------------------------------------------
+
+ROM_START(ramfs)
+ ROM_REGION(0x4000, "exp_rom", 0)
+ ROM_LOAD("ramfs120.rom", 0x0000, 0x4000, CRC(782e6386) SHA1(65493cc1f6ae31cf39298d67dad42ea23be4cae6))
+ROM_END
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void bbc_24bbc_device::device_add_mconfig(machine_config &config)
+{
+ BBC_1MHZBUS_SLOT(config, m_1mhzbus, DERIVED_CLOCK(1, 1), bbc_1mhzbus_devices, nullptr);
+ m_1mhzbus->irq_handler().set(DEVICE_SELF_OWNER, FUNC(bbc_1mhzbus_slot_device::irq_w));
+ m_1mhzbus->nmi_handler().set(DEVICE_SELF_OWNER, FUNC(bbc_1mhzbus_slot_device::nmi_w));
+}
+
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const tiny_rom_entry* bbc_24bbc_device::device_rom_region() const
+{
+ return ROM_NAME(ramfs);
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_24bbc_device - constructor
+//-------------------------------------------------
+
+bbc_24bbc_device::bbc_24bbc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BBC_24BBC, tag, owner, clock)
+ , device_bbc_1mhzbus_interface(mconfig, *this)
+ , m_1mhzbus(*this, "1mhzbus")
+ , m_ram_addr(0)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_24bbc_device::device_start()
+{
+ m_ram = make_unique_clear<uint8_t[]>(0x100000);
+
+ /* register for save states */
+ save_item(NAME(m_ram_addr));
+ save_pointer(NAME(m_ram), 0x100000);
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+uint8_t bbc_24bbc_device::fred_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ switch (offset)
+ {
+ case 0x00:
+ data = (m_ram_addr & 0x0000ff);
+ break;
+ case 0x01:
+ data = (m_ram_addr & 0x00ff00) >> 8;
+ break;
+ case 0x02:
+ data = (m_ram_addr & 0xff0000) >> 16;
+ break;
+ case 0x03:
+ data = m_ram[m_ram_addr & 0xfffff];
+ break;
+ }
+
+ data &= m_1mhzbus->fred_r(offset);
+
+ return data;
+}
+
+void bbc_24bbc_device::fred_w(offs_t offset, uint8_t data)
+{
+ switch (offset)
+ {
+ case 0x00:
+ m_ram_addr = (m_ram_addr & 0xffff00) | data;
+ break;
+ case 0x01:
+ m_ram_addr = (m_ram_addr & 0xff00ff) | (data << 8);
+ break;
+ case 0x02:
+ m_ram_addr = (m_ram_addr & 0x00ffff) | (data << 16);
+ break;
+ case 0x03:
+ m_ram[m_ram_addr & 0xfffff] = data;
+ break;
+ }
+
+ m_1mhzbus->fred_w(offset, data);
+}
+
+uint8_t bbc_24bbc_device::jim_r(offs_t offset)
+{
+ return m_1mhzbus->jim_r(offset);
+}
+
+void bbc_24bbc_device::jim_w(offs_t offset, uint8_t data)
+{
+ m_1mhzbus->jim_w(offset, data);
+}
diff --git a/src/devices/bus/bbc/1mhzbus/24bbc.h b/src/devices/bus/bbc/1mhzbus/24bbc.h
new file mode 100644
index 00000000000..27dbf515225
--- /dev/null
+++ b/src/devices/bus/bbc/1mhzbus/24bbc.h
@@ -0,0 +1,51 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Sprow 24bBC/RAM Disc Board
+
+**********************************************************************/
+
+
+#ifndef MAME_BUS_BBC_1MHZBUS_24BBC_H
+#define MAME_BUS_BBC_1MHZBUS_24BBC_H
+
+#include "1mhzbus.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class bbc_24bbc_device : public device_t, public device_bbc_1mhzbus_interface
+{
+public:
+ // construction/destruction
+ bbc_24bbc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry* device_rom_region() const override;
+
+ virtual uint8_t fred_r(offs_t offset) override;
+ virtual void fred_w(offs_t offset, uint8_t data) override;
+ virtual uint8_t jim_r(offs_t offset) override;
+ virtual void jim_w(offs_t offset, uint8_t data) override;
+
+private:
+ required_device<bbc_1mhzbus_slot_device> m_1mhzbus;
+
+ std::unique_ptr<uint8_t[]> m_ram;
+
+ uint32_t m_ram_addr;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_24BBC, bbc_24bbc_device);
+
+
+#endif /* MAME_BUS_BBC_1MHZBUS_24BBC_H */
diff --git a/src/devices/bus/bbc/1mhzbus/2ndserial.cpp b/src/devices/bus/bbc/1mhzbus/2ndserial.cpp
new file mode 100644
index 00000000000..6d4a53f6a6c
--- /dev/null
+++ b/src/devices/bus/bbc/1mhzbus/2ndserial.cpp
@@ -0,0 +1,200 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Sprow 2nd Serial Port
+
+ http://www.sprow.co.uk/bbc/extraserial.htm
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "2ndserial.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_2NDSERIAL, bbc_2ndserial_device, "bbc_2ndserial", "Sprow 2nd Serial Port");
+
+
+//-------------------------------------------------
+// INPUT_PORTS( 2ndserial )
+//-------------------------------------------------
+
+INPUT_PORTS_START( 2ndserial )
+ PORT_START("LINKS")
+ PORT_CONFNAME(0x03, 0x00, "Base Address")
+ PORT_CONFSETTING(0x00, "&FC60")
+ PORT_CONFSETTING(0x01, "&FC64")
+ PORT_CONFSETTING(0x02, "&FC68")
+ PORT_CONFSETTING(0x03, "&FC6C")
+INPUT_PORTS_END
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor bbc_2ndserial_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( 2ndserial );
+}
+
+
+//-------------------------------------------------
+// ROM( 2ndserial )
+//-------------------------------------------------
+
+ROM_START( 2ndserial )
+ ROM_REGION(0x2000, "exp_rom", 0)
+ ROM_LOAD("2ndserial.rom", 0x0000, 0x2000, CRC(e58cdb76) SHA1(9ebbe845734d77ebf1730ea622ce2db43f18b1c2))
+ROM_END
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void bbc_2ndserial_device::device_add_mconfig(machine_config &config)
+{
+ ACIA6850(config, m_acia);
+ m_acia->txd_handler().set(m_rs232, FUNC(rs232_port_device::write_txd));
+ m_acia->rts_handler().set(m_rs232, FUNC(rs232_port_device::write_rts));
+ m_acia->irq_handler().set(DEVICE_SELF_OWNER, FUNC(bbc_1mhzbus_slot_device::irq_w));
+
+ RS232_PORT(config, m_rs232, default_rs232_devices, nullptr);
+ m_rs232->rxd_handler().set(m_acia, FUNC(acia6850_device::write_rxd));
+ m_rs232->cts_handler().set(m_acia, FUNC(acia6850_device::write_cts));
+
+ CLOCK(config, m_acia_clock_tx, 2.4576_MHz_XTAL);
+ m_acia_clock_tx->signal_handler().set(m_acia, FUNC(acia6850_device::write_txc));
+ CLOCK(config, m_acia_clock_rx, 2.4576_MHz_XTAL);
+ m_acia_clock_rx->signal_handler().set(m_acia, FUNC(acia6850_device::write_rxc));
+
+ BBC_1MHZBUS_SLOT(config, m_1mhzbus, DERIVED_CLOCK(1, 1), bbc_1mhzbus_devices, nullptr);
+ m_1mhzbus->irq_handler().set(DEVICE_SELF_OWNER, FUNC(bbc_1mhzbus_slot_device::irq_w));
+ m_1mhzbus->nmi_handler().set(DEVICE_SELF_OWNER, FUNC(bbc_1mhzbus_slot_device::nmi_w));
+}
+
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const tiny_rom_entry* bbc_2ndserial_device::device_rom_region() const
+{
+ return ROM_NAME(2ndserial);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_2ndserial_device - constructor
+//-------------------------------------------------
+
+bbc_2ndserial_device::bbc_2ndserial_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BBC_2NDSERIAL, tag, owner, clock)
+ , device_bbc_1mhzbus_interface(mconfig, *this)
+ , m_1mhzbus(*this, "1mhzbus")
+ , m_acia(*this, "acia6850")
+ , m_acia_clock_tx(*this, "acia_clock_tx")
+ , m_acia_clock_rx(*this, "acia_clock_rx")
+ , m_rs232(*this, "rs232")
+ , m_links(*this, "LINKS")
+ , m_control(0)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_2ndserial_device::device_start()
+{
+ /* register for save states */
+ save_item(NAME(m_control));
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+uint8_t bbc_2ndserial_device::fred_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+ uint8_t base = 0x60 + (m_links->read() << 2);
+
+ if ((offset & 0xfc) == base)
+ {
+ switch (offset & 0x02)
+ {
+ case 0x00:
+ data = m_acia->read(offset & 1);
+ break;
+ case 0x02:
+ break;
+ }
+ }
+
+ data &= m_1mhzbus->fred_r(offset);
+
+ return data;
+}
+
+void bbc_2ndserial_device::fred_w(offs_t offset, uint8_t data)
+{
+ static const int serial_clocks[8] =
+ {
+ 1, // 000
+ 16, // 001
+ 4, // 010
+ 128, // 011
+ 2, // 100
+ 64, // 101
+ 8, // 110
+ 256 // 111
+ };
+
+ uint8_t base = 0x60 + (m_links->read() << 2);
+
+ if ((offset & 0xfc) == base)
+ {
+ switch (offset & 0x02)
+ {
+ case 0x00:
+ m_acia->write(offset & 1, data);
+ break;
+ case 0x02:
+ m_control = data;
+ m_acia_clock_tx->set_clock_scale((double) 1 / serial_clocks[data & 0x07] );
+ m_acia_clock_rx->set_clock_scale((double) 1 / serial_clocks[data & 0x07] );
+ break;
+ }
+ }
+
+ m_1mhzbus->fred_w(offset, data);
+}
+
+uint8_t bbc_2ndserial_device::jim_r(offs_t offset)
+{
+ return m_1mhzbus->jim_r(offset);
+}
+
+void bbc_2ndserial_device::jim_w(offs_t offset, uint8_t data)
+{
+ m_1mhzbus->jim_w(offset, data);
+}
+
+
+void bbc_2ndserial_device::write_acia_clock(int state)
+{
+ m_acia->write_txc(state);
+ m_acia->write_rxc(state);
+}
diff --git a/src/devices/bus/bbc/1mhzbus/2ndserial.h b/src/devices/bus/bbc/1mhzbus/2ndserial.h
new file mode 100644
index 00000000000..c954098aebd
--- /dev/null
+++ b/src/devices/bus/bbc/1mhzbus/2ndserial.h
@@ -0,0 +1,60 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Sprow 2nd Serial Port
+
+**********************************************************************/
+
+
+#ifndef MAME_BUS_BBC_1MHZBUS_2NDSERIAL_H
+#define MAME_BUS_BBC_1MHZBUS_2NDSERIAL_H
+
+#include "1mhzbus.h"
+#include "bus/rs232/rs232.h"
+#include "machine/6850acia.h"
+#include "machine/clock.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class bbc_2ndserial_device : public device_t, public device_bbc_1mhzbus_interface
+{
+public:
+ // construction/destruction
+ bbc_2ndserial_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry* device_rom_region() const override;
+ virtual ioport_constructor device_input_ports() const override;
+
+ virtual uint8_t fred_r(offs_t offset) override;
+ virtual void fred_w(offs_t offset, uint8_t data) override;
+ virtual uint8_t jim_r(offs_t offset) override;
+ virtual void jim_w(offs_t offset, uint8_t data) override;
+
+private:
+ void write_acia_clock(int state);
+
+ required_device<bbc_1mhzbus_slot_device> m_1mhzbus;
+ required_device<acia6850_device> m_acia;
+ required_device<clock_device> m_acia_clock_tx;
+ required_device<clock_device> m_acia_clock_rx;
+ required_device<rs232_port_device> m_rs232;
+ required_ioport m_links;
+
+ uint8_t m_control;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_2NDSERIAL, bbc_2ndserial_device);
+
+
+#endif /* MAME_BUS_BBC_1MHZBUS_2NDSERIAL_H */
diff --git a/src/devices/bus/bbc/1mhzbus/barrybox.cpp b/src/devices/bus/bbc/1mhzbus/barrybox.cpp
new file mode 100644
index 00000000000..1f9dc091c06
--- /dev/null
+++ b/src/devices/bus/bbc/1mhzbus/barrybox.cpp
@@ -0,0 +1,101 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ The Barry-Box from BML Electronics
+
+ Use with Barry-Box ROM.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "barrybox.h"
+
+#include "sound/dac.h"
+#include "speaker.h"
+
+
+namespace {
+
+class bbc_barrybox_device : public device_t, public device_bbc_1mhzbus_interface
+{
+public:
+ static constexpr feature_type unemulated_features() { return feature::MICROPHONE; }
+
+ bbc_barrybox_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BBC_BARRYBOX, tag, owner, clock)
+ , device_bbc_1mhzbus_interface(mconfig, *this)
+ , m_dac(*this,"dac")
+ {
+ }
+
+protected:
+ // device_t overrides
+ virtual void device_start() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+
+ virtual uint8_t jim_r(offs_t offset) override;
+ virtual void jim_w(offs_t offset, uint8_t data) override;
+
+private:
+ required_device<dac_byte_interface> m_dac;
+};
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void bbc_barrybox_device::device_add_mconfig(machine_config &config)
+{
+ SPEAKER(config, "speaker").front_center();
+ ZN428E(config, m_dac, 0).add_route(ALL_OUTPUTS, "speaker", 0.5);
+
+ // TODO: ZN449E ADC
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_barrybox_device::device_start()
+{
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+uint8_t bbc_barrybox_device::jim_r(offs_t offset)
+{
+ uint8_t data = 0x00;
+
+ if (offset & 0x01)
+ {
+ // ADC busy?
+ }
+
+ if (offset & 0x04)
+ {
+ //data = m_adc->read();
+ }
+
+ return data;
+}
+
+void bbc_barrybox_device::jim_w(offs_t offset, uint8_t data)
+{
+ if (offset & 0x02)
+ {
+ m_dac->write(data);
+ }
+}
+
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(BBC_BARRYBOX, device_bbc_1mhzbus_interface, bbc_barrybox_device, "bbc_barrybox", "The Barry-Box");
diff --git a/src/devices/bus/bbc/1mhzbus/barrybox.h b/src/devices/bus/bbc/1mhzbus/barrybox.h
new file mode 100644
index 00000000000..c51164833a9
--- /dev/null
+++ b/src/devices/bus/bbc/1mhzbus/barrybox.h
@@ -0,0 +1,11 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+#ifndef MAME_BUS_BBC_1MHZBUS_BARRYBOX_H
+#define MAME_BUS_BBC_1MHZBUS_BARRYBOX_H
+
+#include "1mhzbus.h"
+
+
+DECLARE_DEVICE_TYPE(BBC_BARRYBOX, device_bbc_1mhzbus_interface);
+
+#endif // MAME_BUS_BBC_1MHZBUS_BARRYBOX_H
diff --git a/src/devices/bus/bbc/1mhzbus/cc500.cpp b/src/devices/bus/bbc/1mhzbus/cc500.cpp
index c04fc06429e..6da7a1b995c 100644
--- a/src/devices/bus/bbc/1mhzbus/cc500.cpp
+++ b/src/devices/bus/bbc/1mhzbus/cc500.cpp
@@ -38,6 +38,8 @@
#include "emu.h"
#include "cc500.h"
+#include <algorithm>
+
//**************************************************************************
// DEVICE DEFINITIONS
@@ -110,9 +112,9 @@ bbc_cc500_device::bbc_cc500_device(const machine_config &mconfig, const char *ta
void bbc_cc500_device::device_start()
{
- memset(m_palette_ram, 0, sizeof(m_palette_ram));
+ std::fill(std::begin(m_palette_ram), std::end(m_palette_ram), rgb_t(0));
- /* register for save states */
+ // register for save states
save_item(NAME(m_palette_ram));
}
diff --git a/src/devices/bus/bbc/1mhzbus/datacentre.cpp b/src/devices/bus/bbc/1mhzbus/datacentre.cpp
index f21d5af1d54..e6b7ae944dd 100644
--- a/src/devices/bus/bbc/1mhzbus/datacentre.cpp
+++ b/src/devices/bus/bbc/1mhzbus/datacentre.cpp
@@ -276,7 +276,7 @@ void bbc_datacentre_device::jim_w(offs_t offset, uint8_t data)
m_ram[((m_page_ram & 0x0fff) << 8) | offset] = data;
}
-WRITE_LINE_MEMBER(bbc_datacentre_device::irq_w)
+void bbc_datacentre_device::irq_w(int state)
{
if (BIT(m_links->read(), 1))
{
@@ -309,13 +309,13 @@ INPUT_CHANGED_MEMBER(bbc_datacentre_device::import_nvrest)
template<int Drive>
QUICKLOAD_LOAD_MEMBER(bbc_datacentre_device::quickload_cb)
{
- /* simulate *IMPORT from USB to RAMFS */
+ // simulate *IMPORT from USB to RAMFS
if (image.is_filetype("ssd") || image.is_filetype("img") || image.is_filetype("dsd"))
{
- uint32_t ram_addr = (Drive * 0x40000) | 0x1000;
+ uint32_t const ram_addr = (Drive * 0x40000) | 0x1000;
offs_t offset = 0;
- /* import tracks */
+ // import tracks
for (int i = 0; i < 80; i++)
{
image.fread(m_ram.get() + ram_addr + offset, 0xa00);
@@ -328,9 +328,8 @@ QUICKLOAD_LOAD_MEMBER(bbc_datacentre_device::quickload_cb)
}
else
{
- image.seterror(image_error::INVALIDIMAGE, "Invalid filetype, must be SSD, DSD, or IMG");
- return image_init_result::FAIL;
+ return std::make_pair(image_error::INVALIDIMAGE, "Unsupported file type, must be SSD, DSD, or IMG");
}
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
diff --git a/src/devices/bus/bbc/1mhzbus/datacentre.h b/src/devices/bus/bbc/1mhzbus/datacentre.h
index c6846821e9b..df2136137af 100644
--- a/src/devices/bus/bbc/1mhzbus/datacentre.h
+++ b/src/devices/bus/bbc/1mhzbus/datacentre.h
@@ -33,7 +33,7 @@ public:
template<int Drive> DECLARE_QUICKLOAD_LOAD_MEMBER(quickload_cb);
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
// optional information overrides
@@ -47,7 +47,7 @@ protected:
virtual void jim_w(offs_t offset, uint8_t data) override;
private:
- DECLARE_WRITE_LINE_MEMBER(irq_w);
+ void irq_w(int state);
required_ioport m_links;
required_device<ata_interface_device> m_ide;
diff --git a/src/devices/bus/bbc/1mhzbus/emrmidi.cpp b/src/devices/bus/bbc/1mhzbus/emrmidi.cpp
index 6cfbacf23da..77b91c3a106 100644
--- a/src/devices/bus/bbc/1mhzbus/emrmidi.cpp
+++ b/src/devices/bus/bbc/1mhzbus/emrmidi.cpp
@@ -2,7 +2,7 @@
// copyright-holders:Nigel Barnes
/**********************************************************************
- EMR BBC Midi Interface
+ EMR BBC MIDI Interface
http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/EMR_BBCMIDI.html
@@ -27,7 +27,7 @@
// DEVICE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(BBC_EMRMIDI, bbc_emrmidi_device, "bbc_emrmidi", "EMR BBC Midi Interface");
+DEFINE_DEVICE_TYPE(BBC_EMRMIDI, bbc_emrmidi_device, "bbc_emrmidi", "EMR BBC MIDI Interface");
//-------------------------------------------------
@@ -101,7 +101,7 @@ void bbc_emrmidi_device::fred_w(offs_t offset, uint8_t data)
}
}
-WRITE_LINE_MEMBER(bbc_emrmidi_device::write_acia_clock)
+void bbc_emrmidi_device::write_acia_clock(int state)
{
m_acia->write_txc(state);
m_acia->write_rxc(state);
diff --git a/src/devices/bus/bbc/1mhzbus/emrmidi.h b/src/devices/bus/bbc/1mhzbus/emrmidi.h
index 341e487ce24..3eb006c8866 100644
--- a/src/devices/bus/bbc/1mhzbus/emrmidi.h
+++ b/src/devices/bus/bbc/1mhzbus/emrmidi.h
@@ -2,7 +2,7 @@
// copyright-holders:Nigel Barnes
/**********************************************************************
- EMR BBC Midi Interface
+ EMR BBC MIDI Interface
http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/EMR_BBCMIDI.html
@@ -40,7 +40,7 @@ protected:
virtual void fred_w(offs_t offset, uint8_t data) override;
private:
- DECLARE_WRITE_LINE_MEMBER(write_acia_clock);
+ void write_acia_clock(int state);
required_device<acia6850_device> m_acia;
required_device<clock_device> m_acia_clock;
diff --git a/src/devices/bus/bbc/1mhzbus/ide.cpp b/src/devices/bus/bbc/1mhzbus/ide.cpp
index d5fdafb000d..1c6613f1282 100644
--- a/src/devices/bus/bbc/1mhzbus/ide.cpp
+++ b/src/devices/bus/bbc/1mhzbus/ide.cpp
@@ -215,7 +215,7 @@ void bbc_beebide_device::jim_w(offs_t offset, uint8_t data)
m_1mhzbus->jim_w(offset, data);
}
-WRITE_LINE_MEMBER(bbc_beebide_device::irq_w)
+void bbc_beebide_device::irq_w(int state)
{
if (BIT(m_links->read(), 0))
{
diff --git a/src/devices/bus/bbc/1mhzbus/ide.h b/src/devices/bus/bbc/1mhzbus/ide.h
index d326c199ce9..49a5eddb4f7 100644
--- a/src/devices/bus/bbc/1mhzbus/ide.h
+++ b/src/devices/bus/bbc/1mhzbus/ide.h
@@ -68,7 +68,7 @@ protected:
virtual void jim_w(offs_t offset, uint8_t data) override;
private:
- DECLARE_WRITE_LINE_MEMBER(irq_w);
+ void irq_w(int state);
required_device<ata_interface_device> m_ide;
required_device<bbc_1mhzbus_slot_device> m_1mhzbus;
diff --git a/src/devices/bus/bbc/1mhzbus/m2000.cpp b/src/devices/bus/bbc/1mhzbus/m2000.cpp
index 8203cada22e..30eb4b472e5 100644
--- a/src/devices/bus/bbc/1mhzbus/m2000.cpp
+++ b/src/devices/bus/bbc/1mhzbus/m2000.cpp
@@ -155,7 +155,7 @@ void bbc_m2000_device::jim_w(offs_t offset, uint8_t data)
m_1mhzbus->jim_w(offset, data);
}
-WRITE_LINE_MEMBER(bbc_m2000_device::write_acia_clock)
+void bbc_m2000_device::write_acia_clock(int state)
{
m_acia1->write_txc(state);
m_acia1->write_rxc(state);
diff --git a/src/devices/bus/bbc/1mhzbus/m2000.h b/src/devices/bus/bbc/1mhzbus/m2000.h
index eeee1034a4e..71638d3029d 100644
--- a/src/devices/bus/bbc/1mhzbus/m2000.h
+++ b/src/devices/bus/bbc/1mhzbus/m2000.h
@@ -44,7 +44,7 @@ protected:
virtual void jim_w(offs_t offset, uint8_t data) override;
private:
- DECLARE_WRITE_LINE_MEMBER(write_acia_clock);
+ void write_acia_clock(int state);
required_device<bbc_1mhzbus_slot_device> m_1mhzbus;
required_device<acia6850_device> m_acia1;
diff --git a/src/devices/bus/bbc/1mhzbus/opus3.cpp b/src/devices/bus/bbc/1mhzbus/opus3.cpp
index f537eb88b54..bbf76509403 100644
--- a/src/devices/bus/bbc/1mhzbus/opus3.cpp
+++ b/src/devices/bus/bbc/1mhzbus/opus3.cpp
@@ -40,6 +40,9 @@
#include "emu.h"
#include "opus3.h"
+#include "formats/acorn_dsk.h"
+#include "formats/fsd_dsk.h"
+
//**************************************************************************
// DEVICE DEFINITIONS
diff --git a/src/devices/bus/bbc/1mhzbus/opus3.h b/src/devices/bus/bbc/1mhzbus/opus3.h
index 2fd06b4015f..2d14e041b0a 100644
--- a/src/devices/bus/bbc/1mhzbus/opus3.h
+++ b/src/devices/bus/bbc/1mhzbus/opus3.h
@@ -14,8 +14,6 @@
#include "imagedev/floppy.h"
#include "machine/ram.h"
#include "machine/wd_fdc.h"
-#include "formats/acorn_dsk.h"
-#include "formats/fsd_dsk.h"
//**************************************************************************
// TYPE DEFINITIONS
diff --git a/src/devices/bus/bbc/1mhzbus/pms64k.cpp b/src/devices/bus/bbc/1mhzbus/pms64k.cpp
index 0c975b39f48..ef0205d1a4f 100644
--- a/src/devices/bus/bbc/1mhzbus/pms64k.cpp
+++ b/src/devices/bus/bbc/1mhzbus/pms64k.cpp
@@ -4,9 +4,6 @@
PMS 64K Non-Volatile Ram Module
- TODO:
- - Find accompanying software, needed to install utilities to RAM.
-
**********************************************************************/
@@ -22,6 +19,25 @@ DEFINE_DEVICE_TYPE(BBC_PMS64K, bbc_pms64k_device, "bbc_pms64k", "PMS 64K Non-Vol
//-------------------------------------------------
+// ROM( pms64k )
+//-------------------------------------------------
+
+ROM_START(pms64k)
+ ROM_REGION(0x4000, "exp_rom", 0)
+ ROM_LOAD("pms_utility_12d.rom", 0x0000, 0x4000, CRC(c630990e) SHA1(da9abe3b1b0bf34ee5d6ed7ee032686403436289))
+ROM_END
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const tiny_rom_entry *bbc_pms64k_device::device_rom_region() const
+{
+ return ROM_NAME(pms64k);
+}
+
+
+//-------------------------------------------------
// device_add_mconfig - add device configuration
//-------------------------------------------------
@@ -54,6 +70,9 @@ void bbc_pms64k_device::device_start()
{
m_ram = std::make_unique<uint8_t[]>(0x10000);
m_nvram->set_base(m_ram.get(), 0x10000);
+
+ save_pointer(NAME(m_ram), 0x10000);
+ save_item(NAME(m_ram_page));
}
diff --git a/src/devices/bus/bbc/1mhzbus/pms64k.h b/src/devices/bus/bbc/1mhzbus/pms64k.h
index 8b817b7db1d..84975b3dd2a 100644
--- a/src/devices/bus/bbc/1mhzbus/pms64k.h
+++ b/src/devices/bus/bbc/1mhzbus/pms64k.h
@@ -17,20 +17,19 @@
// TYPE DEFINITIONS
//**************************************************************************
-class bbc_pms64k_device:
- public device_t,
- public device_bbc_1mhzbus_interface
+class bbc_pms64k_device : public device_t, public device_bbc_1mhzbus_interface
{
public:
// construction/destruction
bbc_pms64k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
- // device-level overrides
+ // device_t overrides
virtual void device_start() override;
// optional information overrides
virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
virtual void fred_w(offs_t offset, uint8_t data) override;
virtual uint8_t jim_r(offs_t offset) override;
@@ -48,4 +47,4 @@ private:
DECLARE_DEVICE_TYPE(BBC_PMS64K, bbc_pms64k_device);
-#endif /* MAME_BUS_BBC_1MHZBUS_PMS64K_H */
+#endif // MAME_BUS_BBC_1MHZBUS_PMS64K_H
diff --git a/src/devices/bus/bbc/1mhzbus/sasi.cpp b/src/devices/bus/bbc/1mhzbus/sasi.cpp
index 9a55916f8f1..4550a6791c6 100644
--- a/src/devices/bus/bbc/1mhzbus/sasi.cpp
+++ b/src/devices/bus/bbc/1mhzbus/sasi.cpp
@@ -164,12 +164,12 @@ void bbc_sasi_device::jim_w(offs_t offset, uint8_t data)
}
}
-WRITE_LINE_MEMBER(bbc_sasi_device::req_w)
+void bbc_sasi_device::req_w(int state)
{
m_sasi->ack_w(0);
}
-WRITE_LINE_MEMBER(bbc_sasi_device::sel_w)
+void bbc_sasi_device::sel_w(int state)
{
m_sel_state = state;
}
diff --git a/src/devices/bus/bbc/1mhzbus/sasi.h b/src/devices/bus/bbc/1mhzbus/sasi.h
index e1b81125ecd..f7bbb985e27 100644
--- a/src/devices/bus/bbc/1mhzbus/sasi.h
+++ b/src/devices/bus/bbc/1mhzbus/sasi.h
@@ -26,8 +26,8 @@ public:
// construction/destruction
bbc_sasi_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_WRITE_LINE_MEMBER(req_w);
- DECLARE_WRITE_LINE_MEMBER(sel_w);
+ void req_w(int state);
+ void sel_w(int state);
protected:
bbc_sasi_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
diff --git a/src/devices/bus/bbc/1mhzbus/scsi.cpp b/src/devices/bus/bbc/1mhzbus/scsi.cpp
index 26c640467b3..f565dd7eee9 100644
--- a/src/devices/bus/bbc/1mhzbus/scsi.cpp
+++ b/src/devices/bus/bbc/1mhzbus/scsi.cpp
@@ -160,12 +160,12 @@ void bbc_scsi_device::fred_w(offs_t offset, uint8_t data)
}
}
-WRITE_LINE_MEMBER(bbc_scsi_device::bsy_w)
+void bbc_scsi_device::bsy_w(int state)
{
m_scsi->sel_w(0);
}
-WRITE_LINE_MEMBER(bbc_scsi_device::req_w)
+void bbc_scsi_device::req_w(int state)
{
m_scsi->ack_w(0);
diff --git a/src/devices/bus/bbc/1mhzbus/scsi.h b/src/devices/bus/bbc/1mhzbus/scsi.h
index 8a4dabbe113..77cb6a44aae 100644
--- a/src/devices/bus/bbc/1mhzbus/scsi.h
+++ b/src/devices/bus/bbc/1mhzbus/scsi.h
@@ -26,8 +26,8 @@ public:
// construction/destruction
bbc_scsi_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock);
- DECLARE_WRITE_LINE_MEMBER(bsy_w);
- DECLARE_WRITE_LINE_MEMBER(req_w);
+ void bsy_w(int state);
+ void req_w(int state);
protected:
bbc_scsi_device(const machine_config& mconfig, device_type type, const char* tag, device_t* owner, uint32_t clock);
diff --git a/src/devices/bus/bbc/analogue/analogue.cpp b/src/devices/bus/bbc/analogue/analogue.cpp
index e1eb5e3419e..ab4da0b90e2 100644
--- a/src/devices/bus/bbc/analogue/analogue.cpp
+++ b/src/devices/bus/bbc/analogue/analogue.cpp
@@ -57,9 +57,6 @@ bbc_analogue_slot_device::bbc_analogue_slot_device(const machine_config &mconfig
void bbc_analogue_slot_device::device_start()
{
m_card = get_card_device();
-
- // resolve callbacks
- m_lpstb_handler.resolve_safe();
}
uint8_t bbc_analogue_slot_device::ch_r(int channel)
@@ -67,7 +64,7 @@ uint8_t bbc_analogue_slot_device::ch_r(int channel)
if (m_card)
return m_card->ch_r(channel);
else
- return 0x00;
+ return 0xff;
}
uint8_t bbc_analogue_slot_device::pb_r()
@@ -78,6 +75,12 @@ uint8_t bbc_analogue_slot_device::pb_r()
return 0x30;
}
+void bbc_analogue_slot_device::pb_w(uint8_t data)
+{
+ if (m_card)
+ m_card->pb_w(data);
+}
+
//-------------------------------------------------
// SLOT_INTERFACE( bbc_analogue_devices )
@@ -89,7 +92,7 @@ uint8_t bbc_analogue_slot_device::pb_r()
#include "bitstik.h"
//#include "lightpen.h"
//#include "micromike.h"
-//#include "quinkey.h"
+#include "quinkey.h"
#include "cfa3000a.h"
@@ -101,6 +104,6 @@ void bbc_analogue_devices(device_slot_interface &device)
//device.option_add("lightpen", BBC_LIGHTPEN); /* RH Electronics Lightpen */
//device.option_add("micromike", BBC_MICROMIKE); /* Micro Mike */
device.option_add("voltmace3b", BBC_VOLTMACE3B); /* Voltmace Delta 3b "Twin" Joysticks */
- //device.option_add("quinkey", BBC_QUINKEY); /* Microwriter Quinkey */
+ device.option_add("quinkey", BBC_QUINKEY_INTF); /* Microwriter Quinkey */
device.option_add_internal("cfa3000a", CFA3000_ANLG); /* Hanson CFA 3000 Analogue */
}
diff --git a/src/devices/bus/bbc/analogue/analogue.h b/src/devices/bus/bbc/analogue/analogue.h
index bb58d2d0148..22218008481 100644
--- a/src/devices/bus/bbc/analogue/analogue.h
+++ b/src/devices/bus/bbc/analogue/analogue.h
@@ -60,13 +60,14 @@ public:
// callbacks
auto lpstb_handler() { return m_lpstb_handler.bind(); }
- DECLARE_WRITE_LINE_MEMBER(lpstb_w) { m_lpstb_handler(state); }
+ void lpstb_w(int state) { m_lpstb_handler(state); }
uint8_t ch_r(int channel);
uint8_t pb_r();
+ void pb_w(uint8_t data);
protected:
- // device-level overrides
+ // device_t overrides
virtual void device_start() override;
device_bbc_analogue_interface *m_card;
@@ -83,6 +84,7 @@ class device_bbc_analogue_interface : public device_interface
public:
virtual uint8_t ch_r(int channel) { return 0x00; }
virtual uint8_t pb_r() { return 0x30; }
+ virtual void pb_w(uint8_t data) { }
protected:
device_bbc_analogue_interface(const machine_config &mconfig, device_t &device);
diff --git a/src/devices/bus/bbc/analogue/bitstik.cpp b/src/devices/bus/bbc/analogue/bitstik.cpp
index 1913c95c862..f904e20db9f 100644
--- a/src/devices/bus/bbc/analogue/bitstik.cpp
+++ b/src/devices/bus/bbc/analogue/bitstik.cpp
@@ -42,16 +42,16 @@ ROM_END
static INPUT_PORTS_START(bitstik)
PORT_START("CHANNEL0")
- PORT_BIT(0xff, 0x00, IPT_AD_STICK_X) PORT_MINMAX(0x00, 0xff) PORT_SENSITIVITY(25) PORT_KEYDELTA(200) PORT_NAME("AD Stick X") PORT_REVERSE
+ PORT_BIT(0xff, 0x00, IPT_AD_STICK_X) PORT_MINMAX(0x00, 0xff) PORT_SENSITIVITY(25) PORT_KEYDELTA(200) PORT_NAME("AD Stick X")
PORT_START("CHANNEL1")
- PORT_BIT(0xff, 0x00, IPT_AD_STICK_Y) PORT_MINMAX(0x00, 0xff) PORT_SENSITIVITY(25) PORT_KEYDELTA(200) PORT_NAME("AD Stick Y") PORT_REVERSE
+ PORT_BIT(0xff, 0x00, IPT_AD_STICK_Y) PORT_MINMAX(0x00, 0xff) PORT_SENSITIVITY(25) PORT_KEYDELTA(200) PORT_NAME("AD Stick Y")
PORT_START("CHANNEL2")
- PORT_BIT(0xff, 0x00, IPT_AD_STICK_Z) PORT_MINMAX(0x00, 0xff) PORT_SENSITIVITY(25) PORT_KEYDELTA(200) PORT_NAME("AD Stick Z") PORT_REVERSE
+ PORT_BIT(0xff, 0x00, IPT_AD_STICK_Z) PORT_MINMAX(0x00, 0xff) PORT_SENSITIVITY(25) PORT_KEYDELTA(200) PORT_NAME("AD Stick Z")
PORT_START("CHANNEL3")
- PORT_BIT(0xff, IP_ACTIVE_HIGH, IPT_BUTTON3) PORT_NAME("Right Button - Release")
+ PORT_BIT(0xff, IP_ACTIVE_LOW, IPT_BUTTON3) PORT_NAME("Right Button - Release")
PORT_START("BUTTONS")
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_NAME("Top Button - Execute")
diff --git a/src/devices/bus/bbc/analogue/cfa3000a.cpp b/src/devices/bus/bbc/analogue/cfa3000a.cpp
index 0dfd692df12..f48234e091b 100644
--- a/src/devices/bus/bbc/analogue/cfa3000a.cpp
+++ b/src/devices/bus/bbc/analogue/cfa3000a.cpp
@@ -23,16 +23,16 @@ DEFINE_DEVICE_TYPE(CFA3000_ANLG, cfa3000_anlg_device, "cfa3000a", "Henson CFA 30
static INPUT_PORTS_START( cfa3000a )
PORT_START("CHANNEL0")
- PORT_BIT(0xff, 0x80, IPT_PADDLE) PORT_NAME("Background Intensity") PORT_SENSITIVITY(25) PORT_KEYDELTA(5) PORT_CENTERDELTA(0) PORT_REVERSE
+ PORT_BIT(0xff, 0x80, IPT_PADDLE) PORT_NAME("Background Intensity") PORT_SENSITIVITY(25) PORT_KEYDELTA(5) PORT_CENTERDELTA(0)
PORT_START("CHANNEL1")
- PORT_BIT(0xff, 0x00, IPT_UNKNOWN)
+ PORT_BIT(0xff, 0xff, IPT_UNKNOWN)
PORT_START("CHANNEL2")
- PORT_BIT(0xff, 0x80, IPT_PADDLE) PORT_NAME("Age") PORT_SENSITIVITY(25) PORT_KEYDELTA(5) PORT_CENTERDELTA(0) PORT_REVERSE
+ PORT_BIT(0xff, 0x80, IPT_PADDLE) PORT_NAME("Age") PORT_SENSITIVITY(25) PORT_KEYDELTA(5) PORT_CENTERDELTA(0)
PORT_START("CHANNEL3")
- PORT_BIT(0xff, 0x00, IPT_UNKNOWN)
+ PORT_BIT(0xff, 0xff, IPT_UNKNOWN)
PORT_START("BUTTONS")
PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_UNKNOWN)
diff --git a/src/devices/bus/bbc/analogue/joystick.cpp b/src/devices/bus/bbc/analogue/joystick.cpp
index a6e37ebb3ba..434ea1060b2 100644
--- a/src/devices/bus/bbc/analogue/joystick.cpp
+++ b/src/devices/bus/bbc/analogue/joystick.cpp
@@ -24,16 +24,16 @@ DEFINE_DEVICE_TYPE(BBC_VOLTMACE3B, bbc_voltmace3b_device, "bbc_voltmace3b", "Vol
static INPUT_PORTS_START( acornjoy )
PORT_START("JOY0")
- PORT_BIT(0xff, 0x80, IPT_AD_STICK_X) PORT_SENSITIVITY(100) PORT_KEYDELTA(2) PORT_CENTERDELTA(0) PORT_MINMAX(0x00, 0xff) PORT_PLAYER(1)
+ PORT_BIT(0xff, 0x80, IPT_AD_STICK_X) PORT_SENSITIVITY(100) PORT_KEYDELTA(2) PORT_CENTERDELTA(0) PORT_MINMAX(0x00, 0xff) PORT_REVERSE PORT_PLAYER(1)
PORT_START("JOY1")
- PORT_BIT(0xff, 0x80, IPT_AD_STICK_Y) PORT_SENSITIVITY(100) PORT_KEYDELTA(2) PORT_CENTERDELTA(0) PORT_MINMAX(0x00, 0xff) PORT_PLAYER(1)
+ PORT_BIT(0xff, 0x80, IPT_AD_STICK_Y) PORT_SENSITIVITY(100) PORT_KEYDELTA(2) PORT_CENTERDELTA(0) PORT_MINMAX(0x00, 0xff) PORT_REVERSE PORT_PLAYER(1)
PORT_START("JOY2")
- PORT_BIT(0xff, 0x80, IPT_AD_STICK_X) PORT_SENSITIVITY(100) PORT_KEYDELTA(2) PORT_CENTERDELTA(0) PORT_MINMAX(0x00, 0xff) PORT_PLAYER(2)
+ PORT_BIT(0xff, 0x80, IPT_AD_STICK_X) PORT_SENSITIVITY(100) PORT_KEYDELTA(2) PORT_CENTERDELTA(0) PORT_MINMAX(0x00, 0xff) PORT_REVERSE PORT_PLAYER(2)
PORT_START("JOY3")
- PORT_BIT(0xff, 0x80, IPT_AD_STICK_Y) PORT_SENSITIVITY(100) PORT_KEYDELTA(2) PORT_CENTERDELTA(0) PORT_MINMAX(0x00, 0xff) PORT_PLAYER(2)
+ PORT_BIT(0xff, 0x80, IPT_AD_STICK_Y) PORT_SENSITIVITY(100) PORT_KEYDELTA(2) PORT_CENTERDELTA(0) PORT_MINMAX(0x00, 0xff) PORT_REVERSE PORT_PLAYER(2)
PORT_START("BUTTONS")
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_PLAYER(1)
@@ -42,16 +42,16 @@ INPUT_PORTS_END
static INPUT_PORTS_START( voltmace3b )
PORT_START("JOY0")
- PORT_BIT(0xff, 0x80, IPT_AD_STICK_X) PORT_SENSITIVITY(100) PORT_KEYDELTA(2) PORT_CENTERDELTA(20) PORT_MINMAX(0x00, 0xff) PORT_PLAYER(1)
+ PORT_BIT(0xff, 0x80, IPT_AD_STICK_X) PORT_SENSITIVITY(100) PORT_KEYDELTA(2) PORT_CENTERDELTA(20) PORT_MINMAX(0x00, 0xff) PORT_REVERSE PORT_PLAYER(1)
PORT_START("JOY1")
- PORT_BIT(0xff, 0x80, IPT_AD_STICK_Y) PORT_SENSITIVITY(100) PORT_KEYDELTA(2) PORT_CENTERDELTA(20) PORT_MINMAX(0x00, 0xff) PORT_PLAYER(1)
+ PORT_BIT(0xff, 0x80, IPT_AD_STICK_Y) PORT_SENSITIVITY(100) PORT_KEYDELTA(2) PORT_CENTERDELTA(20) PORT_MINMAX(0x00, 0xff) PORT_REVERSE PORT_PLAYER(1)
PORT_START("JOY2")
- PORT_BIT(0xff, 0x80, IPT_AD_STICK_X) PORT_SENSITIVITY(100) PORT_KEYDELTA(2) PORT_CENTERDELTA(20) PORT_MINMAX(0x00, 0xff) PORT_PLAYER(2)
+ PORT_BIT(0xff, 0x80, IPT_AD_STICK_X) PORT_SENSITIVITY(100) PORT_KEYDELTA(2) PORT_CENTERDELTA(20) PORT_MINMAX(0x00, 0xff) PORT_REVERSE PORT_PLAYER(2)
PORT_START("JOY3")
- PORT_BIT(0xff, 0x80, IPT_AD_STICK_Y) PORT_SENSITIVITY(100) PORT_KEYDELTA(2) PORT_CENTERDELTA(20) PORT_MINMAX(0x00, 0xff) PORT_PLAYER(2)
+ PORT_BIT(0xff, 0x80, IPT_AD_STICK_Y) PORT_SENSITIVITY(100) PORT_KEYDELTA(2) PORT_CENTERDELTA(20) PORT_MINMAX(0x00, 0xff) PORT_REVERSE PORT_PLAYER(2)
PORT_START("BUTTONS")
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_PLAYER(1)
diff --git a/src/devices/bus/bbc/analogue/quinkey.cpp b/src/devices/bus/bbc/analogue/quinkey.cpp
new file mode 100644
index 00000000000..b5fee35e7d1
--- /dev/null
+++ b/src/devices/bus/bbc/analogue/quinkey.cpp
@@ -0,0 +1,173 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Microwriter Quinkey
+
+ The Quinkey is provided with an interface that connects to the BBC Micro
+ analogue port, which provides sockets for connecting upto four Quinkey
+ keyboards.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "quinkey.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(BBC_QUINKEY_INTF, bbc_quinkey_intf_device, "bbc_quinkey_intf", "Microwriter Quinkey Interface")
+DEFINE_DEVICE_TYPE(BBC_QUINKEY_SLOT, bbc_quinkey_slot_device, "bbc_quinkey_slot", "Microwriter Quinkey slot")
+DEFINE_DEVICE_TYPE(BBC_QUINKEY, bbc_quinkey_device, "bbc_quinkey", "Microwriter Quinkey")
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void bbc_quinkey_intf_device::device_add_mconfig(machine_config &config)
+{
+ BBC_QUINKEY_SLOT(config, "1", bbc_quinkey_devices, "quinkey");
+ BBC_QUINKEY_SLOT(config, "2", bbc_quinkey_devices, nullptr);
+ BBC_QUINKEY_SLOT(config, "3", bbc_quinkey_devices, nullptr);
+ BBC_QUINKEY_SLOT(config, "4", bbc_quinkey_devices, nullptr);
+}
+
+
+//-------------------------------------------------
+// INPUT_PORTS( quinkey )
+//-------------------------------------------------
+
+static INPUT_PORTS_START( quinkey )
+ PORT_START("KEYS")
+ PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_NAME("Command")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_BUTTON2) PORT_NAME("Thumb")
+ PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_BUTTON3) PORT_NAME("Index Finger")
+ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_BUTTON4) PORT_NAME("Middle Finger")
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_BUTTON5) PORT_NAME("Ring Finger")
+ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_BUTTON6) PORT_NAME("Little Finger")
+ PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_UNUSED)
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_UNUSED)
+INPUT_PORTS_END
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor bbc_quinkey_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(quinkey);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// bbc_quinkey_intf_device - constructor
+//-------------------------------------------------
+
+bbc_quinkey_intf_device::bbc_quinkey_intf_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BBC_QUINKEY_INTF, tag, owner, clock)
+ , device_bbc_analogue_interface(mconfig, *this)
+ , m_quinkey(*this, "%u", 1)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_quinkey_intf_device::device_start()
+{
+}
+
+
+uint8_t bbc_quinkey_intf_device::ch_r(int channel)
+{
+ return m_quinkey[channel]->read();
+}
+
+
+//-------------------------------------------------
+// device_bbc_quinkey_interface - constructor
+//-------------------------------------------------
+
+device_bbc_quinkey_interface::device_bbc_quinkey_interface(const machine_config &mconfig, device_t &device)
+ : device_interface(device, "bbcquinkey")
+ , m_slot(dynamic_cast<bbc_quinkey_slot_device *>(device.owner()))
+{
+}
+
+
+//-------------------------------------------------
+// bbc_quinkey_slot_device - constructor
+//-------------------------------------------------
+
+bbc_quinkey_slot_device::bbc_quinkey_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BBC_QUINKEY_SLOT, tag, owner, clock)
+ , device_single_card_slot_interface<device_bbc_quinkey_interface>(mconfig, *this)
+ , m_card(nullptr)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_quinkey_slot_device::device_start()
+{
+ m_card = get_card_device();
+}
+
+
+uint8_t bbc_quinkey_slot_device::read()
+{
+ if (m_card)
+ return m_card->read();
+ else
+ return 0x00;
+}
+
+
+//-------------------------------------------------
+// bbc_quinkey_device - constructor
+//-------------------------------------------------
+
+bbc_quinkey_device::bbc_quinkey_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BBC_QUINKEY, tag, owner, clock)
+ , device_bbc_quinkey_interface(mconfig, *this)
+ , m_keys(*this, "KEYS")
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_quinkey_device::device_start()
+{
+}
+
+
+uint8_t bbc_quinkey_device::read()
+{
+ return m_keys->read();
+}
+
+
+//-------------------------------------------------
+// SLOT_INTERFACE( bbc_quinkey_devices )
+//-------------------------------------------------
+
+void bbc_quinkey_devices(device_slot_interface &device)
+{
+ device.option_add("quinkey", BBC_QUINKEY);
+}
diff --git a/src/devices/bus/bbc/analogue/quinkey.h b/src/devices/bus/bbc/analogue/quinkey.h
new file mode 100644
index 00000000000..a0a62ca5ef8
--- /dev/null
+++ b/src/devices/bus/bbc/analogue/quinkey.h
@@ -0,0 +1,120 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Microwriter Quinkey
+
+**********************************************************************/
+
+#ifndef MAME_BUS_BBC_ANALOGUE_QUINKEY_H
+#define MAME_BUS_BBC_ANALOGUE_QUINKEY_H
+
+#pragma once
+
+#include "analogue.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> bbc_quinkey_intf_device
+
+class bbc_quinkey_slot_device;
+
+class bbc_quinkey_intf_device : public device_t, public device_bbc_analogue_interface
+{
+public:
+ // construction/destruction
+ bbc_quinkey_intf_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device_t overrides
+ virtual void device_start() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+
+ virtual uint8_t ch_r(int channel) override;
+
+private:
+ required_device_array<bbc_quinkey_slot_device, 4> m_quinkey;
+};
+
+
+// ======================> bbc_quinkey_slot_device
+
+class device_bbc_quinkey_interface;
+
+class bbc_quinkey_slot_device : public device_t, public device_single_card_slot_interface<device_bbc_quinkey_interface>
+{
+public:
+ // construction/destruction
+ template <typename T>
+ bbc_quinkey_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&slot_options, const char *default_option)
+ : bbc_quinkey_slot_device(mconfig, tag, owner)
+ {
+ option_reset();
+ slot_options(*this);
+ set_default_option(default_option);
+ set_fixed(false);
+ }
+
+ bbc_quinkey_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock = 0);
+
+ // callbacks
+ uint8_t read();
+
+protected:
+ // device_t overrides
+ virtual void device_start() override;
+
+ device_bbc_quinkey_interface *m_card;
+};
+
+
+// ======================> device_bbc_quinkey_interface
+
+class device_bbc_quinkey_interface : public device_interface
+{
+public:
+ virtual uint8_t read() { return 0x00; }
+
+protected:
+ device_bbc_quinkey_interface(const machine_config &mconfig, device_t &device);
+
+ bbc_quinkey_slot_device *const m_slot;
+};
+
+
+// ======================> bbc_quinkey_device
+
+class bbc_quinkey_device : public device_t, public device_bbc_quinkey_interface
+{
+public:
+ // construction/destruction
+ bbc_quinkey_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device_t overrides
+ virtual void device_start() override;
+
+ // optional information overrides
+ virtual ioport_constructor device_input_ports() const override;
+
+ virtual uint8_t read() override;
+
+private:
+ required_ioport m_keys;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(BBC_QUINKEY_INTF, bbc_quinkey_intf_device)
+DECLARE_DEVICE_TYPE(BBC_QUINKEY_SLOT, bbc_quinkey_slot_device)
+DECLARE_DEVICE_TYPE(BBC_QUINKEY, bbc_quinkey_device)
+
+void bbc_quinkey_devices(device_slot_interface &device);
+
+
+#endif // MAME_BUS_BBC_ANALOGUE_QUINKEY_H
diff --git a/src/devices/bus/bbc/cart/mastersd.cpp b/src/devices/bus/bbc/cart/mastersd.cpp
index 1c1d21ede72..afeb9921785 100644
--- a/src/devices/bus/bbc/cart/mastersd.cpp
+++ b/src/devices/bus/bbc/cart/mastersd.cpp
@@ -18,6 +18,7 @@
//**************************************************************************
DEFINE_DEVICE_TYPE(BBC_MASTERSD, bbc_mastersd_device, "bbc_mastersd", "MasterSD BBC Master SD Cartridge")
+DEFINE_DEVICE_TYPE(BBC_MASTERSDR2, bbc_mastersdr2_device, "bbc_mastersdr2", "MasterSD R2 BBC Master SD Cartridge")
//-------------------------------------------------
@@ -38,8 +39,8 @@ void bbc_mastersd_device::device_add_mconfig(machine_config &config)
// bbc_mastersd_device - constructor
//-------------------------------------------------
-bbc_mastersd_device::bbc_mastersd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, BBC_MASTERSD, tag, owner, clock)
+bbc_mastersd_device::bbc_mastersd_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, type, tag, owner, clock)
, device_bbc_cart_interface(mconfig, *this)
, m_sdcard(*this, "sdcard")
, m_spi_clock_state(false)
@@ -48,6 +49,16 @@ bbc_mastersd_device::bbc_mastersd_device(const machine_config &mconfig, const ch
{
}
+bbc_mastersd_device::bbc_mastersd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : bbc_mastersd_device(mconfig, BBC_MASTERSD, tag, owner, clock)
+{
+}
+
+bbc_mastersdr2_device::bbc_mastersdr2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : bbc_mastersd_device(mconfig, BBC_MASTERSDR2, tag, owner, clock)
+{
+}
+
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
@@ -110,6 +121,38 @@ uint8_t bbc_mastersd_device::read(offs_t offset, int infc, int infd, int romqa,
return data;
}
+uint8_t bbc_mastersdr2_device::read(offs_t offset, int infc, int infd, int romqa, int oe, int oe2)
+{
+ uint8_t data = 0xff;
+
+ if (infc)
+ {
+ switch (offset)
+ {
+ case 0x80: // SPI controller data port
+ data = m_in_latch;
+ break;
+
+ case 0x81: // SPI controller status register
+ data = m_spi_clock_cycles > 0 ? 0x01 : 0x00;
+ break;
+ }
+ }
+ if (oe)
+ {
+ if (offset >= 0x3600 || romqa == 1)
+ {
+ data = m_ram[(offset & 0x3fff) | (romqa << 14)];
+ }
+ else
+ {
+ data = m_rom[offset & 0x3fff];
+ }
+ }
+
+ return data;
+}
+
//-------------------------------------------------
// write - cartridge data write
//-------------------------------------------------
@@ -139,6 +182,36 @@ void bbc_mastersd_device::write(offs_t offset, uint8_t data, int infc, int infd,
}
}
+void bbc_mastersdr2_device::write(offs_t offset, uint8_t data, int infc, int infd, int romqa, int oe, int oe2)
+{
+ if (infc)
+ {
+ switch (offset)
+ {
+ case 0x80: // SPI controller data port
+ m_out_latch = data;
+ m_spi_clock_cycles = 8;
+
+ if (m_spi_clock_sysclk) // TODO: confirm fast/slow clock dividers
+ m_spi_clock->adjust(attotime::from_hz(16_MHz_XTAL / 2), 0, attotime::from_hz(16_MHz_XTAL / 2));
+ else
+ m_spi_clock->adjust(attotime::from_hz(16_MHz_XTAL / 32), 0, attotime::from_hz(16_MHz_XTAL / 32));
+ break;
+
+ case 0x81: // SPI controller clock register
+ m_spi_clock_sysclk = bool(BIT(data, 0));
+ break;
+ }
+ }
+ if (oe)
+ {
+ if (offset >= 0x3600 || romqa == 1)
+ {
+ m_ram[(offset & 0x3fff) | (romqa << 14)] = data;
+ }
+ }
+}
+
TIMER_CALLBACK_MEMBER(bbc_mastersd_device::spi_clock)
{
diff --git a/src/devices/bus/bbc/cart/mastersd.h b/src/devices/bus/bbc/cart/mastersd.h
index cd6d399176d..6ce6a2574d2 100644
--- a/src/devices/bus/bbc/cart/mastersd.h
+++ b/src/devices/bus/bbc/cart/mastersd.h
@@ -17,6 +17,8 @@
// TYPE DEFINITIONS
//**************************************************************************
+// ======================> bbc_mastersd_device
+
class bbc_mastersd_device : public device_t, public device_bbc_cart_interface
{
public:
@@ -24,6 +26,8 @@ public:
bbc_mastersd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
+ bbc_mastersd_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
// device-level overrides
virtual void device_start() override;
virtual void device_reset() override;
@@ -35,7 +39,6 @@ protected:
virtual uint8_t read(offs_t offset, int infc, int infd, int romqa, int oe, int oe2) override;
virtual void write(offs_t offset, uint8_t data, int infc, int infd, int romqa, int oe, int oe2) override;
-private:
required_device<spi_sdcard_device> m_sdcard;
TIMER_CALLBACK_MEMBER(spi_clock);
@@ -52,8 +55,25 @@ private:
};
+// ======================> bbc_mastersdr2_device
+
+class bbc_mastersdr2_device : public bbc_mastersd_device
+{
+public:
+ // construction/destruction
+ bbc_mastersdr2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // electron_cart_interface overrides
+ virtual uint8_t read(offs_t offset, int infc, int infd, int romqa, int oe, int oe2) override;
+ virtual void write(offs_t offset, uint8_t data, int infc, int infd, int romqa, int oe, int oe2) override;
+};
+
+
+
// device type definition
DECLARE_DEVICE_TYPE(BBC_MASTERSD, bbc_mastersd_device)
+DECLARE_DEVICE_TYPE(BBC_MASTERSDR2, bbc_mastersdr2_device)
#endif // MAME_BUS_BBC_CART_MASTERSD_H
diff --git a/src/devices/bus/bbc/cart/slot.cpp b/src/devices/bus/bbc/cart/slot.cpp
index 04e01ac04db..91ab2779842 100644
--- a/src/devices/bus/bbc/cart/slot.cpp
+++ b/src/devices/bus/bbc/cart/slot.cpp
@@ -75,6 +75,7 @@ void bbcm_cart(device_slot_interface &device)
device.option_add_internal("aqr", ELECTRON_AQR);
device.option_add_internal("click", BBC_CLICK);
device.option_add_internal("mastersd", BBC_MASTERSD);
+ device.option_add_internal("mastersdr2", BBC_MASTERSDR2);
device.option_add_internal("mega256", BBC_MEGA256);
device.option_add_internal("mr8000", BBC_MR8000);
device.option_add_internal("msc", BBC_MSC);
diff --git a/src/devices/bus/bbc/exp/exp.cpp b/src/devices/bus/bbc/exp/exp.cpp
index 4209249a0f9..8339197eccb 100644
--- a/src/devices/bus/bbc/exp/exp.cpp
+++ b/src/devices/bus/bbc/exp/exp.cpp
@@ -60,13 +60,6 @@ bbc_exp_slot_device::bbc_exp_slot_device(const machine_config &mconfig, const ch
void bbc_exp_slot_device::device_start()
{
m_card = get_card_device();
-
- // resolve callbacks
- m_irq_handler.resolve_safe();
- m_nmi_handler.resolve_safe();
-
- m_cb1_handler.resolve_safe();
- m_cb2_handler.resolve_safe();
}
diff --git a/src/devices/bus/bbc/exp/exp.h b/src/devices/bus/bbc/exp/exp.h
index f7d695b59a5..56c9d0b6838 100644
--- a/src/devices/bus/bbc/exp/exp.h
+++ b/src/devices/bus/bbc/exp/exp.h
@@ -82,12 +82,12 @@ public:
uint8_t sheila_r(offs_t offset);
void sheila_w(offs_t offset, uint8_t data);
- DECLARE_WRITE_LINE_MEMBER( irq_w ) { m_irq_handler(state); }
- DECLARE_WRITE_LINE_MEMBER( nmi_w ) { m_nmi_handler(state); }
+ void irq_w(int state) { m_irq_handler(state); }
+ void nmi_w(int state) { m_nmi_handler(state); }
// additional handlers for mertec device
- DECLARE_WRITE_LINE_MEMBER(cb1_w) { m_cb1_handler(state); }
- DECLARE_WRITE_LINE_MEMBER(cb2_w) { m_cb2_handler(state); }
+ void cb1_w(int state) { m_cb1_handler(state); }
+ void cb2_w(int state) { m_cb2_handler(state); }
uint8_t pb_r();
void pb_w(uint8_t data);
diff --git a/src/devices/bus/bbc/exp/mertec.cpp b/src/devices/bus/bbc/exp/mertec.cpp
index 11b3c9dccb9..c561f052460 100644
--- a/src/devices/bus/bbc/exp/mertec.cpp
+++ b/src/devices/bus/bbc/exp/mertec.cpp
@@ -106,7 +106,7 @@ void bbc_mertec_device::device_start()
int bbc_mertec_device::get_analogue_input(int channel_number)
{
- return ((0xff - m_analog->ch_r(channel_number)) << 8);
+ return m_analog->ch_r(channel_number) << 8;
}
void bbc_mertec_device::upd7002_eoc(int data)
diff --git a/src/devices/bus/bbc/fdc/acorn.cpp b/src/devices/bus/bbc/fdc/acorn.cpp
index 22b2cc027c8..8fb970f77d2 100644
--- a/src/devices/bus/bbc/fdc/acorn.cpp
+++ b/src/devices/bus/bbc/fdc/acorn.cpp
@@ -10,6 +10,9 @@
#include "emu.h"
#include "acorn.h"
+#include "formats/acorn_dsk.h"
+#include "formats/fsd_dsk.h"
+
//**************************************************************************
// DEVICE DEFINITIONS
@@ -196,14 +199,14 @@ void bbc_acorn8271_device::write(offs_t offset, uint8_t data)
}
}
-WRITE_LINE_MEMBER(bbc_acorn8271_device::motor_w)
+void bbc_acorn8271_device::motor_w(int state)
{
if (m_floppy[0]->get_device()) m_floppy[0]->get_device()->mon_w(!state);
if (m_floppy[1]->get_device()) m_floppy[1]->get_device()->mon_w(!state);
m_fdc->ready_w(!state);
}
-WRITE_LINE_MEMBER(bbc_acorn8271_device::side_w)
+void bbc_acorn8271_device::side_w(int state)
{
if (m_floppy[0]->get_device()) m_floppy[0]->get_device()->ss_w(state);
if (m_floppy[1]->get_device()) m_floppy[1]->get_device()->ss_w(state);
@@ -255,12 +258,12 @@ void bbc_acorn1770_device::write(offs_t offset, uint8_t data)
}
}
-WRITE_LINE_MEMBER(bbc_acorn1770_device::fdc_intrq_w)
+void bbc_acorn1770_device::fdc_intrq_w(int state)
{
m_slot->intrq_w((state && m_fdc_ie) ? ASSERT_LINE : CLEAR_LINE);
}
-WRITE_LINE_MEMBER(bbc_acorn1770_device::fdc_drq_w)
+void bbc_acorn1770_device::fdc_drq_w(int state)
{
m_slot->drq_w((state && m_fdc_ie) ? ASSERT_LINE : CLEAR_LINE);
}
diff --git a/src/devices/bus/bbc/fdc/acorn.h b/src/devices/bus/bbc/fdc/acorn.h
index 347368ff29f..6b4adea4fbf 100644
--- a/src/devices/bus/bbc/fdc/acorn.h
+++ b/src/devices/bus/bbc/fdc/acorn.h
@@ -16,9 +16,6 @@
#include "imagedev/floppy.h"
#include "machine/i8271.h"
#include "machine/wd_fdc.h"
-#include "formats/acorn_dsk.h"
-#include "formats/fsd_dsk.h"
-#include "formats/pc_dsk.h"
//**************************************************************************
// TYPE DEFINITIONS
@@ -46,8 +43,8 @@ protected:
virtual void write(offs_t offset, uint8_t data) override;
private:
- DECLARE_WRITE_LINE_MEMBER(motor_w);
- DECLARE_WRITE_LINE_MEMBER(side_w);
+ void motor_w(int state);
+ void side_w(int state);
required_device<i8271_device> m_fdc;
required_device_array<floppy_connector, 2> m_floppy;
@@ -73,8 +70,8 @@ protected:
virtual void write(offs_t offset, uint8_t data) override;
private:
- DECLARE_WRITE_LINE_MEMBER(fdc_intrq_w);
- DECLARE_WRITE_LINE_MEMBER(fdc_drq_w);
+ void fdc_intrq_w(int state);
+ void fdc_drq_w(int state);
required_device<wd1770_device> m_fdc;
required_device_array<floppy_connector, 2> m_floppy;
diff --git a/src/devices/bus/bbc/fdc/ams.cpp b/src/devices/bus/bbc/fdc/ams.cpp
index ef64eabd75c..41f4c5a771c 100644
--- a/src/devices/bus/bbc/fdc/ams.cpp
+++ b/src/devices/bus/bbc/fdc/ams.cpp
@@ -6,10 +6,11 @@
**********************************************************************/
-
#include "emu.h"
#include "ams.h"
+#include "formats/acorn_dsk.h"
+
//**************************************************************************
// DEVICE DEFINITIONS
@@ -122,14 +123,14 @@ void bbc_ams3_device::write(offs_t offset, uint8_t data)
}
}
-WRITE_LINE_MEMBER(bbc_ams3_device::motor_w)
+void bbc_ams3_device::motor_w(int state)
{
if (m_floppy[0]->get_device()) m_floppy[0]->get_device()->mon_w(!state);
if (m_floppy[1]->get_device()) m_floppy[1]->get_device()->mon_w(!state);
m_fdc->ready_w(!state);
}
-WRITE_LINE_MEMBER(bbc_ams3_device::side_w)
+void bbc_ams3_device::side_w(int state)
{
if (m_floppy[0]->get_device()) m_floppy[0]->get_device()->ss_w(state);
if (m_floppy[1]->get_device()) m_floppy[1]->get_device()->ss_w(state);
diff --git a/src/devices/bus/bbc/fdc/ams.h b/src/devices/bus/bbc/fdc/ams.h
index a1bdcc27696..8add01e2257 100644
--- a/src/devices/bus/bbc/fdc/ams.h
+++ b/src/devices/bus/bbc/fdc/ams.h
@@ -6,7 +6,6 @@
**********************************************************************/
-
#ifndef MAME_BUS_BBC_FDC_AMS_H
#define MAME_BUS_BBC_FDC_AMS_H
@@ -15,7 +14,6 @@
#include "fdc.h"
#include "imagedev/floppy.h"
#include "machine/i8271.h"
-#include "formats/acorn_dsk.h"
//**************************************************************************
// TYPE DEFINITIONS
@@ -43,9 +41,9 @@ protected:
virtual void write(offs_t offset, uint8_t data) override;
private:
- DECLARE_WRITE_LINE_MEMBER(fdc_intrq_w);
- DECLARE_WRITE_LINE_MEMBER(motor_w);
- DECLARE_WRITE_LINE_MEMBER(side_w);
+ void fdc_intrq_w(int state);
+ void motor_w(int state);
+ void side_w(int state);
required_device<i8271_device> m_fdc;
required_device_array<floppy_connector, 2> m_floppy;
diff --git a/src/devices/bus/bbc/fdc/cumana.cpp b/src/devices/bus/bbc/fdc/cumana.cpp
index 2db9b4b2f2a..edcd90d7fa5 100644
--- a/src/devices/bus/bbc/fdc/cumana.cpp
+++ b/src/devices/bus/bbc/fdc/cumana.cpp
@@ -8,10 +8,12 @@
**********************************************************************/
-
#include "emu.h"
#include "cumana.h"
+#include "formats/acorn_dsk.h"
+#include "formats/fsd_dsk.h"
+
//**************************************************************************
// DEVICE DEFINITIONS
@@ -204,19 +206,19 @@ void bbc_cumanafdc_device::write(offs_t offset, uint8_t data)
}
}
-WRITE_LINE_MEMBER(bbc_cumanafdc_device::fdc_intrq_w)
+void bbc_cumanafdc_device::fdc_intrq_w(int state)
{
if (m_fdc_ie)
m_slot->intrq_w(state);
}
-WRITE_LINE_MEMBER(bbc_cumanafdc_device::fdc_drq_w)
+void bbc_cumanafdc_device::fdc_drq_w(int state)
{
if (m_fdc_ie)
m_slot->drq_w(state);
}
-WRITE_LINE_MEMBER(bbc_cumanafdc_device::motor_w)
+void bbc_cumanafdc_device::motor_w(int state)
{
if (m_floppy[0]->get_device()) m_floppy[0]->get_device()->mon_w(!state);
if (m_floppy[1]->get_device()) m_floppy[1]->get_device()->mon_w(!state);
diff --git a/src/devices/bus/bbc/fdc/cumana.h b/src/devices/bus/bbc/fdc/cumana.h
index d775a68e622..06ad3ca4da0 100644
--- a/src/devices/bus/bbc/fdc/cumana.h
+++ b/src/devices/bus/bbc/fdc/cumana.h
@@ -14,8 +14,6 @@
#include "fdc.h"
#include "imagedev/floppy.h"
#include "machine/wd_fdc.h"
-#include "formats/acorn_dsk.h"
-#include "formats/fsd_dsk.h"
//**************************************************************************
// TYPE DEFINITIONS
@@ -28,9 +26,9 @@ class bbc_cumanafdc_device :
public:
static void floppy_formats(format_registration &fr);
- DECLARE_WRITE_LINE_MEMBER(fdc_intrq_w);
- DECLARE_WRITE_LINE_MEMBER(fdc_drq_w);
- DECLARE_WRITE_LINE_MEMBER(motor_w);
+ void fdc_intrq_w(int state);
+ void fdc_drq_w(int state);
+ void motor_w(int state);
protected:
// construction/destruction
diff --git a/src/devices/bus/bbc/fdc/cv1797.cpp b/src/devices/bus/bbc/fdc/cv1797.cpp
index 32d517f35cb..8c51463bbf6 100644
--- a/src/devices/bus/bbc/fdc/cv1797.cpp
+++ b/src/devices/bus/bbc/fdc/cv1797.cpp
@@ -12,10 +12,12 @@
**********************************************************************/
-
#include "emu.h"
#include "cv1797.h"
+#include "formats/acorn_dsk.h"
+#include "formats/fsd_dsk.h"
+
//**************************************************************************
// DEVICE DEFINITIONS
@@ -144,12 +146,12 @@ void bbc_cv1797_device::write(offs_t offset, uint8_t data)
}
}
-WRITE_LINE_MEMBER(bbc_cv1797_device::fdc_sso_w)
+void bbc_cv1797_device::fdc_sso_w(int state)
{
// TODO: schematic required to confirm usage.
}
-WRITE_LINE_MEMBER(bbc_cv1797_device::fdc_hld_w)
+void bbc_cv1797_device::fdc_hld_w(int state)
{
if (m_floppy)
m_floppy->mon_w(!state);
diff --git a/src/devices/bus/bbc/fdc/cv1797.h b/src/devices/bus/bbc/fdc/cv1797.h
index 16b870f963c..40223fd14b6 100644
--- a/src/devices/bus/bbc/fdc/cv1797.h
+++ b/src/devices/bus/bbc/fdc/cv1797.h
@@ -6,7 +6,6 @@
**********************************************************************/
-
#ifndef MAME_BUS_BBC_FDC_CV1797_H
#define MAME_BUS_BBC_FDC_CV1797_H
@@ -15,8 +14,6 @@
#include "fdc.h"
#include "imagedev/floppy.h"
#include "machine/wd_fdc.h"
-#include "formats/acorn_dsk.h"
-#include "formats/fsd_dsk.h"
//**************************************************************************
// TYPE DEFINITIONS
@@ -44,8 +41,8 @@ protected:
private:
static void floppy_formats(format_registration &fr);
- DECLARE_WRITE_LINE_MEMBER(fdc_sso_w);
- DECLARE_WRITE_LINE_MEMBER(fdc_hld_w);
+ void fdc_sso_w(int state);
+ void fdc_hld_w(int state);
required_device<fd1797_device> m_fdc;
required_device_array<floppy_connector, 2> m_floppies;
diff --git a/src/devices/bus/bbc/fdc/fdc.cpp b/src/devices/bus/bbc/fdc/fdc.cpp
index abfc5e109b1..e13993d7b11 100644
--- a/src/devices/bus/bbc/fdc/fdc.cpp
+++ b/src/devices/bus/bbc/fdc/fdc.cpp
@@ -58,10 +58,6 @@ bbc_fdc_slot_device::bbc_fdc_slot_device(const machine_config &mconfig, const ch
void bbc_fdc_slot_device::device_start()
{
m_card = get_card_device();
-
- // resolve callbacks
- m_intrq_cb.resolve_safe();
- m_drq_cb.resolve_safe();
}
//-------------------------------------------------
diff --git a/src/devices/bus/bbc/fdc/fdc.h b/src/devices/bus/bbc/fdc/fdc.h
index 7138ced7ad1..4ee6c6ec717 100644
--- a/src/devices/bus/bbc/fdc/fdc.h
+++ b/src/devices/bus/bbc/fdc/fdc.h
@@ -48,8 +48,8 @@ public:
uint8_t read(offs_t offset);
void write(offs_t offset, uint8_t data);
- DECLARE_WRITE_LINE_MEMBER( intrq_w ) { m_intrq_cb(state); }
- DECLARE_WRITE_LINE_MEMBER( drq_w) { m_drq_cb(state); }
+ void intrq_w(int state) { m_intrq_cb(state); }
+ void drq_w(int state) { m_drq_cb(state); }
protected:
// device-level overrides
diff --git a/src/devices/bus/bbc/fdc/kenda.cpp b/src/devices/bus/bbc/fdc/kenda.cpp
index 801dd731200..fc71fa88cae 100644
--- a/src/devices/bus/bbc/fdc/kenda.cpp
+++ b/src/devices/bus/bbc/fdc/kenda.cpp
@@ -20,10 +20,11 @@
**********************************************************************/
-
#include "emu.h"
#include "kenda.h"
+#include "formats/acorn_dsk.h"
+
//**************************************************************************
// DEVICE DEFINITIONS
@@ -161,7 +162,7 @@ void bbc_kenda_device::write(offs_t offset, uint8_t data)
}
}
-WRITE_LINE_MEMBER(bbc_kenda_device::motor_w)
+void bbc_kenda_device::motor_w(int state)
{
if (m_floppy[0]->get_device()) m_floppy[0]->get_device()->mon_w(!state);
if (m_floppy[1]->get_device()) m_floppy[1]->get_device()->mon_w(!state);
diff --git a/src/devices/bus/bbc/fdc/kenda.h b/src/devices/bus/bbc/fdc/kenda.h
index 99868f062fb..bea1bd7c3c7 100644
--- a/src/devices/bus/bbc/fdc/kenda.h
+++ b/src/devices/bus/bbc/fdc/kenda.h
@@ -6,7 +6,6 @@
**********************************************************************/
-
#ifndef MAME_BUS_BBC_FDC_KENDA_H
#define MAME_BUS_BBC_FDC_KENDA_H
@@ -15,7 +14,6 @@
#include "fdc.h"
#include "imagedev/floppy.h"
#include "machine/wd_fdc.h"
-#include "formats/acorn_dsk.h"
//**************************************************************************
// TYPE DEFINITIONS
@@ -41,7 +39,7 @@ protected:
private:
static void floppy_formats(format_registration &fr);
- DECLARE_WRITE_LINE_MEMBER(motor_w);
+ void motor_w(int state);
required_device<wd2793_device> m_fdc;
required_device_array<floppy_connector, 2> m_floppy;
diff --git a/src/devices/bus/bbc/fdc/opus.cpp b/src/devices/bus/bbc/fdc/opus.cpp
index 2851fc3de3c..2eaa599fc97 100644
--- a/src/devices/bus/bbc/fdc/opus.cpp
+++ b/src/devices/bus/bbc/fdc/opus.cpp
@@ -12,10 +12,12 @@
**********************************************************************/
-
#include "emu.h"
#include "opus.h"
+#include "formats/acorn_dsk.h"
+#include "formats/fsd_dsk.h"
+
//**************************************************************************
// DEVICE DEFINITIONS
@@ -316,7 +318,7 @@ void bbc_opusfdc_device::write(offs_t offset, uint8_t data)
}
}
-WRITE_LINE_MEMBER(bbc_opusfdc_device::motor_w)
+void bbc_opusfdc_device::motor_w(int state)
{
if (m_floppy[0]->get_device()) m_floppy[0]->get_device()->mon_w(!state);
if (m_floppy[1]->get_device()) m_floppy[1]->get_device()->mon_w(!state);
diff --git a/src/devices/bus/bbc/fdc/opus.h b/src/devices/bus/bbc/fdc/opus.h
index 5cca5a5c701..675fc37f815 100644
--- a/src/devices/bus/bbc/fdc/opus.h
+++ b/src/devices/bus/bbc/fdc/opus.h
@@ -13,8 +13,6 @@
#include "imagedev/floppy.h"
#include "machine/upd765.h"
#include "machine/wd_fdc.h"
-#include "formats/acorn_dsk.h"
-#include "formats/fsd_dsk.h"
//**************************************************************************
// TYPE DEFINITIONS
@@ -52,7 +50,7 @@ class bbc_opusfdc_device :
public:
static void floppy_formats(format_registration &fr);
- DECLARE_WRITE_LINE_MEMBER(motor_w);
+ void motor_w(int state);
protected:
// construction/destruction
diff --git a/src/devices/bus/bbc/fdc/solidisk.cpp b/src/devices/bus/bbc/fdc/solidisk.cpp
index c342fc64355..dee6e4360ba 100644
--- a/src/devices/bus/bbc/fdc/solidisk.cpp
+++ b/src/devices/bus/bbc/fdc/solidisk.cpp
@@ -11,10 +11,12 @@
**********************************************************************/
-
#include "emu.h"
#include "solidisk.h"
+#include "formats/acorn_dsk.h"
+#include "formats/fsd_dsk.h"
+
//**************************************************************************
// DEVICE DEFINITIONS
@@ -226,14 +228,14 @@ INPUT_CHANGED_MEMBER(bbc_stlfdc_device::fdc_changed)
device_reset();
}
-WRITE_LINE_MEMBER(bbc_stlfdc_device::motor_w)
+void bbc_stlfdc_device::motor_w(int state)
{
if (m_floppy[0]->get_device()) m_floppy[0]->get_device()->mon_w(!state);
if (m_floppy[1]->get_device()) m_floppy[1]->get_device()->mon_w(!state);
m_i8271->ready_w(!state);
}
-WRITE_LINE_MEMBER(bbc_stlfdc_device::side_w)
+void bbc_stlfdc_device::side_w(int state)
{
if (m_floppy[0]->get_device()) m_floppy[0]->get_device()->ss_w(state);
if (m_floppy[1]->get_device()) m_floppy[1]->get_device()->ss_w(state);
diff --git a/src/devices/bus/bbc/fdc/solidisk.h b/src/devices/bus/bbc/fdc/solidisk.h
index 025db9ca332..4e372ff758b 100644
--- a/src/devices/bus/bbc/fdc/solidisk.h
+++ b/src/devices/bus/bbc/fdc/solidisk.h
@@ -6,7 +6,6 @@
**********************************************************************/
-
#ifndef MAME_BUS_BBC_FDC_SOLIDISK_H
#define MAME_BUS_BBC_FDC_SOLIDISK_H
@@ -16,8 +15,6 @@
#include "machine/i8271.h"
#include "imagedev/floppy.h"
#include "machine/wd_fdc.h"
-#include "formats/acorn_dsk.h"
-#include "formats/fsd_dsk.h"
//**************************************************************************
// TYPE DEFINITIONS
@@ -35,8 +32,8 @@ protected:
// construction/destruction
bbc_stlfdc_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_WRITE_LINE_MEMBER(motor_w);
- DECLARE_WRITE_LINE_MEMBER(side_w);
+ void motor_w(int state);
+ void side_w(int state);
required_device<wd1770_device> m_wd1770;
optional_device<i8271_device> m_i8271;
diff --git a/src/devices/bus/bbc/fdc/udm.cpp b/src/devices/bus/bbc/fdc/udm.cpp
index dc078aa8dfa..3c913721909 100644
--- a/src/devices/bus/bbc/fdc/udm.cpp
+++ b/src/devices/bus/bbc/fdc/udm.cpp
@@ -6,10 +6,12 @@
**********************************************************************/
-
#include "emu.h"
#include "udm.h"
+#include "formats/acorn_dsk.h"
+#include "formats/fsd_dsk.h"
+
//**************************************************************************
// DEVICE DEFINITIONS
@@ -151,17 +153,17 @@ void bbc_udm_device::write(offs_t offset, uint8_t data)
}
}
-WRITE_LINE_MEMBER(bbc_udm_device::intrq_w)
+void bbc_udm_device::intrq_w(int state)
{
m_slot->intrq_w((state && m_fdc_ie) ? ASSERT_LINE : CLEAR_LINE);
}
-WRITE_LINE_MEMBER(bbc_udm_device::drq_w)
+void bbc_udm_device::drq_w(int state)
{
m_slot->drq_w((state && m_fdc_ie) ? ASSERT_LINE : CLEAR_LINE);
}
-WRITE_LINE_MEMBER(bbc_udm_device::motor_w)
+void bbc_udm_device::motor_w(int state)
{
if (m_floppy[0]->get_device()) m_floppy[0]->get_device()->mon_w(!state);
if (m_floppy[1]->get_device()) m_floppy[1]->get_device()->mon_w(!state);
diff --git a/src/devices/bus/bbc/fdc/udm.h b/src/devices/bus/bbc/fdc/udm.h
index 8e21917efb8..51a360f3729 100644
--- a/src/devices/bus/bbc/fdc/udm.h
+++ b/src/devices/bus/bbc/fdc/udm.h
@@ -6,7 +6,6 @@
**********************************************************************/
-
#ifndef MAME_BUS_BBC_FDC_UDM_H
#define MAME_BUS_BBC_FDC_UDM_H
@@ -15,8 +14,6 @@
#include "fdc.h"
#include "imagedev/floppy.h"
#include "machine/wd_fdc.h"
-#include "formats/acorn_dsk.h"
-#include "formats/fsd_dsk.h"
//**************************************************************************
// TYPE DEFINITIONS
@@ -44,9 +41,9 @@ protected:
private:
static void floppy_formats(format_registration &fr);
- DECLARE_WRITE_LINE_MEMBER(intrq_w);
- DECLARE_WRITE_LINE_MEMBER(drq_w);
- DECLARE_WRITE_LINE_MEMBER(motor_w);
+ void intrq_w(int state);
+ void drq_w(int state);
+ void motor_w(int state);
required_device<wd2793_device> m_fdc;
required_device_array<floppy_connector, 2> m_floppy;
diff --git a/src/devices/bus/bbc/fdc/watford.cpp b/src/devices/bus/bbc/fdc/watford.cpp
index 7f058c41838..cfc23e2dee7 100644
--- a/src/devices/bus/bbc/fdc/watford.cpp
+++ b/src/devices/bus/bbc/fdc/watford.cpp
@@ -10,10 +10,12 @@
**********************************************************************/
-
#include "emu.h"
#include "watford.h"
+#include "formats/acorn_dsk.h"
+#include "formats/fsd_dsk.h"
+
//**************************************************************************
// DEVICE DEFINITIONS
diff --git a/src/devices/bus/bbc/fdc/watford.h b/src/devices/bus/bbc/fdc/watford.h
index 37a635d2afb..9129260f494 100644
--- a/src/devices/bus/bbc/fdc/watford.h
+++ b/src/devices/bus/bbc/fdc/watford.h
@@ -14,8 +14,6 @@
#include "fdc.h"
#include "imagedev/floppy.h"
#include "machine/wd_fdc.h"
-#include "formats/acorn_dsk.h"
-#include "formats/fsd_dsk.h"
//**************************************************************************
// TYPE DEFINITIONS
diff --git a/src/devices/bus/bbc/internal/cumana68k.cpp b/src/devices/bus/bbc/internal/cumana68k.cpp
index 19e71ee8692..4a2d7c71e2e 100644
--- a/src/devices/bus/bbc/internal/cumana68k.cpp
+++ b/src/devices/bus/bbc/internal/cumana68k.cpp
@@ -16,13 +16,14 @@
**********************************************************************/
-
#include "emu.h"
#include "cumana68k.h"
#include "machine/nscsi_bus.h"
#include "bus/nscsi/devices.h"
#include "softlist_dev.h"
+#include "formats/os9_dsk.h"
+
//**************************************************************************
// DEVICE DEFINITIONS
@@ -96,7 +97,7 @@ void bbc_cumana68k_device::device_add_mconfig(machine_config &config)
downcast<nscsi_callback_device&>(*device).req_callback().append(m_pia_sasi, FUNC(pia6821_device::ca1_w));
});
- PIA6821(config, m_pia_sasi, 0);
+ PIA6821(config, m_pia_sasi);
m_pia_sasi->readpa_handler().set(m_sasi, FUNC(nscsi_callback_device::read));
m_pia_sasi->writepa_handler().set(m_sasi, FUNC(nscsi_callback_device::write));
m_pia_sasi->writepb_handler().set(FUNC(bbc_cumana68k_device::pia_sasi_pb_w));
@@ -106,7 +107,7 @@ void bbc_cumana68k_device::device_add_mconfig(machine_config &config)
m_pia_sasi->irqa_handler().set(m_irqs, FUNC(input_merger_device::in_w<0>));
m_pia_sasi->irqb_handler().set(m_irqs, FUNC(input_merger_device::in_w<1>));
- PIA6821(config, m_pia_rtc, 0);
+ PIA6821(config, m_pia_rtc);
m_pia_rtc->readpa_handler().set([this]() { return m_mc146818_data; });
m_pia_rtc->writepa_handler().set([this](uint8_t data) { m_mc146818_data = data; });
m_pia_rtc->writepb_handler().set(FUNC(bbc_cumana68k_device::pia_rtc_pb_w));
@@ -197,13 +198,13 @@ void bbc_cumana68k_device::device_reset_after_children()
// IMPLEMENTATION
//**************************************************************************
-WRITE_LINE_MEMBER(bbc_cumana68k_device::reset68008_w)
+void bbc_cumana68k_device::reset68008_w(int state)
{
m_m68008->set_input_line(INPUT_LINE_HALT, state);
m_m68008->set_input_line(INPUT_LINE_RESET, state);
}
-WRITE_LINE_MEMBER(bbc_cumana68k_device::irq6502_w)
+void bbc_cumana68k_device::irq6502_w(int state)
{
m_m68008->set_input_line(M68K_IRQ_2, state);
}
@@ -255,7 +256,7 @@ void bbc_cumana68k_device::mem6502_w(offs_t offset, uint8_t data)
}
-WRITE_LINE_MEMBER(bbc_cumana68k_device::rtc_ce_w)
+void bbc_cumana68k_device::rtc_ce_w(int state)
{
m_mc146818_ce = !state;
}
@@ -268,7 +269,7 @@ void bbc_cumana68k_device::mc146818_set(int as, int ds, int rw)
/* if address select is set then set the address in the 146818 */
if (m_mc146818_as & !as)
{
- m_rtc->write(0, m_mc146818_data);
+ m_rtc->address_w(m_mc146818_data);
//logerror("addr_w: %02x\n", m_mc146818_data);
}
@@ -277,12 +278,12 @@ void bbc_cumana68k_device::mc146818_set(int as, int ds, int rw)
{
if (m_mc146818_rw)
{
- m_mc146818_data = m_rtc->read(1);
+ m_mc146818_data = m_rtc->data_r();
//logerror("data_r: %02x\n", m_mc146818_data);
}
else
{
- m_rtc->write(1, m_mc146818_data);
+ m_rtc->data_w(m_mc146818_data);
//logerror("data_w: %02x\n", m_mc146818_data);
}
}
diff --git a/src/devices/bus/bbc/internal/cumana68k.h b/src/devices/bus/bbc/internal/cumana68k.h
index 11122f165e1..04e76ab20cc 100644
--- a/src/devices/bus/bbc/internal/cumana68k.h
+++ b/src/devices/bus/bbc/internal/cumana68k.h
@@ -8,19 +8,17 @@
**********************************************************************/
-
#ifndef MAME_BUS_BBC_INTERNAL_CUMANA68K_H
#define MAME_BUS_BBC_INTERNAL_CUMANA68K_H
#include "internal.h"
-#include "cpu/m68000/m68000.h"
+#include "cpu/m68000/m68008.h"
#include "machine/6821pia.h"
#include "machine/input_merger.h"
#include "machine/mc146818.h"
#include "machine/nscsi_cb.h"
#include "imagedev/floppy.h"
#include "machine/wd_fdc.h"
-#include "formats/os9_dsk.h"
//**************************************************************************
// TYPE DEFINITIONS
@@ -51,11 +49,11 @@ protected:
virtual void device_add_mconfig(machine_config &config) override;
virtual const tiny_rom_entry *device_rom_region() const override;
- DECLARE_WRITE_LINE_MEMBER(irq6502_w) override;
+ void irq6502_w(int state) override;
private:
- DECLARE_WRITE_LINE_MEMBER(reset68008_w);
- DECLARE_WRITE_LINE_MEMBER(rtc_ce_w);
+ void reset68008_w(int state);
+ void rtc_ce_w(int state);
required_device<m68000_base_device> m_m68008;
required_device<pia6821_device> m_pia_sasi;
diff --git a/src/devices/bus/bbc/internal/integrab.cpp b/src/devices/bus/bbc/internal/integrab.cpp
index 6d69b9c34c0..1cb750b7022 100644
--- a/src/devices/bus/bbc/internal/integrab.cpp
+++ b/src/devices/bus/bbc/internal/integrab.cpp
@@ -157,11 +157,8 @@ uint8_t bbc_integrab_device::romsel_r(offs_t offset)
switch (offset & 0x0c)
{
- case 0x08:
- data = m_rtc->read(0);
- break;
case 0x0c:
- data = m_rtc->read(1);
+ data = m_rtc->data_r();
break;
}
@@ -194,10 +191,10 @@ void bbc_integrab_device::romsel_w(offs_t offset, uint8_t data)
m_ramsel = data;
break;
case 0x08:
- m_rtc->write(0, data);
+ m_rtc->address_w(data);
break;
case 0x0c:
- m_rtc->write(1, data);
+ m_rtc->data_w(data);
break;
}
diff --git a/src/devices/bus/bbc/internal/internal.cpp b/src/devices/bus/bbc/internal/internal.cpp
index a365b5729dc..4adad689824 100644
--- a/src/devices/bus/bbc/internal/internal.cpp
+++ b/src/devices/bus/bbc/internal/internal.cpp
@@ -69,10 +69,6 @@ bbc_internal_slot_device::bbc_internal_slot_device(const machine_config &mconfig
void bbc_internal_slot_device::device_start()
{
m_card = get_card_device();
-
- // resolve callbacks
- m_irq_handler.resolve_safe();
- m_nmi_handler.resolve_safe();
}
@@ -146,7 +142,7 @@ void bbc_internal_slot_device::latch_fe60_w(uint8_t data)
m_card->latch_fe60_w(data);
}
-WRITE_LINE_MEMBER(bbc_internal_slot_device::irq6502_w)
+void bbc_internal_slot_device::irq6502_w(int state)
{
if (m_card)
m_card->irq6502_w(state);
diff --git a/src/devices/bus/bbc/internal/internal.h b/src/devices/bus/bbc/internal/internal.h
index 3042dd30a0b..7b3210a556e 100644
--- a/src/devices/bus/bbc/internal/internal.h
+++ b/src/devices/bus/bbc/internal/internal.h
@@ -39,7 +39,7 @@ public:
virtual void mos_w(offs_t offset, uint8_t data) { }
virtual void latch_fe60_w(uint8_t data) { }
- virtual DECLARE_WRITE_LINE_MEMBER(irq6502_w) { }
+ virtual void irq6502_w(int state) { }
protected:
device_bbc_internal_interface(const machine_config &mconfig, device_t &device);
@@ -75,8 +75,8 @@ public:
auto irq_handler() { return m_irq_handler.bind(); }
auto nmi_handler() { return m_nmi_handler.bind(); }
- DECLARE_WRITE_LINE_MEMBER(irq_w) { m_irq_handler(state); }
- DECLARE_WRITE_LINE_MEMBER(nmi_w) { m_nmi_handler(state); }
+ void irq_w(int state) { m_irq_handler(state); }
+ void nmi_w(int state) { m_nmi_handler(state); }
virtual bool overrides_ram() { return m_card ? m_card->overrides_ram() : false; }
virtual bool overrides_rom() { return m_card ? m_card->overrides_rom() : false; }
@@ -91,7 +91,7 @@ public:
virtual void mos_w(offs_t offset, uint8_t data);
virtual void latch_fe60_w(uint8_t data);
- virtual DECLARE_WRITE_LINE_MEMBER(irq6502_w);
+ virtual void irq6502_w(int state);
protected:
// device-level overrides
diff --git a/src/devices/bus/bbc/joyport/joyport.cpp b/src/devices/bus/bbc/joyport/joyport.cpp
index 59173030724..44387a80deb 100644
--- a/src/devices/bus/bbc/joyport/joyport.cpp
+++ b/src/devices/bus/bbc/joyport/joyport.cpp
@@ -57,10 +57,6 @@ bbc_joyport_slot_device::bbc_joyport_slot_device(const machine_config &mconfig,
void bbc_joyport_slot_device::device_start()
{
m_device = get_card_device();
-
- // resolve callbacks
- m_cb1_handler.resolve_safe();
- m_cb2_handler.resolve_safe();
}
diff --git a/src/devices/bus/bbc/joyport/joyport.h b/src/devices/bus/bbc/joyport/joyport.h
index 15d81243d84..1463d38eab9 100644
--- a/src/devices/bus/bbc/joyport/joyport.h
+++ b/src/devices/bus/bbc/joyport/joyport.h
@@ -62,8 +62,8 @@ public:
auto cb2_handler() { return m_cb2_handler.bind(); }
// from slot
- DECLARE_WRITE_LINE_MEMBER(cb1_w) { m_cb1_handler(state); }
- DECLARE_WRITE_LINE_MEMBER(cb2_w) { m_cb2_handler(state); }
+ void cb1_w(int state) { m_cb1_handler(state); }
+ void cb2_w(int state) { m_cb2_handler(state); }
// from host
uint8_t pb_r();
diff --git a/src/devices/bus/bbc/modem/modem.cpp b/src/devices/bus/bbc/modem/modem.cpp
index e3b4d164fac..6dfcf4e47f1 100644
--- a/src/devices/bus/bbc/modem/modem.cpp
+++ b/src/devices/bus/bbc/modem/modem.cpp
@@ -57,9 +57,6 @@ bbc_modem_slot_device::bbc_modem_slot_device(const machine_config &mconfig, cons
void bbc_modem_slot_device::device_start()
{
m_card = get_card_device();
-
- // resolve callbacks
- m_irq_handler.resolve_safe();
}
diff --git a/src/devices/bus/bbc/modem/modem.h b/src/devices/bus/bbc/modem/modem.h
index 6c1e7840637..702981f4ddb 100644
--- a/src/devices/bus/bbc/modem/modem.h
+++ b/src/devices/bus/bbc/modem/modem.h
@@ -68,7 +68,7 @@ public:
virtual uint8_t read(offs_t offset);
virtual void write(offs_t offset, uint8_t data);
- DECLARE_WRITE_LINE_MEMBER( irq_w ) { m_irq_handler(state); }
+ void irq_w(int state) { m_irq_handler(state); }
protected:
// device-level overrides
diff --git a/src/devices/bus/bbc/modem/scsiaiv.cpp b/src/devices/bus/bbc/modem/scsiaiv.cpp
index 603b36c9a8a..deb75196810 100644
--- a/src/devices/bus/bbc/modem/scsiaiv.cpp
+++ b/src/devices/bus/bbc/modem/scsiaiv.cpp
@@ -24,7 +24,7 @@ DEFINE_DEVICE_TYPE(BBC_SCSIAIV, bbc_scsiaiv_device, "bbc_scsiaiv", "Acorn AIV SC
// device_add_mconfig - add device configuration
//-------------------------------------------------
-void bbc_scsiaiv_device::device_add_mconfig(machine_config& config)
+void bbc_scsiaiv_device::device_add_mconfig(machine_config &config)
{
NSCSI_BUS(config, "scsi");
NSCSI_CONNECTOR(config, "scsi:0", default_scsi_devices, nullptr);
@@ -36,7 +36,7 @@ void bbc_scsiaiv_device::device_add_mconfig(machine_config& config)
});
}
-//void bbc_vp415_device::device_add_mconfig(machine_config& config)
+//void bbc_vp415_device::device_add_mconfig(machine_config &config)
//{
// bbc_scsiaiv_device::device_add_mconfig(config);
//
@@ -54,19 +54,19 @@ void bbc_scsiaiv_device::device_add_mconfig(machine_config& config)
// bbc_scsiaiv_device - constructor
//-------------------------------------------------
-bbc_scsiaiv_device::bbc_scsiaiv_device(const machine_config& mconfig, device_type type, const char* tag, device_t* owner, uint32_t clock)
+bbc_scsiaiv_device::bbc_scsiaiv_device(const machine_config &mconfig, device_type type, const char* tag, device_t* owner, uint32_t clock)
: device_t(mconfig, type, tag, owner, clock)
, device_bbc_modem_interface(mconfig, *this)
, m_scsi(*this, "scsi:7:scsicb")
{
}
-bbc_scsiaiv_device::bbc_scsiaiv_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock)
+bbc_scsiaiv_device::bbc_scsiaiv_device(const machine_config &mconfig, const char* tag, device_t* owner, uint32_t clock)
: bbc_scsiaiv_device(mconfig, BBC_SCSIAIV, tag, owner, clock)
{
}
-//bbc_vp415_device::bbc_vp415_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock)
+//bbc_vp415_device::bbc_vp415_device(const machine_config &mconfig, const char* tag, device_t* owner, uint32_t clock)
// : bbc_scsiaiv_device(mconfig, BBC_VP415, tag, owner, clock)
//{
//}
@@ -128,12 +128,12 @@ void bbc_scsiaiv_device::write(offs_t offset, uint8_t data)
}
}
-WRITE_LINE_MEMBER(bbc_scsiaiv_device::bsy_w)
+void bbc_scsiaiv_device::bsy_w(int state)
{
m_scsi->sel_w(0);
}
-WRITE_LINE_MEMBER(bbc_scsiaiv_device::req_w)
+void bbc_scsiaiv_device::req_w(int state)
{
m_scsi->ack_w(0);
diff --git a/src/devices/bus/bbc/modem/scsiaiv.h b/src/devices/bus/bbc/modem/scsiaiv.h
index 0b244bb71e3..5c194c655b4 100644
--- a/src/devices/bus/bbc/modem/scsiaiv.h
+++ b/src/devices/bus/bbc/modem/scsiaiv.h
@@ -7,8 +7,8 @@
**********************************************************************/
-#ifndef MAME_BUS_BBC_1MHZBUS_SCSIAIV_H
-#define MAME_BUS_BBC_1MHZBUS_SCSIAIV_H
+#ifndef MAME_BUS_BBC_MODEM_SCSIAIV_H
+#define MAME_BUS_BBC_MODEM_SCSIAIV_H
#include "modem.h"
#include "machine/nscsi_cb.h"
@@ -24,19 +24,19 @@ class bbc_scsiaiv_device:
{
public:
// construction/destruction
- bbc_scsiaiv_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock);
+ bbc_scsiaiv_device(const machine_config &mconfig, const char* tag, device_t* owner, uint32_t clock);
- DECLARE_WRITE_LINE_MEMBER(bsy_w);
- DECLARE_WRITE_LINE_MEMBER(req_w);
+ void bsy_w(int state);
+ void req_w(int state);
protected:
- bbc_scsiaiv_device(const machine_config& mconfig, device_type type, const char* tag, device_t* owner, uint32_t clock);
+ bbc_scsiaiv_device(const machine_config &mconfig, device_type type, const char* tag, device_t* owner, uint32_t clock);
// device-level overrides
virtual void device_start() override;
// optional information overrides
- virtual void device_add_mconfig(machine_config& config) override;
+ virtual void device_add_mconfig(machine_config &config) override;
virtual uint8_t read(offs_t offset) override;
virtual void write(offs_t offset, uint8_t data) override;
@@ -55,11 +55,11 @@ private:
//{
//public:
// // construction/destruction
-// bbc_vp415_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock);
+// bbc_vp415_device(const machine_config &mconfig, const char* tag, device_t* owner, uint32_t clock);
//
//protected:
// // optional information overrides
-// virtual void device_add_mconfig(machine_config& config) override;
+// virtual void device_add_mconfig(machine_config &config) override;
//};
@@ -68,4 +68,4 @@ DECLARE_DEVICE_TYPE(BBC_SCSIAIV, bbc_scsiaiv_device);
//DECLARE_DEVICE_TYPE(BBC_VP415, bbc_vp415_device);
-#endif /* MAME_BUS_BBC_1MHZBUS_SCSIAIV_H */
+#endif /* MAME_BUS_BBC_MODEM_SCSIAIV_H */
diff --git a/src/devices/bus/bbc/rom/pal.cpp b/src/devices/bus/bbc/rom/pal.cpp
index 51667f70955..c0cfb1ac7b5 100644
--- a/src/devices/bus/bbc/rom/pal.cpp
+++ b/src/devices/bus/bbc/rom/pal.cpp
@@ -34,6 +34,12 @@
Not a PALPROM carrier board but a larger ROM carrier containing 4x32K
and TTL circuits to enable and page each ROM into 16K banks.
+ Acornsoft Trilogy Emulator (PAL20R4)
+ An unreleased product that combines the View family of ROMs into a
+ single banked 64K ROM, using a PAL to perform 16K bank switches upon
+ reads from the last 4 bytes of ROM space &BFFC to &BFFF. Only known
+ example loaned by Stuart Swales.
+
***************************************************************************/
#include "emu.h"
@@ -53,6 +59,7 @@ DEFINE_DEVICE_TYPE(BBC_PALTED, bbc_palted_device, "bbc_palted", "Watford Electro
DEFINE_DEVICE_TYPE(BBC_PALABEP, bbc_palabep_device, "bbc_palabep", "P.R.E.S. 32K ROM Carrier (ABE+)")
DEFINE_DEVICE_TYPE(BBC_PALABE, bbc_palabe_device, "bbc_palabe", "P.R.E.S. 32K ROM Carrier (ABE)")
DEFINE_DEVICE_TYPE(BBC_PALMO2, bbc_palmo2_device, "bbc_palmo2", "Instant Mini Office 2 ROM Carrier")
+DEFINE_DEVICE_TYPE(BBC_TRILOGY, bbc_trilogy_device, "bbc_trilogy", "Acornsoft Trilogy Emulator")
//**************************************************************************
@@ -115,6 +122,11 @@ bbc_palmo2_device::bbc_palmo2_device(const machine_config &mconfig, const char *
{
}
+bbc_trilogy_device::bbc_trilogy_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : bbc_pal_device(mconfig, BBC_TRILOGY, tag, owner, clock)
+{
+}
+
//-------------------------------------------------
// device_start - device-specific startup
@@ -310,3 +322,17 @@ uint8_t bbc_palmo2_device::read(offs_t offset)
return get_rom_base()[(offset & 0x3fff) | (m_bank << 13)];
}
+
+uint8_t bbc_trilogy_device::read(offs_t offset)
+{
+ if (!machine().side_effects_disabled())
+ {
+ /* switching zones for Acornsoft Trilogy Emulator */
+ switch (offset & 0x3ff8)
+ {
+ case 0x3ff8: m_bank = offset & 0x03; break;
+ }
+ }
+
+ return get_rom_base()[(offset & 0x3fff) | (m_bank << 14)];
+}
diff --git a/src/devices/bus/bbc/rom/pal.h b/src/devices/bus/bbc/rom/pal.h
index 31c8dcd0d78..23ccd94741f 100644
--- a/src/devices/bus/bbc/rom/pal.h
+++ b/src/devices/bus/bbc/rom/pal.h
@@ -151,6 +151,19 @@ protected:
virtual uint8_t read(offs_t offset) override;
};
+// ======================> bbc_trilogy_device
+
+class bbc_trilogy_device : public bbc_pal_device
+{
+public:
+ // construction/destruction
+ bbc_trilogy_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device_bbc_rom_interface overrides
+ virtual uint8_t read(offs_t offset) override;
+};
+
// device type definition
DECLARE_DEVICE_TYPE(BBC_CCIWORD, bbc_cciword_device)
@@ -162,6 +175,7 @@ DECLARE_DEVICE_TYPE(BBC_PALTED, bbc_palted_device)
DECLARE_DEVICE_TYPE(BBC_PALABEP, bbc_palabep_device)
DECLARE_DEVICE_TYPE(BBC_PALABE, bbc_palabe_device)
DECLARE_DEVICE_TYPE(BBC_PALMO2, bbc_palmo2_device)
+DECLARE_DEVICE_TYPE(BBC_TRILOGY, bbc_trilogy_device)
#endif // MAME_BUS_BBC_ROM_PAL_H
diff --git a/src/devices/bus/bbc/rom/rtc.cpp b/src/devices/bus/bbc/rom/rtc.cpp
index 7d73c24b53e..436783f3641 100644
--- a/src/devices/bus/bbc/rom/rtc.cpp
+++ b/src/devices/bus/bbc/rom/rtc.cpp
@@ -82,22 +82,22 @@ uint8_t bbc_stlrtc_device::read(offs_t offset)
switch (offset & 0x3fc0)
{
case 0x3e00:
- data = m_rtc->read(1);
+ data = m_rtc->data_r();
break;
case 0x3e40:
if (!machine().side_effects_disabled())
- m_rtc->write(0, data);
+ m_rtc->address_w(data);
break;
case 0x3e80:
case 0x3ec0:
- data = m_rtc->read(0);
+ data = m_rtc->get_address(); // FIXME: really?
break;
case 0x3f00:
case 0x3f40:
case 0x3f80:
case 0x3fc0:
if (!machine().side_effects_disabled())
- m_rtc->write(1, data);
+ m_rtc->data_w(data);
break;
}
return data;
diff --git a/src/devices/bus/bbc/rom/slot.cpp b/src/devices/bus/bbc/rom/slot.cpp
index 4c19a767dfe..6ef0dddf180 100644
--- a/src/devices/bus/bbc/rom/slot.cpp
+++ b/src/devices/bus/bbc/rom/slot.cpp
@@ -50,7 +50,7 @@ void device_bbc_rom_interface::rom_alloc(uint32_t size, const char *tag)
{
if (m_rom == nullptr)
{
- m_rom = device().machine().memory().region_alloc(std::string(tag).append(BBC_ROM_REGION_TAG).c_str(), size, 1, ENDIANNESS_LITTLE)->base();
+ m_rom = device().machine().memory().region_alloc(std::string(tag).append(BBC_ROM_REGION_TAG), size, 1, ENDIANNESS_LITTLE)->base();
m_rom_size = size;
}
}
@@ -114,17 +114,14 @@ void bbc_romslot_device::device_start()
// call load
//-------------------------------------------------
-image_init_result bbc_romslot_device::call_load()
+std::pair<std::error_condition, std::string> bbc_romslot_device::call_load()
{
if (m_cart)
{
- uint32_t size = !loaded_through_softlist() ? length() : get_software_region_length("rom");
+ uint32_t const size = !loaded_through_softlist() ? length() : get_software_region_length("rom");
if (size % 0x2000)
- {
- seterror(image_error::INVALIDIMAGE, "Invalid ROM size");
- return image_init_result::FAIL;
- }
+ return std::make_pair(image_error::INVALIDLENGTH, "Invalid ROM size (must be a multiple of 8K)");
m_cart->rom_alloc(size, tag());
@@ -142,7 +139,7 @@ image_init_result bbc_romslot_device::call_load()
m_cart->nvram_alloc(get_software_region_length("nvram"));
}
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
//-------------------------------------------------
@@ -213,6 +210,7 @@ void bbc_romslot_device::write(offs_t offset, uint8_t data)
#include "datagem.h"
#include "dfs.h"
#include "genie.h"
+//#include "gommc.h"
#include "pal.h"
//#include "ramagic.h"
#include "rtc.h"
@@ -234,8 +232,10 @@ void bbc_rom_devices(device_slot_interface &device)
device.option_add_internal("palmo2", BBC_PALMO2);
device.option_add_internal("datagem", BBC_DATAGEM);
device.option_add_internal("genie", BBC_PMSGENIE);
+ //device.option_add_internal("gommc", BBC_GOMMC);
device.option_add_internal("dfse00", BBC_DFSE00);
//device.option_add_internal("ramagic", BBC_RAMAGIC);
device.option_add_internal("stlrtc", BBC_STLRTC);
device.option_add_internal("pmsrtc", BBC_PMSRTC);
+ device.option_add_internal("trilogy", BBC_TRILOGY);
}
diff --git a/src/devices/bus/bbc/rom/slot.h b/src/devices/bus/bbc/rom/slot.h
index 986d796dd0d..c88cabd3c1a 100644
--- a/src/devices/bus/bbc/rom/slot.h
+++ b/src/devices/bus/bbc/rom/slot.h
@@ -29,15 +29,15 @@ class bbc_romslot_device : public device_t,
public device_single_card_slot_interface<device_bbc_rom_interface>
{
public:
- // image-level overrides
- virtual image_init_result call_load() override;
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
virtual void call_unload() override;
virtual bool is_reset_on_load() const noexcept override { return false; }
virtual const char *image_interface() const noexcept override { return "bbc_rom"; }
virtual const char *file_extensions() const noexcept override { return "rom,bin"; }
- // slot interface overrides
+ // device_slot_interface implementation
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
// reading and writing
@@ -55,7 +55,7 @@ protected:
// construction/destruction
bbc_romslot_device(const machine_config &mconfig, device_type type, char const *tag, device_t *owner, uint32_t clock);
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
uint32_t m_slot_size;
diff --git a/src/devices/bus/bbc/tube/tube.cpp b/src/devices/bus/bbc/tube/tube.cpp
index 505b7a25030..f72b1072731 100644
--- a/src/devices/bus/bbc/tube/tube.cpp
+++ b/src/devices/bus/bbc/tube/tube.cpp
@@ -29,8 +29,8 @@ DEFINE_DEVICE_TYPE(BBC_TUBE_SLOT, bbc_tube_slot_device, "bbc_tube_slot", "BBC Mi
device_bbc_tube_interface::device_bbc_tube_interface(const machine_config &mconfig, device_t &device)
: device_interface(device, "bbctube")
+ , m_slot(dynamic_cast<bbc_tube_slot_device*>(device.owner()))
{
- m_slot = dynamic_cast<bbc_tube_slot_device *>(device.owner());
}
@@ -59,9 +59,6 @@ bbc_tube_slot_device::bbc_tube_slot_device(const machine_config &mconfig, const
void bbc_tube_slot_device::device_start()
{
m_card = get_card_device();
-
- // resolve callbacks
- m_irq_handler.resolve_safe();
}
@@ -122,6 +119,7 @@ void bbc_tube_devices(device_slot_interface &device)
device.option_add("arm", BBC_TUBE_ARM); /* Acorn ANC13 ARM Evaluation System */
device.option_add("80286", BBC_TUBE_80286); /* Acorn 80286 2nd Processor */
device.option_add("a500", BBC_TUBE_A500); /* Acorn A500 2nd Processor */
+ device.option_add("a500d", BBC_TUBE_A500D); /* Acorn A500 (Dual MEMC) 2nd Processor */
device.option_add("casper", BBC_TUBE_CASPER); /* Casper 68000 2nd Processor */
//device.option_add("cms6502", BBC_TUBE_CMS6502); /* CMS 6502 2nd processor */
device.option_add("cms6809", BBC_TUBE_CMS6809); /* CMS 6809 2nd processor */
@@ -157,6 +155,7 @@ void bbc_extube_devices(device_slot_interface &device)
device.option_add("80286", BBC_TUBE_80286); /* Acorn 80286 2nd Processor */
device.option_add("pcplus", BBC_TUBE_PCPLUS); /* Solidisk PC-Plus co-processor */
device.option_add("a500", BBC_TUBE_A500); /* Acorn A500 2nd Processor */
+ device.option_add("a500d", BBC_TUBE_A500D); /* Acorn A500 (Dual MEMC) 2nd Processor */
//device.option_add("pmsb2p", BBC_TUBE_PMSB2P); /* PMS B2P-6502 */
device.option_add("zep100m", BBC_TUBE_ZEP100M); /* Torch Z80 Communicator (ZEP100) (Master) */
@@ -197,6 +196,8 @@ void electron_tube_devices(device_slot_interface &device)
device.option_add("arm", BBC_TUBE_ARM); /* Acorn ANC13 ARM Evaluation System */
device.option_add("65c102", BBC_TUBE_65C102); /* Acorn ADC06 65C102 co-processor */
device.option_add("80186", BBC_TUBE_80186); /* Acorn ADC08 80186 co-processor */
+ device.option_add("a500", BBC_TUBE_A500); /* Acorn A500 2nd Processor */
+ device.option_add("a500d", BBC_TUBE_A500D); /* Acorn A500 (Dual MEMC) 2nd Processor */
device.option_add("pcplus", BBC_TUBE_PCPLUS); /* Solidisk PC-Plus co-processor */
device.option_add("arm7", BBC_TUBE_ARM7); /* Sprow ARM7 co-processor */
device.option_add("rc6502", BBC_TUBE_RC6502); /* ReCo6502 (6502) */
diff --git a/src/devices/bus/bbc/tube/tube.h b/src/devices/bus/bbc/tube/tube.h
index 97c18ab0d34..4a81e3aaa3a 100644
--- a/src/devices/bus/bbc/tube/tube.h
+++ b/src/devices/bus/bbc/tube/tube.h
@@ -73,7 +73,7 @@ public:
uint8_t host_r(offs_t offset);
void host_w(offs_t offset, uint8_t data);
- DECLARE_WRITE_LINE_MEMBER( irq_w ) { m_irq_handler(state); }
+ void irq_w(int state) { m_irq_handler(state); }
protected:
// device-level overrides
@@ -100,7 +100,7 @@ public:
protected:
device_bbc_tube_interface(const machine_config &mconfig, device_t &device);
- bbc_tube_slot_device *m_slot;
+ bbc_tube_slot_device *const m_slot;
};
diff --git a/src/devices/bus/bbc/tube/tube_32016.cpp b/src/devices/bus/bbc/tube/tube_32016.cpp
index e62e3003998..01019302aec 100644
--- a/src/devices/bus/bbc/tube/tube_32016.cpp
+++ b/src/devices/bus/bbc/tube/tube_32016.cpp
@@ -268,7 +268,7 @@ void bbc_tube_32016_device::device_reset()
// IMPLEMENTATION
//**************************************************************************
-WRITE_LINE_MEMBER(bbc_tube_32016_device::prst_w)
+void bbc_tube_32016_device::prst_w(int state)
{
device_reset();
diff --git a/src/devices/bus/bbc/tube/tube_32016.h b/src/devices/bus/bbc/tube/tube_32016.h
index 242b4eb773b..3feea1970de 100644
--- a/src/devices/bus/bbc/tube/tube_32016.h
+++ b/src/devices/bus/bbc/tube/tube_32016.h
@@ -61,7 +61,7 @@ protected:
void tube_32016_mem(address_map &map);
- DECLARE_WRITE_LINE_MEMBER(prst_w);
+ void prst_w(int state);
};
diff --git a/src/devices/bus/bbc/tube/tube_6502.cpp b/src/devices/bus/bbc/tube/tube_6502.cpp
index e7cc3157c90..8cb22337e40 100644
--- a/src/devices/bus/bbc/tube/tube_6502.cpp
+++ b/src/devices/bus/bbc/tube/tube_6502.cpp
@@ -95,13 +95,14 @@ ROM_END
ROM_START( tube_6502p )
ROM_REGION(0x1000, "rom", 0)
- ROM_DEFAULT_BIOS("005")
- ROM_SYSTEM_BIOS(0, "005", "Tube 0.05") // Iss.F
- ROMX_LOAD("6502tube_005.rom", 0x0000, 0x1000, CRC(0d4cd088) SHA1(f68a74f2529e2719193f81032af298e606792ce8), ROM_BIOS(0))
- ROM_SYSTEM_BIOS(1, "004", "Tube 0.04")
- ROMX_LOAD("6502tube_004.rom", 0x0000, 0x1000, CRC(64698ffa) SHA1(b7d47ac65291a7d7bd03b6b82ee08cff291c8609), ROM_BIOS(1))
- ROM_SYSTEM_BIOS(2, "001", "Tube 0.01") // Iss.C
- ROMX_LOAD("6502tube_001.rom", 0x0000, 0x1000, CRC(83bee05d) SHA1(4a00d4d3deec0ab43dc6647ac591bd71f4b24a51), ROM_BIOS(2))
+ ROM_SYSTEM_BIOS(0, "006", "Tube 0.06") // Iss.A
+ ROMX_LOAD("6502tube_006.rom", 0x0000, 0x1000, CRC(1f8d2f60) SHA1(dee529f502d24174186269ba7728c023133b92de), ROM_BIOS(0))
+ ROM_SYSTEM_BIOS(1, "005", "Tube 0.05") // Iss.F
+ ROMX_LOAD("6502tube_005.rom", 0x0000, 0x1000, CRC(0d4cd088) SHA1(f68a74f2529e2719193f81032af298e606792ce8), ROM_BIOS(2))
+ ROM_SYSTEM_BIOS(2, "004", "Tube 0.04")
+ ROMX_LOAD("6502tube_004.rom", 0x0000, 0x1000, CRC(64698ffa) SHA1(b7d47ac65291a7d7bd03b6b82ee08cff291c8609), ROM_BIOS(3))
+ ROM_SYSTEM_BIOS(3, "001", "Tube 0.01") // Iss.C
+ ROMX_LOAD("6502tube_001.rom", 0x0000, 0x1000, CRC(83bee05d) SHA1(4a00d4d3deec0ab43dc6647ac591bd71f4b24a51), ROM_BIOS(3))
ROM_END
ROM_START( tube_6502e )
@@ -263,7 +264,7 @@ void bbc_tube_6502_device::device_reset()
// IMPLEMENTATION
//**************************************************************************
-WRITE_LINE_MEMBER(bbc_tube_6502_device::prst_w)
+void bbc_tube_6502_device::prst_w(int state)
{
device_reset();
diff --git a/src/devices/bus/bbc/tube/tube_6502.h b/src/devices/bus/bbc/tube/tube_6502.h
index a68e9c3f51e..f2b12a5c3f0 100644
--- a/src/devices/bus/bbc/tube/tube_6502.h
+++ b/src/devices/bus/bbc/tube/tube_6502.h
@@ -60,7 +60,7 @@ protected:
required_device<ram_device> m_ram;
required_memory_region m_rom;
- DECLARE_WRITE_LINE_MEMBER(prst_w);
+ void prst_w(int state);
};
diff --git a/src/devices/bus/bbc/tube/tube_80186.cpp b/src/devices/bus/bbc/tube/tube_80186.cpp
index 07456c67a38..245cd3ff0e1 100644
--- a/src/devices/bus/bbc/tube/tube_80186.cpp
+++ b/src/devices/bus/bbc/tube/tube_80186.cpp
@@ -169,7 +169,7 @@ void bbc_tube_pcplus_device::device_reset()
// IMPLEMENTATION
//**************************************************************************
-WRITE_LINE_MEMBER(bbc_tube_80186_device::prst_w)
+void bbc_tube_80186_device::prst_w(int state)
{
device_reset();
diff --git a/src/devices/bus/bbc/tube/tube_80186.h b/src/devices/bus/bbc/tube/tube_80186.h
index 448ef06cc7f..a9c2f446fd8 100644
--- a/src/devices/bus/bbc/tube/tube_80186.h
+++ b/src/devices/bus/bbc/tube/tube_80186.h
@@ -53,7 +53,7 @@ protected:
void tube_80186_io(address_map &map);
void tube_80186_mem(address_map &map);
- DECLARE_WRITE_LINE_MEMBER(prst_w);
+ void prst_w(int state);
};
diff --git a/src/devices/bus/bbc/tube/tube_80286.cpp b/src/devices/bus/bbc/tube/tube_80286.cpp
index ffdfc0edb6f..34917acf629 100644
--- a/src/devices/bus/bbc/tube/tube_80286.cpp
+++ b/src/devices/bus/bbc/tube/tube_80286.cpp
@@ -129,7 +129,7 @@ void bbc_tube_80286_device::device_reset()
// IMPLEMENTATION
//**************************************************************************
-WRITE_LINE_MEMBER(bbc_tube_80286_device::prst_w)
+void bbc_tube_80286_device::prst_w(int state)
{
device_reset();
diff --git a/src/devices/bus/bbc/tube/tube_80286.h b/src/devices/bus/bbc/tube/tube_80286.h
index 6ac75975fa7..0cadfb708e1 100644
--- a/src/devices/bus/bbc/tube/tube_80286.h
+++ b/src/devices/bus/bbc/tube/tube_80286.h
@@ -55,7 +55,7 @@ private:
void tube_80286_io(address_map &map);
void tube_80286_mem(address_map &map);
- DECLARE_WRITE_LINE_MEMBER(prst_w);
+ void prst_w(int state);
};
diff --git a/src/devices/bus/bbc/tube/tube_a500.cpp b/src/devices/bus/bbc/tube/tube_a500.cpp
index f9406f2d2f0..a0ff2f1abbc 100644
--- a/src/devices/bus/bbc/tube/tube_a500.cpp
+++ b/src/devices/bus/bbc/tube/tube_a500.cpp
@@ -6,19 +6,78 @@
http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Acorn_A5002ndProc.html
-**********************************************************************/
+ Notes:
+ The dual MEMC ROMs are claimed to be from an Acorn M4 board, it's original
+ purpose as a co-processor is unknown.
+**********************************************************************/
#include "emu.h"
#include "tube_a500.h"
+
+#include "cpu/arm/arm.h"
+#include "machine/acorn_ioc.h"
+#include "machine/acorn_memc.h"
+#include "machine/acorn_vidc.h"
+#include "machine/archimedes_keyb.h"
+#include "machine/input_merger.h"
+#include "machine/tube.h"
+
+#include "screen.h"
#include "softlist_dev.h"
-//**************************************************************************
-// DEVICE DEFINITIONS
-//**************************************************************************
+namespace {
+
+class bbc_tube_a500_device : public device_t, public device_bbc_tube_interface
+{
+public:
+ bbc_tube_a500_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ bbc_tube_a500_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
-DEFINE_DEVICE_TYPE(BBC_TUBE_A500, bbc_tube_a500_device, "bbc_tube_a500", "Acorn A500 2nd Processor")
+ // device_t overrides
+ virtual void device_start() override { }
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+ virtual uint8_t host_r(offs_t offset) override { return m_ula->host_r(offset); }
+ virtual void host_w(offs_t offset, uint8_t data) override { m_ula->host_w(offset, data); }
+
+ required_device<arm_cpu_device> m_maincpu;
+ required_device<acorn_ioc_device> m_ioc;
+ required_device<acorn_memc_device> m_memc;
+ required_device<acorn_vidc10_device> m_vidc;
+ required_device<tube_device> m_ula;
+ required_device<input_merger_device> m_irqs;
+ required_device<input_merger_device> m_fiqs;
+
+private:
+ void arm_mem(address_map &map);
+ void a500_map(address_map &map);
+
+ void prst_w(int state) { m_maincpu->set_input_line(INPUT_LINE_RESET, state); }
+};
+
+
+// ======================> bbc_tube_a500d_device
+
+class bbc_tube_a500d_device : public bbc_tube_a500_device
+{
+public:
+ bbc_tube_a500d_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+private:
+ void a500d_map(address_map &map);
+};
//-------------------------------------------------
@@ -36,24 +95,54 @@ void bbc_tube_a500_device::a500_map(address_map &map)
map(0x00000000, 0x01ffffff).rw(m_memc, FUNC(acorn_memc_device::logical_r), FUNC(acorn_memc_device::logical_w));
map(0x02000000, 0x023fffff).ram().mirror(0xc00000);
map(0x03000000, 0x033fffff).m(m_ioc, FUNC(acorn_ioc_device::map));
+ map(0x03000000, 0x03001fff).rw(m_ula, FUNC(tube_device::parasite_r), FUNC(tube_device::parasite_w)).umask32(0x000000ff);
map(0x03400000, 0x035fffff).w(m_vidc, FUNC(acorn_vidc10_device::write));
map(0x03600000, 0x037fffff).w(m_memc, FUNC(acorn_memc_device::registers_w));
map(0x03800000, 0x039fffff).rom().mirror(0x600000).region("maincpu", 0).w(m_memc, FUNC(acorn_memc_device::page_w));
}
+void bbc_tube_a500d_device::a500d_map(address_map &map)
+{
+ map(0x00000000, 0x01ffffff).rw(m_memc, FUNC(acorn_memc_device::logical_r), FUNC(acorn_memc_device::logical_w));
+ map(0x02000000, 0x027fffff).ram().mirror(0x800000);
+ map(0x03000000, 0x033fffff).m(m_ioc, FUNC(acorn_ioc_device::map));
+ map(0x03400000, 0x035fffff).w(m_vidc, FUNC(acorn_vidc10_device::write));
+ map(0x03600000, 0x037fffff).w(m_memc, FUNC(acorn_memc_device::registers_w));
+ map(0x03800000, 0x039fffff).rom().mirror(0x600000).region("maincpu", 0).w(m_memc, FUNC(acorn_memc_device::page_w));
+}
+
+
//-------------------------------------------------
-// ROM( tube_a500 )
+// rom_region - device-specific ROM region
//-------------------------------------------------
ROM_START(tube_a500)
ROM_REGION(0x200000, "maincpu", 0)
- // TODO: verify ROMs, they are claimed to be from an Acorn M4 but contents suggest A500 2nd processor
+ ROM_LOAD32_BYTE("0.bin", 0x000000, 0x04000, CRC(7ecfeb0e) SHA1(f9cd49f86e4b210cde6b14752cdbc2962e86551f))
+ ROM_LOAD32_BYTE("1.bin", 0x000001, 0x04000, CRC(f3bf6c3b) SHA1(e66496a1bf7a7f7bf300e8baebc40a4b37c19c1e))
+ ROM_LOAD32_BYTE("2.bin", 0x000002, 0x04000, CRC(6b73d4af) SHA1(7ebc8c7268cda6c8bd4dcbf3b63a7ffff4d2c43c))
+ ROM_LOAD32_BYTE("3.bin", 0x000003, 0x04000, CRC(607f2f49) SHA1(c46448435b86d1397c7cb144bece87e73a9220aa))
+ROM_END
+
+ROM_START(tube_a500d)
+ ROM_REGION(0x200000, "maincpu", 0)
ROM_LOAD32_BYTE("m4_brazil_8mbaddr_rom0.bin", 0x000000, 0x04000, CRC(f01fb7a6) SHA1(840a15882797572db4764f37b725cf9c5a07a8cb))
ROM_LOAD32_BYTE("m4_brazil_8mbaddr_rom1.bin", 0x000001, 0x04000, CRC(924e4181) SHA1(4f1903ef83cb6e0cef130005b0442a6548915b8a))
ROM_LOAD32_BYTE("m4_brazil_8mbaddr_rom2.bin", 0x000002, 0x04000, CRC(c210e9a5) SHA1(ee09b8bac275153467ec31f7a16c366a0f97b550))
ROM_LOAD32_BYTE("m4_brazil_8mbaddr_rom3.bin", 0x000003, 0x04000, CRC(1e520555) SHA1(9b6bdeef8d7fb22ef0203c2f531a4e0a55e22c6f))
ROM_END
+const tiny_rom_entry *bbc_tube_a500_device::device_rom_region() const
+{
+ return ROM_NAME( tube_a500 );
+}
+
+const tiny_rom_entry *bbc_tube_a500d_device::device_rom_region() const
+{
+ return ROM_NAME( tube_a500d );
+}
+
+
//-------------------------------------------------
// device_add_mconfig - add device configuration
//-------------------------------------------------
@@ -79,10 +168,8 @@ void bbc_tube_a500_device::device_add_mconfig(machine_config &config)
m_ioc->fiq_w().set(m_fiqs, FUNC(input_merger_device::in_w<1>));
m_ioc->irq_w().set(m_irqs, FUNC(input_merger_device::in_w<1>));
m_ioc->kout_w().set("keyboard", FUNC(archimedes_keyboard_device::kin_w));
- m_ioc->peripheral_r<4>().set(m_ula, FUNC(tube_device::parasite_r));
- m_ioc->peripheral_w<4>().set(m_ula, FUNC(tube_device::parasite_w));
- m_ioc->peripheral_r<6>().set_log("IOC: External Expansion R");
- m_ioc->peripheral_w<6>().set_log("IOC: External Expansion W");
+ m_ioc->peripheral_r<6>().set([this]() { logerror("%s IOC: External Expansion R\n", machine().describe_context()); return 0xffffffff; });
+ m_ioc->peripheral_w<6>().set([this](uint32_t data) { logerror("%s IOC: External Expansion W %08X\n", machine().describe_context(), data); });
ARCHIMEDES_KEYBOARD(config, "keyboard").kout().set(m_ioc, FUNC(acorn_ioc_device::kin_w));
@@ -94,18 +181,20 @@ void bbc_tube_a500_device::device_add_mconfig(machine_config &config)
m_vidc->vblank().set(m_memc, FUNC(acorn_memc_device::vidrq_w));
m_vidc->sound_drq().set(m_memc, FUNC(acorn_memc_device::sndrq_w));
- //SOFTWARE_LIST(config, "flop_ls_arm").set_original("BBC_flop_arm").set_filter("A500");
+ //SOFTWARE_LIST(config, "flop_ls_arm").set_original("bbc_flop_arm").set_filter("A500");
}
-//-------------------------------------------------
-// rom_region - device-specific ROM region
-//-------------------------------------------------
-
-const tiny_rom_entry *bbc_tube_a500_device::device_rom_region() const
+void bbc_tube_a500d_device::device_add_mconfig(machine_config &config)
{
- return ROM_NAME( tube_a500 );
+ bbc_tube_a500_device::device_add_mconfig(config);
+
+ m_memc->set_addrmap(0, &bbc_tube_a500d_device::a500d_map);
+
+ m_ioc->peripheral_r<4>().set(m_ula, FUNC(tube_device::parasite_r));
+ m_ioc->peripheral_w<4>().set(m_ula, FUNC(tube_device::parasite_w));
}
+
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
@@ -114,8 +203,8 @@ const tiny_rom_entry *bbc_tube_a500_device::device_rom_region() const
// bbc_tube_a500_device - constructor
//-------------------------------------------------
-bbc_tube_a500_device::bbc_tube_a500_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, BBC_TUBE_A500, tag, owner, clock)
+bbc_tube_a500_device::bbc_tube_a500_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, type, tag, owner, clock)
, device_bbc_tube_interface(mconfig, *this)
, m_maincpu(*this, "maincpu")
, m_ioc(*this, "ioc")
@@ -127,30 +216,18 @@ bbc_tube_a500_device::bbc_tube_a500_device(const machine_config &mconfig, const
{
}
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-
-void bbc_tube_a500_device::device_start()
+bbc_tube_a500_device::bbc_tube_a500_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : bbc_tube_a500_device(mconfig, BBC_TUBE_A500, tag, owner, clock)
{
}
-
-//**************************************************************************
-// IMPLEMENTATION
-//**************************************************************************
-
-WRITE_LINE_MEMBER(bbc_tube_a500_device::prst_w)
+bbc_tube_a500d_device::bbc_tube_a500d_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : bbc_tube_a500_device(mconfig, BBC_TUBE_A500D, tag, owner, clock)
{
- m_maincpu->set_input_line(INPUT_LINE_RESET, state);
}
-uint8_t bbc_tube_a500_device::host_r(offs_t offset)
-{
- return m_ula->host_r(offset);
-}
+} // anonymous namespace
-void bbc_tube_a500_device::host_w(offs_t offset, uint8_t data)
-{
- m_ula->host_w(offset, data);
-}
+
+DEFINE_DEVICE_TYPE_PRIVATE(BBC_TUBE_A500, device_bbc_tube_interface, bbc_tube_a500_device, "bbc_tube_a500", "Acorn A500 2nd Processor")
+DEFINE_DEVICE_TYPE_PRIVATE(BBC_TUBE_A500D, device_bbc_tube_interface, bbc_tube_a500d_device, "bbc_tube_a500d", "Acorn A500 (Dual MEMC) 2nd Processor")
diff --git a/src/devices/bus/bbc/tube/tube_a500.h b/src/devices/bus/bbc/tube/tube_a500.h
index 31af8f227f1..30a7fa58911 100644
--- a/src/devices/bus/bbc/tube/tube_a500.h
+++ b/src/devices/bus/bbc/tube/tube_a500.h
@@ -1,72 +1,12 @@
// license:BSD-3-Clause
// copyright-holders:Nigel Barnes
-/**********************************************************************
-
- Acorn A500 2nd processor
-
- http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Acorn_A5002ndProc.html
-
-**********************************************************************/
-
-
#ifndef MAME_BUS_BBC_TUBE_A500_H
#define MAME_BUS_BBC_TUBE_A500_H
#include "tube.h"
-#include "cpu/arm/arm.h"
-#include "machine/tube.h"
-#include "machine/input_merger.h"
-#include "machine/acorn_ioc.h"
-#include "machine/acorn_memc.h"
-#include "machine/acorn_vidc.h"
-#include "machine/archimedes_keyb.h"
-#include "screen.h"
-
-
-
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-// ======================> bbc_tube_a500_device
-
-class bbc_tube_a500_device :
- public device_t,
- public device_bbc_tube_interface
-{
-public:
- // construction/destruction
- bbc_tube_a500_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- // device-level overrides
- virtual void device_start() override;
-
- // optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
-
- virtual uint8_t host_r(offs_t offset) override;
- virtual void host_w(offs_t offset, uint8_t data) override;
-
-private:
- required_device<arm_cpu_device> m_maincpu;
- required_device<acorn_ioc_device> m_ioc;
- required_device<acorn_memc_device> m_memc;
- required_device<acorn_vidc10_device> m_vidc;
- required_device<tube_device> m_ula;
- required_device<input_merger_device> m_irqs;
- required_device<input_merger_device> m_fiqs;
-
- void arm_mem(address_map &map);
- void a500_map(address_map &map);
-
- DECLARE_WRITE_LINE_MEMBER(prst_w);
-};
-
-// device type definition
-DECLARE_DEVICE_TYPE(BBC_TUBE_A500, bbc_tube_a500_device)
+DECLARE_DEVICE_TYPE(BBC_TUBE_A500, device_bbc_tube_interface)
+DECLARE_DEVICE_TYPE(BBC_TUBE_A500D, device_bbc_tube_interface)
-#endif /* MAME_BUS_BBC_TUBE_A500_H */
+#endif // MAME_BUS_BBC_TUBE_A500_H
diff --git a/src/devices/bus/bbc/tube/tube_arm.cpp b/src/devices/bus/bbc/tube/tube_arm.cpp
index c015871ffa5..f550a245e6e 100644
--- a/src/devices/bus/bbc/tube/tube_arm.cpp
+++ b/src/devices/bus/bbc/tube/tube_arm.cpp
@@ -134,7 +134,7 @@ void bbc_tube_arm_device::device_reset()
// IMPLEMENTATION
//**************************************************************************
-WRITE_LINE_MEMBER(bbc_tube_arm_device::prst_w)
+void bbc_tube_arm_device::prst_w(int state)
{
device_reset();
diff --git a/src/devices/bus/bbc/tube/tube_arm.h b/src/devices/bus/bbc/tube/tube_arm.h
index c84ddc97748..f2af17b0f54 100644
--- a/src/devices/bus/bbc/tube/tube_arm.h
+++ b/src/devices/bus/bbc/tube/tube_arm.h
@@ -51,7 +51,7 @@ private:
void tube_arm_mem(address_map &map);
- DECLARE_WRITE_LINE_MEMBER(prst_w);
+ void prst_w(int state);
};
diff --git a/src/devices/bus/bbc/tube/tube_arm7.cpp b/src/devices/bus/bbc/tube/tube_arm7.cpp
index e79b83ad997..f67c89e4c77 100644
--- a/src/devices/bus/bbc/tube/tube_arm7.cpp
+++ b/src/devices/bus/bbc/tube/tube_arm7.cpp
@@ -132,7 +132,7 @@ void bbc_tube_arm7_device::device_reset()
// IMPLEMENTATION
//**************************************************************************
-WRITE_LINE_MEMBER(bbc_tube_arm7_device::prst_w)
+void bbc_tube_arm7_device::prst_w(int state)
{
device_reset();
@@ -159,13 +159,13 @@ void bbc_tube_arm7_device::update_interrupts()
m_maincpu->set_input_line(ARM7_IRQ_LINE, irq ? ASSERT_LINE : CLEAR_LINE);
}
-WRITE_LINE_MEMBER(bbc_tube_arm7_device::efiq_w)
+void bbc_tube_arm7_device::efiq_w(int state)
{
m_efiq_state = state;
update_interrupts();
}
-WRITE_LINE_MEMBER(bbc_tube_arm7_device::exint3_w)
+void bbc_tube_arm7_device::exint3_w(int state)
{
m_exint3_state = state;
if (state)
diff --git a/src/devices/bus/bbc/tube/tube_arm7.h b/src/devices/bus/bbc/tube/tube_arm7.h
index e203c26388a..ff290127395 100644
--- a/src/devices/bus/bbc/tube/tube_arm7.h
+++ b/src/devices/bus/bbc/tube/tube_arm7.h
@@ -67,7 +67,7 @@ private:
void arm7_map(address_map& map);
- DECLARE_WRITE_LINE_MEMBER(prst_w);
+ void prst_w(int state);
uint32_t oki_reg_r(offs_t offset);
void oki_reg_w(offs_t offset, uint32_t data);
@@ -79,8 +79,8 @@ private:
void update_bank0();
void update_interrupts();
- DECLARE_WRITE_LINE_MEMBER(efiq_w);
- DECLARE_WRITE_LINE_MEMBER(exint3_w);
+ void efiq_w(int state);
+ void exint3_w(int state);
int m_efiq_state;
int m_exint3_state;
diff --git a/src/devices/bus/bbc/tube/tube_rc6502.cpp b/src/devices/bus/bbc/tube/tube_rc6502.cpp
index 7aeeee283a2..85f3fce1f11 100644
--- a/src/devices/bus/bbc/tube/tube_rc6502.cpp
+++ b/src/devices/bus/bbc/tube/tube_rc6502.cpp
@@ -234,7 +234,7 @@ void bbc_tube_rc6502_device::device_reset()
// IMPLEMENTATION
//**************************************************************************
-WRITE_LINE_MEMBER(bbc_tube_rc6502_device::prst_w)
+void bbc_tube_rc6502_device::prst_w(int state)
{
device_reset();
diff --git a/src/devices/bus/bbc/tube/tube_rc6502.h b/src/devices/bus/bbc/tube/tube_rc6502.h
index cc1e12d71c8..0d47f0862dd 100644
--- a/src/devices/bus/bbc/tube/tube_rc6502.h
+++ b/src/devices/bus/bbc/tube/tube_rc6502.h
@@ -63,7 +63,7 @@ protected:
required_device<ram_device> m_ram;
required_ioport m_config;
- DECLARE_WRITE_LINE_MEMBER(prst_w);
+ void prst_w(int state);
private:
void tube_rc6502_mem(address_map &map);
diff --git a/src/devices/bus/bbc/tube/tube_z80.cpp b/src/devices/bus/bbc/tube/tube_z80.cpp
index f273c2f37d4..a16ff13b4a5 100644
--- a/src/devices/bus/bbc/tube/tube_z80.cpp
+++ b/src/devices/bus/bbc/tube/tube_z80.cpp
@@ -155,7 +155,7 @@ void bbc_tube_z80_device::device_reset()
// IMPLEMENTATION
//**************************************************************************
-WRITE_LINE_MEMBER(bbc_tube_z80_device::prst_w)
+void bbc_tube_z80_device::prst_w(int state)
{
device_reset();
diff --git a/src/devices/bus/bbc/tube/tube_z80.h b/src/devices/bus/bbc/tube/tube_z80.h
index e878f61627d..508f3812cce 100644
--- a/src/devices/bus/bbc/tube/tube_z80.h
+++ b/src/devices/bus/bbc/tube/tube_z80.h
@@ -63,7 +63,7 @@ private:
void tube_z80_io(address_map &map);
void tube_z80_mem(address_map &map);
- DECLARE_WRITE_LINE_MEMBER(prst_w);
+ void prst_w(int state);
};
diff --git a/src/devices/bus/bbc/userport/beebspch.cpp b/src/devices/bus/bbc/userport/beebspch.cpp
index 728d8ae6658..f3cfa608203 100644
--- a/src/devices/bus/bbc/userport/beebspch.cpp
+++ b/src/devices/bus/bbc/userport/beebspch.cpp
@@ -100,12 +100,12 @@ void bbc_beebspch_device::pb_w(uint8_t data)
m_nsp->ald_w(data & 0x3f);
}
-WRITE_LINE_MEMBER(bbc_beebspch_device::cb1_w)
+void bbc_beebspch_device::cb1_w(int state)
{
m_slot->cb1_w(state);
}
-WRITE_LINE_MEMBER(bbc_beebspch_device::cb2_w)
+void bbc_beebspch_device::cb2_w(int state)
{
m_slot->cb2_w(state);
}
diff --git a/src/devices/bus/bbc/userport/beebspch.h b/src/devices/bus/bbc/userport/beebspch.h
index 79e6abf64ab..1f4eea20ef7 100644
--- a/src/devices/bus/bbc/userport/beebspch.h
+++ b/src/devices/bus/bbc/userport/beebspch.h
@@ -27,8 +27,8 @@ public:
// construction/destruction
bbc_beebspch_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_WRITE_LINE_MEMBER(cb1_w);
- DECLARE_WRITE_LINE_MEMBER(cb2_w);
+ void cb1_w(int state);
+ void cb2_w(int state);
protected:
// device-level overrides
diff --git a/src/devices/bus/bbc/userport/lcd.cpp b/src/devices/bus/bbc/userport/lcd.cpp
index f5f92270ca9..2821187b56c 100644
--- a/src/devices/bus/bbc/userport/lcd.cpp
+++ b/src/devices/bus/bbc/userport/lcd.cpp
@@ -37,7 +37,12 @@ void bbc_lcd_device::device_add_mconfig(machine_config &config)
PALETTE(config, "palette", FUNC(bbc_lcd_device::lcd_palette), 3);
- HD44780(config, m_lcdc);
+ HD44780(config, m_lcdc, 122'427); // This uses a standard Hitachi LM044L
+ // LCD module, which uses an HD44780A00 clocked using its internal
+ // oscillator, using a "204" (200KOhm) Rf resistor. At 5V this should
+ // oscillate at around 1 / (2 * PI * resistance * 6.5pF) Hz.
+ // This is quite slow compared to the recommended datasheet clock speed,
+ // but is verified from pictures of an original Hitachi LM044L Module.
m_lcdc->set_lcd_size(4, 20);
m_lcdc->set_pixel_update_cb(FUNC(bbc_lcd_device::lcd_pixel_update));
}
diff --git a/src/devices/bus/bbc/userport/lvlecho.cpp b/src/devices/bus/bbc/userport/lvlecho.cpp
new file mode 100644
index 00000000000..04f6ed2db71
--- /dev/null
+++ b/src/devices/bus/bbc/userport/lvlecho.cpp
@@ -0,0 +1,278 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ LVL Echo Keyboard
+
+ Notes:
+ - the Echo is a 3 octave keyboard with 37 keys, but the software seems to
+ support a 5 octave keyboard.
+ - keys 33, 34, 35 are polled additionally for an unknown reason, maybe an
+ octave offset switch?
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "lvlecho.h"
+
+
+namespace {
+
+class bbc_lvlecho_device : public device_t, public device_bbc_userport_interface
+{
+public:
+ bbc_lvlecho_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BBC_LVLECHO, tag, owner, clock)
+ , device_bbc_userport_interface(mconfig, *this)
+ , m_kbd(*this, "KEY_%u", 0)
+ , m_key(0)
+ {
+ }
+
+protected:
+ // device_t overrides
+ virtual void device_start() override;
+
+ // optional information overrides
+ virtual ioport_constructor device_input_ports() const override;
+
+ virtual uint8_t pb_r() override
+ {
+ return m_kbd[m_key]->read();
+ }
+
+ virtual void pb_w(uint8_t data) override
+ {
+ m_key = data & 0x3f;
+ }
+
+private:
+ required_ioport_array<64> m_kbd;
+
+ uint8_t m_key;
+};
+
+
+//-------------------------------------------------
+// INPUT_PORTS( lvlecho )
+//-------------------------------------------------
+
+static INPUT_PORTS_START( lvlecho )
+ PORT_START("KEY_0")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("C2")
+
+ PORT_START("KEY_1")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("C2#")
+
+ PORT_START("KEY_2")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("D2")
+
+ PORT_START("KEY_3")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("D2#")
+
+ PORT_START("KEY_4")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("E2")
+
+ PORT_START("KEY_5")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("F2")
+
+ PORT_START("KEY_6")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("F2#")
+
+ PORT_START("KEY_7")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("G2")
+
+ PORT_START("KEY_8")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("G2#")
+
+ PORT_START("KEY_9")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("A2")
+
+ PORT_START("KEY_10")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("A2#")
+
+ PORT_START("KEY_11")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("B2")
+
+ PORT_START("KEY_12")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("C3") PORT_CODE(KEYCODE_TAB)
+
+ PORT_START("KEY_13")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("C3#") PORT_CODE(KEYCODE_1)
+
+ PORT_START("KEY_14")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("D3") PORT_CODE(KEYCODE_Q)
+
+ PORT_START("KEY_15")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("D3#") PORT_CODE(KEYCODE_2)
+
+ PORT_START("KEY_16")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("E3") PORT_CODE(KEYCODE_W)
+
+ PORT_START("KEY_17")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("F3") PORT_CODE(KEYCODE_E)
+
+ PORT_START("KEY_18")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("F3#") PORT_CODE(KEYCODE_4)
+
+ PORT_START("KEY_19")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("G3") PORT_CODE(KEYCODE_R)
+
+ PORT_START("KEY_20")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("G3#") PORT_CODE(KEYCODE_5)
+
+ PORT_START("KEY_21")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("A3") PORT_CODE(KEYCODE_T)
+
+ PORT_START("KEY_22")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("A3#") PORT_CODE(KEYCODE_6)
+
+ PORT_START("KEY_23")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("B3") PORT_CODE(KEYCODE_Y)
+
+ PORT_START("KEY_24")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("C4") PORT_CODE(KEYCODE_U)
+
+ PORT_START("KEY_25")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("C4#") PORT_CODE(KEYCODE_8)
+
+ PORT_START("KEY_26")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("D4") PORT_CODE(KEYCODE_I)
+
+ PORT_START("KEY_27")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("D4#") PORT_CODE(KEYCODE_9)
+
+ PORT_START("KEY_28")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("E4") PORT_CODE(KEYCODE_O)
+
+ PORT_START("KEY_29")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("F4") PORT_CODE(KEYCODE_P)
+
+ PORT_START("KEY_30")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("F4#") PORT_CODE(KEYCODE_A)
+
+ PORT_START("KEY_31")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("G4") PORT_CODE(KEYCODE_Z)
+
+ PORT_START("KEY_32")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("G4#") PORT_CODE(KEYCODE_S)
+
+ PORT_START("KEY_33")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("A4") PORT_CODE(KEYCODE_X)
+
+ PORT_START("KEY_34")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("A4#") PORT_CODE(KEYCODE_D)
+
+ PORT_START("KEY_35")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("B4") PORT_CODE(KEYCODE_C)
+
+ PORT_START("KEY_36")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("C5") PORT_CODE(KEYCODE_V)
+
+ PORT_START("KEY_37")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("C5#") PORT_CODE(KEYCODE_G)
+
+ PORT_START("KEY_38")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("D5") PORT_CODE(KEYCODE_B)
+
+ PORT_START("KEY_39")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("D5#") PORT_CODE(KEYCODE_H)
+
+ PORT_START("KEY_40")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("E5") PORT_CODE(KEYCODE_N)
+
+ PORT_START("KEY_41")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("F5") PORT_CODE(KEYCODE_M)
+
+ PORT_START("KEY_42")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("F5#") PORT_CODE(KEYCODE_K)
+
+ PORT_START("KEY_43")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("G5") PORT_CODE(KEYCODE_COMMA)
+
+ PORT_START("KEY_44")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("G5#") PORT_CODE(KEYCODE_L)
+
+ PORT_START("KEY_45")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("A5") PORT_CODE(KEYCODE_STOP)
+
+ PORT_START("KEY_46")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("A5#") PORT_CODE(KEYCODE_COLON)
+
+ PORT_START("KEY_47")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("B5") PORT_CODE(KEYCODE_SLASH)
+
+ PORT_START("KEY_48")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("C6") PORT_CODE(KEYCODE_RSHIFT)
+
+ PORT_START("KEY_49")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("C6#")
+
+ PORT_START("KEY_50")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("D6")
+
+ PORT_START("KEY_51")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("D6#")
+
+ PORT_START("KEY_52")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("E6")
+
+ PORT_START("KEY_53")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("F6")
+
+ PORT_START("KEY_54")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("F6#")
+
+ PORT_START("KEY_55")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("G6")
+
+ PORT_START("KEY_56")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("G6#")
+
+ PORT_START("KEY_57")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("A6")
+
+ PORT_START("KEY_58")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("A6#")
+
+ PORT_START("KEY_59")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("B6")
+
+ PORT_START("KEY_60")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("C7")
+
+ PORT_START("KEY_61")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_UNUSED)
+
+ PORT_START("KEY_62")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_UNUSED)
+
+ PORT_START("KEY_63")
+ PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_UNUSED)
+INPUT_PORTS_END
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor bbc_lvlecho_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( lvlecho );
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void bbc_lvlecho_device::device_start()
+{
+ save_item(NAME(m_key));
+}
+
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(BBC_LVLECHO, device_bbc_userport_interface, bbc_lvlecho_device, "bbc_lvlecho", "LVL Echo Keyboard")
diff --git a/src/devices/bus/bbc/userport/lvlecho.h b/src/devices/bus/bbc/userport/lvlecho.h
new file mode 100644
index 00000000000..f089459eec8
--- /dev/null
+++ b/src/devices/bus/bbc/userport/lvlecho.h
@@ -0,0 +1,13 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+#ifndef MAME_BUS_BBC_USERPORT_LVLECHO_H
+#define MAME_BUS_BBC_USERPORT_LVLECHO_H
+
+#pragma once
+
+#include "userport.h"
+
+
+DECLARE_DEVICE_TYPE(BBC_LVLECHO, device_bbc_userport_interface)
+
+#endif // MAME_BUS_BBC_USERPORT_LVLECHO_H
diff --git a/src/devices/bus/bbc/userport/m4000.cpp b/src/devices/bus/bbc/userport/m4000.cpp
index 910f2f8b3f1..64ed023f211 100644
--- a/src/devices/bus/bbc/userport/m4000.cpp
+++ b/src/devices/bus/bbc/userport/m4000.cpp
@@ -9,15 +9,44 @@
**********************************************************************/
-
#include "emu.h"
#include "m4000.h"
-//**************************************************************************
-// DEVICE DEFINITIONS
-//**************************************************************************
-DEFINE_DEVICE_TYPE(BBC_M4000, bbc_m4000_device, "bbc_m4000", "Hybrid Music 4000 Keyboard")
+namespace {
+
+
+class bbc_m4000_device : public device_t, public device_bbc_userport_interface
+{
+public:
+ bbc_m4000_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, BBC_M4000, tag, owner, clock)
+ , device_bbc_userport_interface(mconfig, *this)
+ , m_kbd(*this, "KBLOCK_%u", 1)
+ , m_clk(0)
+ , m_dsb(0)
+ , m_out(0)
+ {
+ }
+
+protected:
+ // device_t overrides
+ virtual void device_start() override;
+
+ // optional information overrides
+ virtual ioport_constructor device_input_ports() const override;
+
+ virtual uint8_t pb_r() override;
+ virtual void write_cb1(int state) override;
+ virtual void write_cb2(int state) override;
+
+private:
+ required_ioport_array<8> m_kbd;
+
+ int m_clk;
+ int m_dsb;
+ uint8_t m_out;
+};
//-------------------------------------------------
@@ -26,72 +55,72 @@ DEFINE_DEVICE_TYPE(BBC_M4000, bbc_m4000_device, "bbc_m4000", "Hybrid Music 4000
static INPUT_PORTS_START( m4000 )
PORT_START("KBLOCK_1")
- PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("C2")
- PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("C2#")
- PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("D2")
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("D2#")
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("E2")
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("F2")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("F2#")
- PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("G2")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C2") PORT_CODE(KEYCODE_TAB)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C2#") PORT_CODE(KEYCODE_1)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("D2") PORT_CODE(KEYCODE_Q)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("D2#") PORT_CODE(KEYCODE_2)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("E2") PORT_CODE(KEYCODE_W)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F2") PORT_CODE(KEYCODE_E)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F2#") PORT_CODE(KEYCODE_4)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("G2") PORT_CODE(KEYCODE_R)
PORT_START("KBLOCK_2")
- PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("G2#")
- PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("A2")
- PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("A2#")
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("B2")
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("C3")
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("C3#")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("D3")
- PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("D3#")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("G2#") PORT_CODE(KEYCODE_5)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("A2") PORT_CODE(KEYCODE_T)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("A2#") PORT_CODE(KEYCODE_6)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("B2") PORT_CODE(KEYCODE_Y)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C3") PORT_CODE(KEYCODE_U)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C3#") PORT_CODE(KEYCODE_8)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("D3") PORT_CODE(KEYCODE_I)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("D3#") PORT_CODE(KEYCODE_9)
PORT_START("KBLOCK_3")
- PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("E3")
- PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("F3")
- PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("F3#")
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("G3")
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("G3#")
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("A3")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("A3#")
- PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("B3")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("E3") PORT_CODE(KEYCODE_O)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F3") PORT_CODE(KEYCODE_P)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F3#") PORT_CODE(KEYCODE_A)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("G3") PORT_CODE(KEYCODE_Z)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("G3#") PORT_CODE(KEYCODE_S)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("A3") PORT_CODE(KEYCODE_X)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("A3#") PORT_CODE(KEYCODE_D)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("B3") PORT_CODE(KEYCODE_C)
PORT_START("KBLOCK_4")
- PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("C4")
- PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("C4#")
- PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("D4")
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("D4#")
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("E4")
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("F4")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("F4#")
- PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("G4")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C4") PORT_CODE(KEYCODE_V)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C4#") PORT_CODE(KEYCODE_G)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("D4") PORT_CODE(KEYCODE_B)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("D4#") PORT_CODE(KEYCODE_H)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("E4") PORT_CODE(KEYCODE_N)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F4") PORT_CODE(KEYCODE_M)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F4#") PORT_CODE(KEYCODE_K)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("G4") PORT_CODE(KEYCODE_COMMA)
PORT_START("KBLOCK_5")
- PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("G4#")
- PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("A4")
- PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("A4#")
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("B4")
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("C5")
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("C5#")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("D5")
- PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("D5#")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("G4#") PORT_CODE(KEYCODE_L)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("A4") PORT_CODE(KEYCODE_STOP)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("A4#") PORT_CODE(KEYCODE_COLON)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("B4") PORT_CODE(KEYCODE_SLASH)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C5") PORT_CODE(KEYCODE_RSHIFT)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C5#")
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("D5")
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("D5#")
PORT_START("KBLOCK_6")
- PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("E5")
- PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("F5")
- PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("F5#")
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("G5")
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("G5#")
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("A5")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("A5#")
- PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("B5")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("E5")
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F5")
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F5#")
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("G5")
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("G5#")
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("A5")
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("A5#")
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("B5")
PORT_START("KBLOCK_7")
- PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("C6")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C6")
PORT_BIT(0xfe, IP_ACTIVE_LOW, IPT_UNUSED)
PORT_START("KBLOCK_8")
PORT_BIT(0x7f, IP_ACTIVE_LOW, IPT_UNUSED)
- PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("Foot Switch")
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Foot Switch")
INPUT_PORTS_END
@@ -105,25 +134,6 @@ ioport_constructor bbc_m4000_device::device_input_ports() const
}
-//**************************************************************************
-// LIVE DEVICE
-//**************************************************************************
-
-//-------------------------------------------------
-// bbc_m4000_device - constructor
-//-------------------------------------------------
-
-bbc_m4000_device::bbc_m4000_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, BBC_M4000, tag, owner, clock)
- , device_bbc_userport_interface(mconfig, *this)
- , m_kbd(*this, "KBLOCK_%u", 1)
- , m_clk(0)
- , m_dsb(0)
- , m_out(0)
-{
-}
-
-
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
@@ -168,3 +178,8 @@ uint8_t bbc_m4000_device::pb_r()
return data;
}
+
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(BBC_M4000, device_bbc_userport_interface, bbc_m4000_device, "bbc_m4000", "Hybrid Music 4000 Keyboard")
diff --git a/src/devices/bus/bbc/userport/m4000.h b/src/devices/bus/bbc/userport/m4000.h
index df9c5e556cf..75297243c27 100644
--- a/src/devices/bus/bbc/userport/m4000.h
+++ b/src/devices/bus/bbc/userport/m4000.h
@@ -1,15 +1,5 @@
// license:BSD-3-Clause
// copyright-holders:Nigel Barnes
-/**********************************************************************
-
- Hybrid Music 4000 Keyboard
-
- https://www.retro-kit.co.uk/page.cfm/content/Hybrid-Music-4000-Keyboard/
- http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Hybrid_Music4000.html
-
-**********************************************************************/
-
-
#ifndef MAME_BUS_BBC_USERPORT_M4000_H
#define MAME_BUS_BBC_USERPORT_M4000_H
@@ -17,42 +7,7 @@
#include "userport.h"
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-// ======================> bbc_m4000_device
-
-class bbc_m4000_device :
- public device_t,
- public device_bbc_userport_interface
-{
-public:
- // construction/destruction
- bbc_m4000_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- // device-level overrides
- virtual void device_start() override;
-
- // optional information overrides
- virtual ioport_constructor device_input_ports() const override;
-
- virtual uint8_t pb_r() override;
- virtual void write_cb1(int state) override;
- virtual void write_cb2(int state) override;
-
-private:
- required_ioport_array<8> m_kbd;
-
- int m_clk;
- int m_dsb;
- uint8_t m_out;
-};
-
-
-// device type definition
-DECLARE_DEVICE_TYPE(BBC_M4000, bbc_m4000_device)
+DECLARE_DEVICE_TYPE(BBC_M4000, device_bbc_userport_interface)
#endif // MAME_BUS_BBC_USERPORT_M4000_H
diff --git a/src/devices/bus/bbc/userport/palext.cpp b/src/devices/bus/bbc/userport/palext.cpp
index dab527e478b..090fae74593 100644
--- a/src/devices/bus/bbc/userport/palext.cpp
+++ b/src/devices/bus/bbc/userport/palext.cpp
@@ -16,6 +16,9 @@
#include "emu.h"
#include "palext.h"
+#include <algorithm>
+
+
//**************************************************************************
// DEVICE DEFINITIONS
//**************************************************************************
@@ -76,9 +79,9 @@ bbc_cpalette_device::bbc_cpalette_device(const machine_config &mconfig, const ch
void bbc_palext_device::device_start()
{
- memset(m_palette_ram, 0, sizeof(m_palette_ram));
+ std::fill(std::begin(m_palette_ram), std::end(m_palette_ram), rgb_t(0));
- /* register for save states */
+ // register for save states
save_item(NAME(m_colour));
save_item(NAME(m_palette_ram));
}
diff --git a/src/devices/bus/bbc/userport/sdcard.h b/src/devices/bus/bbc/userport/sdcard.h
index bfa86ad359b..0bab3d85e21 100644
--- a/src/devices/bus/bbc/userport/sdcard.h
+++ b/src/devices/bus/bbc/userport/sdcard.h
@@ -63,7 +63,7 @@ protected:
virtual void write_cb2(int state) override;
private:
- bool m_turbo;;
+ bool m_turbo;
};
diff --git a/src/devices/bus/bbc/userport/userport.cpp b/src/devices/bus/bbc/userport/userport.cpp
index 6bf5476db9c..d3b6467dd21 100644
--- a/src/devices/bus/bbc/userport/userport.cpp
+++ b/src/devices/bus/bbc/userport/userport.cpp
@@ -26,10 +26,10 @@ DEFINE_DEVICE_TYPE(BBC_USERPORT_SLOT, bbc_userport_slot_device, "bbc_userport_sl
// device_bbc_userport_interface - constructor
//-------------------------------------------------
-device_bbc_userport_interface::device_bbc_userport_interface(const machine_config &mconfig, device_t &device) :
- device_interface(device, "bbcuserport")
+device_bbc_userport_interface::device_bbc_userport_interface(const machine_config &mconfig, device_t &device)
+ : device_interface(device, "bbcuserport")
+ , m_slot(dynamic_cast<bbc_userport_slot_device *>(device.owner()))
{
- m_slot = dynamic_cast<bbc_userport_slot_device *>(device.owner());
}
@@ -69,10 +69,6 @@ bbc_userport_slot_device::bbc_userport_slot_device(const machine_config &mconfig
void bbc_userport_slot_device::device_start()
{
m_device = get_card_device();
-
- // resolve callbacks
- m_cb1_handler.resolve_safe();
- m_cb2_handler.resolve_safe();
}
@@ -132,6 +128,7 @@ void bbc_userport_slot_device::write_cb2(int state)
//#include "digitiser.h"
//#include "ev1.h"
#include "lcd.h"
+#include "lvlecho.h"
#include "m4000.h"
#include "palext.h"
#include "pointer.h"
@@ -153,6 +150,7 @@ void bbc_userport_devices(device_slot_interface &device)
//device.option_add("ev1", BBC_EV1); /* Micro-Robotics EV1 */
//device.option_add("hobbit", BBC_HOBBIT); /* Hobbit Floppy Tape System (Ikon) */
device.option_add("lcd", BBC_LCD); /* Sprow LCD Display */
+ device.option_add("lvlecho", BBC_LVLECHO); /* LVL Echo Keyboard */
device.option_add("m4000", BBC_M4000); /* Hybrid Music 4000 Keyboard */
device.option_add("m512mouse", BBC_M512MOUSE); /* Acorn Mouse (provided with Master 512) */
device.option_add("sdcard", BBC_SDCARD); /* SD Card */
diff --git a/src/devices/bus/bbc/userport/userport.h b/src/devices/bus/bbc/userport/userport.h
index 29374eb9058..222e05efd24 100644
--- a/src/devices/bus/bbc/userport/userport.h
+++ b/src/devices/bus/bbc/userport/userport.h
@@ -62,8 +62,8 @@ public:
auto cb2_handler() { return m_cb2_handler.bind(); }
// from slot
- DECLARE_WRITE_LINE_MEMBER(cb1_w) { m_cb1_handler(state); }
- DECLARE_WRITE_LINE_MEMBER(cb2_w) { m_cb2_handler(state); }
+ void cb1_w(int state) { m_cb1_handler(state); }
+ void cb2_w(int state) { m_cb2_handler(state); }
// from host
uint8_t pb_r();
@@ -99,7 +99,7 @@ public:
protected:
device_bbc_userport_interface(const machine_config &mconfig, device_t &device);
- bbc_userport_slot_device *m_slot;
+ bbc_userport_slot_device *const m_slot;
};
diff --git a/src/devices/bus/bbc/userport/usersplit.cpp b/src/devices/bus/bbc/userport/usersplit.cpp
index 520abaebdb9..38d2c3b197f 100644
--- a/src/devices/bus/bbc/userport/usersplit.cpp
+++ b/src/devices/bus/bbc/userport/usersplit.cpp
@@ -109,25 +109,25 @@ void bbc_usersplit_device::write_cb2(int state)
}
-WRITE_LINE_MEMBER(bbc_usersplit_device::cb1a_w)
+void bbc_usersplit_device::cb1a_w(int state)
{
if (m_selected == 0x00)
m_slot->cb1_w(state);
}
-WRITE_LINE_MEMBER(bbc_usersplit_device::cb2a_w)
+void bbc_usersplit_device::cb2a_w(int state)
{
if (m_selected == 0x00)
m_slot->cb2_w(state);
}
-WRITE_LINE_MEMBER(bbc_usersplit_device::cb1b_w)
+void bbc_usersplit_device::cb1b_w(int state)
{
if (m_selected == 0x01)
m_slot->cb1_w(state);
}
-WRITE_LINE_MEMBER(bbc_usersplit_device::cb2b_w)
+void bbc_usersplit_device::cb2b_w(int state)
{
if (m_selected == 0x01)
m_slot->cb2_w(state);
diff --git a/src/devices/bus/bbc/userport/usersplit.h b/src/devices/bus/bbc/userport/usersplit.h
index 27ce11a9fde..01b1ed5de08 100644
--- a/src/devices/bus/bbc/userport/usersplit.h
+++ b/src/devices/bus/bbc/userport/usersplit.h
@@ -44,10 +44,10 @@ protected:
virtual void write_cb2(int state) override;
private:
- DECLARE_WRITE_LINE_MEMBER(cb1a_w);
- DECLARE_WRITE_LINE_MEMBER(cb2a_w);
- DECLARE_WRITE_LINE_MEMBER(cb1b_w);
- DECLARE_WRITE_LINE_MEMBER(cb2b_w);
+ void cb1a_w(int state);
+ void cb2a_w(int state);
+ void cb1b_w(int state);
+ void cb2b_w(int state);
required_device_array<bbc_userport_slot_device, 2> m_userport;
uint8_t m_selected;
diff --git a/src/devices/bus/bml3/bml3bus.cpp b/src/devices/bus/bml3/bml3bus.cpp
index 54e63ea70ec..8c564cc2bb8 100644
--- a/src/devices/bus/bml3/bml3bus.cpp
+++ b/src/devices/bus/bml3/bml3bus.cpp
@@ -104,11 +104,15 @@ bml3bus_device::bml3bus_device(const machine_config &mconfig, const char *tag, d
bml3bus_device::bml3bus_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, type, tag, owner, clock),
- m_space(*this, finder_base::DUMMY_TAG, -1, 8),
m_out_nmi_cb(*this),
m_out_irq_cb(*this),
m_out_firq_cb(*this)
{
+ // clear slots
+ for (auto & elem : m_device_list)
+ {
+ elem = nullptr;
+ }
}
//-------------------------------------------------
@@ -117,16 +121,6 @@ bml3bus_device::bml3bus_device(const machine_config &mconfig, device_type type,
void bml3bus_device::device_start()
{
- // resolve callbacks
- m_out_nmi_cb.resolve_safe();
- m_out_irq_cb.resolve_safe();
- m_out_firq_cb.resolve_safe();
-
- // clear slots
- for (auto & elem : m_device_list)
- {
- elem = nullptr;
- }
}
//-------------------------------------------------
@@ -152,6 +146,24 @@ void bml3bus_device::add_bml3bus_card(int slot, device_bml3bus_card_interface &c
m_device_list[slot] = &card;
}
+void bml3bus_device::map_exrom(address_space_installer &space)
+{
+ for (auto & elem : m_device_list)
+ {
+ if (elem != nullptr)
+ elem->map_exrom(space);
+ }
+}
+
+void bml3bus_device::map_io(address_space_installer &space)
+{
+ for (auto & elem : m_device_list)
+ {
+ if (elem != nullptr)
+ elem->map_io(space);
+ }
+}
+
void bml3bus_device::set_nmi_line(int state)
{
m_out_nmi_cb(state);
@@ -168,9 +180,9 @@ void bml3bus_device::set_firq_line(int state)
}
// interrupt request from bml3bus card
-WRITE_LINE_MEMBER( bml3bus_device::nmi_w ) { m_out_nmi_cb(state); }
-WRITE_LINE_MEMBER( bml3bus_device::irq_w ) { m_out_irq_cb(state); }
-WRITE_LINE_MEMBER( bml3bus_device::firq_w ) { m_out_firq_cb(state); }
+void bml3bus_device::nmi_w(int state) { m_out_nmi_cb(state); }
+void bml3bus_device::irq_w(int state) { m_out_irq_cb(state); }
+void bml3bus_device::firq_w(int state) { m_out_firq_cb(state); }
//**************************************************************************
// DEVICE CONFIG BML3BUS CARD INTERFACE
diff --git a/src/devices/bus/bml3/bml3bus.h b/src/devices/bus/bml3/bml3bus.h
index b3c36ed9c70..3663c4d3b61 100644
--- a/src/devices/bus/bml3/bml3bus.h
+++ b/src/devices/bus/bml3/bml3bus.h
@@ -75,16 +75,18 @@ public:
bml3bus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// inline configuration
- template <class Object> void set_space(Object &&tag, int spacenum) { m_space.set_tag(std::forward<Object>(tag), spacenum); }
auto nmi_callback() { return m_out_nmi_cb.bind(); }
auto irq_callback() { return m_out_irq_cb.bind(); }
auto firq_callback() { return m_out_firq_cb.bind(); }
device_bml3bus_card_interface *get_bml3bus_card(int slot);
- DECLARE_WRITE_LINE_MEMBER( nmi_w );
- DECLARE_WRITE_LINE_MEMBER( irq_w );
- DECLARE_WRITE_LINE_MEMBER( firq_w );
+ void map_exrom(address_space_installer &space);
+ void map_io(address_space_installer &space);
+
+ void nmi_w(int state);
+ void irq_w(int state);
+ void firq_w(int state);
protected:
bml3bus_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
@@ -95,15 +97,11 @@ protected:
void add_bml3bus_card(int slot, device_bml3bus_card_interface &card);
- address_space &space() const { return *m_space; }
-
void set_nmi_line(int state);
void set_irq_line(int state);
void set_firq_line(int state);
- // internal state
- required_address_space m_space;
-
+ // line callbacks
devcb_write_line m_out_nmi_cb;
devcb_write_line m_out_irq_cb;
devcb_write_line m_out_firq_cb;
@@ -131,7 +129,8 @@ public:
protected:
virtual void interface_pre_start() override;
- address_space &space() { return m_bml3bus->space(); }
+ virtual void map_exrom(address_space_installer &space) { }
+ virtual void map_io(address_space_installer &space) { }
void raise_slot_nmi() { m_bml3bus->set_nmi_line(ASSERT_LINE); }
void lower_slot_nmi() { m_bml3bus->set_nmi_line(CLEAR_LINE); }
diff --git a/src/devices/bus/bml3/bml3kanji.cpp b/src/devices/bus/bml3/bml3kanji.cpp
index 22bfe8d58a9..0e2f9cf7d39 100644
--- a/src/devices/bus/bml3/bml3kanji.cpp
+++ b/src/devices/bus/bml3/bml3kanji.cpp
@@ -22,10 +22,8 @@
DEFINE_DEVICE_TYPE(BML3BUS_KANJI, bml3bus_kanji_device, "bml3kanji", "Hitachi MP-9740 Kanji Character ROM Card")
-#define KANJI_ROM_REGION "kanji_rom"
-
ROM_START( kanji )
- ROM_REGION( 0x20000, KANJI_ROM_REGION, ROMREGION_ERASEFF )
+ ROM_REGION( 0x20000, "kanji_rom", ROMREGION_ERASEFF )
ROM_LOAD("kanji.rom", 0x00000, 0x20000, BAD_DUMP CRC(de99a726) SHA1(65fead5d0d779b242f6e0ac25fcc9899dc343101))
ROM_END
@@ -61,7 +59,8 @@ void bml3bus_kanji_device::bml3_kanji_w(offs_t offset, uint8_t data)
bml3bus_kanji_device::bml3bus_kanji_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, BML3BUS_KANJI, tag, owner, clock),
- device_bml3bus_card_interface(mconfig, *this), m_kanji_addr(0), m_rom(nullptr)
+ device_bml3bus_card_interface(mconfig, *this), m_kanji_addr(0),
+ m_rom(*this, "kanji_rom")
{
}
@@ -72,11 +71,13 @@ bml3bus_kanji_device::bml3bus_kanji_device(const machine_config &mconfig, const
void bml3bus_kanji_device::device_start()
{
- m_rom = memregion(KANJI_ROM_REGION)->base();
+ save_item(NAME(m_kanji_addr));
+}
+void bml3bus_kanji_device::map_io(address_space_installer &space)
+{
// install into memory
- address_space &space_prg = space();
- space_prg.install_readwrite_handler(0xff75, 0xff76, read8sm_delegate(*this, FUNC(bml3bus_kanji_device::bml3_kanji_r)), write8sm_delegate(*this, FUNC(bml3bus_kanji_device::bml3_kanji_w)));
+ space.install_readwrite_handler(0xff75, 0xff76, read8sm_delegate(*this, FUNC(bml3bus_kanji_device::bml3_kanji_r)), write8sm_delegate(*this, FUNC(bml3bus_kanji_device::bml3_kanji_w)));
}
void bml3bus_kanji_device::device_reset()
diff --git a/src/devices/bus/bml3/bml3kanji.h b/src/devices/bus/bml3/bml3kanji.h
index 2ce54ed8230..d1e456508ae 100644
--- a/src/devices/bus/bml3/bml3kanji.h
+++ b/src/devices/bus/bml3/bml3kanji.h
@@ -37,10 +37,12 @@ protected:
// optional information overrides
virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void map_io(address_space_installer &space) override;
+
uint16_t m_kanji_addr;
private:
- uint8_t *m_rom;
+ required_region_ptr<uint8_t> m_rom;
};
// device type definition
diff --git a/src/devices/bus/bml3/bml3mp1802.cpp b/src/devices/bus/bml3/bml3mp1802.cpp
index 61900cd020f..9ee4c8a3248 100644
--- a/src/devices/bus/bml3/bml3mp1802.cpp
+++ b/src/devices/bus/bml3/bml3mp1802.cpp
@@ -30,21 +30,18 @@ static void mp1802_floppies(device_slot_interface &device)
device.option_add("dd", FLOPPY_525_DD);
}
-WRITE_LINE_MEMBER( bml3bus_mp1802_device::bml3_wd17xx_intrq_w )
+void bml3bus_mp1802_device::nmi_w(int state)
{
if (state)
- {
raise_slot_nmi();
+ else
lower_slot_nmi();
- }
}
-#define MP1802_ROM_REGION "mp1802_rom"
-
ROM_START( mp1802 )
- ROM_REGION(0x10000, MP1802_ROM_REGION, 0)
+ ROM_REGION(0x800, "mp1802_rom", 0)
// MP-1802 disk controller ROM, which replaces part of the system ROM
- ROM_LOAD( "mp1802.rom", 0xf800, 0x800, BAD_DUMP CRC(8d0dc101) SHA1(92f7d1cebecafa7472e45c4999520de5c01c6dbc))
+ ROM_LOAD( "mp1802.rom", 0x000, 0x800, BAD_DUMP CRC(8d0dc101) SHA1(92f7d1cebecafa7472e45c4999520de5c01c6dbc))
ROM_END
@@ -61,12 +58,15 @@ void bml3bus_mp1802_device::device_add_mconfig(machine_config &config)
constexpr auto CLK16M = 32.256_MHz_XTAL / 2;
MB8866(config, m_fdc, CLK16M / 16); // 16MCLK divided by IC628 (HD74LS93P)
- m_fdc->intrq_wr_callback().set(FUNC(bml3bus_mp1802_device::bml3_wd17xx_intrq_w));
+ m_fdc->intrq_wr_callback().set(m_nmigate, FUNC(input_merger_device::in_w<0>));
- FLOPPY_CONNECTOR(config, m_floppy0, mp1802_floppies, "dd", floppy_image_device::default_mfm_floppy_formats);
- FLOPPY_CONNECTOR(config, m_floppy1, mp1802_floppies, "dd", floppy_image_device::default_mfm_floppy_formats);
- FLOPPY_CONNECTOR(config, m_floppy2, mp1802_floppies, nullptr, floppy_image_device::default_mfm_floppy_formats);
- FLOPPY_CONNECTOR(config, m_floppy3, mp1802_floppies, nullptr, floppy_image_device::default_mfm_floppy_formats);
+ INPUT_MERGER_ALL_HIGH(config, m_nmigate);
+ m_nmigate->output_handler().set(FUNC(bml3bus_mp1802_device::nmi_w));
+
+ FLOPPY_CONNECTOR(config, m_floppy[0], mp1802_floppies, "dd", floppy_image_device::default_mfm_floppy_formats);
+ FLOPPY_CONNECTOR(config, m_floppy[1], mp1802_floppies, "dd", floppy_image_device::default_mfm_floppy_formats);
+ FLOPPY_CONNECTOR(config, m_floppy[2], mp1802_floppies, nullptr, floppy_image_device::default_mfm_floppy_formats);
+ FLOPPY_CONNECTOR(config, m_floppy[3], mp1802_floppies, nullptr, floppy_image_device::default_mfm_floppy_formats);
SOFTWARE_LIST(config, "flop_list").set_original("bml3_flop").set_filter("5");
}
@@ -81,28 +81,23 @@ const tiny_rom_entry *bml3bus_mp1802_device::device_rom_region() const
uint8_t bml3bus_mp1802_device::bml3_mp1802_r()
{
- return m_fdc->drq_r() ? 0x00 : 0x80;
+ return (m_fdc->drq_r() ? 0x00 : 0x80) | (m_fdc->intrq_r() ? 0x00 : 0x40);
}
void bml3bus_mp1802_device::bml3_mp1802_w(uint8_t data)
{
- floppy_image_device *floppy = nullptr;
-
- switch (data & 0x03)
- {
- case 0: floppy = m_floppy0->get_device(); break;
- case 1: floppy = m_floppy1->get_device(); break;
- case 2: floppy = m_floppy2->get_device(); break;
- case 3: floppy = m_floppy3->get_device(); break;
- }
+ floppy_image_device *floppy = m_floppy[data & 0x03]->get_device();
m_fdc->set_floppy(floppy);
+ m_fdc->dden_w(!BIT(data, 5));
if (floppy)
{
floppy->mon_w(!BIT(data, 3));
floppy->ss_w(BIT(data, 4));
}
+
+ m_nmigate->in_w<1>(!BIT(data, 6));
}
@@ -114,10 +109,9 @@ bml3bus_mp1802_device::bml3bus_mp1802_device(const machine_config &mconfig, cons
device_t(mconfig, BML3BUS_MP1802, tag, owner, clock),
device_bml3bus_card_interface(mconfig, *this),
m_fdc(*this, "fdc"),
- m_floppy0(*this, "fdc:0"),
- m_floppy1(*this, "fdc:1"),
- m_floppy2(*this, "fdc:2"),
- m_floppy3(*this, "fdc:3"), m_rom(nullptr)
+ m_floppy(*this, "fdc:%u", 0U),
+ m_nmigate(*this, "nmigate"),
+ m_rom(*this, "mp1802_rom")
{
}
@@ -128,17 +122,22 @@ bml3bus_mp1802_device::bml3bus_mp1802_device(const machine_config &mconfig, cons
void bml3bus_mp1802_device::device_start()
{
- m_rom = memregion(MP1802_ROM_REGION)->base();
-
- // install into memory
- address_space &space_prg = space();
- space_prg.install_readwrite_handler(0xff00, 0xff03, read8sm_delegate(*m_fdc, FUNC(mb8866_device::read)), write8sm_delegate(*m_fdc, FUNC(mb8866_device::write)));
- space_prg.install_readwrite_handler(0xff04, 0xff04, read8smo_delegate(*this, FUNC(bml3bus_mp1802_device::bml3_mp1802_r)), write8smo_delegate(*this, FUNC(bml3bus_mp1802_device::bml3_mp1802_w)));
- // overwriting the main ROM (rather than using e.g. install_rom) should mean that bank switches for RAM expansion still work...
- uint8_t *mainrom = device().machine().root_device().memregion("maincpu")->base();
- memcpy(mainrom + 0xf800, m_rom + 0xf800, 0x800);
}
void bml3bus_mp1802_device::device_reset()
{
+ bml3_mp1802_w(0);
+}
+
+void bml3bus_mp1802_device::map_exrom(address_space_installer &space)
+{
+ space.install_rom(0xf800, 0xfeff, &m_rom[0]);
+ space.install_rom(0xfff0, 0xffff, &m_rom[0x7f0]);
+}
+
+void bml3bus_mp1802_device::map_io(address_space_installer &space)
+{
+ // install into memory
+ space.install_readwrite_handler(0xff00, 0xff03, read8sm_delegate(*m_fdc, FUNC(mb8866_device::read)), write8sm_delegate(*m_fdc, FUNC(mb8866_device::write)));
+ space.install_readwrite_handler(0xff04, 0xff04, read8smo_delegate(*this, FUNC(bml3bus_mp1802_device::bml3_mp1802_r)), write8smo_delegate(*this, FUNC(bml3bus_mp1802_device::bml3_mp1802_w)));
}
diff --git a/src/devices/bus/bml3/bml3mp1802.h b/src/devices/bus/bml3/bml3mp1802.h
index d1bbdad744b..ecc379261c6 100644
--- a/src/devices/bus/bml3/bml3mp1802.h
+++ b/src/devices/bus/bml3/bml3mp1802.h
@@ -16,6 +16,7 @@
#include "bml3bus.h"
#include "imagedev/floppy.h"
+#include "machine/input_merger.h"
#include "machine/wd_fdc.h"
@@ -42,16 +43,17 @@ protected:
virtual void device_add_mconfig(machine_config &config) override;
virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void map_exrom(address_space_installer &space) override;
+ virtual void map_io(address_space_installer &space) override;
+
private:
- DECLARE_WRITE_LINE_MEMBER(bml3_wd17xx_intrq_w);
+ void nmi_w(int state);
required_device<mb8866_device> m_fdc;
- required_device<floppy_connector> m_floppy0;
- required_device<floppy_connector> m_floppy1;
- required_device<floppy_connector> m_floppy2;
- required_device<floppy_connector> m_floppy3;
+ required_device_array<floppy_connector, 4> m_floppy;
+ required_device<input_merger_device> m_nmigate;
- uint8_t *m_rom;
+ required_region_ptr<uint8_t> m_rom;
};
// device type definition
diff --git a/src/devices/bus/bml3/bml3mp1805.cpp b/src/devices/bus/bml3/bml3mp1805.cpp
index 78b58782d6e..e16c924a62d 100644
--- a/src/devices/bus/bml3/bml3mp1805.cpp
+++ b/src/devices/bus/bml3/bml3mp1805.cpp
@@ -26,12 +26,10 @@
DEFINE_DEVICE_TYPE(BML3BUS_MP1805, bml3bus_mp1805_device, "bml3mp1805", "Hitachi MP-1805 Floppy Controller Card")
-#define MP1805_ROM_REGION "mp1805_rom"
-
ROM_START( mp1805 )
- ROM_REGION(0x10000, MP1805_ROM_REGION, 0)
+ ROM_REGION(0x800, "mp1805_rom", 0)
// MP-1805 disk controller ROM, which replaces part of the system ROM
- ROM_LOAD( "mp1805.rom", 0xf800, 0x0800, BAD_DUMP CRC(b532d8d9) SHA1(6f1160356d5bf64b5926b1fdb60db414edf65f22))
+ ROM_LOAD( "mp1805.rom", 0x000, 0x800, BAD_DUMP CRC(b532d8d9) SHA1(6f1160356d5bf64b5926b1fdb60db414edf65f22))
ROM_END
// Although the drive is single-sided, D88 images are double-sided,
@@ -53,7 +51,6 @@ void bml3bus_mp1805_device::floppy_drives(device_slot_interface &device)
void bml3bus_mp1805_device::device_add_mconfig(machine_config &config)
{
MC6843(config, m_mc6843, 500000);
- m_mc6843->force_ready();
m_mc6843->irq().set(FUNC(bml3bus_mp1805_device::nmi_w));
FLOPPY_CONNECTOR(config, m_floppy[0], floppy_drives, "mb_6890", floppy_image_device::default_mfm_floppy_formats).enable_sound(true);
@@ -135,7 +132,8 @@ bml3bus_mp1805_device::bml3bus_mp1805_device(const machine_config &mconfig, cons
device_t(mconfig, BML3BUS_MP1805, tag, owner, clock),
device_bml3bus_card_interface(mconfig, *this),
m_floppy(*this, "%u", 0U),
- m_mc6843(*this, "mc6843"), m_rom(nullptr)
+ m_mc6843(*this, "mc6843"),
+ m_rom(*this, "mp1805_rom")
{
}
@@ -146,16 +144,6 @@ bml3bus_mp1805_device::bml3bus_mp1805_device(const machine_config &mconfig, cons
void bml3bus_mp1805_device::device_start()
{
- m_rom = memregion(MP1805_ROM_REGION)->base();
-
- // install into memory
- address_space &space_prg = space();
- space_prg.install_device(0xff18, 0xff1f, *m_mc6843, &mc6843_device::map);
- space_prg.install_readwrite_handler(0xff20, 0xff20, read8smo_delegate(*this, FUNC(bml3bus_mp1805_device::bml3_mp1805_r)), write8smo_delegate(*this, FUNC(bml3bus_mp1805_device::bml3_mp1805_w)));
- // overwriting the main ROM (rather than using e.g. install_rom) should mean that bank switches for RAM expansion still work...
- uint8_t *mainrom = device().machine().root_device().memregion("maincpu")->base();
- memcpy(mainrom + 0xf800, m_rom + 0xf800, 0x800);
-
save_item(NAME(m_control));
}
@@ -163,3 +151,16 @@ void bml3bus_mp1805_device::device_reset()
{
m_control = 0;
}
+
+void bml3bus_mp1805_device::map_exrom(address_space_installer &space)
+{
+ space.install_rom(0xf800, 0xfeff, &m_rom[0]);
+ space.install_rom(0xfff0, 0xffff, &m_rom[0x7f0]);
+}
+
+void bml3bus_mp1805_device::map_io(address_space_installer &space)
+{
+ // install into memory
+ space.install_device(0xff18, 0xff1f, *m_mc6843, &mc6843_device::map);
+ space.install_readwrite_handler(0xff20, 0xff20, read8smo_delegate(*this, FUNC(bml3bus_mp1805_device::bml3_mp1805_r)), write8smo_delegate(*this, FUNC(bml3bus_mp1805_device::bml3_mp1805_w)));
+}
diff --git a/src/devices/bus/bml3/bml3mp1805.h b/src/devices/bus/bml3/bml3mp1805.h
index f3c4de448d3..3dfecc0ec22 100644
--- a/src/devices/bus/bml3/bml3mp1805.h
+++ b/src/devices/bus/bml3/bml3mp1805.h
@@ -41,11 +41,14 @@ protected:
virtual void device_add_mconfig(machine_config &config) override;
virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void map_exrom(address_space_installer &space) override;
+ virtual void map_io(address_space_installer &space) override;
+
+private:
required_device_array<floppy_connector, 4> m_floppy;
required_device<mc6843_device> m_mc6843;
-private:
- uint8_t *m_rom;
+ required_region_ptr<uint8_t> m_rom;
uint8_t m_control;
diff --git a/src/devices/bus/bml3/bml3rtc.cpp b/src/devices/bus/bml3/bml3rtc.cpp
index 6fbe66f166e..28971440f49 100644
--- a/src/devices/bus/bml3/bml3rtc.cpp
+++ b/src/devices/bus/bml3/bml3rtc.cpp
@@ -95,13 +95,15 @@ bml3bus_rtc_device::bml3bus_rtc_device(const machine_config &mconfig, const char
void bml3bus_rtc_device::device_start()
{
- // install into memory
- address_space &space_prg = space();
- space_prg.install_readwrite_handler(0xff38, 0xff3a, read8sm_delegate(*this, FUNC(bml3bus_rtc_device::bml3_rtc_r)), write8sm_delegate(*this, FUNC(bml3bus_rtc_device::bml3_rtc_w)));
-
m_addr_latch = 0;
m_data_latch = 0;
save_item(NAME(m_addr_latch));
save_item(NAME(m_data_latch));
}
+
+void bml3bus_rtc_device::map_io(address_space_installer &space)
+{
+ // install into memory
+ space.install_readwrite_handler(0xff38, 0xff3a, read8sm_delegate(*this, FUNC(bml3bus_rtc_device::bml3_rtc_r)), write8sm_delegate(*this, FUNC(bml3bus_rtc_device::bml3_rtc_w)));
+}
diff --git a/src/devices/bus/bml3/bml3rtc.h b/src/devices/bus/bml3/bml3rtc.h
index 16c6cbd0e9c..155bce0904c 100644
--- a/src/devices/bus/bml3/bml3rtc.h
+++ b/src/devices/bus/bml3/bml3rtc.h
@@ -39,6 +39,8 @@ protected:
// optional information overrides
virtual void device_add_mconfig(machine_config &config) override;
+ virtual void map_io(address_space_installer &space) override;
+
private:
required_device<msm5832_device> m_rtc;
diff --git a/src/devices/bus/c64/4dxh.h b/src/devices/bus/c64/4dxh.h
index 620228e4942..0e39bf15f08 100644
--- a/src/devices/bus/c64/4dxh.h
+++ b/src/devices/bus/c64/4dxh.h
@@ -32,8 +32,8 @@ public:
virtual ioport_constructor device_input_ports() const override;
// device_pet_user_port_interface overrides
- virtual WRITE_LINE_MEMBER( input_4 ) override { output_6(state); }
- virtual WRITE_LINE_MEMBER( input_6 ) override { output_4(state); }
+ virtual void input_4(int state) override { output_6(state); }
+ virtual void input_6(int state) override { output_4(state); }
protected:
// device-level overrides
diff --git a/src/devices/bus/c64/4ksa.h b/src/devices/bus/c64/4ksa.h
index 6208ab201d2..1951b6d90c4 100644
--- a/src/devices/bus/c64/4ksa.h
+++ b/src/devices/bus/c64/4ksa.h
@@ -32,8 +32,8 @@ public:
virtual ioport_constructor device_input_ports() const override;
// device_pet_user_port_interface overrides
- virtual WRITE_LINE_MEMBER( input_4 ) override { output_6(state); }
- virtual WRITE_LINE_MEMBER( input_6 ) override { output_4(state); }
+ virtual void input_4(int state) override { output_6(state); }
+ virtual void input_6(int state) override { output_4(state); }
protected:
// device-level overrides
diff --git a/src/devices/bus/c64/4tba.h b/src/devices/bus/c64/4tba.h
index dc4f3b2186c..699edc5b77f 100644
--- a/src/devices/bus/c64/4tba.h
+++ b/src/devices/bus/c64/4tba.h
@@ -32,8 +32,8 @@ public:
virtual ioport_constructor device_input_ports() const override;
// device_pet_user_port_interface overrides
- virtual WRITE_LINE_MEMBER( input_4 ) override { output_6(state); }
- virtual WRITE_LINE_MEMBER( input_6 ) override { output_4(state); }
+ virtual void input_4(int state) override { output_6(state); }
+ virtual void input_6(int state) override { output_4(state); }
protected:
// device-level overrides
diff --git a/src/devices/bus/c64/bn1541.cpp b/src/devices/bus/c64/bn1541.cpp
index ffdf84b77d1..ec89d07edb4 100644
--- a/src/devices/bus/c64/bn1541.cpp
+++ b/src/devices/bus/c64/bn1541.cpp
@@ -140,7 +140,7 @@ void c64_bn1541_device::update_output()
// input_8 - CIA2 PC write
//-------------------------------------------------
-WRITE_LINE_MEMBER(c64_bn1541_device::input_8)
+void c64_bn1541_device::input_8(int state)
{
if (LOG) logerror("C64 parallel strobe %u\n", state);
diff --git a/src/devices/bus/c64/bn1541.h b/src/devices/bus/c64/bn1541.h
index af6fedd7c97..f98f0a96684 100644
--- a/src/devices/bus/c64/bn1541.h
+++ b/src/devices/bus/c64/bn1541.h
@@ -58,15 +58,15 @@ protected:
virtual void parallel_strobe_w(int state) override;
// device_pet_user_port_interface overrides
- virtual DECLARE_WRITE_LINE_MEMBER(input_8) override;
- virtual WRITE_LINE_MEMBER(input_c) override { if (state) m_parallel_output |= 1; else m_parallel_output &= ~1; update_output(); }
- virtual WRITE_LINE_MEMBER(input_d) override { if (state) m_parallel_output |= 2; else m_parallel_output &= ~2; update_output(); }
- virtual WRITE_LINE_MEMBER(input_e) override { if (state) m_parallel_output |= 4; else m_parallel_output &= ~4; update_output(); }
- virtual WRITE_LINE_MEMBER(input_f) override { if (state) m_parallel_output |= 8; else m_parallel_output &= ~8; update_output(); }
- virtual WRITE_LINE_MEMBER(input_h) override { if (state) m_parallel_output |= 16; else m_parallel_output &= ~16; update_output(); }
- virtual WRITE_LINE_MEMBER(input_j) override { if (state) m_parallel_output |= 32; else m_parallel_output &= ~32; update_output(); }
- virtual WRITE_LINE_MEMBER(input_k) override { if (state) m_parallel_output |= 64; else m_parallel_output &= ~64; update_output(); }
- virtual WRITE_LINE_MEMBER(input_l) override { if (state) m_parallel_output |= 128; else m_parallel_output &= ~128; update_output(); }
+ virtual void input_8(int state) override;
+ virtual void input_c(int state) override { if (state) m_parallel_output |= 1; else m_parallel_output &= ~1; update_output(); }
+ virtual void input_d(int state) override { if (state) m_parallel_output |= 2; else m_parallel_output &= ~2; update_output(); }
+ virtual void input_e(int state) override { if (state) m_parallel_output |= 4; else m_parallel_output &= ~4; update_output(); }
+ virtual void input_f(int state) override { if (state) m_parallel_output |= 8; else m_parallel_output &= ~8; update_output(); }
+ virtual void input_h(int state) override { if (state) m_parallel_output |= 16; else m_parallel_output &= ~16; update_output(); }
+ virtual void input_j(int state) override { if (state) m_parallel_output |= 32; else m_parallel_output &= ~32; update_output(); }
+ virtual void input_k(int state) override { if (state) m_parallel_output |= 64; else m_parallel_output &= ~64; update_output(); }
+ virtual void input_l(int state) override { if (state) m_parallel_output |= 128; else m_parallel_output &= ~128; update_output(); }
private:
void update_output();
diff --git a/src/devices/bus/c64/buscard.cpp b/src/devices/bus/c64/buscard.cpp
index aef66ef022b..11402ad69ce 100644
--- a/src/devices/bus/c64/buscard.cpp
+++ b/src/devices/bus/c64/buscard.cpp
@@ -210,7 +210,7 @@ void c64_buscard_device::ppi_pc_w(uint8_t data)
// Centronics interface
//-------------------------------------------------
-WRITE_LINE_MEMBER( c64_buscard_device::busy_w )
+void c64_buscard_device::busy_w(int state)
{
m_busy = state;
}
diff --git a/src/devices/bus/c64/buscard.h b/src/devices/bus/c64/buscard.h
index 151598060ad..f51bbb38658 100644
--- a/src/devices/bus/c64/buscard.h
+++ b/src/devices/bus/c64/buscard.h
@@ -71,7 +71,7 @@ private:
void ppi_pb_w(uint8_t data);
uint8_t ppi_pc_r();
void ppi_pc_w(uint8_t data);
- DECLARE_WRITE_LINE_MEMBER( busy_w );
+ void busy_w(int state);
bool pd_pgm1(offs_t offset, int sphi2);
bool pd_pgm234(offs_t offset, int sphi2, int bank);
diff --git a/src/devices/bus/c64/buscard2.cpp b/src/devices/bus/c64/buscard2.cpp
index 65ee3b0ebb8..2546914cacc 100644
--- a/src/devices/bus/c64/buscard2.cpp
+++ b/src/devices/bus/c64/buscard2.cpp
@@ -10,6 +10,42 @@
**********************************************************************/
+/*
+
+PCB Layout
+----------
+
+|------| |-------------|
+| CN1 |-------------| CN2 |
+| |-
+| RIOT SW1 LS245 LS245 |
+| |
+| PIA |CN3
+| |
+| LS164 PROM1 ROM |
+| LS164 PROM2 |
+| LS00 LS00 LS133 |-
+| LS00 LS211 |
+|-------| CN5 |-----------|
+ | CN4 |
+ |--------------|
+
+Notes:
+ All IC's shown.
+
+ RIOT - Rockwell R6532AP
+ PIA - Motorola MC6821P
+ ROM - Fujitsu MBM2764-25 8Kx8 EPROM (no label)
+ PROM1 - Signetics N82S129N 256x4 Bipolar PROM (no label)
+ PROM2 - Signetics N82S129N 256x4 Bipolar PROM (no label)
+ CN1 - 11x2 PCB edge, parallel printer
+ CN2 - 12x2 PCB edge, IEEE-488
+ CN3 - 22x2, cartridge port passthru
+ CN4 - 22x2 PCB edge, cartridge port
+ CN5 - 3 pin PCB header, clip to C64 R44 (_HIRAM)
+
+*/
+
#include "emu.h"
#include "buscard2.h"
@@ -30,7 +66,6 @@ ROM_START( buscard2 )
ROM_REGION( 0x2000, "rom", 0 )
ROM_LOAD( "v2.12.bin", 0x0000, 0x2000, CRC(1c9b2edb) SHA1(04f0a248370281fd42389928e32d11aba597cf01) )
- // dumps coming soon
ROM_REGION( 0x200, "prom", 0 )
ROM_LOAD( "82s129.1", 0x000, 0x100, NO_DUMP )
ROM_LOAD( "82s129.2", 0x100, 0x100, NO_DUMP )
@@ -90,24 +125,14 @@ ioport_constructor c64_buscard2_device::device_input_ports() const
//-------------------------------------------------
-// Centronics interface
-//-------------------------------------------------
-
-WRITE_LINE_MEMBER( c64_buscard2_device::busy_w )
-{
- m_busy = state;
-}
-
-
-//-------------------------------------------------
// device_add_mconfig - add device configuration
//-------------------------------------------------
void c64_buscard2_device::device_add_mconfig(machine_config &config)
{
- RIOT6532(config, m_riot, 0);
+ MOS6532(config, m_riot, 0);
- PIA6821(config, m_pia, 0);
+ PIA6821(config, m_pia);
IEEE488(config, m_bus, 0);
ieee488_slot_device::add_cbm_defaults(config, nullptr);
diff --git a/src/devices/bus/c64/buscard2.h b/src/devices/bus/c64/buscard2.h
index e0250f03d03..233cdaf79d8 100644
--- a/src/devices/bus/c64/buscard2.h
+++ b/src/devices/bus/c64/buscard2.h
@@ -15,8 +15,8 @@
#include "bus/c64/exp.h"
#include "bus/centronics/ctronics.h"
#include "bus/ieee488/ieee488.h"
-#include "machine/6532riot.h"
#include "machine/6821pia.h"
+#include "machine/mos6530.h"
@@ -27,7 +27,7 @@
// ======================> c64_buscard2_device
class c64_buscard2_device : public device_t,
- public device_c64_expansion_card_interface
+ public device_c64_expansion_card_interface
{
public:
// construction/destruction
@@ -50,7 +50,7 @@ protected:
virtual int c64_exrom_r(offs_t offset, int sphi2, int ba, int rw) override;
private:
- required_device<riot6532_device> m_riot;
+ required_device<mos6532_device> m_riot;
required_device<pia6821_device> m_pia;
required_device<ieee488_device> m_bus;
required_device<centronics_device> m_centronics;
@@ -61,7 +61,7 @@ private:
bool m_busy;
- DECLARE_WRITE_LINE_MEMBER( busy_w );
+ void busy_w(int state) { m_busy = state; }
};
diff --git a/src/devices/bus/c64/c128_partner.cpp b/src/devices/bus/c64/c128_partner.cpp
index 7c6cf1aea97..1c53ed4036d 100644
--- a/src/devices/bus/c64/c128_partner.cpp
+++ b/src/devices/bus/c64/c128_partner.cpp
@@ -44,7 +44,7 @@ DEFINE_DEVICE_TYPE(C128_PARTNER, c128_partner_cartridge_device, "c128_partner",
// INPUT_PORTS( c128_partner )
//-------------------------------------------------
-WRITE_LINE_MEMBER( c128_partner_cartridge_device::nmi_w )
+void c128_partner_cartridge_device::nmi_w(int state)
{
if (state)
{
diff --git a/src/devices/bus/c64/c128_partner.h b/src/devices/bus/c64/c128_partner.h
index 3f91afbb0e9..faf8a2a8b11 100644
--- a/src/devices/bus/c64/c128_partner.h
+++ b/src/devices/bus/c64/c128_partner.h
@@ -33,7 +33,7 @@ public:
// optional information overrides
virtual ioport_constructor device_input_ports() const override;
- DECLARE_WRITE_LINE_MEMBER( nmi_w );
+ void nmi_w(int state);
protected:
// device-level overrides
diff --git a/src/devices/bus/c64/dqbb.cpp b/src/devices/bus/c64/dqbb.cpp
index e08bfbd05b5..e4d50057537 100644
--- a/src/devices/bus/c64/dqbb.cpp
+++ b/src/devices/bus/c64/dqbb.cpp
@@ -75,6 +75,25 @@ void c64_dqbb_cartridge_device::device_reset()
}
+void c64_dqbb_cartridge_device::nvram_default()
+{
+}
+
+
+bool c64_dqbb_cartridge_device::nvram_read(util::read_stream &file)
+{
+ auto const [err, actual] = read(file, m_nvram.get(), 0x4000);
+ return !err && (actual == 0x4000);
+}
+
+
+bool c64_dqbb_cartridge_device::nvram_write(util::write_stream &file)
+{
+ auto const [err, actual] = write(file, m_nvram.get(), 0x4000);
+ return !err;
+}
+
+
//-------------------------------------------------
// c64_cd_r - cartridge data read
//-------------------------------------------------
diff --git a/src/devices/bus/c64/dqbb.h b/src/devices/bus/c64/dqbb.h
index 9770793bdd0..35a18f7e344 100644
--- a/src/devices/bus/c64/dqbb.h
+++ b/src/devices/bus/c64/dqbb.h
@@ -31,16 +31,16 @@ public:
c64_dqbb_cartridge_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
virtual void device_reset() override;
- // device_nvram_interface overrides
- virtual void nvram_default() override { }
- virtual bool nvram_read(util::read_stream &file) override { size_t actual; return !file.read(m_nvram.get(), 0x4000, actual) && actual == 0x4000; }
- virtual bool nvram_write(util::write_stream &file) override { size_t actual; return !file.write(m_nvram.get(), 0x4000, actual) && actual == 0x4000; }
+ // device_nvram_interface implementation
+ virtual void nvram_default() override;
+ virtual bool nvram_read(util::read_stream &file) override;
+ virtual bool nvram_write(util::write_stream &file) override;
- // device_c64_expansion_card_interface overrides
+ // device_c64_expansion_card_interface implementation
virtual uint8_t c64_cd_r(offs_t offset, uint8_t data, int sphi2, int ba, int roml, int romh, int io1, int io2) override;
virtual void c64_cd_w(offs_t offset, uint8_t data, int sphi2, int ba, int roml, int romh, int io1, int io2) override;
diff --git a/src/devices/bus/c64/exp.cpp b/src/devices/bus/c64/exp.cpp
index 72d66ce6f30..7a53fadbf14 100644
--- a/src/devices/bus/c64/exp.cpp
+++ b/src/devices/bus/c64/exp.cpp
@@ -9,6 +9,10 @@
#include "emu.h"
#include "exp.h"
+#include "formats/cbm_crt.h"
+
+#include <tuple>
+
//**************************************************************************
@@ -60,7 +64,7 @@ c64_expansion_slot_device::c64_expansion_slot_device(const machine_config &mconf
device_t(mconfig, C64_EXPANSION_SLOT, tag, owner, clock),
device_single_card_slot_interface<device_c64_expansion_card_interface>(mconfig, *this),
device_cartrom_image_interface(mconfig, *this),
- m_read_dma_cd(*this),
+ m_read_dma_cd(*this, 0),
m_write_dma_cd(*this),
m_write_irq(*this),
m_write_nmi(*this),
@@ -77,14 +81,6 @@ c64_expansion_slot_device::c64_expansion_slot_device(const machine_config &mconf
void c64_expansion_slot_device::device_start()
{
m_card = get_card_device();
-
- // resolve callbacks
- m_read_dma_cd.resolve_safe(0);
- m_write_dma_cd.resolve_safe();
- m_write_irq.resolve_safe();
- m_write_nmi.resolve_safe();
- m_write_dma.resolve_safe();
- m_write_reset.resolve_safe();
}
@@ -101,8 +97,10 @@ void c64_expansion_slot_device::device_reset()
// call_load -
//-------------------------------------------------
-image_init_result c64_expansion_slot_device::call_load()
+std::pair<std::error_condition, std::string> c64_expansion_slot_device::call_load()
{
+ std::error_condition err;
+
if (m_card)
{
m_card->m_roml_size = 0;
@@ -114,11 +112,16 @@ image_init_result c64_expansion_slot_device::call_load()
if (!loaded_through_softlist())
{
+ util::core_file &file = image_core_file();
size = length();
if (is_filetype("80"))
{
- fread(m_card->m_roml, size);
+ std::size_t actual;
+ std::tie(err, m_card->m_roml, actual) = read(file, size);
+ if (!err && (actual != size))
+ err = std::errc::io_error;
+
m_card->m_roml_size = size;
m_card->m_exrom = 0;
@@ -129,7 +132,11 @@ image_init_result c64_expansion_slot_device::call_load()
}
else if (is_filetype("a0"))
{
- fread(m_card->m_romh, 0x2000);
+ std::size_t actual;
+ std::tie(err, m_card->m_roml, actual) = read(file, 0x2000);
+ if (!err && (actual != 0x2000))
+ err = std::errc::io_error;
+
m_card->m_romh_size = 0x2000;
m_card->m_exrom = 0;
@@ -137,14 +144,18 @@ image_init_result c64_expansion_slot_device::call_load()
}
else if (is_filetype("e0"))
{
- fread(m_card->m_romh, 0x2000);
+ std::size_t actual;
+ std::tie(err, m_card->m_roml, actual) = read(file, 0x2000);
+ if (!err && (actual != 0x2000))
+ err = std::errc::io_error;
+
m_card->m_romh_size = 0x2000;
m_card->m_game = 0;
}
else if (is_filetype("crt"))
{
- if (cbm_crt_read_header(image_core_file(), &m_card->m_roml_size, &m_card->m_romh_size, &m_card->m_exrom, &m_card->m_game))
+ if (cbm_crt_read_header(file, &m_card->m_roml_size, &m_card->m_romh_size, &m_card->m_exrom, &m_card->m_game))
{
uint8_t *roml = nullptr;
uint8_t *romh = nullptr;
@@ -155,9 +166,13 @@ image_init_result c64_expansion_slot_device::call_load()
if (m_card->m_roml_size) roml = m_card->m_roml.get();
if (m_card->m_romh_size) romh = m_card->m_romh.get();
- cbm_crt_read_data(image_core_file(), roml, romh);
+ cbm_crt_read_data(file, roml, romh);
}
}
+ else
+ {
+ err = image_error::INVALIDIMAGE;
+ }
}
else
{
@@ -190,13 +205,10 @@ image_init_result c64_expansion_slot_device::call_load()
}
if ((m_card->m_roml_size & (m_card->m_roml_size - 1)) || (m_card->m_romh_size & (m_card->m_romh_size - 1)))
- {
- seterror(image_error::INVALIDIMAGE, "ROM size must be power of 2");
- return image_init_result::FAIL;
- }
+ return std::make_pair(image_error::INVALIDLENGTH, "ROM size must be power of 2");
}
- return image_init_result::PASS;
+ return std::make_pair(err, std::string());
}
@@ -360,6 +372,7 @@ void c64_expansion_slot_device::set_passthrough()
#include "sw8k.h"
#include "swiftlink.h"
#include "system3.h"
+#include "tibdd001.h"
#include "tdos.h"
#include "turbo232.h"
#include "vizastar.h"
@@ -392,6 +405,7 @@ void c64_expansion_cards(device_slot_interface &device)
device.option_add("speakez", C64_SPEAKEASY);
device.option_add("supercpu", C64_SUPERCPU);
device.option_add("swiftlink", C64_SWIFTLINK);
+ device.option_add("tibdd001", C64_TIB_DD_001);
device.option_add("turbo232", C64_TURBO232);
device.option_add("buscard", C64_BUSCARD);
device.option_add("buscard2", C64_BUSCARD2);
diff --git a/src/devices/bus/c64/exp.h b/src/devices/bus/c64/exp.h
index d5861b0c4a3..68974431d56 100644
--- a/src/devices/bus/c64/exp.h
+++ b/src/devices/bus/c64/exp.h
@@ -37,7 +37,6 @@
#pragma once
#include "imagedev/cartrom.h"
-#include "formats/cbm_crt.h"
@@ -83,10 +82,10 @@ public:
// cartridge interface
uint8_t dma_cd_r(offs_t offset) { return m_read_dma_cd(offset); }
void dma_cd_w(offs_t offset, uint8_t data) { m_write_dma_cd(offset, data); }
- DECLARE_WRITE_LINE_MEMBER( irq_w ) { m_write_irq(state); }
- DECLARE_WRITE_LINE_MEMBER( nmi_w ) { m_write_nmi(state); }
- DECLARE_WRITE_LINE_MEMBER( dma_w ) { m_write_dma(state); }
- DECLARE_WRITE_LINE_MEMBER( reset_w ) { m_write_reset(state); }
+ void irq_w(int state) { m_write_irq(state); }
+ void nmi_w(int state) { m_write_nmi(state); }
+ void dma_w(int state) { m_write_dma(state); }
+ void reset_w(int state) { m_write_reset(state); }
int phi2() { return clock(); }
int dotclock() { return phi2() * 8; }
int hiram() { return m_hiram; }
@@ -95,18 +94,18 @@ public:
void set_passthrough();
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
virtual void device_reset() override;
- // image-level overrides
- virtual image_init_result call_load() override;
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
virtual bool is_reset_on_load() const noexcept override { return true; }
virtual const char *image_interface() const noexcept override { return "c64_cart,vic10_cart"; }
virtual const char *file_extensions() const noexcept override { return "80,a0,e0,crt"; }
- // slot interface overrides
+ // device_slot_interface implementation
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
devcb_read8 m_read_dma_cd;
diff --git a/src/devices/bus/c64/fcc.cpp b/src/devices/bus/c64/fcc.cpp
index 07ff8840e3a..879f69899ba 100644
--- a/src/devices/bus/c64/fcc.cpp
+++ b/src/devices/bus/c64/fcc.cpp
@@ -123,6 +123,25 @@ void c64_final_chesscard_device::device_reset()
}
+void c64_final_chesscard_device::nvram_default()
+{
+}
+
+
+bool c64_final_chesscard_device::nvram_read(util::read_stream &file)
+{
+ auto const [err, actual] = read(file, m_nvram.get(), 0x2000);
+ return !err && (actual == 0x2000);
+}
+
+
+bool c64_final_chesscard_device::nvram_write(util::write_stream &file)
+{
+ auto const [err, actual] = write(file, m_nvram.get(), 0x2000);
+ return !err;
+}
+
+
//-------------------------------------------------
// c64_cd_r - cartridge data read
//-------------------------------------------------
diff --git a/src/devices/bus/c64/fcc.h b/src/devices/bus/c64/fcc.h
index 33baea0707c..90d3ba5556a 100644
--- a/src/devices/bus/c64/fcc.h
+++ b/src/devices/bus/c64/fcc.h
@@ -32,20 +32,18 @@ public:
c64_final_chesscard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
-
- // optional information overrides
+ // device_t implementation
virtual void device_add_mconfig(machine_config &config) override;
virtual ioport_constructor device_input_ports() const override;
+ virtual void device_start() override;
+ virtual void device_reset() override;
- // device_nvram_interface overrides
- virtual void nvram_default() override { }
- virtual bool nvram_read(util::read_stream &file) override { size_t actual; return !file.read(m_nvram.get(), 0x2000, actual) && actual == 0x2000; }
- virtual bool nvram_write(util::write_stream &file) override { size_t actual; return !file.write(m_nvram.get(), 0x2000, actual) && actual == 0x2000; }
+ // device_nvram_interface implementation
+ virtual void nvram_default() override;
+ virtual bool nvram_read(util::read_stream &file) override;
+ virtual bool nvram_write(util::write_stream &file) override;
- // device_c64_expansion_card_interface overrides
+ // device_c64_expansion_card_interface implementation
virtual uint8_t c64_cd_r(offs_t offset, uint8_t data, int sphi2, int ba, int roml, int romh, int io1, int io2) override;
virtual void c64_cd_w(offs_t offset, uint8_t data, int sphi2, int ba, int roml, int romh, int io1, int io2) override;
@@ -57,8 +55,8 @@ private:
uint8_t m_bank;
int m_hidden;
- DECLARE_WRITE_LINE_MEMBER(mainlatch_int) { m_slot->nmi_w(state); }
- uint8_t rom_r(offs_t offset) { return m_romx[offset]; } // cartridge cpu rom
+ void mainlatch_int(int state) { m_slot->nmi_w(state); }
+ uint8_t rom_r(offs_t offset) { return m_romx[offset]; } // cartridge CPU ROM
uint8_t nvram_r(offs_t offset) { return m_nvram[offset & 0x1fff]; }
void nvram_w(offs_t offset, uint8_t data) { m_nvram[offset & 0x1fff] = data; }
diff --git a/src/devices/bus/c64/geocable.h b/src/devices/bus/c64/geocable.h
index 587a94ad80c..d4a9d543ea6 100644
--- a/src/devices/bus/c64/geocable.h
+++ b/src/devices/bus/c64/geocable.h
@@ -37,15 +37,15 @@ protected:
virtual void device_add_mconfig(machine_config &config) override;
// device_pet_user_port_interface overrides
- virtual DECLARE_WRITE_LINE_MEMBER(input_c) override { m_centronics->write_data0(state); }
- virtual DECLARE_WRITE_LINE_MEMBER(input_d) override { m_centronics->write_data1(state); }
- virtual DECLARE_WRITE_LINE_MEMBER(input_e) override { m_centronics->write_data2(state); }
- virtual DECLARE_WRITE_LINE_MEMBER(input_f) override { m_centronics->write_data3(state); }
- virtual DECLARE_WRITE_LINE_MEMBER(input_h) override { m_centronics->write_data4(state); }
- virtual DECLARE_WRITE_LINE_MEMBER(input_j) override { m_centronics->write_data5(state); }
- virtual DECLARE_WRITE_LINE_MEMBER(input_k) override { m_centronics->write_data6(state); }
- virtual DECLARE_WRITE_LINE_MEMBER(input_l) override { m_centronics->write_data7(state); }
- virtual DECLARE_WRITE_LINE_MEMBER(input_m) override { m_centronics->write_strobe(state); }
+ virtual void input_c(int state) override { m_centronics->write_data0(state); }
+ virtual void input_d(int state) override { m_centronics->write_data1(state); }
+ virtual void input_e(int state) override { m_centronics->write_data2(state); }
+ virtual void input_f(int state) override { m_centronics->write_data3(state); }
+ virtual void input_h(int state) override { m_centronics->write_data4(state); }
+ virtual void input_j(int state) override { m_centronics->write_data5(state); }
+ virtual void input_k(int state) override { m_centronics->write_data6(state); }
+ virtual void input_l(int state) override { m_centronics->write_data7(state); }
+ virtual void input_m(int state) override { m_centronics->write_strobe(state); }
private:
required_device<centronics_device> m_centronics;
diff --git a/src/devices/bus/c64/magic_formel.cpp b/src/devices/bus/c64/magic_formel.cpp
index 1e6c38d1685..87be010f13e 100644
--- a/src/devices/bus/c64/magic_formel.cpp
+++ b/src/devices/bus/c64/magic_formel.cpp
@@ -83,7 +83,7 @@ void c64_magic_formel_cartridge_device::pia_pb_w(uint8_t data)
m_pb7 = BIT(data, 7);
}
-WRITE_LINE_MEMBER( c64_magic_formel_cartridge_device::pia_cb2_w )
+void c64_magic_formel_cartridge_device::pia_cb2_w(int state)
{
if (!state)
{
@@ -98,7 +98,7 @@ WRITE_LINE_MEMBER( c64_magic_formel_cartridge_device::pia_cb2_w )
void c64_magic_formel_cartridge_device::device_add_mconfig(machine_config &config)
{
- PIA6821(config, m_pia, 0);
+ PIA6821(config, m_pia);
m_pia->writepa_handler().set(FUNC(c64_magic_formel_cartridge_device::pia_pa_w));
m_pia->writepb_handler().set(FUNC(c64_magic_formel_cartridge_device::pia_pb_w));
m_pia->cb2_handler().set(FUNC(c64_magic_formel_cartridge_device::pia_cb2_w));
diff --git a/src/devices/bus/c64/magic_formel.h b/src/devices/bus/c64/magic_formel.h
index ab16d4a0e34..15123d6b453 100644
--- a/src/devices/bus/c64/magic_formel.h
+++ b/src/devices/bus/c64/magic_formel.h
@@ -48,7 +48,7 @@ protected:
private:
void pia_pa_w(uint8_t data);
void pia_pb_w(uint8_t data);
- DECLARE_WRITE_LINE_MEMBER( pia_cb2_w );
+ void pia_cb2_w(int state);
required_device<pia6821_device> m_pia;
memory_share_creator<uint8_t> m_ram;
diff --git a/src/devices/bus/c64/magic_voice.cpp b/src/devices/bus/c64/magic_voice.cpp
index faac3bc0a33..b9e0949ed3d 100644
--- a/src/devices/bus/c64/magic_voice.cpp
+++ b/src/devices/bus/c64/magic_voice.cpp
@@ -73,7 +73,7 @@ DEFINE_DEVICE_TYPE(C64_MAGIC_VOICE, c64_magic_voice_cartridge_device, "c64_magic
// tpi6525_interface tpi_intf
//-------------------------------------------------
-WRITE_LINE_MEMBER( c64_magic_voice_cartridge_device::tpi_irq_w )
+void c64_magic_voice_cartridge_device::tpi_irq_w(int state)
{
m_slot->nmi_w(state);
}
@@ -174,12 +174,12 @@ void c64_magic_voice_cartridge_device::tpi_pb_w(uint8_t data)
m_tpi_pb = data;
}
-WRITE_LINE_MEMBER( c64_magic_voice_cartridge_device::tpi_ca_w )
+void c64_magic_voice_cartridge_device::tpi_ca_w(int state)
{
m_tpi_pc6 = state;
}
-WRITE_LINE_MEMBER( c64_magic_voice_cartridge_device::tpi_cb_w )
+void c64_magic_voice_cartridge_device::tpi_cb_w(int state)
{
m_exrom = state;
}
@@ -188,7 +188,7 @@ WRITE_LINE_MEMBER( c64_magic_voice_cartridge_device::tpi_cb_w )
// t6721_interface
//-------------------------------------------------
-WRITE_LINE_MEMBER( c64_magic_voice_cartridge_device::phi2_w )
+void c64_magic_voice_cartridge_device::phi2_w(int state)
{
if (state)
{
@@ -198,14 +198,14 @@ WRITE_LINE_MEMBER( c64_magic_voice_cartridge_device::phi2_w )
}
}
-WRITE_LINE_MEMBER( c64_magic_voice_cartridge_device::dtrd_w )
+void c64_magic_voice_cartridge_device::dtrd_w(int state)
{
m_fifo->so_w(!state);
m_pd = m_fifo->read();
}
-WRITE_LINE_MEMBER( c64_magic_voice_cartridge_device::apd_w )
+void c64_magic_voice_cartridge_device::apd_w(int state)
{
if (state)
{
diff --git a/src/devices/bus/c64/magic_voice.h b/src/devices/bus/c64/magic_voice.h
index f6c4a4d138e..ac489f45f7c 100644
--- a/src/devices/bus/c64/magic_voice.h
+++ b/src/devices/bus/c64/magic_voice.h
@@ -47,17 +47,17 @@ protected:
private:
offs_t get_offset(offs_t offset);
- DECLARE_WRITE_LINE_MEMBER( tpi_irq_w );
+ void tpi_irq_w(int state);
uint8_t tpi_pa_r();
void tpi_pa_w(uint8_t data);
uint8_t tpi_pb_r();
void tpi_pb_w(uint8_t data);
- DECLARE_WRITE_LINE_MEMBER( tpi_ca_w );
- DECLARE_WRITE_LINE_MEMBER( tpi_cb_w );
+ void tpi_ca_w(int state);
+ void tpi_cb_w(int state);
- DECLARE_WRITE_LINE_MEMBER( phi2_w );
- DECLARE_WRITE_LINE_MEMBER( dtrd_w );
- DECLARE_WRITE_LINE_MEMBER( apd_w );
+ void phi2_w(int state);
+ void dtrd_w(int state);
+ void apd_w(int state);
required_device<t6721a_device> m_vslsi;
required_device<tpi6525_device> m_tpi;
diff --git a/src/devices/bus/c64/midi_maplin.cpp b/src/devices/bus/c64/midi_maplin.cpp
index adc8556a7bd..d276c3f5bb2 100644
--- a/src/devices/bus/c64/midi_maplin.cpp
+++ b/src/devices/bus/c64/midi_maplin.cpp
@@ -28,12 +28,12 @@
DEFINE_DEVICE_TYPE(C64_MIDI_MAPLIN, c64_maplin_midi_cartridge_device, "c64_midimap", "C64 Maplin MIDI")
-WRITE_LINE_MEMBER( c64_maplin_midi_cartridge_device::acia_irq_w )
+void c64_maplin_midi_cartridge_device::acia_irq_w(int state)
{
m_slot->irq_w(state);
}
-WRITE_LINE_MEMBER( c64_maplin_midi_cartridge_device::write_acia_clock )
+void c64_maplin_midi_cartridge_device::write_acia_clock(int state)
{
m_acia->write_txc(state);
m_acia->write_rxc(state);
diff --git a/src/devices/bus/c64/midi_maplin.h b/src/devices/bus/c64/midi_maplin.h
index d0798d9217f..285088a9b46 100644
--- a/src/devices/bus/c64/midi_maplin.h
+++ b/src/devices/bus/c64/midi_maplin.h
@@ -41,8 +41,8 @@ protected:
virtual void c64_cd_w(offs_t offset, uint8_t data, int sphi2, int ba, int roml, int romh, int io1, int io2) override;
private:
- DECLARE_WRITE_LINE_MEMBER( acia_irq_w );
- DECLARE_WRITE_LINE_MEMBER( write_acia_clock );
+ void acia_irq_w(int state);
+ void write_acia_clock(int state);
required_device<acia6850_device> m_acia;
};
diff --git a/src/devices/bus/c64/midi_namesoft.cpp b/src/devices/bus/c64/midi_namesoft.cpp
index d4e7c8b59ac..980b0bd1b0d 100644
--- a/src/devices/bus/c64/midi_namesoft.cpp
+++ b/src/devices/bus/c64/midi_namesoft.cpp
@@ -28,12 +28,12 @@
DEFINE_DEVICE_TYPE(C64_MIDI_NAMESOFT, c64_namesoft_midi_cartridge_device, "c64_midins", "C64 Namesoft MIDI")
-WRITE_LINE_MEMBER( c64_namesoft_midi_cartridge_device::acia_irq_w )
+void c64_namesoft_midi_cartridge_device::acia_irq_w(int state)
{
m_slot->nmi_w(state);
}
-WRITE_LINE_MEMBER( c64_namesoft_midi_cartridge_device::write_acia_clock )
+void c64_namesoft_midi_cartridge_device::write_acia_clock(int state)
{
m_acia->write_txc(state);
m_acia->write_rxc(state);
diff --git a/src/devices/bus/c64/midi_namesoft.h b/src/devices/bus/c64/midi_namesoft.h
index d2183d271d0..276afff80b6 100644
--- a/src/devices/bus/c64/midi_namesoft.h
+++ b/src/devices/bus/c64/midi_namesoft.h
@@ -41,8 +41,8 @@ protected:
virtual void c64_cd_w(offs_t offset, uint8_t data, int sphi2, int ba, int roml, int romh, int io1, int io2) override;
private:
- DECLARE_WRITE_LINE_MEMBER( acia_irq_w );
- DECLARE_WRITE_LINE_MEMBER( write_acia_clock );
+ void acia_irq_w(int state);
+ void write_acia_clock(int state);
required_device<acia6850_device> m_acia;
};
diff --git a/src/devices/bus/c64/midi_passport.cpp b/src/devices/bus/c64/midi_passport.cpp
index 05a3fbb1a36..81a5edbf59c 100644
--- a/src/devices/bus/c64/midi_passport.cpp
+++ b/src/devices/bus/c64/midi_passport.cpp
@@ -33,21 +33,21 @@ DEFINE_DEVICE_TYPE(C64_MIDI_PASSPORT, c64_passport_midi_cartridge_device, "c64_m
// ptm6840_interface ptm_intf
//-------------------------------------------------
-WRITE_LINE_MEMBER( c64_passport_midi_cartridge_device::ptm_irq_w )
+void c64_passport_midi_cartridge_device::ptm_irq_w(int state)
{
m_ptm_irq = state;
m_slot->irq_w(m_ptm_irq || m_acia_irq);
}
-WRITE_LINE_MEMBER( c64_passport_midi_cartridge_device::acia_irq_w )
+void c64_passport_midi_cartridge_device::acia_irq_w(int state)
{
m_acia_irq = state;
m_slot->irq_w(m_ptm_irq || m_acia_irq);
}
-WRITE_LINE_MEMBER( c64_passport_midi_cartridge_device::write_acia_clock )
+void c64_passport_midi_cartridge_device::write_acia_clock(int state)
{
m_acia->write_txc(state);
m_acia->write_rxc(state);
diff --git a/src/devices/bus/c64/midi_passport.h b/src/devices/bus/c64/midi_passport.h
index d6b4cf16eb7..42bf7a3d90a 100644
--- a/src/devices/bus/c64/midi_passport.h
+++ b/src/devices/bus/c64/midi_passport.h
@@ -42,9 +42,9 @@ protected:
virtual void c64_cd_w(offs_t offset, uint8_t data, int sphi2, int ba, int roml, int romh, int io1, int io2) override;
private:
- DECLARE_WRITE_LINE_MEMBER( ptm_irq_w );
- DECLARE_WRITE_LINE_MEMBER( acia_irq_w );
- DECLARE_WRITE_LINE_MEMBER( write_acia_clock );
+ void ptm_irq_w(int state);
+ void acia_irq_w(int state);
+ void write_acia_clock(int state);
required_device<acia6850_device> m_acia;
required_device<ptm6840_device> m_ptm;
diff --git a/src/devices/bus/c64/midi_sci.cpp b/src/devices/bus/c64/midi_sci.cpp
index 14309ee5e7c..d6d4c92c7fa 100644
--- a/src/devices/bus/c64/midi_sci.cpp
+++ b/src/devices/bus/c64/midi_sci.cpp
@@ -28,12 +28,12 @@
DEFINE_DEVICE_TYPE(C64_MIDI_SCI, c64_sequential_midi_cartridge_device, "c64_midisci", "C64 Sequential Circuits MIDI")
-WRITE_LINE_MEMBER( c64_sequential_midi_cartridge_device::acia_irq_w )
+void c64_sequential_midi_cartridge_device::acia_irq_w(int state)
{
m_slot->irq_w(state);
}
-WRITE_LINE_MEMBER( c64_sequential_midi_cartridge_device::write_acia_clock )
+void c64_sequential_midi_cartridge_device::write_acia_clock(int state)
{
m_acia->write_txc(state);
m_acia->write_rxc(state);
diff --git a/src/devices/bus/c64/midi_sci.h b/src/devices/bus/c64/midi_sci.h
index 5ab0d8d45db..d455b53e5d4 100644
--- a/src/devices/bus/c64/midi_sci.h
+++ b/src/devices/bus/c64/midi_sci.h
@@ -41,8 +41,8 @@ protected:
virtual void c64_cd_w(offs_t offset, uint8_t data, int sphi2, int ba, int roml, int romh, int io1, int io2) override;
private:
- DECLARE_WRITE_LINE_MEMBER( acia_irq_w );
- DECLARE_WRITE_LINE_MEMBER( write_acia_clock );
+ void acia_irq_w(int state);
+ void write_acia_clock(int state);
required_device<acia6850_device> m_acia;
};
diff --git a/src/devices/bus/c64/midi_siel.cpp b/src/devices/bus/c64/midi_siel.cpp
index eea7a4b333d..343eff94f69 100644
--- a/src/devices/bus/c64/midi_siel.cpp
+++ b/src/devices/bus/c64/midi_siel.cpp
@@ -28,12 +28,12 @@
DEFINE_DEVICE_TYPE(C64_MIDI_SIEL, c64_siel_midi_cartridge_device, "c64_midisiel", "C64 Siel MIDI")
-WRITE_LINE_MEMBER( c64_siel_midi_cartridge_device::acia_irq_w )
+void c64_siel_midi_cartridge_device::acia_irq_w(int state)
{
m_slot->irq_w(state);
}
-WRITE_LINE_MEMBER( c64_siel_midi_cartridge_device::write_acia_clock )
+void c64_siel_midi_cartridge_device::write_acia_clock(int state)
{
m_acia->write_txc(state);
m_acia->write_rxc(state);
diff --git a/src/devices/bus/c64/midi_siel.h b/src/devices/bus/c64/midi_siel.h
index 412d1a224b7..32e77b1f997 100644
--- a/src/devices/bus/c64/midi_siel.h
+++ b/src/devices/bus/c64/midi_siel.h
@@ -41,8 +41,8 @@ protected:
virtual void c64_cd_w(offs_t offset, uint8_t data, int sphi2, int ba, int roml, int romh, int io1, int io2) override;
private:
- DECLARE_WRITE_LINE_MEMBER( acia_irq_w );
- DECLARE_WRITE_LINE_MEMBER( write_acia_clock );
+ void acia_irq_w(int state);
+ void write_acia_clock(int state);
required_device<acia6850_device> m_acia;
};
diff --git a/src/devices/bus/c64/multiscreen.cpp b/src/devices/bus/c64/multiscreen.cpp
index 890c1a35799..f7b9b3a33d6 100644
--- a/src/devices/bus/c64/multiscreen.cpp
+++ b/src/devices/bus/c64/multiscreen.cpp
@@ -117,8 +117,8 @@ void c64_multiscreen_cartridge_device::device_add_mconfig(machine_config &config
m6802_cpu_device &cpu(M6802(config, MC6802P_TAG, XTAL(4'000'000)));
cpu.set_addrmap(AS_PROGRAM, &c64_multiscreen_cartridge_device::multiscreen_mem);
- PIA6821(config, MC6821P_0_TAG, 0);
- PIA6821(config, MC6821P_1_TAG, 0);
+ PIA6821(config, MC6821P_0_TAG);
+ PIA6821(config, MC6821P_1_TAG);
}
diff --git a/src/devices/bus/c64/neoram.cpp b/src/devices/bus/c64/neoram.cpp
index c0f292da161..e10ccac39b5 100644
--- a/src/devices/bus/c64/neoram.cpp
+++ b/src/devices/bus/c64/neoram.cpp
@@ -76,6 +76,25 @@ uint8_t c64_neoram_cartridge_device::c64_cd_r(offs_t offset, uint8_t data, int s
}
+void c64_neoram_cartridge_device::nvram_default()
+{
+}
+
+
+bool c64_neoram_cartridge_device::nvram_read(util::read_stream &file)
+{
+ auto const [err, actual] = read(file, m_nvram.get(), 0x200000);
+ return !err && (actual == 0x200000);
+}
+
+
+bool c64_neoram_cartridge_device::nvram_write(util::write_stream &file)
+{
+ auto const [err, actual] = write(file, m_nvram.get(), 0x200000);
+ return !err;
+}
+
+
//-------------------------------------------------
// c64_cd_w - cartridge data write
//-------------------------------------------------
diff --git a/src/devices/bus/c64/neoram.h b/src/devices/bus/c64/neoram.h
index d54e8e18cc4..1a374440c45 100644
--- a/src/devices/bus/c64/neoram.h
+++ b/src/devices/bus/c64/neoram.h
@@ -31,16 +31,16 @@ public:
c64_neoram_cartridge_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
virtual void device_reset() override;
- // device_nvram_interface overrides
- virtual void nvram_default() override { }
- virtual bool nvram_read(util::read_stream &file) override { size_t actual; return !file.read(m_nvram.get(), 0x200000, actual) && actual == 0x200000; }
- virtual bool nvram_write(util::write_stream &file) override { size_t actual; return !file.write(m_nvram.get(), 0x200000, actual) && actual == 0x200000; }
+ // device_nvram_interface implementation
+ virtual void nvram_default() override;
+ virtual bool nvram_read(util::read_stream &file) override;
+ virtual bool nvram_write(util::write_stream &file) override;
- // device_c64_expansion_card_interface overrides
+ // device_c64_expansion_card_interface implementation
virtual uint8_t c64_cd_r(offs_t offset, uint8_t data, int sphi2, int ba, int roml, int romh, int io1, int io2) override;
virtual void c64_cd_w(offs_t offset, uint8_t data, int sphi2, int ba, int roml, int romh, int io1, int io2) override;
diff --git a/src/devices/bus/c64/partner.cpp b/src/devices/bus/c64/partner.cpp
index b77cf610d17..631a7a1c370 100644
--- a/src/devices/bus/c64/partner.cpp
+++ b/src/devices/bus/c64/partner.cpp
@@ -43,7 +43,7 @@ DEFINE_DEVICE_TYPE(C64_PARTNER, c64_partner_cartridge_device, "c64_partner", "C6
// INPUT_PORTS( c64_partner )
//-------------------------------------------------
-WRITE_LINE_MEMBER( c64_partner_cartridge_device::nmi_w )
+void c64_partner_cartridge_device::nmi_w(int state)
{
if (!state && !m_a6 && !m_nmi)
{
diff --git a/src/devices/bus/c64/partner.h b/src/devices/bus/c64/partner.h
index 4dd71542571..e28274a34bd 100644
--- a/src/devices/bus/c64/partner.h
+++ b/src/devices/bus/c64/partner.h
@@ -31,7 +31,7 @@ public:
// optional information overrides
virtual ioport_constructor device_input_ports() const override;
- DECLARE_WRITE_LINE_MEMBER( nmi_w );
+ void nmi_w(int state);
protected:
// device-level overrides
diff --git a/src/devices/bus/c64/sfx_sound_expander.cpp b/src/devices/bus/c64/sfx_sound_expander.cpp
index a85b93bccbf..99d5922e9c2 100644
--- a/src/devices/bus/c64/sfx_sound_expander.cpp
+++ b/src/devices/bus/c64/sfx_sound_expander.cpp
@@ -31,7 +31,7 @@ DEFINE_DEVICE_TYPE(C64_SFX_SOUND_EXPANDER, c64_sfx_sound_expander_cartridge_devi
// ym3526_interface ym3526_config
//-------------------------------------------------
-WRITE_LINE_MEMBER( c64_sfx_sound_expander_cartridge_device::opl_irq_w )
+void c64_sfx_sound_expander_cartridge_device::opl_irq_w(int state)
{
m_slot->irq_w(state);
}
diff --git a/src/devices/bus/c64/sfx_sound_expander.h b/src/devices/bus/c64/sfx_sound_expander.h
index 52e006ce686..8b0a454fdc8 100644
--- a/src/devices/bus/c64/sfx_sound_expander.h
+++ b/src/devices/bus/c64/sfx_sound_expander.h
@@ -45,7 +45,7 @@ protected:
virtual int c64_exrom_r(offs_t offset, int sphi2, int ba, int rw) override;
private:
- DECLARE_WRITE_LINE_MEMBER( opl_irq_w );
+ void opl_irq_w(int state);
required_device<ym3526_device> m_opl;
required_device<c64_expansion_slot_device> m_exp;
diff --git a/src/devices/bus/c64/speakeasy.cpp b/src/devices/bus/c64/speakeasy.cpp
index 23caee3488f..b3e8a060d3d 100644
--- a/src/devices/bus/c64/speakeasy.cpp
+++ b/src/devices/bus/c64/speakeasy.cpp
@@ -35,7 +35,7 @@ void c64_speakeasy_cartridge_device::device_add_mconfig(machine_config &config)
{
SPEAKER(config, "mono").front_center();
- VOTRAX_SC01(config, m_votrax, 720000).add_route(ALL_OUTPUTS, "mono", 0.85);
+ VOTRAX_SC01A(config, m_votrax, 720000).add_route(ALL_OUTPUTS, "mono", 0.85);
}
diff --git a/src/devices/bus/c64/swiftlink.cpp b/src/devices/bus/c64/swiftlink.cpp
index 3855da85ca3..f9698e192b6 100644
--- a/src/devices/bus/c64/swiftlink.cpp
+++ b/src/devices/bus/c64/swiftlink.cpp
@@ -156,7 +156,7 @@ void c64_swiftlink_cartridge_device::c64_cd_w(offs_t offset, uint8_t data, int s
// acia_irq_w -
//-------------------------------------------------
-WRITE_LINE_MEMBER( c64_swiftlink_cartridge_device::acia_irq_w )
+void c64_swiftlink_cartridge_device::acia_irq_w(int state)
{
switch (m_irq)
{
diff --git a/src/devices/bus/c64/swiftlink.h b/src/devices/bus/c64/swiftlink.h
index 409cfafa33a..65c25d97b73 100644
--- a/src/devices/bus/c64/swiftlink.h
+++ b/src/devices/bus/c64/swiftlink.h
@@ -45,7 +45,7 @@ protected:
virtual void c64_cd_w(offs_t offset, uint8_t data, int sphi2, int ba, int roml, int romh, int io1, int io2) override;
private:
- DECLARE_WRITE_LINE_MEMBER( acia_irq_w );
+ void acia_irq_w(int state);
required_device<mos6551_device> m_acia;
required_ioport m_io_cs;
diff --git a/src/devices/bus/c64/tibdd001.cpp b/src/devices/bus/c64/tibdd001.cpp
new file mode 100644
index 00000000000..d5646ccc72b
--- /dev/null
+++ b/src/devices/bus/c64/tibdd001.cpp
@@ -0,0 +1,164 @@
+// license:BSD-3-Clause
+// copyright-holders:Curt Coder
+/**********************************************************************
+
+ TIB Disc Drive DD-001 cartridge emulation
+
+**********************************************************************/
+
+/*
+
+ PCB Layout
+ ----------
+
+ |---------------|
+ | CN1 |
+ | |
+ | FDC |
+ | 16MHz|
+ | LS00 LS00 |
+ | ROM |
+ | |
+ |||||||||||||||
+
+Notes: (All ICs shown)
+ FDC - GoldStar GM82C765B Floppy Disk Subsystem Controller
+ ROM - Texas Instruments TMS2764JL-25 8Kx8 EPROM
+ CN1 - floppy connector
+
+*/
+
+#include "emu.h"
+#include "tibdd001.h"
+
+#include "formats/tibdd001_dsk.h"
+
+
+
+//**************************************************************************
+// MACROS/CONSTANTS
+//**************************************************************************
+
+#define GM82C765B_TAG "u4"
+
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(C64_TIB_DD_001, c64_tib_dd_001_device, "c64_tibdd001", "C64 TIB Disc Drive DD-001 cartridge")
+
+
+static void tib_dd_001_floppies(device_slot_interface &device)
+{
+ device.option_add("35dd", FLOPPY_35_DD);
+}
+
+void c64_tib_dd_001_device::floppy_formats(format_registration &fr)
+{
+ fr.add_mfm_containers();
+ fr.add(FLOPPY_TIB_DD_001_FORMAT);
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void c64_tib_dd_001_device::device_add_mconfig(machine_config &config)
+{
+ WD37C65C(config, m_fdc, 16'000'000);
+ m_fdc->hdl_wr_callback().set(FUNC(c64_tib_dd_001_device::motor_w));
+
+ FLOPPY_CONNECTOR(config, m_floppy, tib_dd_001_floppies, "35dd", c64_tib_dd_001_device::floppy_formats, true).enable_sound(true);
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// c64_tib_dd_001_device - constructor
+//-------------------------------------------------
+
+c64_tib_dd_001_device::c64_tib_dd_001_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, C64_TIB_DD_001, tag, owner, clock),
+ device_c64_expansion_card_interface(mconfig, *this),
+ m_fdc(*this, GM82C765B_TAG),
+ m_floppy(*this, GM82C765B_TAG":0")
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void c64_tib_dd_001_device::device_start()
+{
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void c64_tib_dd_001_device::device_reset()
+{
+}
+
+
+//-------------------------------------------------
+// c64_cd_r - cartridge data read
+//-------------------------------------------------
+
+uint8_t c64_tib_dd_001_device::c64_cd_r(offs_t offset, uint8_t data, int sphi2, int ba, int roml, int romh, int io1, int io2)
+{
+ if (!roml)
+ {
+ data = m_roml[offset & 0x1fff];
+ }
+
+ if (sphi2 && !io1)
+ {
+ if (BIT(offset, 0))
+ {
+ data = m_fdc->fifo_r();
+ }
+ else
+ {
+ data = m_fdc->msr_r();
+ }
+ }
+
+ if (sphi2 && !io2)
+ {
+ m_fdc->reset();
+ }
+
+ return data;
+}
+
+
+//-------------------------------------------------
+// c64_cd_w - cartridge data write
+//-------------------------------------------------
+
+void c64_tib_dd_001_device::c64_cd_w(offs_t offset, uint8_t data, int sphi2, int ba, int roml, int romh, int io1, int io2)
+{
+ if (sphi2 && !io1)
+ {
+ if (BIT(offset, 0))
+ {
+ m_fdc->fifo_w(data);
+ }
+ }
+
+ if (sphi2 && !io2)
+ {
+ m_fdc->reset();
+ }
+}
diff --git a/src/devices/bus/c64/tibdd001.h b/src/devices/bus/c64/tibdd001.h
new file mode 100644
index 00000000000..12705c436bd
--- /dev/null
+++ b/src/devices/bus/c64/tibdd001.h
@@ -0,0 +1,60 @@
+// license:BSD-3-Clause
+// copyright-holders:Curt Coder
+/**********************************************************************
+
+ TIB Disc Drive DD-001 cartridge emulation
+
+**********************************************************************/
+
+#ifndef MAME_BUS_C64_TIB_DD_001_H
+#define MAME_BUS_C64_TIB_DD_001_H
+
+#pragma once
+
+
+#include "exp.h"
+#include "imagedev/floppy.h"
+#include "machine/upd765.h"
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> c64_tib_dd_001_device
+
+class c64_tib_dd_001_device : public device_t,
+ public device_c64_expansion_card_interface
+{
+public:
+ // construction/destruction
+ c64_tib_dd_001_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+
+ // device_c64_expansion_card_interface overrides
+ virtual uint8_t c64_cd_r(offs_t offset, uint8_t data, int sphi2, int ba, int roml, int romh, int io1, int io2) override;
+ virtual void c64_cd_w(offs_t offset, uint8_t data, int sphi2, int ba, int roml, int romh, int io1, int io2) override;
+
+private:
+ static void floppy_formats(format_registration &fr);
+
+ required_device<upd765_family_device> m_fdc;
+ required_device<floppy_connector> m_floppy;
+
+ void motor_w(int state) { m_floppy->get_device()->mon_w(!state); }
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(C64_TIB_DD_001, c64_tib_dd_001_device)
+
+
+#endif // MAME_BUS_C64_TIB_DD_001_H
diff --git a/src/devices/bus/c64/turbo232.cpp b/src/devices/bus/c64/turbo232.cpp
index f9113bed1c5..2bcacce91b7 100644
--- a/src/devices/bus/c64/turbo232.cpp
+++ b/src/devices/bus/c64/turbo232.cpp
@@ -200,7 +200,7 @@ void c64_turbo232_cartridge_device::c64_cd_w(offs_t offset, uint8_t data, int sp
// acia_irq_w -
//-------------------------------------------------
-WRITE_LINE_MEMBER( c64_turbo232_cartridge_device::acia_irq_w )
+void c64_turbo232_cartridge_device::acia_irq_w(int state)
{
switch (m_irq)
{
diff --git a/src/devices/bus/c64/turbo232.h b/src/devices/bus/c64/turbo232.h
index 4f5638f88fa..68d0929f629 100644
--- a/src/devices/bus/c64/turbo232.h
+++ b/src/devices/bus/c64/turbo232.h
@@ -45,7 +45,7 @@ protected:
virtual void c64_cd_w(offs_t offset, uint8_t data, int sphi2, int ba, int roml, int romh, int io1, int io2) override;
private:
- DECLARE_WRITE_LINE_MEMBER( acia_irq_w );
+ void acia_irq_w(int state);
required_device<mos6551_device> m_acia;
required_device<rs232_port_device> m_rs232;
diff --git a/src/devices/bus/casloopy/rom.cpp b/src/devices/bus/casloopy/rom.cpp
new file mode 100644
index 00000000000..a43629e24ba
--- /dev/null
+++ b/src/devices/bus/casloopy/rom.cpp
@@ -0,0 +1,117 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/***********************************************************************************************************
+
+ Casio Loopy cart emulation
+
+ ***********************************************************************************************************/
+
+
+#include "emu.h"
+#include "rom.h"
+
+
+//-------------------------------------------------
+// casloopy_rom_device - constructor
+//-------------------------------------------------
+
+DEFINE_DEVICE_TYPE(CASLOOPY_ROM_STD, casloopy_rom_device, "casloopy_rom", "Casio Loopy Standard Cart")
+DEFINE_DEVICE_TYPE(CASLOOPY_ROM_ADPCM, casloopy_adpcm_device, "casloopy_adpcm", "Casio Loopy ADPCM Cart")
+
+
+casloopy_rom_device::casloopy_rom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, type, tag, owner, clock), device_casloopy_cart_interface(mconfig, *this)
+ , m_rom_base(nullptr)
+ , m_nvram_base(nullptr)
+ , m_rom_size(0)
+ , m_nvram_size(0)
+{
+}
+
+casloopy_rom_device::casloopy_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : casloopy_rom_device(mconfig, CASLOOPY_ROM_STD, tag, owner, clock)
+{
+}
+
+casloopy_adpcm_device::casloopy_adpcm_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : casloopy_rom_device(mconfig, CASLOOPY_ROM_ADPCM, tag, owner, clock)
+{
+}
+
+
+/*-------------------------------------------------
+ device_t implementation
+ -------------------------------------------------*/
+
+void casloopy_rom_device::device_start()
+{
+}
+
+void casloopy_adpcm_device::device_add_mconfig(machine_config &config)
+{
+ casloopy_rom_device::device_add_mconfig(config);
+
+ // TODO: Add support for the MSM6653A ADPCM chip, or samples
+ // and route to the speakers
+}
+
+
+/*-------------------------------------------------
+ load/unload
+ -------------------------------------------------*/
+
+std::error_condition casloopy_rom_device::load()
+{
+ memory_region *const romregion = memregion("^rom");
+ m_rom_base = reinterpret_cast<const u16 *>(romregion->base());
+ m_rom_size = romregion->bytes() / 2;
+
+ memory_region *const nvramregion = memregion("^nvram");
+ if (nvramregion)
+ {
+ m_nvram_base = reinterpret_cast<u8 *>(nvramregion->base());
+ m_nvram_size = nvramregion->bytes();
+
+ if (m_nvram_size & (m_nvram_size - 1))
+ return image_error::BADSOFTWARE;
+
+ save_pointer(NAME(m_nvram_base), m_nvram_size);
+ battery_load(m_nvram_base, m_nvram_size, nullptr);
+ }
+
+ return std::error_condition();
+}
+
+
+void casloopy_rom_device::unload()
+{
+ if (m_nvram_base)
+ battery_save(m_nvram_base, m_nvram_size);
+}
+
+
+/*-------------------------------------------------
+ read/write
+ -------------------------------------------------*/
+
+u16 casloopy_rom_device::rom_r(offs_t offset)
+{
+ if (offset < m_rom_size)
+ return m_rom_base[offset];
+ else
+ return 0xffff;
+}
+
+u8 casloopy_rom_device::ram_r(offs_t offset)
+{
+ if (m_nvram_base)
+ return m_nvram_base[offset & (m_nvram_size - 1)];
+ else
+ return 0xff;
+}
+
+void casloopy_rom_device::ram_w(offs_t offset, u8 data)
+{
+ if (m_nvram_base)
+ m_nvram_base[offset & (m_nvram_size - 1)] = data;
+}
diff --git a/src/devices/bus/casloopy/rom.h b/src/devices/bus/casloopy/rom.h
new file mode 100644
index 00000000000..76adb3e767a
--- /dev/null
+++ b/src/devices/bus/casloopy/rom.h
@@ -0,0 +1,58 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+#ifndef MAME_BUS_CASLOOPY_ROM_H
+#define MAME_BUS_CASLOOPY_ROM_H
+
+#pragma once
+
+#include "slot.h"
+
+
+// ======================> casloopy_rom_device
+
+class casloopy_rom_device : public device_t,
+ public device_casloopy_cart_interface
+{
+public:
+ // construction/destruction
+ casloopy_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ // load/unload
+ virtual std::error_condition load() override;
+ virtual void unload() override;
+
+ // read/write
+ virtual u16 rom_r(offs_t offset) override;
+ virtual u8 ram_r(offs_t offset) override;
+ virtual void ram_w(offs_t offset, u8 data) override;
+
+protected:
+ casloopy_rom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
+ virtual void device_start() override;
+
+private:
+ const u16 *m_rom_base;
+ u8 *m_nvram_base;
+ u32 m_rom_size;
+ u32 m_nvram_size;
+};
+
+
+// ======================> casloopy_adpcm_device
+
+class casloopy_adpcm_device : public casloopy_rom_device
+{
+public:
+ // construction/destruction
+ casloopy_adpcm_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(CASLOOPY_ROM_STD, casloopy_rom_device)
+DECLARE_DEVICE_TYPE(CASLOOPY_ROM_ADPCM, casloopy_adpcm_device)
+
+#endif // MAME_BUS_CASLOOPY_ROM_H
diff --git a/src/devices/bus/casloopy/slot.cpp b/src/devices/bus/casloopy/slot.cpp
new file mode 100644
index 00000000000..e1490496e21
--- /dev/null
+++ b/src/devices/bus/casloopy/slot.cpp
@@ -0,0 +1,149 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/***********************************************************************************************************
+
+ Casio Loopy cart slot emulation
+
+ ***********************************************************************************************************/
+
+#include "emu.h"
+#include "slot.h"
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(CASLOOPY_CART_SLOT, casloopy_cart_slot_device, "casloopy_cart_slot", "Casio Loopy Cartridge Slot")
+
+//**************************************************************************
+// casloopy Cartridges Interface
+//**************************************************************************
+
+//-------------------------------------------------
+// device_casloopy_cart_interface - constructor
+//-------------------------------------------------
+
+device_casloopy_cart_interface::device_casloopy_cart_interface(const machine_config &mconfig, device_t &device)
+ : device_interface(device, "casloopy_cart")
+ , m_slot(dynamic_cast<casloopy_cart_slot_device *>(device.owner()))
+{
+}
+
+
+//-------------------------------------------------
+// ~device_casloopy_cart_interface - destructor
+//-------------------------------------------------
+
+device_casloopy_cart_interface::~device_casloopy_cart_interface()
+{
+}
+
+
+void device_casloopy_cart_interface::battery_load(void *buffer, int length, int fill)
+{
+ assert(m_slot);
+ m_slot->battery_load(buffer, length, fill);
+}
+
+void device_casloopy_cart_interface::battery_load(void *buffer, int length, void *def_buffer)
+{
+ assert(m_slot);
+ m_slot->battery_load(buffer, length, def_buffer);
+}
+
+void device_casloopy_cart_interface::battery_save(const void *buffer, int length)
+{
+ assert(m_slot);
+ m_slot->battery_save(buffer, length);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// casloopy_cart_slot_device - constructor
+//-------------------------------------------------
+casloopy_cart_slot_device::casloopy_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ device_t(mconfig, CASLOOPY_CART_SLOT, tag, owner, clock),
+ device_cartrom_image_interface(mconfig, *this),
+ device_single_card_slot_interface<device_casloopy_cart_interface>(mconfig, *this),
+ m_cart(nullptr)
+{
+}
+
+
+//-------------------------------------------------
+// casloopy_cart_slot_device - destructor
+//-------------------------------------------------
+
+casloopy_cart_slot_device::~casloopy_cart_slot_device()
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void casloopy_cart_slot_device::device_start()
+{
+ m_cart = get_card_device();
+}
+
+
+
+/*-------------------------------------------------
+ call load
+ -------------------------------------------------*/
+
+std::pair<std::error_condition, std::string> casloopy_cart_slot_device::call_load()
+{
+ if (!m_cart)
+ return std::make_pair(std::error_condition(), std::string());
+
+ memory_region *romregion = loaded_through_softlist() ? memregion("rom") : nullptr;
+ if (loaded_through_softlist() && !romregion)
+ return std::make_pair(image_error::INVALIDLENGTH, "Software list item has no 'rom' data area");
+
+ const u32 len = loaded_through_softlist() ? romregion->bytes() : length();
+
+ if (!loaded_through_softlist())
+ {
+ romregion = machine().memory().region_alloc(subtag("rom"), len, 2, ENDIANNESS_BIG);
+ u16 *const rombase = reinterpret_cast<u16 *>(romregion->base());
+ const u32 cnt = fread(rombase, len);
+ if (cnt != len)
+ return std::make_pair(std::errc::io_error, "Error reading cartridge file");
+
+ // CPU is big Endian, but conventional ROM dump format is little Endian
+ if (ENDIANNESS_NATIVE != ENDIANNESS_LITTLE)
+ {
+ for (u32 i = 0; (len / 2) > i; ++i)
+ rombase[i] = swapendian_int16(rombase[i]);
+ }
+ }
+
+ return std::make_pair(m_cart->load(), std::string());
+}
+
+
+/*-------------------------------------------------
+ call unload
+ -------------------------------------------------*/
+
+void casloopy_cart_slot_device::call_unload()
+{
+ if (m_cart)
+ m_cart->unload();
+}
+
+
+/*-------------------------------------------------
+ get default card software
+ -------------------------------------------------*/
+
+std::string casloopy_cart_slot_device::get_default_card_software(get_default_card_software_hook &hook) const
+{
+ return software_get_default_slot("std");
+}
diff --git a/src/devices/bus/casloopy/slot.h b/src/devices/bus/casloopy/slot.h
new file mode 100644
index 00000000000..cc317dd817a
--- /dev/null
+++ b/src/devices/bus/casloopy/slot.h
@@ -0,0 +1,90 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+#ifndef MAME_BUS_CASLOOPY_SLOT_H
+#define MAME_BUS_CASLOOPY_SLOT_H
+
+#include "imagedev/cartrom.h"
+
+#include <system_error>
+#include <utility>
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+ ***************************************************************************/
+
+class casloopy_cart_slot_device;
+
+
+class device_casloopy_cart_interface : public device_interface
+{
+public:
+ virtual ~device_casloopy_cart_interface();
+
+ // load/unload
+ virtual std::error_condition load() = 0;
+ virtual void unload() = 0;
+
+ // read/write
+ virtual u16 rom_r(offs_t offset) = 0;
+ virtual u8 ram_r(offs_t offset) = 0;
+ virtual void ram_w(offs_t offset, u8 data) = 0;
+
+protected:
+ // construction/destruction
+ device_casloopy_cart_interface(const machine_config &mconfig, device_t &device);
+
+ // helpers for slot stuff
+ void battery_load(void *buffer, int length, int fill);
+ void battery_load(void *buffer, int length, void *def_buffer);
+ void battery_save(const void *buffer, int length);
+
+private:
+ casloopy_cart_slot_device *const m_slot;
+};
+
+
+class casloopy_cart_slot_device : public device_t,
+ public device_cartrom_image_interface,
+ public device_single_card_slot_interface<device_casloopy_cart_interface>
+{
+public:
+ // construction/destruction
+ template <typename T>
+ casloopy_cart_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock, T &&opts, char const *dflt)
+ : casloopy_cart_slot_device(mconfig, tag, owner, clock)
+ {
+ option_reset();
+ opts(*this);
+ set_default_option(dflt);
+ set_fixed(false);
+ }
+ casloopy_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+ virtual ~casloopy_cart_slot_device();
+
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
+ virtual void call_unload() override;
+
+ virtual bool is_reset_on_load() const noexcept override { return true; }
+ virtual const char *image_interface() const noexcept override { return "casloopy_cart"; }
+ virtual const char *file_extensions() const noexcept override { return "bin"; }
+
+ // device_slot_interface implementation
+ virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
+
+ // reading and writing
+ u16 rom_r(offs_t offset) { return m_cart ? m_cart->rom_r(offset) : 0xffff; }
+ u8 ram_r(offs_t offset) { return m_cart ? m_cart->ram_r(offset) : 0xff; }
+ void ram_w(offs_t offset, u8 data) { if (m_cart) m_cart->ram_w(offset, data); }
+
+protected:
+ // device_t implementation
+ virtual void device_start() override;
+
+ device_casloopy_cart_interface *m_cart;
+};
+
+DECLARE_DEVICE_TYPE(CASLOOPY_CART_SLOT, casloopy_cart_slot_device)
+
+#endif // MAME_BUS_CASLOOPY_SLOT_H
diff --git a/src/devices/bus/cbm2/exp.cpp b/src/devices/bus/cbm2/exp.cpp
index c43e540e181..187c98ef5aa 100644
--- a/src/devices/bus/cbm2/exp.cpp
+++ b/src/devices/bus/cbm2/exp.cpp
@@ -9,6 +9,8 @@
#include "emu.h"
#include "exp.h"
+#include <tuple>
+
//**************************************************************************
@@ -83,30 +85,41 @@ void cbm2_expansion_slot_device::device_start()
// call_load -
//-------------------------------------------------
-image_init_result cbm2_expansion_slot_device::call_load()
+std::pair<std::error_condition, std::string> cbm2_expansion_slot_device::call_load()
{
- size_t size;
+ std::error_condition err;
if (m_card)
{
if (!loaded_through_softlist())
{
- size = length();
+ util::core_file &file = image_core_file();
+ size_t const size = length();
if (is_filetype("20"))
{
- m_card->m_bank1 = std::make_unique<uint8_t[]>(size);
- fread(m_card->m_bank1, size);
+ size_t actual;
+ std::tie(err, m_card->m_bank1, actual) = util::read(file, size);
+ if (!err && (actual != size))
+ err = std::errc::io_error;
}
else if (is_filetype("40"))
{
- m_card->m_bank2 = std::make_unique<uint8_t[]>(size);
- fread(m_card->m_bank2, size);
+ size_t actual;
+ std::tie(err, m_card->m_bank2, actual) = util::read(file, size);
+ if (!err && (actual != size))
+ err = std::errc::io_error;
}
else if (is_filetype("60"))
{
- m_card->m_bank3 = std::make_unique<uint8_t[]>(size);
- fread(m_card->m_bank3, size);
+ size_t actual;
+ std::tie(err, m_card->m_bank3, actual) = util::read(file, size);
+ if (!err && (actual != size))
+ err = std::errc::io_error;
+ }
+ else
+ {
+ err = image_error::INVALIDIMAGE;
}
}
else
@@ -117,7 +130,7 @@ image_init_result cbm2_expansion_slot_device::call_load()
}
}
- return image_init_result::PASS;
+ return std::make_pair(err, std::string());
}
diff --git a/src/devices/bus/cbm2/exp.h b/src/devices/bus/cbm2/exp.h
index 19ed3d01dac..83eac3589bf 100644
--- a/src/devices/bus/cbm2/exp.h
+++ b/src/devices/bus/cbm2/exp.h
@@ -66,17 +66,17 @@ public:
int phi2() { return clock(); }
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
- // image-level overrides
- virtual image_init_result call_load() override;
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
virtual bool is_reset_on_load() const noexcept override { return true; }
virtual const char *image_interface() const noexcept override { return "cbm2_cart"; }
virtual const char *file_extensions() const noexcept override { return "20,40,60"; }
- // slot interface overrides
+ // device_slot_interface implementation
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
device_cbm2_expansion_card_interface *m_card;
diff --git a/src/devices/bus/cbm2/user.cpp b/src/devices/bus/cbm2/user.cpp
index 5dc12567096..8aa9153e30e 100644
--- a/src/devices/bus/cbm2/user.cpp
+++ b/src/devices/bus/cbm2/user.cpp
@@ -62,12 +62,6 @@ cbm2_user_port_device::cbm2_user_port_device(const machine_config &mconfig, cons
void cbm2_user_port_device::device_start()
{
m_card = get_card_device();
-
- // resolve callbacks
- m_write_irq.resolve_safe();
- m_write_sp.resolve_safe();
- m_write_cnt.resolve_safe();
- m_write_flag.resolve_safe();
}
diff --git a/src/devices/bus/cbm2/user.h b/src/devices/bus/cbm2/user.h
index 4a49807118d..8f5de9555a9 100644
--- a/src/devices/bus/cbm2/user.h
+++ b/src/devices/bus/cbm2/user.h
@@ -92,19 +92,19 @@ public:
void d1_w(uint8_t data) { if (m_card != nullptr) m_card->cbm2_d1_w(data); }
uint8_t d2_r() { uint8_t data = 0xff; if (m_card != nullptr) data = m_card->cbm2_d2_r(); return data; }
void d2_w(uint8_t data) { if (m_card != nullptr) m_card->cbm2_d2_w(data); }
- DECLARE_READ_LINE_MEMBER( pb2_r ) { return m_card ? m_card->cbm2_pb2_r() : 1; }
- DECLARE_WRITE_LINE_MEMBER( pb2_w ) { if (m_card != nullptr) m_card->cbm2_pb2_w(state); }
- DECLARE_READ_LINE_MEMBER( pb3_r ) { return m_card ? m_card->cbm2_pb3_r() : 1; }
- DECLARE_WRITE_LINE_MEMBER( pb3_w ) { if (m_card != nullptr) m_card->cbm2_pb3_w(state); }
- DECLARE_WRITE_LINE_MEMBER( pc_w ) { if (m_card != nullptr) m_card->cbm2_pc_w(state); }
- DECLARE_WRITE_LINE_MEMBER( cnt_w ) { if (m_card != nullptr) m_card->cbm2_cnt_w(state); }
- DECLARE_WRITE_LINE_MEMBER( sp_w ) { if (m_card != nullptr) m_card->cbm2_sp_w(state); }
+ int pb2_r() { return m_card ? m_card->cbm2_pb2_r() : 1; }
+ void pb2_w(int state) { if (m_card != nullptr) m_card->cbm2_pb2_w(state); }
+ int pb3_r() { return m_card ? m_card->cbm2_pb3_r() : 1; }
+ void pb3_w(int state) { if (m_card != nullptr) m_card->cbm2_pb3_w(state); }
+ void pc_w(int state) { if (m_card != nullptr) m_card->cbm2_pc_w(state); }
+ void cnt_w(int state) { if (m_card != nullptr) m_card->cbm2_cnt_w(state); }
+ void sp_w(int state) { if (m_card != nullptr) m_card->cbm2_sp_w(state); }
// cartridge interface
- DECLARE_WRITE_LINE_MEMBER( irq_w ) { m_write_irq(state); }
- DECLARE_WRITE_LINE_MEMBER( cia_sp_w ) { m_write_sp(state); }
- DECLARE_WRITE_LINE_MEMBER( cia_cnt_w ) { m_write_cnt(state); }
- DECLARE_WRITE_LINE_MEMBER( flag_w ) { m_write_flag(state); }
+ void irq_w(int state) { m_write_irq(state); }
+ void cia_sp_w(int state) { m_write_sp(state); }
+ void cia_cnt_w(int state) { m_write_cnt(state); }
+ void flag_w(int state) { m_write_flag(state); }
protected:
// device-level overrides
diff --git a/src/devices/bus/cbmiec/c1526.cpp b/src/devices/bus/cbmiec/c1526.cpp
index 7123782d42c..45e4540e236 100644
--- a/src/devices/bus/cbmiec/c1526.cpp
+++ b/src/devices/bus/cbmiec/c1526.cpp
@@ -23,7 +23,7 @@
// DEVICE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(C1526, c1526_device, "c1526", "Commodore 1526/MPS802 Printer")
+DEFINE_DEVICE_TYPE(C1526, c1526_device, "c1526", "Commodore 1526/MPS-802 Dot Matrix Printer")
DEFINE_DEVICE_TYPE(C4023, c4023_device, "c4023", "Commodore 4023 Printer")
diff --git a/src/devices/bus/cbmiec/c1541.cpp b/src/devices/bus/cbmiec/c1541.cpp
index a547fc6f208..961fe5c76db 100644
--- a/src/devices/bus/cbmiec/c1541.cpp
+++ b/src/devices/bus/cbmiec/c1541.cpp
@@ -10,8 +10,6 @@
TODO:
- - c1540 fails to load the directory intermittently
-
- hardware extensions
- Dolphin-DOS 2.0
- Dolphin-DOS 3.0
@@ -141,6 +139,8 @@
#include "bus/centronics/ctronics.h"
+#include "formats/d64_dsk.h"
+#include "formats/g64_dsk.h"
#include "formats/fs_cbmdos.h"
@@ -712,7 +712,7 @@ void c1541_prologic_dos_classic_device::c1541pdc_mem(address_map &map)
}
-WRITE_LINE_MEMBER( c1541_device_base::via0_irq_w )
+void c1541_device_base::via0_irq_w(int state)
{
m_via0_irq = state;
@@ -794,7 +794,7 @@ void c1541_device_base::via0_pb_w(uint8_t data)
m_bus->clk_w(this, !BIT(data, 3));
}
-WRITE_LINE_MEMBER( c1541_device_base::via0_ca2_w )
+void c1541_device_base::via0_ca2_w(int state)
{
if (m_other != nullptr)
{
@@ -823,7 +823,7 @@ uint8_t c1541c_device::via0_pa_r()
}
-WRITE_LINE_MEMBER( c1541_device_base::via1_irq_w )
+void c1541_device_base::via1_irq_w(int state)
{
m_via1_irq = state;
@@ -893,12 +893,12 @@ void c1541_device_base::via1_pb_w(uint8_t data)
// C64H156_INTERFACE( ga_intf )
//-------------------------------------------------
-WRITE_LINE_MEMBER( c1541_device_base::atn_w )
+void c1541_device_base::atn_w(int state)
{
set_iec_data();
}
-WRITE_LINE_MEMBER( c1541_device_base::byte_w )
+void c1541_device_base::byte_w(int state)
{
m_maincpu->set_input_line(M6502_SET_OVERFLOW, state);
@@ -967,7 +967,6 @@ void c1541_device_base::device_add_mconfig(machine_config &config)
{
M6502(config, m_maincpu, XTAL(16'000'000)/16);
m_maincpu->set_addrmap(AS_PROGRAM, &c1541_device_base::c1541_mem);
- //config.set_perfect_quantum(m_maincpu); FIXME: not safe in a slot device - add barriers
MOS6522(config, m_via0, XTAL(16'000'000)/16);
m_via0->readpa_handler().set(FUNC(c1541_device_base::via0_pa_r));
@@ -1025,7 +1024,7 @@ void c1541_prologic_dos_classic_device::device_add_mconfig(machine_config &confi
m_maincpu->set_addrmap(AS_PROGRAM, &c1541_prologic_dos_classic_device::c1541pdc_mem);
- PIA6821(config, m_pia, 0);
+ PIA6821(config, m_pia);
m_pia->readpb_handler().set(FUNC(c1541_prologic_dos_classic_device::pia_pb_r));
m_pia->writepa_handler().set(FUNC(c1541_prologic_dos_classic_device::pia_pa_w));
m_pia->writepb_handler().set(FUNC(c1541_prologic_dos_classic_device::pia_pb_w));
diff --git a/src/devices/bus/cbmiec/c1541.h b/src/devices/bus/cbmiec/c1541.h
index de79cc95f90..09e12a0f265 100644
--- a/src/devices/bus/cbmiec/c1541.h
+++ b/src/devices/bus/cbmiec/c1541.h
@@ -68,17 +68,17 @@ private:
inline void set_iec_data();
- DECLARE_WRITE_LINE_MEMBER( via0_irq_w );
+ void via0_irq_w(int state);
virtual uint8_t via0_pa_r();
void via0_pa_w(uint8_t data);
uint8_t via0_pb_r();
void via0_pb_w(uint8_t data);
- DECLARE_WRITE_LINE_MEMBER( via0_ca2_w );
- DECLARE_WRITE_LINE_MEMBER( via1_irq_w );
+ void via0_ca2_w(int state);
+ void via1_irq_w(int state);
uint8_t via1_pb_r();
void via1_pb_w(uint8_t data);
- DECLARE_WRITE_LINE_MEMBER( atn_w );
- DECLARE_WRITE_LINE_MEMBER( byte_w );
+ void atn_w(int state);
+ void byte_w(int state);
static void floppy_formats(format_registration &fr);
diff --git a/src/devices/bus/cbmiec/c1571.cpp b/src/devices/bus/cbmiec/c1571.cpp
index f2d41120f5e..19ff695828b 100644
--- a/src/devices/bus/cbmiec/c1571.cpp
+++ b/src/devices/bus/cbmiec/c1571.cpp
@@ -22,6 +22,9 @@
#include "emu.h"
#include "c1571.h"
+#include "formats/d64_dsk.h"
+#include "formats/g64_dsk.h"
+#include "formats/d71_dsk.h"
//**************************************************************************
@@ -172,7 +175,7 @@ void mini_chief_device::mini_chief_mem(address_map &map)
}
-WRITE_LINE_MEMBER( c1571_device::via0_irq_w )
+void c1571_device::via0_irq_w(int state)
{
m_via0_irq = state;
@@ -400,7 +403,7 @@ void c1571_device::via1_w(offs_t offset, uint8_t data)
m_ga->ted_w(1);
}
-WRITE_LINE_MEMBER( c1571_device::via1_irq_w )
+void c1571_device::via1_irq_w(int state)
{
m_via1_irq = state;
@@ -470,14 +473,14 @@ void c1571_device::via1_pb_w(uint8_t data)
// MOS6526_INTERFACE( cia_intf )
//-------------------------------------------------
-WRITE_LINE_MEMBER( c1571_device::cia_irq_w )
+void c1571_device::cia_irq_w(int state)
{
m_cia_irq = state;
m_maincpu->set_input_line(INPUT_LINE_IRQ0, (m_via0_irq || m_via1_irq || m_cia_irq) ? ASSERT_LINE : CLEAR_LINE);
}
-WRITE_LINE_MEMBER( c1571_device::cia_pc_w )
+void c1571_device::cia_pc_w(int state)
{
if (m_other != nullptr)
{
@@ -485,14 +488,14 @@ WRITE_LINE_MEMBER( c1571_device::cia_pc_w )
}
}
-WRITE_LINE_MEMBER( c1571_device::cia_cnt_w )
+void c1571_device::cia_cnt_w(int state)
{
m_cnt_out = state;
update_iec();
}
-WRITE_LINE_MEMBER( c1571_device::cia_sp_w )
+void c1571_device::cia_sp_w(int state)
{
m_sp_out = state;
@@ -552,7 +555,7 @@ void mini_chief_device::cia_pb_w(uint8_t data)
// C64H156_INTERFACE( ga_intf )
//-------------------------------------------------
-WRITE_LINE_MEMBER( c1571_device::byte_w )
+void c1571_device::byte_w(int state)
{
m_via1->write_ca1(state);
@@ -599,7 +602,6 @@ void c1571_device::add_base_mconfig(machine_config &config)
{
M6502(config, m_maincpu, 16_MHz_XTAL / 16);
m_maincpu->set_addrmap(AS_PROGRAM, &c1571_device::c1571_mem);
- //config.set_perfect_quantum(m_maincpu); FIXME: not safe in a slot device - add barriers
MOS6522(config, m_via0, 16_MHz_XTAL / 16);
m_via0->readpa_handler().set(FUNC(c1571_device::via0_pa_r));
diff --git a/src/devices/bus/cbmiec/c1571.h b/src/devices/bus/cbmiec/c1571.h
index 103da690a2c..0b83fccfb21 100644
--- a/src/devices/bus/cbmiec/c1571.h
+++ b/src/devices/bus/cbmiec/c1571.h
@@ -43,7 +43,7 @@ public:
// construction/destruction
c1571_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_WRITE_LINE_MEMBER( via0_irq_w );
+ void via0_irq_w(int state);
uint8_t via0_pa_r();
void via0_pa_w(uint8_t data);
uint8_t via0_pb_r();
@@ -51,18 +51,18 @@ public:
uint8_t via1_r(offs_t offset);
void via1_w(offs_t offset, uint8_t data);
- DECLARE_WRITE_LINE_MEMBER( via1_irq_w );
+ void via1_irq_w(int state);
uint8_t via1_pb_r();
void via1_pb_w(uint8_t data);
- DECLARE_WRITE_LINE_MEMBER( cia_irq_w );
- DECLARE_WRITE_LINE_MEMBER( cia_pc_w );
- DECLARE_WRITE_LINE_MEMBER( cia_cnt_w );
- DECLARE_WRITE_LINE_MEMBER( cia_sp_w );
+ void cia_irq_w(int state);
+ void cia_pc_w(int state);
+ void cia_cnt_w(int state);
+ void cia_sp_w(int state);
uint8_t cia_pb_r();
void cia_pb_w(uint8_t data);
- DECLARE_WRITE_LINE_MEMBER( byte_w );
+ void byte_w(int state);
static void floppy_formats(format_registration &fr);
diff --git a/src/devices/bus/cbmiec/c1581.cpp b/src/devices/bus/cbmiec/c1581.cpp
index b139a272266..21c70937eb3 100644
--- a/src/devices/bus/cbmiec/c1581.cpp
+++ b/src/devices/bus/cbmiec/c1581.cpp
@@ -17,6 +17,9 @@
#include "emu.h"
#include "c1581.h"
+#include "cpu/m6502/m6502.h"
+#include "formats/d81_dsk.h"
+
//**************************************************************************
@@ -102,14 +105,14 @@ void c1581_device::c1581_mem(address_map &map)
// MOS8520_INTERFACE( cia_intf )
//-------------------------------------------------
-WRITE_LINE_MEMBER( c1581_device::cnt_w )
+void c1581_device::cnt_w(int state)
{
m_cnt_out = state;
update_iec();
}
-WRITE_LINE_MEMBER( c1581_device::sp_w )
+void c1581_device::sp_w(int state)
{
m_sp_out = state;
diff --git a/src/devices/bus/cbmiec/c1581.h b/src/devices/bus/cbmiec/c1581.h
index 1fef8579460..299e735844a 100644
--- a/src/devices/bus/cbmiec/c1581.h
+++ b/src/devices/bus/cbmiec/c1581.h
@@ -12,8 +12,6 @@
#pragma once
#include "cbmiec.h"
-#include "cpu/m6502/m6502.h"
-#include "formats/d81_dsk.h"
#include "imagedev/floppy.h"
#include "machine/mos6526.h"
#include "machine/wd_fdc.h"
@@ -67,8 +65,8 @@ private:
void update_iec();
- DECLARE_WRITE_LINE_MEMBER( cnt_w );
- DECLARE_WRITE_LINE_MEMBER( sp_w );
+ void cnt_w(int state);
+ void sp_w(int state);
uint8_t cia_pa_r();
void cia_pa_w(uint8_t data);
uint8_t cia_pb_r();
diff --git a/src/devices/bus/cbmiec/c64_nl10.cpp b/src/devices/bus/cbmiec/c64_nl10.cpp
index d4ed3467016..6def72ed1ec 100644
--- a/src/devices/bus/cbmiec/c64_nl10.cpp
+++ b/src/devices/bus/cbmiec/c64_nl10.cpp
@@ -9,6 +9,8 @@
#include "emu.h"
#include "c64_nl10.h"
+#include "cpu/m6800/m6801.h"
+
//**************************************************************************
@@ -55,6 +57,28 @@ c64_nl10_interface_device::c64_nl10_interface_device(const machine_config &mconf
//-------------------------------------------------
+// mem_map - CPU memory map
+//-------------------------------------------------
+
+void c64_nl10_interface_device::mem_map(address_map &map)
+{
+ map(0x6000, 0x7fff).ram();
+ map(0x8000, 0xffff).rom().region("rom", 0);
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - machine configuration
+//-------------------------------------------------
+
+void c64_nl10_interface_device::device_add_mconfig(machine_config &config)
+{
+ hd6303y_cpu_device &bufcpu(HD6303Y(config, "bufcpu", 8'000'000));
+ bufcpu.set_addrmap(AS_PROGRAM, &c64_nl10_interface_device::mem_map);
+}
+
+
+//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
diff --git a/src/devices/bus/cbmiec/c64_nl10.h b/src/devices/bus/cbmiec/c64_nl10.h
index 68f9f135c91..a45322e3f53 100644
--- a/src/devices/bus/cbmiec/c64_nl10.h
+++ b/src/devices/bus/cbmiec/c64_nl10.h
@@ -27,11 +27,10 @@ public:
// construction/destruction
c64_nl10_interface_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- // optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
-
protected:
// device-level overrides
+ virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override;
virtual void device_start() override;
virtual void device_reset() override;
@@ -39,6 +38,9 @@ protected:
void cbm_iec_atn(int state) override;
void cbm_iec_data(int state) override;
void cbm_iec_reset(int state) override;
+
+private:
+ void mem_map(address_map &map);
};
diff --git a/src/devices/bus/cbmiec/cbmiec.cpp b/src/devices/bus/cbmiec/cbmiec.cpp
index 4ee8f287200..43faf6e17a3 100644
--- a/src/devices/bus/cbmiec/cbmiec.cpp
+++ b/src/devices/bus/cbmiec/cbmiec.cpp
@@ -302,12 +302,6 @@ cbm_iec_device::cbm_iec_device(const machine_config &mconfig, const char *tag, d
void cbm_iec_device::device_start()
{
- // resolve callbacks
- m_write_srq.resolve_safe();
- m_write_atn.resolve_safe();
- m_write_clk.resolve_safe();
- m_write_data.resolve_safe();
- m_write_reset.resolve_safe();
}
@@ -494,6 +488,7 @@ int cbm_iec_device::get_signal(int signal)
#include "vic1515.h"
#include "vic1520.h"
#include "c1526.h"
+#include "mps1200.h"
void cbm_iec_devices(device_slot_interface &device)
{
@@ -529,4 +524,6 @@ void cbm_iec_devices(device_slot_interface &device)
device.option_add("fd148", FD148);
device.option_add("msdsd1", MSD_SD1);
device.option_add("msdsd2", MSD_SD2);
+ device.option_add("mps1200", MPS1200);
+ device.option_add("mps1250", MPS1250);
}
diff --git a/src/devices/bus/cbmiec/cbmiec.h b/src/devices/bus/cbmiec/cbmiec.h
index 0683a98b4f8..732be55fe19 100644
--- a/src/devices/bus/cbmiec/cbmiec.h
+++ b/src/devices/bus/cbmiec/cbmiec.h
@@ -50,18 +50,18 @@ public:
void add_device(cbm_iec_slot_device *slot, device_t *target);
// reads for both host and peripherals
- DECLARE_READ_LINE_MEMBER( srq_r ) { return get_signal(SRQ); }
- DECLARE_READ_LINE_MEMBER( atn_r ) { return get_signal(ATN); }
- DECLARE_READ_LINE_MEMBER( clk_r ) { return get_signal(CLK); }
- DECLARE_READ_LINE_MEMBER( data_r ) { return get_signal(DATA); }
- DECLARE_READ_LINE_MEMBER( reset_r ) { return get_signal(RESET); }
+ int srq_r() { return get_signal(SRQ); }
+ int atn_r() { return get_signal(ATN); }
+ int clk_r() { return get_signal(CLK); }
+ int data_r() { return get_signal(DATA); }
+ int reset_r() { return get_signal(RESET); }
// writes for host (driver_device)
- DECLARE_WRITE_LINE_MEMBER( host_srq_w ) { set_signal(this, SRQ, state); }
- DECLARE_WRITE_LINE_MEMBER( host_atn_w ) { set_signal(this, ATN, state); }
- DECLARE_WRITE_LINE_MEMBER( host_clk_w ) { set_signal(this, CLK, state); }
- DECLARE_WRITE_LINE_MEMBER( host_data_w ) { set_signal(this, DATA, state); }
- DECLARE_WRITE_LINE_MEMBER( host_reset_w ) { set_signal(this, RESET, state); }
+ void host_srq_w(int state) { set_signal(this, SRQ, state); }
+ void host_atn_w(int state) { set_signal(this, ATN, state); }
+ void host_clk_w(int state) { set_signal(this, CLK, state); }
+ void host_data_w(int state) { set_signal(this, DATA, state); }
+ void host_reset_w(int state) { set_signal(this, RESET, state); }
// writes for peripherals (device_t)
void srq_w(device_t *device, int state) { set_signal(device, SRQ, state); }
diff --git a/src/devices/bus/cbmiec/fd2000.cpp b/src/devices/bus/cbmiec/fd2000.cpp
index 34e06d70dbf..4b4834271a1 100644
--- a/src/devices/bus/cbmiec/fd2000.cpp
+++ b/src/devices/bus/cbmiec/fd2000.cpp
@@ -20,6 +20,8 @@
#include "emu.h"
#include "fd2000.h"
+#include "formats/d81_dsk.h"
+
//**************************************************************************
diff --git a/src/devices/bus/cbmiec/fd2000.h b/src/devices/bus/cbmiec/fd2000.h
index 0b247405e7e..7ffe3192b79 100644
--- a/src/devices/bus/cbmiec/fd2000.h
+++ b/src/devices/bus/cbmiec/fd2000.h
@@ -13,7 +13,6 @@
#include "cbmiec.h"
#include "cpu/m6502/m65c02.h"
-#include "formats/d81_dsk.h"
#include "imagedev/floppy.h"
#include "machine/6522via.h"
#include "machine/upd765.h"
diff --git a/src/devices/bus/cbmiec/interpod.cpp b/src/devices/bus/cbmiec/interpod.cpp
index c5479a30b18..b256f42de19 100644
--- a/src/devices/bus/cbmiec/interpod.cpp
+++ b/src/devices/bus/cbmiec/interpod.cpp
@@ -111,8 +111,8 @@ const tiny_rom_entry *cbm_interpod_device::device_rom_region() const
void cbm_interpod_device::interpod_mem(address_map &map)
{
- map(0x0000, 0x007f).mirror(0x3b80).m(m_riot, FUNC(mos6532_new_device::ram_map));
- map(0x0400, 0x041f).mirror(0x3be0).m(m_riot, FUNC(mos6532_new_device::io_map));
+ map(0x0000, 0x007f).mirror(0x3b80).m(m_riot, FUNC(mos6532_device::ram_map));
+ map(0x0400, 0x041f).mirror(0x3be0).m(m_riot, FUNC(mos6532_device::io_map));
map(0x2000, 0x2001).mirror(0x9ffe).rw(m_acia, FUNC(acia6850_device::read), FUNC(acia6850_device::write));
map(0x4000, 0x47ff).mirror(0xb800).rom().region(R6502_TAG, 0);
map(0x8000, 0x800f).mirror(0x5ff0).m(m_via, FUNC(via6522_device::map));
@@ -130,7 +130,7 @@ void cbm_interpod_device::device_add_mconfig(machine_config &config)
MOS6522(config, m_via, 1000000);
- MOS6532_NEW(config, m_riot, 1000000);
+ MOS6532(config, m_riot, 1000000);
ACIA6850(config, m_acia, 0);
diff --git a/src/devices/bus/cbmiec/interpod.h b/src/devices/bus/cbmiec/interpod.h
index 823ab0c64e7..7278ed68c1a 100644
--- a/src/devices/bus/cbmiec/interpod.h
+++ b/src/devices/bus/cbmiec/interpod.h
@@ -16,7 +16,7 @@
#include "bus/ieee488/ieee488.h"
#include "cpu/m6502/m6502.h"
#include "machine/6522via.h"
-#include "machine/mos6530n.h"
+#include "machine/mos6530.h"
#include "machine/6850acia.h"
@@ -46,7 +46,7 @@ protected:
private:
required_device<cpu_device> m_maincpu;
required_device<via6522_device> m_via;
- required_device<mos6532_new_device> m_riot;
+ required_device<mos6532_device> m_riot;
required_device<acia6850_device> m_acia;
required_device<ieee488_device> m_ieee;
required_device<rs232_port_device> m_rs232;
diff --git a/src/devices/bus/cbmiec/mps1200.cpp b/src/devices/bus/cbmiec/mps1200.cpp
new file mode 100644
index 00000000000..6ceac358d2e
--- /dev/null
+++ b/src/devices/bus/cbmiec/mps1200.cpp
@@ -0,0 +1,317 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/**********************************************************************
+
+ Commodore MPS-1200 & MPS-1250 printers (skeleton)
+
+ The MPS-1200's CPU board was originally designed for a standard
+ Centronics parallel interface (Y8300). However, an alternate
+ "Basic Interface Pack" board (Y8306) instead supported the IEC bus
+ using some extra LSTTL glue logic to convert serial data input to
+ the parallel format read by the CPU. The later MPS-1250 board
+ (Y8307) had hardware to support both serial and parallel
+ interfaces, but only used one at a time.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "mps1200.h"
+
+#include "cpu/m6502/m50734.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+// device type definitions
+DEFINE_DEVICE_TYPE(MPS1200, mps1200_device, "mps1200", "Commodore MPS-1200 Dot Matrix Printer")
+DEFINE_DEVICE_TYPE(MPS1250, mps1250_device, "mps1250", "Commodore MPS-1250 Dot Matrix Printer")
+
+
+//-------------------------------------------------
+// mps1200_device - constructor
+//-------------------------------------------------
+
+mps1200_device::mps1200_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, type, tag, owner, clock)
+ , device_cbm_iec_interface(mconfig, *this)
+ , m_mpscpu(*this, "mpscpu")
+{
+}
+
+mps1200_device::mps1200_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : mps1200_device(mconfig, MPS1200, tag, owner, clock)
+{
+}
+
+
+//-------------------------------------------------
+// mps1250_device - constructor
+//-------------------------------------------------
+
+mps1250_device::mps1250_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : mps1200_device(mconfig, MPS1250, tag, owner, clock)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void mps1200_device::device_start()
+{
+}
+
+
+//-------------------------------------------------
+// cbm_iec_atn - ATN line handler
+//-------------------------------------------------
+
+void mps1200_device::cbm_iec_atn(int state)
+{
+ // TODO
+}
+
+
+//-------------------------------------------------
+// cbm_iec_data - serial data line handler
+//-------------------------------------------------
+
+void mps1200_device::cbm_iec_data(int state)
+{
+ // TODO
+}
+
+
+//-------------------------------------------------
+// cbm_iec_reset - reset line handler
+//-------------------------------------------------
+
+void mps1200_device::cbm_iec_reset(int state)
+{
+ // TODO
+}
+
+
+//-------------------------------------------------
+// mem_map - address map for main memory space
+//-------------------------------------------------
+
+void mps1200_device::mem_map(address_map &map)
+{
+ map(0x0000, 0x1fff).mirror(0x6000).ram().share("ram"); // M5M5165P-12
+ map(0x8000, 0xffff).rom().region("firmware", 0x8000);
+}
+
+
+//-------------------------------------------------
+// data_map - address map for data memory space
+//-------------------------------------------------
+
+void mps1200_device::data_map(address_map &map)
+{
+ map(0x0000, 0x1fff).mirror(0x6000).ram().share("ram");
+ map(0x8000, 0xffff).rom().region("firmware", 0);
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - device-specific config
+//-------------------------------------------------
+
+void mps1200_device::device_add_mconfig(machine_config &config)
+{
+ M50734(config, m_mpscpu, 8_MHz_XTAL);
+ m_mpscpu->set_addrmap(AS_PROGRAM, &mps1200_device::mem_map);
+ m_mpscpu->set_addrmap(AS_DATA, &mps1200_device::data_map);
+}
+
+
+//**************************************************************************
+// INPUT PORTS
+//**************************************************************************
+
+static INPUT_PORTS_START(mps1200)
+ PORT_START("SW")
+ PORT_DIPNAME(0x0080, 0x0080, "Device Number" ) PORT_DIPLOCATION("SW1:1")
+ PORT_DIPSETTING(0x0080, "4" )
+ PORT_DIPSETTING(0x0000, "5" )
+ PORT_DIPNAME(0x0040, 0x0040, "ASCII Translation" ) PORT_DIPLOCATION("SW1:2")
+ PORT_DIPSETTING(0x0040, "PET ASCII" )
+ PORT_DIPSETTING(0x0000, "ASCII" ) // access to full ascii character set
+ PORT_DIPNAME(0x0020, 0x0020, "Control Code Mode" ) PORT_DIPLOCATION("SW1:3")
+ PORT_DIPSETTING(0x0020, "Commodore" )
+ PORT_DIPSETTING(0x0000, "Epson FX" ) // access to escape control codes when using Epson printer driver (software-specific use)
+ PORT_DIPNAME(0x0010, 0x0010, "Print Quality" ) PORT_DIPLOCATION("SW1:4")
+ PORT_DIPSETTING(0x0010, "Draft" )
+ PORT_DIPSETTING(0x0000, "NLQ" )
+ PORT_DIPNAME(0x0008, 0x0008, "Page Length" ) PORT_DIPLOCATION("SW1:5")
+ PORT_DIPSETTING(0x0008, "11 inch" )
+ PORT_DIPSETTING(0x0000, "12 inch" )
+ PORT_DIPNAME(0x0004, 0x0000, "Paper End Detect" ) PORT_DIPLOCATION("SW1:6")
+ PORT_DIPSETTING(0x0004, "Enabled" ) // when enabled printer stops printing 2 inches before end of page and beeps to change paper
+ PORT_DIPSETTING(0x0000, "Disabled" ) // so generally leave this disabled (ON) to allow printing closer to the end of a page
+ PORT_DIPNAME(0x0002, 0x0002, "Automatic Line Feed" ) PORT_DIPLOCATION("SW1:7") // only does something if sw1:3 is on, otherwise ignored
+ PORT_DIPSETTING(0x0002, "Disabled" )
+ PORT_DIPSETTING(0x0000, "Enabled" )
+ PORT_DIPNAME(0x0001, 0x0001, "Character Spacing" ) PORT_DIPLOCATION("SW1:8")
+ PORT_DIPSETTING(0x0001, "Pica / 10 cpi" ) // 10 characters per inch (standard character spacing)
+ PORT_DIPSETTING(0x0000, "Compressed / 17 cpi") // 17 characters per inch
+
+ PORT_DIPNAME(0xe000, 0xe000, "International Character Set" ) PORT_DIPLOCATION("SW2:1,2,3")
+ PORT_DIPSETTING(0xe000, "US/UK/Netherlands" ) // off off off US/UK/Netherlands (default all off)
+ PORT_DIPSETTING(0xc000, "Switzerland" ) // on on off Switzerland
+ PORT_DIPSETTING(0xa000, "Italy" ) // on off on Italy
+ PORT_DIPSETTING(0x8000, DEF_STR(Unused)) // on off off Unused
+ PORT_DIPSETTING(0x6000, "France/Belgium" ) // off on on France/Belgium
+ PORT_DIPSETTING(0x4000, "Sweden/Finland" ) // off on off Sweden/Finland
+ PORT_DIPSETTING(0x2000, "Denmark/Norway" ) // off off on Denmark/Norway
+ PORT_DIPSETTING(0x0000, "Spain" ) // on on on Spain
+ PORT_DIPNAME(0x1000, 0x1000, DEF_STR(Unused)) PORT_DIPLOCATION("SW2:4")
+ PORT_DIPSETTING(0x1000, DEF_STR(Off))
+ PORT_DIPSETTING(0x0000, DEF_STR(On))
+ PORT_BIT(0x0f00, IP_ACTIVE_HIGH, IPT_UNUSED)
+INPUT_PORTS_END
+
+static INPUT_PORTS_START(mps1250) // all DIP switches correct as per manual
+ PORT_START("SW") // all off = acts like Commodore VIC-1525 or MPS-803
+ PORT_DIPNAME(0x0080, 0x0080, "Interface" ) PORT_DIPLOCATION("SW1:1")
+ PORT_DIPSETTING(0x0080, "Commodore Serial IEC" ) // use with VIC20/C64/C128
+ PORT_DIPSETTING(0x0000, "Parallel" ) // use with PC or Amiga
+
+// when sw1:1 is off (IEC mode) these settings apply....
+ PORT_DIPNAME(0x0040, 0x0040, "ASCII Translation" ) PORT_DIPLOCATION("SW1:2") PORT_CONDITION("SW", 0x80, EQUALS, 0x80)
+ PORT_DIPSETTING(0x0040, "PET ASCII" )
+ PORT_DIPSETTING(0x0000, "ASCII" ) // access to full ascii character set
+ PORT_DIPNAME(0x0020, 0x0020, "Control Code Mode" ) PORT_DIPLOCATION("SW1:3") PORT_CONDITION("SW", 0x80, EQUALS, 0x80)
+ PORT_DIPSETTING(0x0020, "Commodore" )
+ PORT_DIPSETTING(0x0000, "Epson FX" ) // access to escape control codes when using Epson printer driver (software-specific use)
+ PORT_DIPNAME(0x0010, 0x0010, "Print Quality" ) PORT_DIPLOCATION("SW1:4") PORT_CONDITION("SW", 0x80, EQUALS, 0x80)
+ PORT_DIPSETTING(0x0010, "Draft" )
+ PORT_DIPSETTING(0x0000, "NLQ" )
+ PORT_DIPNAME(0x0008, 0x0008, "Device Number" ) PORT_DIPLOCATION("SW1:5") PORT_CONDITION("SW", 0x80, EQUALS, 0x80)
+ PORT_DIPSETTING(0x0008, "4" )
+ PORT_DIPSETTING(0x0000, "5" )
+ PORT_DIPNAME(0x0004, 0x0000, "Paper End Detect" ) PORT_DIPLOCATION("SW1:6") PORT_CONDITION("SW", 0x80, EQUALS, 0x80)
+ PORT_DIPSETTING(0x0004, "Enabled" ) // when enabled printer stops printing 2 inches before end of page and beeps to change paper
+ PORT_DIPSETTING(0x0000, "Disabled" ) // so generally leave this disabled (ON) to allow printing closer to the end of a page
+ PORT_DIPNAME(0x0002, 0x0002, "Automatic Line Feed" ) PORT_DIPLOCATION("SW1:7") PORT_CONDITION("SW", 0x80, EQUALS, 0x80) // only does something if sw1:3 is on, otherwise ignored
+ PORT_DIPSETTING(0x0002, "Disabled" )
+ PORT_DIPSETTING(0x0000, "Enabled" ) // adds a line feed to each carriage return received
+ PORT_DIPNAME(0x0001, 0x0001, "Character Spacing" ) PORT_DIPLOCATION("SW1:8") PORT_CONDITION("SW", 0x80, EQUALS, 0x80)
+ PORT_DIPSETTING(0x0001, "Pica / 10 cpi" ) // 10 characters per inch (standard character spacing)
+ PORT_DIPSETTING(0x0000, "Compressed / 17 cpi") // 17 characters per inch
+
+// when sw1:1 is on (parallel mode) these settings apply....
+ PORT_DIPNAME(0x0040, 0x0040, "Automatic Line Feed" ) PORT_DIPLOCATION("SW1:2") PORT_CONDITION("SW", 0x80, EQUALS, 0x00)
+ PORT_DIPSETTING(0x0040, "Disabled" )
+ PORT_DIPSETTING(0x0000, "Enabled" ) // adds a line feed (LF) to each carriage return received
+ PORT_DIPNAME(0x0030, 0x0030, "Printer Configuration" ) PORT_DIPLOCATION("SW1:3,4") PORT_CONDITION("SW", 0x80, EQUALS, 0x00)
+ PORT_DIPSETTING(0x0030, "Epson #1" ) // off off (best for use with Amiga or PC and Epson printer driver)
+ PORT_DIPSETTING(0x0020, "Epson #2" ) // on off (gives access to full list of international character sets)
+ PORT_DIPSETTING(0x0010, "Epson #3" ) // off on (gives access to partial list of international character sets and other options)
+ PORT_DIPSETTING(0x0000, "IBM Graphics Printer" ) // on on (for use with IBM-compatible PC)
+
+// when Epson #1 is selected these settings apply....
+ PORT_DIPNAME(0x0008, 0x0008, "ASCII Codes 128-159" ) PORT_DIPLOCATION("SW1:5") PORT_CONDITION("SW", 0xb0, EQUALS, 0x30)
+ PORT_DIPSETTING(0x0008, "High-bit Control Codes" ) // standard characters
+ PORT_DIPSETTING(0x0000, "Line and Block Graphics" ) // graphics characters
+ PORT_DIPNAME(0x0004, 0x0004, "Zero" ) PORT_DIPLOCATION("SW1:6") PORT_CONDITION("SW", 0xb0, EQUALS, 0x30)
+ PORT_DIPSETTING(0x0004, "Not Slashed" )
+ PORT_DIPSETTING(0x0000, "Slashed" )
+ PORT_DIPNAME(0x0002, 0x0002, "Print Quality" ) PORT_DIPLOCATION("SW1:7") PORT_CONDITION("SW", 0xb0, EQUALS, 0x30) // only active if sw1:3 is on
+ PORT_DIPSETTING(0x0002, "Draft" )
+ PORT_DIPSETTING(0x0000, "NLQ" )
+ PORT_DIPNAME(0x0001, 0x0001, "Character Spacing" ) PORT_DIPLOCATION("SW1:8") PORT_CONDITION("SW", 0xb0, EQUALS, 0x30)
+ PORT_DIPSETTING(0x0001, "Pica / 10 cpi" ) // 10 characters per inch (standard character spacing)
+ PORT_DIPSETTING(0x0000, "Compressed / 17 cpi") // 17 characters per inch
+
+// when Epson #2 is selected these settings apply....
+ PORT_DIPNAME(0x000e, 0x000e, "International Character Set" ) PORT_DIPLOCATION("SW1:5,6,7") PORT_CONDITION("SW", 0xb0, EQUALS, 0x20)
+ PORT_DIPSETTING(0x000e, "USA" ) // off off off USA
+ PORT_DIPSETTING(0x000c, "England" ) // on on off England
+ PORT_DIPSETTING(0x000a, "Sweden" ) // on off on Sweden
+ PORT_DIPSETTING(0x0008, "France" ) // on off off Unused
+ PORT_DIPSETTING(0x0006, "Italy" ) // off on on Italy
+ PORT_DIPSETTING(0x0004, "Germany" ) // off on off Germany
+ PORT_DIPSETTING(0x0002, "Denmark" ) // off off on Denmark
+ PORT_DIPSETTING(0x0000, "Spain" ) // on on on Spain
+ PORT_DIPNAME(0x0001, 0x0001, "Page Length" ) PORT_DIPLOCATION("SW1:8") PORT_CONDITION("SW", 0xb0, EQUALS, 0x20)
+ PORT_DIPSETTING(0x0001, "11 inch" )
+ PORT_DIPSETTING(0x0000, "12 inch" )
+
+// when Epson #3 is selected these settings apply....
+ PORT_DIPNAME(0x0008, 0x0008, "ASCII Codes 128-159" ) PORT_DIPLOCATION("SW1:5") PORT_CONDITION("SW", 0xb0, EQUALS, 0x10)
+ PORT_DIPSETTING(0x0008, "High-bit Control Codes" ) // standard characters
+ PORT_DIPSETTING(0x0000, "Line and Block Graphics" ) // graphics characters
+ PORT_DIPNAME(0x0006, 0x0006, "International Character Set" ) PORT_DIPLOCATION("SW1:6,7") PORT_CONDITION("SW", 0xb0, EQUALS, 0x10)
+ PORT_DIPSETTING(0x0006, "USA" ) // off off USA
+ PORT_DIPSETTING(0x0004, "France" ) // on off France
+ PORT_DIPSETTING(0x0002, "Germany" ) // off on Germany
+ PORT_DIPSETTING(0x0000, "England" ) // on on England
+ PORT_DIPNAME(0x0001, 0x0001, "Character Spacing" ) PORT_DIPLOCATION("SW1:8") PORT_CONDITION("SW", 0xb0, EQUALS, 0x10)
+ PORT_DIPSETTING(0x0001, "Pica / 10 cpi" ) // 10 characters per inch (standard character spacing)
+ PORT_DIPSETTING(0x0000, "Compressed / 17 cpi") // 17 characters per inch
+
+// when IBM Graphics Printer #1 is selected these settings apply....
+ PORT_DIPNAME(0x0008, 0x0008, "ASCII Codes 128-159" ) PORT_DIPLOCATION("SW1:5") PORT_CONDITION("SW", 0xb0, EQUALS, 0x00)
+ PORT_DIPSETTING(0x0008, "High-bit Control Codes" ) // IBM-graphics set 1
+ PORT_DIPSETTING(0x0000, "Accented Characters" ) // IBM-graphics set 2
+ PORT_DIPNAME(0x0004, 0x0004, "Line Spacing" ) PORT_DIPLOCATION("SW1:6") PORT_CONDITION("SW", 0xb0, EQUALS, 0x00)
+ PORT_DIPSETTING(0x0004, "1/6 inch" )
+ PORT_DIPSETTING(0x0000, "1/8 inch" )
+ PORT_DIPNAME(0x0002, 0x0002, "Auto Carriage Return" ) PORT_DIPLOCATION("SW1:7") PORT_CONDITION("SW", 0xb0, EQUALS, 0x00)
+ PORT_DIPSETTING(0x0002, "Enabled" ) // carriage return (CR) is inserted when printer receives a line feed
+ PORT_DIPSETTING(0x0000, "Disabled" )
+ PORT_DIPNAME(0x0001, 0x0001, "Buffer-Full Printing" ) PORT_DIPLOCATION("SW1:8") PORT_CONDITION("SW", 0xb0, EQUALS, 0x00)
+ PORT_DIPSETTING(0x0001, "Enabled" ) // Determines how the printer acts when receiving more characters than will fit on one line without a
+ PORT_DIPSETTING(0x0000, "Disabled" ) // carriage return received. 'Enabled' will insert a line feed at the right hard margin and 'disabled'
+ // will return the carriage to the left margin and the remaining characters will overwrite the line.
+ PORT_BIT(0x0f00, IP_ACTIVE_HIGH, IPT_UNUSED)
+INPUT_PORTS_END
+
+
+//-------------------------------------------------
+// device_input_ports - device-specific ports
+//-------------------------------------------------
+
+ioport_constructor mps1200_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(mps1200);
+}
+
+ioport_constructor mps1250_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(mps1250);
+}
+
+
+//**************************************************************************
+// ROM DEFINITIONS
+//**************************************************************************
+
+ROM_START(mps1200)
+ ROM_REGION(0x10000, "firmware", 0)
+ ROM_LOAD("mps1200-k405-0202.bin", 0x00000, 0x10000, CRC(87aa884a) SHA1(0ceb753c17599bc69458cfbb1cb3e81c2b60d107)) // "VER 1.01" "JUL-24-86" "Y8306 COMMODORE B.I.P."
+ROM_END
+
+ROM_START(mps1250)
+ ROM_REGION(0x10000, "firmware", 0)
+ ROM_LOAD("mps1250_k111_0201.bin", 0x00000, 0x10000, CRC(f2de9b69) SHA1(bb7357e83497b333e3f95548d94970003b2dfa9d)) // "VER 1.34" "MAR-03-87" "Y8307 COMMODORE DUAL B.I.P."
+ROM_END
+
+//-------------------------------------------------
+// device_rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const tiny_rom_entry *mps1200_device::device_rom_region() const
+{
+ return ROM_NAME(mps1200);
+}
+
+const tiny_rom_entry *mps1250_device::device_rom_region() const
+{
+ return ROM_NAME(mps1250);
+}
diff --git a/src/devices/bus/cbmiec/mps1200.h b/src/devices/bus/cbmiec/mps1200.h
new file mode 100644
index 00000000000..7d72b70d3ee
--- /dev/null
+++ b/src/devices/bus/cbmiec/mps1200.h
@@ -0,0 +1,70 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/**********************************************************************
+
+ Commodore MPS-1200 & MPS-1250 printers
+
+**********************************************************************/
+
+#ifndef MAME_BUS_CBMIEC_MPS1200_H
+#define MAME_BUS_CBMIEC_MPS1200_H
+
+#pragma once
+
+#include "cbmiec.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> mps1200_device
+
+class mps1200_device : public device_t, public device_cbm_iec_interface
+{
+public:
+ // device type constructor
+ mps1200_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ static constexpr feature_type unemulated_features() { return feature::PRINTER; }
+
+protected:
+ mps1200_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual ioport_constructor device_input_ports() const override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+ // device_cbm_iec_interface overrides
+ void cbm_iec_atn(int state) override;
+ void cbm_iec_data(int state) override;
+ void cbm_iec_reset(int state) override;
+
+private:
+ void mem_map(address_map &map);
+ void data_map(address_map &map);
+
+ required_device<cpu_device> m_mpscpu;
+};
+
+// ======================> mps1250_device
+
+class mps1250_device : public mps1200_device
+{
+public:
+ // device type constructor
+ mps1250_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual ioport_constructor device_input_ports() const override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+};
+
+
+// device type declarations
+DECLARE_DEVICE_TYPE(MPS1200, mps1200_device)
+DECLARE_DEVICE_TYPE(MPS1250, mps1250_device)
+
+#endif // MAME_BUS_CBMIEC_MPS1200_H
diff --git a/src/devices/bus/cbmiec/vic1520.cpp b/src/devices/bus/cbmiec/vic1520.cpp
index 8e535c230e6..c77175fb83b 100644
--- a/src/devices/bus/cbmiec/vic1520.cpp
+++ b/src/devices/bus/cbmiec/vic1520.cpp
@@ -41,14 +41,6 @@ PD7 Y MOTOR COM D
//**************************************************************************
-// MACROS / CONSTANTS
-//**************************************************************************
-
-#define M6500_1_TAG "u1"
-
-
-
-//**************************************************************************
// DEVICE DEFINITIONS
//**************************************************************************
@@ -60,7 +52,7 @@ DEFINE_DEVICE_TYPE(VIC1520, vic1520_device, "vic1520", "VIC-1520 Color Printer P
//-------------------------------------------------
ROM_START( vic1520 )
- ROM_REGION( 0x800, M6500_1_TAG, 0 )
+ ROM_REGION( 0x800, "mcu", 0 )
ROM_SYSTEM_BIOS( 0, "r01", "325340-01" )
ROMX_LOAD( "325340-01.u1", 0x000, 0x800, CRC(3757da6f) SHA1(8ab43603f74b0f269bbe890d1939a9ae31307eb1), ROM_BIOS(0) )
ROM_SYSTEM_BIOS( 1, "r03", "325340-03" )
@@ -79,25 +71,17 @@ const tiny_rom_entry *vic1520_device::device_rom_region() const
//-------------------------------------------------
-// ADDRESS_MAP( vic1520_mem )
-//-------------------------------------------------
-
-void vic1520_device::vic1520_mem(address_map &map)
-{
- map.global_mask(0xfff);
- map(0x000, 0x03f).ram();
- map(0x800, 0xfff).rom().region(M6500_1_TAG, 0);
-}
-
-
-//-------------------------------------------------
// device_add_mconfig - add device configuration
//-------------------------------------------------
void vic1520_device::device_add_mconfig(machine_config &config)
{
- m6502_device &cpu(M6502(config, M6500_1_TAG, XTAL(2'000'000))); // M6500/1
- cpu.set_addrmap(AS_PROGRAM, &vic1520_device::vic1520_mem);
+ M6500_1(config, m_mcu, 2_MHz_XTAL); // MPS 6500/1
+ m_mcu->pa_out_cb().set(FUNC(vic1520_device::port_w));
+ m_mcu->pb_in_cb().set(FUNC(vic1520_device::select_r));
+ m_mcu->pb_out_cb().set(FUNC(vic1520_device::led_w));
+ m_mcu->pc_out_cb().set(FUNC(vic1520_device::pen_w));
+ m_mcu->pd_out_cb().set(FUNC(vic1520_device::motor_w));
}
@@ -128,9 +112,11 @@ ioport_constructor vic1520_device::device_input_ports() const
// vic1520_device - constructor
//-------------------------------------------------
-vic1520_device::vic1520_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, VIC1520, tag, owner, clock),
- device_cbm_iec_interface(mconfig, *this)
+vic1520_device::vic1520_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, VIC1520, tag, owner, clock)
+ , device_cbm_iec_interface(mconfig, *this)
+ , m_mcu(*this, "mcu")
+ , m_pa_data(0xff)
{
}
@@ -141,24 +127,45 @@ vic1520_device::vic1520_device(const machine_config &mconfig, const char *tag, d
void vic1520_device::device_start()
{
+ save_item(NAME(m_pa_data));
}
//-------------------------------------------------
-// device_reset - device-specific reset
+// cbm_iec_atn -
//-------------------------------------------------
-void vic1520_device::device_reset()
+void vic1520_device::cbm_iec_atn(int state)
{
+ if (state && BIT(m_pa_data, 0))
+ {
+ m_pa_data &= 0xfe;
+ m_mcu->pa_w(m_pa_data);
+ }
+ else if (!state && !BIT(m_pa_data, 0))
+ {
+ m_pa_data |= 0x01;
+ m_mcu->pa_w(m_pa_data);
+ }
}
//-------------------------------------------------
-// cbm_iec_atn -
+// cbm_iec_clk -
//-------------------------------------------------
-void vic1520_device::cbm_iec_atn(int state)
+void vic1520_device::cbm_iec_clk(int state)
{
+ if (state && BIT(m_pa_data, 1))
+ {
+ m_pa_data &= 0xfd;
+ m_mcu->pa_w(m_pa_data);
+ }
+ else if (!state && !BIT(m_pa_data, 1))
+ {
+ m_pa_data |= 0x02;
+ m_mcu->pa_w(m_pa_data);
+ }
}
@@ -168,6 +175,16 @@ void vic1520_device::cbm_iec_atn(int state)
void vic1520_device::cbm_iec_data(int state)
{
+ if (state && BIT(m_pa_data, 7))
+ {
+ m_pa_data &= 0x7f;
+ m_mcu->pa_w(m_pa_data);
+ }
+ else if (!state && !BIT(m_pa_data, 7))
+ {
+ m_pa_data |= 0x80;
+ m_mcu->pa_w(m_pa_data);
+ }
}
@@ -177,8 +194,52 @@ void vic1520_device::cbm_iec_data(int state)
void vic1520_device::cbm_iec_reset(int state)
{
- if (!state)
- {
- device_reset();
- }
+ m_mcu->set_input_line(INPUT_LINE_RESET, state ? CLEAR_LINE : ASSERT_LINE);
+}
+
+
+//-------------------------------------------------
+// port_w - issue response on data line
+//-------------------------------------------------
+
+void vic1520_device::port_w(u8 data)
+{
+ m_bus->data_w(this, !BIT(data, 6) && (data & 0x21) != 0x01);
+}
+
+
+//-------------------------------------------------
+// select_r -
+//-------------------------------------------------
+
+u8 vic1520_device::select_r()
+{
+ return 0xff;
+}
+
+
+//-------------------------------------------------
+// led_w -
+//-------------------------------------------------
+
+void vic1520_device::led_w(u8 data)
+{
+}
+
+
+//-------------------------------------------------
+// pen_w -
+//-------------------------------------------------
+
+void vic1520_device::pen_w(u8 data)
+{
+}
+
+
+//-------------------------------------------------
+// motor_w -
+//-------------------------------------------------
+
+void vic1520_device::motor_w(u8 data)
+{
}
diff --git a/src/devices/bus/cbmiec/vic1520.h b/src/devices/bus/cbmiec/vic1520.h
index 2ba2520d7c5..37659c19942 100644
--- a/src/devices/bus/cbmiec/vic1520.h
+++ b/src/devices/bus/cbmiec/vic1520.h
@@ -12,7 +12,7 @@
#pragma once
#include "cbmiec.h"
-#include "cpu/m6502/m6502.h"
+#include "cpu/m6502/m6500_1.h"
@@ -26,12 +26,11 @@ class vic1520_device : public device_t, public device_cbm_iec_interface
{
public:
// construction/destruction
- vic1520_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ vic1520_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
protected:
// device-level overrides
virtual void device_start() override;
- virtual void device_reset() override;
// optional information overrides
virtual const tiny_rom_entry *device_rom_region() const override;
@@ -40,11 +39,20 @@ protected:
// device_cbm_iec_interface overrides
void cbm_iec_atn(int state) override;
+ void cbm_iec_clk(int state) override;
void cbm_iec_data(int state) override;
void cbm_iec_reset(int state) override;
private:
- void vic1520_mem(address_map &map);
+ void port_w(u8 data);
+ u8 select_r();
+ void led_w(u8 data);
+ void pen_w(u8 data);
+ void motor_w(u8 data);
+
+ required_device<m6500_1_device> m_mcu;
+
+ u8 m_pa_data;
};
diff --git a/src/devices/bus/cbus/mpu_pc98.cpp b/src/devices/bus/cbus/mpu_pc98.cpp
index 2ba192d4b0d..bd06c177aae 100644
--- a/src/devices/bus/cbus/mpu_pc98.cpp
+++ b/src/devices/bus/cbus/mpu_pc98.cpp
@@ -30,7 +30,7 @@ DIP-SWs
1 irq3
*/
-WRITE_LINE_MEMBER( mpu_pc98_device::mpu_irq_out )
+void mpu_pc98_device::mpu_irq_out(int state)
{
}
diff --git a/src/devices/bus/cbus/mpu_pc98.h b/src/devices/bus/cbus/mpu_pc98.h
index 798f8b8f11e..59bbf542166 100644
--- a/src/devices/bus/cbus/mpu_pc98.h
+++ b/src/devices/bus/cbus/mpu_pc98.h
@@ -30,7 +30,7 @@ protected:
private:
// called back by the MPU401 core to set the IRQ line state
- DECLARE_WRITE_LINE_MEMBER(mpu_irq_out);
+ void mpu_irq_out(int state);
void map(address_map &map);
diff --git a/src/devices/bus/cbus/pc9801_118.cpp b/src/devices/bus/cbus/pc9801_118.cpp
index 403a23b4658..c1326270ffc 100644
--- a/src/devices/bus/cbus/pc9801_118.cpp
+++ b/src/devices/bus/cbus/pc9801_118.cpp
@@ -37,7 +37,7 @@
// device type definition
DEFINE_DEVICE_TYPE(PC9801_118, pc9801_118_device, "pc9801_118", "NEC PC-9801-118")
-WRITE_LINE_MEMBER(pc9801_118_device::sound_irq)
+void pc9801_118_device::sound_irq(int state)
{
// TODO: sometimes misfired irq causes sound or even host hang
m_bus->int_w<5>(state);
diff --git a/src/devices/bus/cbus/pc9801_118.h b/src/devices/bus/cbus/pc9801_118.h
index 94ac3bfe24c..f847307413f 100644
--- a/src/devices/bus/cbus/pc9801_118.h
+++ b/src/devices/bus/cbus/pc9801_118.h
@@ -52,7 +52,7 @@ private:
uint8_t m_ext_reg;
- DECLARE_WRITE_LINE_MEMBER(sound_irq);
+ void sound_irq(int state);
};
diff --git a/src/devices/bus/cbus/pc9801_26.cpp b/src/devices/bus/cbus/pc9801_26.cpp
index 8f8b15740bd..c98e6d56ca2 100644
--- a/src/devices/bus/cbus/pc9801_26.cpp
+++ b/src/devices/bus/cbus/pc9801_26.cpp
@@ -27,7 +27,7 @@
// device type definition
DEFINE_DEVICE_TYPE(PC9801_26, pc9801_26_device, "pc9801_26", "NEC PC-9801-26")
-WRITE_LINE_MEMBER(pc9801_26_device::sound_irq)
+void pc9801_26_device::sound_irq(int state)
{
// TODO: sometimes misfired irq causes sound or even host hang
m_bus->int_w<5>(state);
diff --git a/src/devices/bus/cbus/pc9801_26.h b/src/devices/bus/cbus/pc9801_26.h
index 80cd57a20cd..3b18abfd66d 100644
--- a/src/devices/bus/cbus/pc9801_26.h
+++ b/src/devices/bus/cbus/pc9801_26.h
@@ -45,7 +45,7 @@ private:
required_device<pc9801_slot_device> m_bus;
required_device<ym2203_device> m_opn;
- DECLARE_WRITE_LINE_MEMBER(sound_irq);
+ void sound_irq(int state);
u32 m_rom_base;
};
diff --git a/src/devices/bus/cbus/pc9801_55.cpp b/src/devices/bus/cbus/pc9801_55.cpp
index 879ad2f1a66..f9cee085d2c 100644
--- a/src/devices/bus/cbus/pc9801_55.cpp
+++ b/src/devices/bus/cbus/pc9801_55.cpp
@@ -56,7 +56,7 @@ const tiny_rom_entry *pc9801_55l_device::device_rom_region() const
// device_add_mconfig - add device configuration
//-------------------------------------------------
-WRITE_LINE_MEMBER(pc9801_55_device::scsi_irq_w)
+void pc9801_55_device::scsi_irq_w(int state)
{
// TODO: should be INT3, but BIOS configures as INT0 somewhere (unhandled dip reading?)
m_bus->int_w<0>(state);
diff --git a/src/devices/bus/cbus/pc9801_55.h b/src/devices/bus/cbus/pc9801_55.h
index b74c754c2b8..0b20fc1f588 100644
--- a/src/devices/bus/cbus/pc9801_55.h
+++ b/src/devices/bus/cbus/pc9801_55.h
@@ -31,7 +31,7 @@ public:
static constexpr feature_type unemulated_features() { return feature::DISK; }
- DECLARE_WRITE_LINE_MEMBER(scsi_irq_w);
+ void scsi_irq_w(int state);
protected:
// device-level overrides
diff --git a/src/devices/bus/cbus/pc9801_86.cpp b/src/devices/bus/cbus/pc9801_86.cpp
index 740906357c5..a474e33cc6d 100644
--- a/src/devices/bus/cbus/pc9801_86.cpp
+++ b/src/devices/bus/cbus/pc9801_86.cpp
@@ -44,7 +44,7 @@
// device type definition
DEFINE_DEVICE_TYPE(PC9801_86, pc9801_86_device, "pc9801_86", "NEC PC-9801-86")
-WRITE_LINE_MEMBER(pc9801_86_device::sound_irq)
+void pc9801_86_device::sound_irq(int state)
{
m_fmirq = state ? true : false;
// TODO: sometimes misfired irq causes sound or even host hang
diff --git a/src/devices/bus/cbus/pc9801_86.h b/src/devices/bus/cbus/pc9801_86.h
index 7903f11e0b9..70102a03907 100644
--- a/src/devices/bus/cbus/pc9801_86.h
+++ b/src/devices/bus/cbus/pc9801_86.h
@@ -29,7 +29,7 @@ public:
pc9801_86_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
pc9801_86_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_WRITE_LINE_MEMBER(sound_irq);
+ void sound_irq(int state);
protected:
// device-level overrides
diff --git a/src/devices/bus/cbus/pc9801_cbus.cpp b/src/devices/bus/cbus/pc9801_cbus.cpp
index 9077d8cc4ea..5f6dfce58a7 100644
--- a/src/devices/bus/cbus/pc9801_cbus.cpp
+++ b/src/devices/bus/cbus/pc9801_cbus.cpp
@@ -88,18 +88,6 @@ void pc9801_slot_device::device_config_complete()
//-------------------------------------------------
-// device_resolve_objects - resolve objects that
-// may be needed for other devices to set
-// initial conditions at start time
-//-------------------------------------------------
-
-void pc9801_slot_device::device_resolve_objects()
-{
- m_int_callback.resolve_all_safe();
-}
-
-
-//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
diff --git a/src/devices/bus/cbus/pc9801_cbus.h b/src/devices/bus/cbus/pc9801_cbus.h
index ab7085dfa86..e59f76bf096 100644
--- a/src/devices/bus/cbus/pc9801_cbus.h
+++ b/src/devices/bus/cbus/pc9801_cbus.h
@@ -116,10 +116,9 @@ public:
void flush_install_io(const char *client_tag, u16 old_io, u16 new_io, u16 size, read8sm_delegate rhandler, write8sm_delegate whandler);
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
virtual void device_config_complete() override;
- virtual void device_resolve_objects() override;
private:
// device_pc9801_slot_card_interface *m_card;
diff --git a/src/devices/bus/centronics/chessmec.h b/src/devices/bus/centronics/chessmec.h
index 07bbd8970c3..60596c347cc 100644
--- a/src/devices/bus/centronics/chessmec.h
+++ b/src/devices/bus/centronics/chessmec.h
@@ -27,9 +27,9 @@ protected:
virtual void device_start() override { }
virtual void device_add_mconfig(machine_config &config) override;
- virtual DECLARE_WRITE_LINE_MEMBER(input_data0) override { if (started()) m_chessm->data0_w(state); }
- virtual DECLARE_WRITE_LINE_MEMBER(input_data1) override { if (started()) m_chessm->reset_w(state); }
- virtual DECLARE_WRITE_LINE_MEMBER(input_data7) override { if (started()) m_chessm->data1_w(state); }
+ virtual void input_data0(int state) override { if (started()) m_chessm->data0_w(state); }
+ virtual void input_data1(int state) override { if (started()) m_chessm->reset_w(state); }
+ virtual void input_data7(int state) override { if (started()) m_chessm->data1_w(state); }
private:
required_device<chessmachine_device> m_chessm;
diff --git a/src/devices/bus/centronics/comxpl80.h b/src/devices/bus/centronics/comxpl80.h
index f64a31da6d0..f01bb29008a 100644
--- a/src/devices/bus/centronics/comxpl80.h
+++ b/src/devices/bus/centronics/comxpl80.h
@@ -38,14 +38,14 @@ protected:
virtual void device_add_mconfig(machine_config &config) override;
virtual ioport_constructor device_input_ports() const override;
- virtual DECLARE_WRITE_LINE_MEMBER( input_data0 ) override { if (state) m_data |= 0x01; else m_data &= ~0x01; }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data1 ) override { if (state) m_data |= 0x02; else m_data &= ~0x02; }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data2 ) override { if (state) m_data |= 0x04; else m_data &= ~0x04; }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data3 ) override { if (state) m_data |= 0x08; else m_data &= ~0x08; }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data4 ) override { if (state) m_data |= 0x10; else m_data &= ~0x10; }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data5 ) override { if (state) m_data |= 0x20; else m_data &= ~0x20; }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data6 ) override { if (state) m_data |= 0x40; else m_data &= ~0x40; }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data7 ) override { if (state) m_data |= 0x80; else m_data &= ~0x80; }
+ virtual void input_data0(int state) override { if (state) m_data |= 0x01; else m_data &= ~0x01; }
+ virtual void input_data1(int state) override { if (state) m_data |= 0x02; else m_data &= ~0x02; }
+ virtual void input_data2(int state) override { if (state) m_data |= 0x04; else m_data &= ~0x04; }
+ virtual void input_data3(int state) override { if (state) m_data |= 0x08; else m_data &= ~0x08; }
+ virtual void input_data4(int state) override { if (state) m_data |= 0x10; else m_data &= ~0x10; }
+ virtual void input_data5(int state) override { if (state) m_data |= 0x20; else m_data &= ~0x20; }
+ virtual void input_data6(int state) override { if (state) m_data |= 0x40; else m_data &= ~0x40; }
+ virtual void input_data7(int state) override { if (state) m_data |= 0x80; else m_data &= ~0x80; }
private:
required_memory_region m_plotter;
diff --git a/src/devices/bus/centronics/covox.cpp b/src/devices/bus/centronics/covox.cpp
index d37d96ce958..4b3521b5955 100644
--- a/src/devices/bus/centronics/covox.cpp
+++ b/src/devices/bus/centronics/covox.cpp
@@ -4,6 +4,10 @@
Covox Speech Thing
+ Notes:
+ - "Jast Sound" is very similar conceptually to a Covox Speech Thing.
+ https://www.generation-msx.nl/hardware/jast/jast-sound/1638/
+
***************************************************************************/
#include "emu.h"
diff --git a/src/devices/bus/centronics/covox.h b/src/devices/bus/centronics/covox.h
index da6ed1063aa..54f80e857a0 100644
--- a/src/devices/bus/centronics/covox.h
+++ b/src/devices/bus/centronics/covox.h
@@ -30,14 +30,14 @@ protected:
// optional information overrides
virtual void device_add_mconfig(machine_config &config) override;
- virtual DECLARE_WRITE_LINE_MEMBER( input_data0 ) override { if (state) m_data |= 0x01; else m_data &= ~0x01; update_dac(); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data1 ) override { if (state) m_data |= 0x02; else m_data &= ~0x02; update_dac(); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data2 ) override { if (state) m_data |= 0x04; else m_data &= ~0x04; update_dac(); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data3 ) override { if (state) m_data |= 0x08; else m_data &= ~0x08; update_dac(); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data4 ) override { if (state) m_data |= 0x10; else m_data &= ~0x10; update_dac(); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data5 ) override { if (state) m_data |= 0x20; else m_data &= ~0x20; update_dac(); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data6 ) override { if (state) m_data |= 0x40; else m_data &= ~0x40; update_dac(); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data7 ) override { if (state) m_data |= 0x80; else m_data &= ~0x80; update_dac(); }
+ virtual void input_data0(int state) override { if (state) m_data |= 0x01; else m_data &= ~0x01; update_dac(); }
+ virtual void input_data1(int state) override { if (state) m_data |= 0x02; else m_data &= ~0x02; update_dac(); }
+ virtual void input_data2(int state) override { if (state) m_data |= 0x04; else m_data &= ~0x04; update_dac(); }
+ virtual void input_data3(int state) override { if (state) m_data |= 0x08; else m_data &= ~0x08; update_dac(); }
+ virtual void input_data4(int state) override { if (state) m_data |= 0x10; else m_data &= ~0x10; update_dac(); }
+ virtual void input_data5(int state) override { if (state) m_data |= 0x20; else m_data &= ~0x20; update_dac(); }
+ virtual void input_data6(int state) override { if (state) m_data |= 0x40; else m_data &= ~0x40; update_dac(); }
+ virtual void input_data7(int state) override { if (state) m_data |= 0x80; else m_data &= ~0x80; update_dac(); }
private:
required_device<dac_byte_interface> m_dac;
@@ -66,16 +66,16 @@ protected:
// optional information overrides
virtual void device_add_mconfig(machine_config &config) override;
- virtual DECLARE_WRITE_LINE_MEMBER( input_strobe ) override { m_strobe = state; update_dac(); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data0 ) override { if (state) m_data |= 0x01; else m_data &= ~0x01; update_dac(); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data1 ) override { if (state) m_data |= 0x02; else m_data &= ~0x02; update_dac(); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data2 ) override { if (state) m_data |= 0x04; else m_data &= ~0x04; update_dac(); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data3 ) override { if (state) m_data |= 0x08; else m_data &= ~0x08; update_dac(); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data4 ) override { if (state) m_data |= 0x10; else m_data &= ~0x10; update_dac(); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data5 ) override { if (state) m_data |= 0x20; else m_data &= ~0x20; update_dac(); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data6 ) override { if (state) m_data |= 0x40; else m_data &= ~0x40; update_dac(); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data7 ) override { if (state) m_data |= 0x80; else m_data &= ~0x80; update_dac(); if (started()) output_busy(state); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_autofd ) override { m_autofd = state; update_dac(); }
+ virtual void input_strobe(int state) override { m_strobe = state; update_dac(); }
+ virtual void input_data0(int state) override { if (state) m_data |= 0x01; else m_data &= ~0x01; update_dac(); }
+ virtual void input_data1(int state) override { if (state) m_data |= 0x02; else m_data &= ~0x02; update_dac(); }
+ virtual void input_data2(int state) override { if (state) m_data |= 0x04; else m_data &= ~0x04; update_dac(); }
+ virtual void input_data3(int state) override { if (state) m_data |= 0x08; else m_data &= ~0x08; update_dac(); }
+ virtual void input_data4(int state) override { if (state) m_data |= 0x10; else m_data &= ~0x10; update_dac(); }
+ virtual void input_data5(int state) override { if (state) m_data |= 0x20; else m_data &= ~0x20; update_dac(); }
+ virtual void input_data6(int state) override { if (state) m_data |= 0x40; else m_data &= ~0x40; update_dac(); }
+ virtual void input_data7(int state) override { if (state) m_data |= 0x80; else m_data &= ~0x80; update_dac(); if (started()) output_busy(state); }
+ virtual void input_autofd(int state) override { m_autofd = state; update_dac(); }
private:
required_device<dac_byte_interface> m_ldac;
diff --git a/src/devices/bus/centronics/ctronics.cpp b/src/devices/bus/centronics/ctronics.cpp
index 81812bc37f6..156c4e3578a 100644
--- a/src/devices/bus/centronics/ctronics.cpp
+++ b/src/devices/bus/centronics/ctronics.cpp
@@ -51,25 +51,6 @@ void centronics_device::device_reset()
void centronics_device::device_start()
{
- m_strobe_handler.resolve_safe();
- m_data0_handler.resolve_safe();
- m_data1_handler.resolve_safe();
- m_data2_handler.resolve_safe();
- m_data3_handler.resolve_safe();
- m_data4_handler.resolve_safe();
- m_data5_handler.resolve_safe();
- m_data6_handler.resolve_safe();
- m_data7_handler.resolve_safe();
- m_ack_handler.resolve_safe();
- m_busy_handler.resolve_safe();
- m_perror_handler.resolve_safe();
- m_select_handler.resolve_safe();
- m_autofd_handler.resolve_safe();
- m_fault_handler.resolve_safe();
- m_init_handler.resolve_safe();
- m_sense_handler.resolve_safe();
- m_select_in_handler.resolve_safe();
-
m_sense_handler(0);
// pull up
@@ -104,23 +85,23 @@ void centronics_device::set_output_latch(output_latch_device &latch)
latch.bit_handler<7>().set(*this, FUNC(centronics_device::write_data7));
}
-WRITE_LINE_MEMBER( centronics_device::write_strobe ) { if (m_dev) m_dev->input_strobe(state); }
-WRITE_LINE_MEMBER( centronics_device::write_data0 ) { if (m_dev) m_dev->input_data0(state); }
-WRITE_LINE_MEMBER( centronics_device::write_data1 ) { if (m_dev) m_dev->input_data1(state); }
-WRITE_LINE_MEMBER( centronics_device::write_data2 ) { if (m_dev) m_dev->input_data2(state); }
-WRITE_LINE_MEMBER( centronics_device::write_data3 ) { if (m_dev) m_dev->input_data3(state); }
-WRITE_LINE_MEMBER( centronics_device::write_data4 ) { if (m_dev) m_dev->input_data4(state); }
-WRITE_LINE_MEMBER( centronics_device::write_data5 ) { if (m_dev) m_dev->input_data5(state); }
-WRITE_LINE_MEMBER( centronics_device::write_data6 ) { if (m_dev) m_dev->input_data6(state); }
-WRITE_LINE_MEMBER( centronics_device::write_data7 ) { if (m_dev) m_dev->input_data7(state); }
-WRITE_LINE_MEMBER( centronics_device::write_ack ) { if (m_dev) m_dev->input_ack(state); }
-WRITE_LINE_MEMBER( centronics_device::write_busy ) { if (m_dev) m_dev->input_busy(state); }
-WRITE_LINE_MEMBER( centronics_device::write_perror ) { if (m_dev) m_dev->input_perror(state); }
-WRITE_LINE_MEMBER( centronics_device::write_select ) { if (m_dev) m_dev->input_select(state); }
-WRITE_LINE_MEMBER( centronics_device::write_autofd ) { if (m_dev) m_dev->input_autofd(state); }
-WRITE_LINE_MEMBER( centronics_device::write_fault ) { if (m_dev) m_dev->input_fault(state); }
-WRITE_LINE_MEMBER( centronics_device::write_init ) { if (m_dev) m_dev->input_init(state); }
-WRITE_LINE_MEMBER( centronics_device::write_select_in ) { if (m_dev) m_dev->input_select_in(state); }
+void centronics_device::write_strobe(int state) { if (m_dev) m_dev->input_strobe(state); }
+void centronics_device::write_data0(int state) { if (m_dev) m_dev->input_data0(state); }
+void centronics_device::write_data1(int state) { if (m_dev) m_dev->input_data1(state); }
+void centronics_device::write_data2(int state) { if (m_dev) m_dev->input_data2(state); }
+void centronics_device::write_data3(int state) { if (m_dev) m_dev->input_data3(state); }
+void centronics_device::write_data4(int state) { if (m_dev) m_dev->input_data4(state); }
+void centronics_device::write_data5(int state) { if (m_dev) m_dev->input_data5(state); }
+void centronics_device::write_data6(int state) { if (m_dev) m_dev->input_data6(state); }
+void centronics_device::write_data7(int state) { if (m_dev) m_dev->input_data7(state); }
+void centronics_device::write_ack(int state) { if (m_dev) m_dev->input_ack(state); }
+void centronics_device::write_busy(int state) { if (m_dev) m_dev->input_busy(state); }
+void centronics_device::write_perror(int state) { if (m_dev) m_dev->input_perror(state); }
+void centronics_device::write_select(int state) { if (m_dev) m_dev->input_select(state); }
+void centronics_device::write_autofd(int state) { if (m_dev) m_dev->input_autofd(state); }
+void centronics_device::write_fault(int state) { if (m_dev) m_dev->input_fault(state); }
+void centronics_device::write_init(int state) { if (m_dev) m_dev->input_init(state); }
+void centronics_device::write_select_in(int state) { if (m_dev) m_dev->input_select_in(state); }
// class device_centronics_peripheral_interface
@@ -142,10 +123,12 @@ device_centronics_peripheral_interface::~device_centronics_peripheral_interface(
#include "epson_lx810l.h"
#include "nec_p72.h"
#include "printer.h"
+#include "digiblst.h"
#include "covox.h"
#include "samdac.h"
#include "chessmec.h"
#include "smartboard.h"
+#include "nlq401.h"
void centronics_devices(device_slot_interface &device)
{
@@ -156,9 +139,11 @@ void centronics_devices(device_slot_interface &device)
device.option_add("ap2000", EPSON_AP2000);
device.option_add("p72", NEC_P72);
device.option_add("printer", CENTRONICS_PRINTER);
+ device.option_add("digiblst", CENTRONICS_DIGIBLASTER);
device.option_add("covox", CENTRONICS_COVOX);
device.option_add("covox_stereo", CENTRONICS_COVOX_STEREO);
device.option_add("samdac", CENTRONICS_SAMDAC);
device.option_add("chessmec", CENTRONICS_CHESSMEC);
device.option_add("smartboard", CENTRONICS_SMARTBOARD);
+ device.option_add("nlq401", NLQ401);
}
diff --git a/src/devices/bus/centronics/ctronics.h b/src/devices/bus/centronics/ctronics.h
index 44de7930cc8..15e17e3782b 100644
--- a/src/devices/bus/centronics/ctronics.h
+++ b/src/devices/bus/centronics/ctronics.h
@@ -60,23 +60,23 @@ public:
void set_output_latch(output_latch_device &latch);
- DECLARE_WRITE_LINE_MEMBER( write_strobe );
- DECLARE_WRITE_LINE_MEMBER( write_data0 );
- DECLARE_WRITE_LINE_MEMBER( write_data1 );
- DECLARE_WRITE_LINE_MEMBER( write_data2 );
- DECLARE_WRITE_LINE_MEMBER( write_data3 );
- DECLARE_WRITE_LINE_MEMBER( write_data4 );
- DECLARE_WRITE_LINE_MEMBER( write_data5 );
- DECLARE_WRITE_LINE_MEMBER( write_data6 );
- DECLARE_WRITE_LINE_MEMBER( write_data7 );
- DECLARE_WRITE_LINE_MEMBER( write_ack );
- DECLARE_WRITE_LINE_MEMBER( write_busy );
- DECLARE_WRITE_LINE_MEMBER( write_perror );
- DECLARE_WRITE_LINE_MEMBER( write_select );
- DECLARE_WRITE_LINE_MEMBER( write_autofd );
- DECLARE_WRITE_LINE_MEMBER( write_fault );
- DECLARE_WRITE_LINE_MEMBER( write_init );
- DECLARE_WRITE_LINE_MEMBER( write_select_in );
+ void write_strobe(int state);
+ void write_data0(int state);
+ void write_data1(int state);
+ void write_data2(int state);
+ void write_data3(int state);
+ void write_data4(int state);
+ void write_data5(int state);
+ void write_data6(int state);
+ void write_data7(int state);
+ void write_ack(int state);
+ void write_busy(int state);
+ void write_perror(int state);
+ void write_select(int state);
+ void write_autofd(int state);
+ void write_fault(int state);
+ void write_init(int state);
+ void write_select_in(int state);
protected:
// device-level overrides
@@ -115,44 +115,44 @@ class device_centronics_peripheral_interface : public device_interface
public:
virtual ~device_centronics_peripheral_interface();
- DECLARE_WRITE_LINE_MEMBER( output_strobe ) { m_slot->m_strobe_handler(state); }
- DECLARE_WRITE_LINE_MEMBER( output_data0 ) { m_slot->m_data0_handler(state); }
- DECLARE_WRITE_LINE_MEMBER( output_data1 ) { m_slot->m_data1_handler(state); }
- DECLARE_WRITE_LINE_MEMBER( output_data2 ) { m_slot->m_data2_handler(state); }
- DECLARE_WRITE_LINE_MEMBER( output_data3 ) { m_slot->m_data3_handler(state); }
- DECLARE_WRITE_LINE_MEMBER( output_data4 ) { m_slot->m_data4_handler(state); }
- DECLARE_WRITE_LINE_MEMBER( output_data5 ) { m_slot->m_data5_handler(state); }
- DECLARE_WRITE_LINE_MEMBER( output_data6 ) { m_slot->m_data6_handler(state); }
- DECLARE_WRITE_LINE_MEMBER( output_data7 ) { m_slot->m_data7_handler(state); }
- DECLARE_WRITE_LINE_MEMBER( output_ack ) { m_slot->m_ack_handler(state); }
- DECLARE_WRITE_LINE_MEMBER( output_busy ) { m_slot->m_busy_handler(state); }
- DECLARE_WRITE_LINE_MEMBER( output_perror ) { m_slot->m_perror_handler(state); }
- DECLARE_WRITE_LINE_MEMBER( output_select ) { m_slot->m_select_handler(state); }
- DECLARE_WRITE_LINE_MEMBER( output_autofd ) { m_slot->m_autofd_handler(state); }
- DECLARE_WRITE_LINE_MEMBER( output_fault ) { m_slot->m_fault_handler(state); }
- DECLARE_WRITE_LINE_MEMBER( output_init ) { m_slot->m_init_handler(state); }
- DECLARE_WRITE_LINE_MEMBER( output_select_in ) { m_slot->m_select_in_handler(state); }
+ void output_strobe(int state) { m_slot->m_strobe_handler(state); }
+ void output_data0(int state) { m_slot->m_data0_handler(state); }
+ void output_data1(int state) { m_slot->m_data1_handler(state); }
+ void output_data2(int state) { m_slot->m_data2_handler(state); }
+ void output_data3(int state) { m_slot->m_data3_handler(state); }
+ void output_data4(int state) { m_slot->m_data4_handler(state); }
+ void output_data5(int state) { m_slot->m_data5_handler(state); }
+ void output_data6(int state) { m_slot->m_data6_handler(state); }
+ void output_data7(int state) { m_slot->m_data7_handler(state); }
+ void output_ack(int state) { m_slot->m_ack_handler(state); }
+ void output_busy(int state) { m_slot->m_busy_handler(state); }
+ void output_perror(int state) { m_slot->m_perror_handler(state); }
+ void output_select(int state) { m_slot->m_select_handler(state); }
+ void output_autofd(int state) { m_slot->m_autofd_handler(state); }
+ void output_fault(int state) { m_slot->m_fault_handler(state); }
+ void output_init(int state) { m_slot->m_init_handler(state); }
+ void output_select_in(int state) { m_slot->m_select_in_handler(state); }
protected:
device_centronics_peripheral_interface(const machine_config &mconfig, device_t &device);
- virtual DECLARE_WRITE_LINE_MEMBER( input_strobe ) { }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data0 ) { }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data1 ) { }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data2 ) { }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data3 ) { }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data4 ) { }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data5 ) { }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data6 ) { }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data7 ) { }
- virtual DECLARE_WRITE_LINE_MEMBER( input_ack ) { }
- virtual DECLARE_WRITE_LINE_MEMBER( input_busy ) { }
- virtual DECLARE_WRITE_LINE_MEMBER( input_perror ) { }
- virtual DECLARE_WRITE_LINE_MEMBER( input_select ) { }
- virtual DECLARE_WRITE_LINE_MEMBER( input_autofd ) { }
- virtual DECLARE_WRITE_LINE_MEMBER( input_fault ) { }
- virtual DECLARE_WRITE_LINE_MEMBER( input_init ) { }
- virtual DECLARE_WRITE_LINE_MEMBER( input_select_in ) { }
+ virtual void input_strobe(int state) { }
+ virtual void input_data0(int state) { }
+ virtual void input_data1(int state) { }
+ virtual void input_data2(int state) { }
+ virtual void input_data3(int state) { }
+ virtual void input_data4(int state) { }
+ virtual void input_data5(int state) { }
+ virtual void input_data6(int state) { }
+ virtual void input_data7(int state) { }
+ virtual void input_ack(int state) { }
+ virtual void input_busy(int state) { }
+ virtual void input_perror(int state) { }
+ virtual void input_select(int state) { }
+ virtual void input_autofd(int state) { }
+ virtual void input_fault(int state) { }
+ virtual void input_init(int state) { }
+ virtual void input_select_in(int state) { }
virtual bool supports_pin35_5v() { return false; }
diff --git a/src/devices/bus/centronics/digiblst.cpp b/src/devices/bus/centronics/digiblst.cpp
index af02c153653..3b66d35b9df 100644
--- a/src/devices/bus/centronics/digiblst.cpp
+++ b/src/devices/bus/centronics/digiblst.cpp
@@ -15,7 +15,7 @@
//**************************************************************************
// device type definition
-DEFINE_DEVICE_TYPE(CENTRONICS_DIGIBLASTER, centronics_digiblaster_device, "digiblst", "Digiblaster (DIY)")
+DEFINE_DEVICE_TYPE(CENTRONICS_DIGIBLASTER, centronics_digiblaster_device, "cpcdigiblst", "Digiblaster (DIY)")
/***************************************************************************
diff --git a/src/devices/bus/centronics/digiblst.h b/src/devices/bus/centronics/digiblst.h
index 00a8246b802..cae7d7b5767 100644
--- a/src/devices/bus/centronics/digiblst.h
+++ b/src/devices/bus/centronics/digiblst.h
@@ -36,14 +36,14 @@ protected:
// optional information overrides
virtual void device_add_mconfig(machine_config &config) override;
- virtual DECLARE_WRITE_LINE_MEMBER( input_data0 ) override { if (state) m_data |= 0x01; else m_data &= ~0x01; update_dac(); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data1 ) override { if (state) m_data |= 0x02; else m_data &= ~0x02; update_dac(); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data2 ) override { if (state) m_data |= 0x04; else m_data &= ~0x04; update_dac(); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data3 ) override { if (state) m_data |= 0x08; else m_data &= ~0x08; update_dac(); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data4 ) override { if (state) m_data |= 0x10; else m_data &= ~0x10; update_dac(); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data5 ) override { if (state) m_data |= 0x20; else m_data &= ~0x20; update_dac(); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data6 ) override { if (state) m_data |= 0x40; else m_data &= ~0x40; update_dac(); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_strobe ) override { if (state) m_data &= ~0x80; else m_data |= 0x80; update_dac(); }
+ virtual void input_data0(int state) override { if (state) m_data |= 0x01; else m_data &= ~0x01; update_dac(); }
+ virtual void input_data1(int state) override { if (state) m_data |= 0x02; else m_data &= ~0x02; update_dac(); }
+ virtual void input_data2(int state) override { if (state) m_data |= 0x04; else m_data &= ~0x04; update_dac(); }
+ virtual void input_data3(int state) override { if (state) m_data |= 0x08; else m_data &= ~0x08; update_dac(); }
+ virtual void input_data4(int state) override { if (state) m_data |= 0x10; else m_data &= ~0x10; update_dac(); }
+ virtual void input_data5(int state) override { if (state) m_data |= 0x20; else m_data &= ~0x20; update_dac(); }
+ virtual void input_data6(int state) override { if (state) m_data |= 0x40; else m_data &= ~0x40; update_dac(); }
+ virtual void input_strobe(int state) override { if (state) m_data &= ~0x80; else m_data |= 0x80; update_dac(); }
private:
required_device<dac_byte_interface> m_dac;
diff --git a/src/devices/bus/centronics/dsjoy.h b/src/devices/bus/centronics/dsjoy.h
index bcb91afceed..0ae1486f1e3 100644
--- a/src/devices/bus/centronics/dsjoy.h
+++ b/src/devices/bus/centronics/dsjoy.h
@@ -25,12 +25,12 @@ protected:
virtual void device_start() override;
virtual ioport_constructor device_input_ports() const override;
- virtual DECLARE_WRITE_LINE_MEMBER( input_data0 ) override { if (state) m_data |= 0x01; else m_data &= ~0x01; update_perror(); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data1 ) override { if (state) m_data |= 0x02; else m_data &= ~0x02; update_perror(); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data2 ) override { if (state) m_data |= 0x04; else m_data &= ~0x04; update_perror(); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data3 ) override { if (state) m_data |= 0x08; else m_data &= ~0x08; update_perror(); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data4 ) override { if (state) m_data |= 0x10; else m_data &= ~0x10; update_perror(); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data5 ) override { if (state) m_data |= 0x20; else m_data &= ~0x20; update_perror(); }
+ virtual void input_data0(int state) override { if (state) m_data |= 0x01; else m_data &= ~0x01; update_perror(); }
+ virtual void input_data1(int state) override { if (state) m_data |= 0x02; else m_data &= ~0x02; update_perror(); }
+ virtual void input_data2(int state) override { if (state) m_data |= 0x04; else m_data &= ~0x04; update_perror(); }
+ virtual void input_data3(int state) override { if (state) m_data |= 0x08; else m_data &= ~0x08; update_perror(); }
+ virtual void input_data4(int state) override { if (state) m_data |= 0x10; else m_data &= ~0x10; update_perror(); }
+ virtual void input_data5(int state) override { if (state) m_data |= 0x20; else m_data &= ~0x20; update_perror(); }
private:
required_ioport m_lptjoy;
diff --git a/src/devices/bus/centronics/epson_lx800.cpp b/src/devices/bus/centronics/epson_lx800.cpp
index 3733c92cb2b..9022f0befa4 100644
--- a/src/devices/bus/centronics/epson_lx800.cpp
+++ b/src/devices/bus/centronics/epson_lx800.cpp
@@ -274,32 +274,32 @@ void epson_lx800_device::portc_w(offs_t offset, uint8_t data)
m_beep->set_state(!BIT(data, 7));
}
-READ_LINE_MEMBER( epson_lx800_device::an0_r )
+int epson_lx800_device::an0_r()
{
return BIT(ioport("DIPSW2")->read(), 0);
}
-READ_LINE_MEMBER( epson_lx800_device::an1_r )
+int epson_lx800_device::an1_r()
{
return BIT(ioport("DIPSW2")->read(), 1);
}
-READ_LINE_MEMBER( epson_lx800_device::an2_r )
+int epson_lx800_device::an2_r()
{
return BIT(ioport("DIPSW2")->read(), 2);
}
-READ_LINE_MEMBER( epson_lx800_device::an3_r )
+int epson_lx800_device::an3_r()
{
return BIT(ioport("DIPSW2")->read(), 3); // can also read an external line AUTO_FEED_XT
}
-READ_LINE_MEMBER( epson_lx800_device::an4_r )
+int epson_lx800_device::an4_r()
{
return 0; // Printer select line (0=always selected)
}
-READ_LINE_MEMBER( epson_lx800_device::an5_r )
+int epson_lx800_device::an5_r()
{
return 1; // Monitors 24v line, should return 4.08 volts
}
@@ -315,12 +315,12 @@ uint8_t epson_lx800_device::centronics_data_r()
return 0x55;
}
-WRITE_LINE_MEMBER( epson_lx800_device::centronics_pe_w )
+void epson_lx800_device::centronics_pe_w(int state)
{
logerror("centronics: pe = %d\n", state);
}
-WRITE_LINE_MEMBER( epson_lx800_device::reset_w )
+void epson_lx800_device::reset_w(int state)
{
logerror("cpu reset");
m_maincpu->reset();
diff --git a/src/devices/bus/centronics/epson_lx800.h b/src/devices/bus/centronics/epson_lx800.h
index c6534f3d62f..b1ec0b7ce82 100644
--- a/src/devices/bus/centronics/epson_lx800.h
+++ b/src/devices/bus/centronics/epson_lx800.h
@@ -50,16 +50,16 @@ private:
uint8_t portc_r(offs_t offset);
void portc_w(offs_t offset, uint8_t data);
- DECLARE_READ_LINE_MEMBER(an0_r);
- DECLARE_READ_LINE_MEMBER(an1_r);
- DECLARE_READ_LINE_MEMBER(an2_r);
- DECLARE_READ_LINE_MEMBER(an3_r);
- DECLARE_READ_LINE_MEMBER(an4_r);
- DECLARE_READ_LINE_MEMBER(an5_r);
+ int an0_r();
+ int an1_r();
+ int an2_r();
+ int an3_r();
+ int an4_r();
+ int an5_r();
uint8_t centronics_data_r();
- DECLARE_WRITE_LINE_MEMBER(centronics_pe_w);
- DECLARE_WRITE_LINE_MEMBER(reset_w);
+ void centronics_pe_w(int state);
+ void reset_w(int state);
void lx800_mem(address_map &map);
diff --git a/src/devices/bus/centronics/epson_lx810l.cpp b/src/devices/bus/centronics/epson_lx810l.cpp
index 24f9b90c50f..bdbb9ffaa06 100644
--- a/src/devices/bus/centronics/epson_lx810l.cpp
+++ b/src/devices/bus/centronics/epson_lx810l.cpp
@@ -522,7 +522,7 @@ void epson_lx810l_device::cr_stepper(uint8_t data)
}
}
-WRITE_LINE_MEMBER( epson_lx810l_device::e05a30_ready )
+void epson_lx810l_device::e05a30_ready(int state)
{
// must be longer than attotime::zero - 0.09 is minimum to initialize properly
m_maincpu->pulse_input_line(INPUT_LINE_NMI, attotime::from_double(0.09));
@@ -533,7 +533,7 @@ WRITE_LINE_MEMBER( epson_lx810l_device::e05a30_ready )
Extended Timer Output
***************************************************************************/
-WRITE_LINE_MEMBER( epson_lx810l_device::co0_w )
+void epson_lx810l_device::co0_w(int state)
{
/* Printhead is being fired on !state. */
if (!state) {
diff --git a/src/devices/bus/centronics/epson_lx810l.h b/src/devices/bus/centronics/epson_lx810l.h
index 1b5581a606b..37383771b5d 100644
--- a/src/devices/bus/centronics/epson_lx810l.h
+++ b/src/devices/bus/centronics/epson_lx810l.h
@@ -34,16 +34,16 @@ public:
epson_lx810l_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
/* Centronics stuff */
- virtual DECLARE_WRITE_LINE_MEMBER( input_strobe ) override { m_e05a30->centronics_input_strobe(state); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data0 ) override { m_e05a30->centronics_input_data0(state); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data1 ) override { m_e05a30->centronics_input_data1(state); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data2 ) override { m_e05a30->centronics_input_data2(state); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data3 ) override { m_e05a30->centronics_input_data3(state); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data4 ) override { m_e05a30->centronics_input_data4(state); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data5 ) override { m_e05a30->centronics_input_data5(state); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data6 ) override { m_e05a30->centronics_input_data6(state); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data7 ) override { m_e05a30->centronics_input_data7(state); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_init ) override { m_e05a30->centronics_input_init(state); }
+ virtual void input_strobe(int state) override { m_e05a30->centronics_input_strobe(state); }
+ virtual void input_data0(int state) override { m_e05a30->centronics_input_data0(state); }
+ virtual void input_data1(int state) override { m_e05a30->centronics_input_data1(state); }
+ virtual void input_data2(int state) override { m_e05a30->centronics_input_data2(state); }
+ virtual void input_data3(int state) override { m_e05a30->centronics_input_data3(state); }
+ virtual void input_data4(int state) override { m_e05a30->centronics_input_data4(state); }
+ virtual void input_data5(int state) override { m_e05a30->centronics_input_data5(state); }
+ virtual void input_data6(int state) override { m_e05a30->centronics_input_data6(state); }
+ virtual void input_data7(int state) override { m_e05a30->centronics_input_data7(state); }
+ virtual void input_init(int state) override { m_e05a30->centronics_input_init(state); }
/* Panel buttons */
DECLARE_INPUT_CHANGED_MEMBER(online_sw);
@@ -80,7 +80,7 @@ private:
void fakemem_w(uint8_t data);
/* Extended Timer Output */
- DECLARE_WRITE_LINE_MEMBER(co0_w);
+ void co0_w(int state);
/* ADC */
uint8_t an0_r();
@@ -97,17 +97,17 @@ private:
void printhead(uint16_t data);
void pf_stepper(uint8_t data);
void cr_stepper(uint8_t data);
- DECLARE_WRITE_LINE_MEMBER(e05a30_ready);
+ void e05a30_ready(int state);
- DECLARE_WRITE_LINE_MEMBER(e05a30_centronics_ack) { output_ack(state); }
- DECLARE_WRITE_LINE_MEMBER(e05a30_centronics_busy) { output_busy(state); }
- DECLARE_WRITE_LINE_MEMBER(e05a30_centronics_perror) { output_perror(state); }
- DECLARE_WRITE_LINE_MEMBER(e05a30_centronics_fault) { output_fault(state); }
- DECLARE_WRITE_LINE_MEMBER(e05a30_centronics_select) { output_select(state); }
+ void e05a30_centronics_ack(int state) { output_ack(state); }
+ void e05a30_centronics_busy(int state) { output_busy(state); }
+ void e05a30_centronics_perror(int state) { output_perror(state); }
+ void e05a30_centronics_fault(int state) { output_fault(state); }
+ void e05a30_centronics_select(int state) { output_select(state); }
- DECLARE_WRITE_LINE_MEMBER(e05a30_cpu_reset) { if (!state) m_maincpu->pulse_input_line(INPUT_LINE_RESET, attotime::zero); } // reset cpu
+ void e05a30_cpu_reset(int state) { if (!state) m_maincpu->pulse_input_line(INPUT_LINE_RESET, attotime::zero); } // reset cpu
- DECLARE_WRITE_LINE_MEMBER(e05a30_ready_led)
+ void e05a30_ready_led(int state)
{
m_ready_led = state;
m_bitmap_printer->set_led_state(bitmap_printer_device::LED_READY, m_ready_led);
diff --git a/src/devices/bus/centronics/nlq401.cpp b/src/devices/bus/centronics/nlq401.cpp
new file mode 100644
index 00000000000..92325fd11bf
--- /dev/null
+++ b/src/devices/bus/centronics/nlq401.cpp
@@ -0,0 +1,310 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/**********************************************************************
+
+ Schneider NLQ 401 Matrix Printer (skeleton)
+
+ This appears to be an OEM version of a Centronics Printer Corp.
+ product. The hardware (but not the firmware) is also said to be
+ identical with the Brother M1009.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "nlq401.h"
+
+#include "cpu/upd7810/upd7810.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITION
+//**************************************************************************
+
+// device type definition
+DEFINE_DEVICE_TYPE(NLQ401, nlq401_device, "nlq401", "Schneider NLQ 401 Matrix Printer")
+
+
+//-------------------------------------------------
+// nlq401_device - constructor
+//-------------------------------------------------
+
+nlq401_device::nlq401_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, NLQ401, tag, owner, clock)
+ , device_centronics_peripheral_interface(mconfig, *this)
+ , m_inpexp(*this, "inpexp")
+ , m_outexp(*this, "outexp")
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void nlq401_device::device_start()
+{
+}
+
+
+//-------------------------------------------------
+// input_data0 - DATA1 line handler
+//-------------------------------------------------
+
+void nlq401_device::input_data0(int state)
+{
+ // TODO
+}
+
+//-------------------------------------------------
+// input_data1 - DATA2 line handler
+//-------------------------------------------------
+
+void nlq401_device::input_data1(int state)
+{
+ // TODO
+}
+
+//-------------------------------------------------
+// input_data2 - DATA3 line handler
+//-------------------------------------------------
+
+void nlq401_device::input_data2(int state)
+{
+ // TODO
+}
+
+//-------------------------------------------------
+// input_data3 - DATA4 line handler
+//-------------------------------------------------
+
+void nlq401_device::input_data3(int state)
+{
+ // TODO
+}
+
+//-------------------------------------------------
+// input_data4 - DATA5 line handler
+//-------------------------------------------------
+
+void nlq401_device::input_data4(int state)
+{
+ // TODO
+}
+
+//-------------------------------------------------
+// input_data5 - DATA6 line handler
+//-------------------------------------------------
+
+void nlq401_device::input_data5(int state)
+{
+ // TODO
+}
+
+//-------------------------------------------------
+// input_data6 - DATA7 line handler
+//-------------------------------------------------
+
+void nlq401_device::input_data6(int state)
+{
+ // TODO
+}
+
+//-------------------------------------------------
+// input_data7 - DATA8 line handler
+//-------------------------------------------------
+
+void nlq401_device::input_data7(int state)
+{
+ // TODO
+}
+
+//-------------------------------------------------
+// input_strobe - DATA STROBE line handler
+//-------------------------------------------------
+
+void nlq401_device::input_strobe(int state)
+{
+ // TODO
+}
+
+//-------------------------------------------------
+// input_init - INIT line handler
+//-------------------------------------------------
+
+void nlq401_device::input_init(int state)
+{
+ // TODO
+}
+
+
+//-------------------------------------------------
+// expander_w - write from MCU to expanders
+//-------------------------------------------------
+
+void nlq401_device::expander_w(u8 data)
+{
+ m_outexp->write_h(BIT(data, 0, 4));
+ m_outexp->write_s(BIT(data, 4, 3));
+ m_inpexp->write_s(BIT(data, 4, 3));
+ m_outexp->write_std(BIT(data, 7));
+}
+
+//-------------------------------------------------
+// expander_r - read from expander port
+//-------------------------------------------------
+
+u8 nlq401_device::expander_r()
+{
+ return 0x87 | (m_inpexp->read_h() << 3);
+}
+
+
+//-------------------------------------------------
+// mem_map - address map for microcontroller
+//-------------------------------------------------
+
+void nlq401_device::mem_map(address_map &map)
+{
+ map(0x0000, 0x3fff).rom().region("prom", 0);
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - device-specific config
+//-------------------------------------------------
+
+void nlq401_device::device_add_mconfig(machine_config &config)
+{
+ upd7810_device &mcu(UPD7810(config, "mcu", 11_MHz_XTAL));
+ mcu.set_addrmap(AS_PROGRAM, &nlq401_device::mem_map);
+ mcu.pb_out_cb().set(FUNC(nlq401_device::expander_w));
+ mcu.pc_in_cb().set(FUNC(nlq401_device::expander_r));
+
+ TMS1025(config, m_inpexp); // B8 (labeled M50780 on schematic)
+ m_inpexp->set_ms(0);
+ m_inpexp->read_port1_callback().set_ioport("P1");
+ m_inpexp->read_port2_callback().set_ioport("P2");
+ m_inpexp->read_port3_callback().set_ioport("P3");
+ m_inpexp->read_port4_callback().set_ioport("P4");
+ m_inpexp->read_port5_callback().set_ioport("P5");
+ m_inpexp->read_port6_callback().set_ioport("P6");
+
+ TMS1025(config, m_outexp); // B2 (labeled M50780 on schematic)
+ m_outexp->set_ms(1); // tied to _RESET
+ //m_outexp->write_port1_callback().set(FUNC(nlq401_device::cr_w));
+ //m_outexp->write_port2_callback().set(FUNC(nlq401_device::lf_w));
+ //m_outexp->write_port3_callback().set(FUNC(nlq401_device::ack_w));
+ //m_outexp->write_port4_callback().set(FUNC(nlq401_device::head_5_8_w));
+ //m_outexp->write_port5_callback().set(FUNC(nlq401_device::head_1_4_w));
+ //m_outexp->write_port7_callback().set(FUNC(nlq401_device::led_w));
+}
+
+
+//**************************************************************************
+// INPUT PORTS
+//**************************************************************************
+
+static INPUT_PORTS_START(nlq401)
+ PORT_START("SW1")
+ PORT_DIPNAME(0x01, 0x01, "DIP11") PORT_DIPLOCATION("SW1:8")
+ PORT_DIPSETTING(0x01, DEF_STR(Off))
+ PORT_DIPSETTING(0x00, DEF_STR(On))
+ PORT_DIPNAME(0x02, 0x02, "DIP12") PORT_DIPLOCATION("SW1:7")
+ PORT_DIPSETTING(0x02, DEF_STR(Off))
+ PORT_DIPSETTING(0x00, DEF_STR(On))
+ PORT_DIPNAME(0x04, 0x04, "DIP13") PORT_DIPLOCATION("SW1:6")
+ PORT_DIPSETTING(0x04, DEF_STR(Off))
+ PORT_DIPSETTING(0x00, DEF_STR(On))
+ PORT_DIPNAME(0x08, 0x08, "DIP14") PORT_DIPLOCATION("SW1:5")
+ PORT_DIPSETTING(0x08, DEF_STR(Off))
+ PORT_DIPSETTING(0x00, DEF_STR(On))
+ PORT_DIPNAME(0x10, 0x10, "DIP15") PORT_DIPLOCATION("SW1:4")
+ PORT_DIPSETTING(0x10, DEF_STR(Off))
+ PORT_DIPSETTING(0x00, DEF_STR(On))
+
+ PORT_START("P1")
+ PORT_BIT(1, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("HP SW")
+ PORT_BIT(2, IP_ACTIVE_LOW, IPT_UNKNOWN)
+ PORT_BIT(4, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("PE SW")
+ PORT_BIT(8, IP_ACTIVE_LOW, IPT_UNKNOWN)
+
+ PORT_START("P2")
+ PORT_BIT(1, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("LF SW")
+ PORT_DIPNAME(2, 2, "DIP28") PORT_DIPLOCATION("SW2:8")
+ PORT_DIPSETTING(2, DEF_STR(Off))
+ PORT_DIPSETTING(0, DEF_STR(On))
+ PORT_DIPNAME(4, 4, "DIP27") PORT_DIPLOCATION("SW2:7")
+ PORT_DIPSETTING(4, DEF_STR(Off))
+ PORT_DIPSETTING(0, DEF_STR(On))
+ PORT_DIPNAME(8, 8, "DIP16") PORT_DIPLOCATION("SW1:3")
+ PORT_DIPSETTING(8, DEF_STR(Off))
+ PORT_DIPSETTING(0, DEF_STR(On))
+
+ PORT_START("P3")
+ PORT_DIPNAME(1, 1, "DIP17") PORT_DIPLOCATION("SW1:2")
+ PORT_DIPSETTING(1, DEF_STR(Off))
+ PORT_DIPSETTING(0, DEF_STR(On))
+ PORT_DIPNAME(2, 2, "DIP18") PORT_DIPLOCATION("SW1:1")
+ PORT_DIPSETTING(2, DEF_STR(Off))
+ PORT_DIPSETTING(0, DEF_STR(On))
+ PORT_DIPNAME(4, 4, "DIP26") PORT_DIPLOCATION("SW2:6")
+ PORT_DIPSETTING(4, DEF_STR(Off))
+ PORT_DIPSETTING(0, DEF_STR(On))
+ PORT_DIPNAME(8, 8, "DIP25") PORT_DIPLOCATION("SW2:5")
+ PORT_DIPSETTING(8, DEF_STR(Off))
+ PORT_DIPSETTING(0, DEF_STR(On))
+
+ PORT_START("P4")
+ PORT_DIPNAME(1, 1, "DIP24") PORT_DIPLOCATION("SW2:4")
+ PORT_DIPSETTING(1, DEF_STR(Off))
+ PORT_DIPSETTING(0, DEF_STR(On))
+ PORT_DIPNAME(2, 2, "DIP23") PORT_DIPLOCATION("SW2:3")
+ PORT_DIPSETTING(2, DEF_STR(Off))
+ PORT_DIPSETTING(0, DEF_STR(On))
+ PORT_DIPNAME(4, 4, "DIP22") PORT_DIPLOCATION("SW2:2")
+ PORT_DIPSETTING(4, DEF_STR(Off))
+ PORT_DIPSETTING(0, DEF_STR(On))
+ PORT_DIPNAME(8, 8, "DIP21") PORT_DIPLOCATION("SW2:1")
+ PORT_DIPSETTING(8, DEF_STR(Off))
+ PORT_DIPSETTING(0, DEF_STR(On))
+
+ PORT_START("P5")
+ PORT_BIT(1, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("DSR")
+ PORT_BIT(2, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("CTS")
+ PORT_BIT(4, IP_ACTIVE_LOW, IPT_UNKNOWN)
+ PORT_BIT(8, IP_ACTIVE_LOW, IPT_UNKNOWN)
+
+ PORT_START("P6")
+ PORT_BIT(1, IP_ACTIVE_HIGH, IPT_OTHER) PORT_NAME("ONL SW")
+ PORT_BIT(2, IP_ACTIVE_LOW, IPT_UNKNOWN)
+ PORT_BIT(4, IP_ACTIVE_LOW, IPT_UNKNOWN)
+ PORT_BIT(8, IP_ACTIVE_LOW, IPT_UNKNOWN)
+INPUT_PORTS_END
+
+//-------------------------------------------------
+// device_input_ports - device-specific ports
+//-------------------------------------------------
+
+ioport_constructor nlq401_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(nlq401);
+}
+
+
+//**************************************************************************
+// ROM DEFINITION
+//**************************************************************************
+
+ROM_START(nlq401)
+ ROM_REGION(0x4000, "prom", 0)
+ ROM_LOAD("schneider_nlq401_rev004.bin", 0x0000, 0x4000, CRC(5c331aed) SHA1(b6374abaebb8e484e573caa21b1cc87f1554c8d6))
+ROM_END
+
+//-------------------------------------------------
+// device_rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const tiny_rom_entry *nlq401_device::device_rom_region() const
+{
+ return ROM_NAME(nlq401);
+}
diff --git a/src/devices/bus/centronics/nlq401.h b/src/devices/bus/centronics/nlq401.h
new file mode 100644
index 00000000000..291a10cb0bf
--- /dev/null
+++ b/src/devices/bus/centronics/nlq401.h
@@ -0,0 +1,60 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+
+#ifndef MAME_BUS_CENTRONICS_NLQ401_H
+#define MAME_BUS_CENTRONICS_NLQ401_H
+
+#pragma once
+
+#include "ctronics.h"
+#include "machine/tms1024.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> nlq401_device
+
+class nlq401_device : public device_t, public device_centronics_peripheral_interface
+{
+public:
+ // device type constructor
+ nlq401_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ static constexpr feature_type unemulated_features() { return feature::PRINTER; }
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual ioport_constructor device_input_ports() const override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+ // device_centronics_peripheral_interface overrides
+ virtual void input_data0(int state) override;
+ virtual void input_data1(int state) override;
+ virtual void input_data2(int state) override;
+ virtual void input_data3(int state) override;
+ virtual void input_data4(int state) override;
+ virtual void input_data5(int state) override;
+ virtual void input_data6(int state) override;
+ virtual void input_data7(int state) override;
+ virtual void input_strobe(int state) override;
+ virtual void input_init(int state) override;
+ virtual bool supports_pin35_5v() override { return true; }
+
+private:
+ void expander_w(u8 data);
+ u8 expander_r();
+
+ void mem_map(address_map &map);
+
+ required_device<tms1025_device> m_inpexp;
+ required_device<tms1025_device> m_outexp;
+};
+
+// device type declaration
+DECLARE_DEVICE_TYPE(NLQ401, nlq401_device)
+
+#endif // MAME_BUS_CENTRONICS_NLQ401_H
diff --git a/src/devices/bus/centronics/printer.cpp b/src/devices/bus/centronics/printer.cpp
index b1b136cfc66..25deb42cdd1 100644
--- a/src/devices/bus/centronics/printer.cpp
+++ b/src/devices/bus/centronics/printer.cpp
@@ -65,7 +65,7 @@ void centronics_printer_device::device_reset()
sets us busy when the printer goes offline
-------------------------------------------------*/
-WRITE_LINE_MEMBER(centronics_printer_device::printer_online)
+void centronics_printer_device::printer_online(int state)
{
output_perror(!state);
}
@@ -116,7 +116,7 @@ TIMER_CALLBACK_MEMBER(centronics_printer_device::busy_timer_tick)
ready
-------------------------------------------------*/
-WRITE_LINE_MEMBER( centronics_printer_device::input_strobe )
+void centronics_printer_device::input_strobe(int state)
{
/* look for a high -> low transition */
if (m_strobe == true && state == false && m_busy == false)
@@ -134,7 +134,7 @@ WRITE_LINE_MEMBER( centronics_printer_device::input_strobe )
printer (centronics mode)
-------------------------------------------------*/
-WRITE_LINE_MEMBER(centronics_printer_device::input_init)
+void centronics_printer_device::input_init(int state)
{
/* reset printer if line is low */
if (state == false)
diff --git a/src/devices/bus/centronics/printer.h b/src/devices/bus/centronics/printer.h
index e959959be0c..ff4d0e3fe16 100644
--- a/src/devices/bus/centronics/printer.h
+++ b/src/devices/bus/centronics/printer.h
@@ -17,16 +17,16 @@ public:
// construction/destruction
centronics_printer_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual DECLARE_WRITE_LINE_MEMBER( input_strobe ) override;
- virtual DECLARE_WRITE_LINE_MEMBER( input_data0 ) override { if (state) m_data |= 0x01; else m_data &= ~0x01; }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data1 ) override { if (state) m_data |= 0x02; else m_data &= ~0x02; }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data2 ) override { if (state) m_data |= 0x04; else m_data &= ~0x04; }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data3 ) override { if (state) m_data |= 0x08; else m_data &= ~0x08; }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data4 ) override { if (state) m_data |= 0x10; else m_data &= ~0x10; }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data5 ) override { if (state) m_data |= 0x20; else m_data &= ~0x20; }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data6 ) override { if (state) m_data |= 0x40; else m_data &= ~0x40; }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data7 ) override { if (state) m_data |= 0x80; else m_data &= ~0x80; }
- virtual DECLARE_WRITE_LINE_MEMBER( input_init ) override;
+ virtual void input_strobe(int state) override;
+ virtual void input_data0(int state) override { if (state) m_data |= 0x01; else m_data &= ~0x01; }
+ virtual void input_data1(int state) override { if (state) m_data |= 0x02; else m_data &= ~0x02; }
+ virtual void input_data2(int state) override { if (state) m_data |= 0x04; else m_data &= ~0x04; }
+ virtual void input_data3(int state) override { if (state) m_data |= 0x08; else m_data &= ~0x08; }
+ virtual void input_data4(int state) override { if (state) m_data |= 0x10; else m_data &= ~0x10; }
+ virtual void input_data5(int state) override { if (state) m_data |= 0x20; else m_data &= ~0x20; }
+ virtual void input_data6(int state) override { if (state) m_data |= 0x40; else m_data &= ~0x40; }
+ virtual void input_data7(int state) override { if (state) m_data |= 0x80; else m_data &= ~0x80; }
+ virtual void input_init(int state) override;
protected:
// device-level overrides
@@ -37,7 +37,7 @@ protected:
virtual bool supports_pin35_5v() override { return true; }
private:
- DECLARE_WRITE_LINE_MEMBER( printer_online );
+ void printer_online(int state);
TIMER_CALLBACK_MEMBER(ack_timer_tick);
TIMER_CALLBACK_MEMBER(busy_timer_tick);
diff --git a/src/devices/bus/centronics/samdac.cpp b/src/devices/bus/centronics/samdac.cpp
index 01b18963e44..46a7682f4ba 100644
--- a/src/devices/bus/centronics/samdac.cpp
+++ b/src/devices/bus/centronics/samdac.cpp
@@ -64,7 +64,7 @@ void centronics_samdac_device::device_start()
// IMPLEMENTATION
//**************************************************************************
-WRITE_LINE_MEMBER( centronics_samdac_device::input_strobe )
+void centronics_samdac_device::input_strobe(int state)
{
// raising edge, write to left channel
if (m_strobe == 0 && state == 1)
diff --git a/src/devices/bus/centronics/samdac.h b/src/devices/bus/centronics/samdac.h
index 79cd654e267..7c793d59a0a 100644
--- a/src/devices/bus/centronics/samdac.h
+++ b/src/devices/bus/centronics/samdac.h
@@ -28,15 +28,15 @@ public:
centronics_samdac_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// from centronics port
- virtual DECLARE_WRITE_LINE_MEMBER( input_strobe ) override;
- virtual DECLARE_WRITE_LINE_MEMBER( input_data0 ) override { update_data(0, state); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data1 ) override { update_data(1, state); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data2 ) override { update_data(2, state); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data3 ) override { update_data(3, state); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data4 ) override { update_data(4, state); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data5 ) override { update_data(5, state); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data6 ) override { update_data(6, state); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data7 ) override { update_data(7, state); }
+ virtual void input_strobe(int state) override;
+ virtual void input_data0(int state) override { update_data(0, state); }
+ virtual void input_data1(int state) override { update_data(1, state); }
+ virtual void input_data2(int state) override { update_data(2, state); }
+ virtual void input_data3(int state) override { update_data(3, state); }
+ virtual void input_data4(int state) override { update_data(4, state); }
+ virtual void input_data5(int state) override { update_data(5, state); }
+ virtual void input_data6(int state) override { update_data(6, state); }
+ virtual void input_data7(int state) override { update_data(7, state); }
protected:
virtual void device_add_mconfig(machine_config &config) override;
diff --git a/src/devices/bus/centronics/smartboard.h b/src/devices/bus/centronics/smartboard.h
index 4988086b11f..25131141b3f 100644
--- a/src/devices/bus/centronics/smartboard.h
+++ b/src/devices/bus/centronics/smartboard.h
@@ -27,8 +27,8 @@ protected:
virtual void device_start() override { }
virtual void device_add_mconfig(machine_config &config) override;
- virtual DECLARE_WRITE_LINE_MEMBER(input_data0) override { if (started()) m_smartboard->data0_w(state); }
- virtual DECLARE_WRITE_LINE_MEMBER(input_data7) override { if (started()) m_smartboard->data1_w(state); }
+ virtual void input_data0(int state) override { if (started()) m_smartboard->data0_w(state); }
+ virtual void input_data7(int state) override { if (started()) m_smartboard->data1_w(state); }
private:
required_device<tasc_sb30_device> m_smartboard;
diff --git a/src/devices/bus/centronics/spjoy.h b/src/devices/bus/centronics/spjoy.h
index d13f2f90555..1095f242def 100644
--- a/src/devices/bus/centronics/spjoy.h
+++ b/src/devices/bus/centronics/spjoy.h
@@ -25,14 +25,14 @@ protected:
virtual void device_start() override;
virtual ioport_constructor device_input_ports() const override;
- virtual DECLARE_WRITE_LINE_MEMBER( input_data0 ) override { if (state) m_data |= 0x01; else m_data &= ~0x01; update_busy_ack(); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data1 ) override { if (state) m_data |= 0x02; else m_data &= ~0x02; update_busy_ack(); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data2 ) override { if (state) m_data |= 0x04; else m_data &= ~0x04; update_busy_ack(); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data3 ) override { if (state) m_data |= 0x08; else m_data &= ~0x08; update_busy_ack(); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data4 ) override { if (state) m_data |= 0x10; else m_data &= ~0x10; update_busy_ack(); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data5 ) override { if (state) m_data |= 0x20; else m_data &= ~0x20; update_busy_ack(); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data6 ) override { if (state) m_data |= 0x40; else m_data &= ~0x40; update_busy_ack(); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data7 ) override { if (state) m_data |= 0x80; else m_data &= ~0x80; update_busy_ack(); }
+ virtual void input_data0(int state) override { if (state) m_data |= 0x01; else m_data &= ~0x01; update_busy_ack(); }
+ virtual void input_data1(int state) override { if (state) m_data |= 0x02; else m_data &= ~0x02; update_busy_ack(); }
+ virtual void input_data2(int state) override { if (state) m_data |= 0x04; else m_data &= ~0x04; update_busy_ack(); }
+ virtual void input_data3(int state) override { if (state) m_data |= 0x08; else m_data &= ~0x08; update_busy_ack(); }
+ virtual void input_data4(int state) override { if (state) m_data |= 0x10; else m_data &= ~0x10; update_busy_ack(); }
+ virtual void input_data5(int state) override { if (state) m_data |= 0x20; else m_data &= ~0x20; update_busy_ack(); }
+ virtual void input_data6(int state) override { if (state) m_data |= 0x40; else m_data &= ~0x40; update_busy_ack(); }
+ virtual void input_data7(int state) override { if (state) m_data |= 0x80; else m_data &= ~0x80; update_busy_ack(); }
private:
required_ioport_array<2> m_joy;
diff --git a/src/devices/bus/cgenie/expansion/expansion.cpp b/src/devices/bus/cgenie/expansion/expansion.cpp
index d35d75401bd..577c8a4409b 100644
--- a/src/devices/bus/cgenie/expansion/expansion.cpp
+++ b/src/devices/bus/cgenie/expansion/expansion.cpp
@@ -53,10 +53,6 @@ cg_exp_slot_device::~cg_exp_slot_device()
void cg_exp_slot_device::device_start()
{
- // resolve callbacks
- m_int_handler.resolve_safe();
- m_nmi_handler.resolve_safe();
- m_reset_handler.resolve_safe();
}
diff --git a/src/devices/bus/cgenie/expansion/expansion.h b/src/devices/bus/cgenie/expansion/expansion.h
index 5d128128fa8..c8284b43a70 100644
--- a/src/devices/bus/cgenie/expansion/expansion.h
+++ b/src/devices/bus/cgenie/expansion/expansion.h
@@ -73,9 +73,9 @@ public:
auto reset_handler() { return m_reset_handler.bind(); }
// called from cart device
- DECLARE_WRITE_LINE_MEMBER( int_w ) { m_int_handler(state); }
- DECLARE_WRITE_LINE_MEMBER( nmi_w ) { m_nmi_handler(state); }
- DECLARE_WRITE_LINE_MEMBER( reset_w ) { m_reset_handler(state); }
+ void int_w(int state) { m_int_handler(state); }
+ void nmi_w(int state) { m_nmi_handler(state); }
+ void reset_w(int state) { m_reset_handler(state); }
required_address_space m_program;
required_address_space m_io;
diff --git a/src/devices/bus/cgenie/expansion/floppy.cpp b/src/devices/bus/cgenie/expansion/floppy.cpp
index a97c3d46e66..a52b39a9ea5 100644
--- a/src/devices/bus/cgenie/expansion/floppy.cpp
+++ b/src/devices/bus/cgenie/expansion/floppy.cpp
@@ -177,21 +177,18 @@ TIMER_DEVICE_CALLBACK_MEMBER( cgenie_fdc_device::timer_callback )
DEVICE_IMAGE_LOAD_MEMBER( cgenie_fdc_device::socket_load )
{
- uint32_t size = m_socket->common_get_size("rom");
+ uint32_t const size = m_socket->common_get_size("rom");
if (size > 0x1000)
- {
- image.seterror(image_error::INVALIDIMAGE, "Unsupported ROM size");
- return image_init_result::FAIL;
- }
+ return std::make_pair(image_error::INVALIDLENGTH, "Unsupported ROM size (must be no more than 4K)");
m_socket->rom_alloc(0x1000, GENERIC_ROM8_WIDTH, ENDIANNESS_LITTLE);
m_socket->common_load_rom(m_socket->get_rom_base(), size, "rom");
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
-WRITE_LINE_MEMBER( cgenie_fdc_device::intrq_w )
+void cgenie_fdc_device::intrq_w(int state)
{
if (VERBOSE)
logerror("cgenie_fdc_device::intrq_w: %d\n", state);
diff --git a/src/devices/bus/cgenie/expansion/floppy.h b/src/devices/bus/cgenie/expansion/floppy.h
index ca64b39f0d7..81e45bd2eb9 100644
--- a/src/devices/bus/cgenie/expansion/floppy.h
+++ b/src/devices/bus/cgenie/expansion/floppy.h
@@ -39,7 +39,7 @@ protected:
private:
DECLARE_DEVICE_IMAGE_LOAD_MEMBER(socket_load);
- DECLARE_WRITE_LINE_MEMBER(intrq_w);
+ void intrq_w(int state);
TIMER_DEVICE_CALLBACK_MEMBER(timer_callback);
diff --git a/src/devices/bus/cgenie/parallel/printer.cpp b/src/devices/bus/cgenie/parallel/printer.cpp
index 9a3e9df5dc4..57c666183cc 100644
--- a/src/devices/bus/cgenie/parallel/printer.cpp
+++ b/src/devices/bus/cgenie/parallel/printer.cpp
@@ -81,22 +81,22 @@ void cgenie_printer_device::device_reset()
// IMPLEMENTATION
//**************************************************************************
-WRITE_LINE_MEMBER( cgenie_printer_device::busy_w )
+void cgenie_printer_device::busy_w(int state)
{
m_centronics_busy = state;
}
-WRITE_LINE_MEMBER( cgenie_printer_device::perror_w )
+void cgenie_printer_device::perror_w(int state)
{
m_centronics_out_of_paper = state;
}
-WRITE_LINE_MEMBER( cgenie_printer_device::select_w )
+void cgenie_printer_device::select_w(int state)
{
m_centronics_unit_sel = state;
}
-WRITE_LINE_MEMBER( cgenie_printer_device::fault_w )
+void cgenie_printer_device::fault_w(int state)
{
m_centronics_ready = state;
}
diff --git a/src/devices/bus/cgenie/parallel/printer.h b/src/devices/bus/cgenie/parallel/printer.h
index 6da59e68ea0..6d1d49ad61e 100644
--- a/src/devices/bus/cgenie/parallel/printer.h
+++ b/src/devices/bus/cgenie/parallel/printer.h
@@ -37,10 +37,10 @@ protected:
virtual void pb_w(uint8_t data) override;
private:
- DECLARE_WRITE_LINE_MEMBER(busy_w);
- DECLARE_WRITE_LINE_MEMBER(perror_w);
- DECLARE_WRITE_LINE_MEMBER(select_w);
- DECLARE_WRITE_LINE_MEMBER(fault_w);
+ void busy_w(int state);
+ void perror_w(int state);
+ void select_w(int state);
+ void fault_w(int state);
required_device<centronics_device> m_centronics;
required_device<output_latch_device> m_latch;
diff --git a/src/devices/bus/chanf/slot.cpp b/src/devices/bus/chanf/slot.cpp
index 9a49d62ca82..6092103eb1d 100644
--- a/src/devices/bus/chanf/slot.cpp
+++ b/src/devices/bus/chanf/slot.cpp
@@ -44,11 +44,11 @@ device_channelf_cart_interface::~device_channelf_cart_interface()
// rom_alloc - alloc the space for the cart
//-------------------------------------------------
-void device_channelf_cart_interface::rom_alloc(uint32_t size, const char *tag)
+void device_channelf_cart_interface::rom_alloc(uint32_t size)
{
if (m_rom == nullptr)
{
- m_rom = device().machine().memory().region_alloc(std::string(tag).append(CHANFSLOT_ROM_REGION_TAG).c_str(), size, 1, ENDIANNESS_LITTLE)->base();
+ m_rom = device().machine().memory().region_alloc(device().subtag("^cart:rom"), size, 1, ENDIANNESS_LITTLE)->base();
m_rom_size = size;
}
}
@@ -146,12 +146,12 @@ static const char *chanf_get_slot(int type)
call load
-------------------------------------------------*/
-image_init_result channelf_cart_slot_device::call_load()
+std::pair<std::error_condition, std::string> channelf_cart_slot_device::call_load()
{
if (m_cart)
{
- uint32_t len = !loaded_through_softlist() ? length() : get_software_region_length("rom");
- m_cart->rom_alloc(len, tag());
+ uint32_t const len = !loaded_through_softlist() ? length() : get_software_region_length("rom");
+ m_cart->rom_alloc(len);
if (!loaded_through_softlist())
fread(m_cart->get_rom_base(), len);
@@ -180,11 +180,9 @@ image_init_result channelf_cart_slot_device::call_load()
}
//printf("Type: %s\n", chanf_get_slot(m_type));
-
- return image_init_result::PASS;
}
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
diff --git a/src/devices/bus/chanf/slot.h b/src/devices/bus/chanf/slot.h
index eaf8a787857..2b534cdbe78 100644
--- a/src/devices/bus/chanf/slot.h
+++ b/src/devices/bus/chanf/slot.h
@@ -37,7 +37,7 @@ public:
virtual void write_ram(offs_t offset, uint8_t data) { }
virtual void write_bank(uint8_t data) { }
- void rom_alloc(uint32_t size, const char *tag);
+ void rom_alloc(uint32_t size);
void ram_alloc(uint32_t size);
uint8_t* get_rom_base() { return m_rom; }
uint8_t* get_ram_base() { return &m_ram[0]; }
@@ -77,15 +77,15 @@ public:
channelf_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
virtual ~channelf_cart_slot_device();
- // image-level overrides
- virtual image_init_result call_load() override;
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
virtual void call_unload() override { }
virtual bool is_reset_on_load() const noexcept override { return true; }
virtual const char *image_interface() const noexcept override { return "channelf_cart"; }
virtual const char *file_extensions() const noexcept override { return "bin,chf"; }
- // slot interface overrides
+ // device_slot_interface implementation
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
int get_type() { return m_type; }
@@ -99,7 +99,7 @@ public:
void write_bank(uint8_t data);
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
int m_type;
@@ -111,11 +111,4 @@ protected:
// device type definition
DECLARE_DEVICE_TYPE(CHANF_CART_SLOT, channelf_cart_slot_device)
-
-/***************************************************************************
- DEVICE CONFIGURATION MACROS
- ***************************************************************************/
-
-#define CHANFSLOT_ROM_REGION_TAG ":cart:rom"
-
#endif // MAME_BUS_CHANF_SLOT_H
diff --git a/src/devices/bus/coco/coco_dcmodem.cpp b/src/devices/bus/coco/coco_dcmodem.cpp
index fc26e61fb1f..0618c2fdbad 100644
--- a/src/devices/bus/coco/coco_dcmodem.cpp
+++ b/src/devices/bus/coco/coco_dcmodem.cpp
@@ -49,7 +49,7 @@ namespace
virtual void device_add_mconfig(machine_config &config) override;
// callbacks
- WRITE_LINE_MEMBER(uart_irq_w)
+ void uart_irq_w(int state)
{
set_line_value(line::CART, state != 0);
}
diff --git a/src/devices/bus/coco/coco_fdc.cpp b/src/devices/bus/coco/coco_fdc.cpp
index 94d83954d59..2eac7f8b7f3 100644
--- a/src/devices/bus/coco/coco_fdc.cpp
+++ b/src/devices/bus/coco/coco_fdc.cpp
@@ -14,9 +14,8 @@
cartridge, it is dealt with in the main coco.cpp file.
The wd's variables are mapped to $FF48-$FF4B on the CoCo and on $FF40-$FF43
- on the Dragon. In addition, there is another register
- called DSKREG that controls the interface with the wd1793. DSKREG is
- detailed below: But they appear to be
+ on the Dragon. In addition, there is another register called DSKREG that
+ controls the interface with the wd1793. DSKREG is detailed below:
References:
CoCo: Disk Basic Unravelled
@@ -42,58 +41,68 @@
---------------------------------------------------------------------------
- Disto No Halt Extension
+ Disto Super Controller II
+ Mini Expansion Bus
+ No Halt Extension. Implemented by using a read and write cache.
- The Disto Super Controller II includes "no halt" circuitry. Implemented
- by using a read and write cache.
+ CachDat - Cache Data Register
+ $FF74 & $FF75: Read/Write cache data.
- CachDat - Cache Data Register
- $FF74 & $FF75: Read/Write cache data.
+ Normally cache size is 256 bytes. But a common upgrade is to change
+ it to 512 bytes.
- CachCtrl - Cache Controller
- $FF76: Read
- Bit 7 low indicates an interrupt request from the disk controller
-
- $FF76: Write:
- 00000000 = Caching off
- 00001000 = Tell cache controller to send interrupt when device is
- ready to send/receive a buffer (seek done, etc.)
- 00000111 = Read cache on - Get next 256 data bytes from controller
- to cache
- 00000100 = Write cache on - Next 256 bytes stored in cache are
- sector
- 00000110 = Copy Write cache to controller
+ CachCtrl - Cache Controller
+ $FF76 & $FF77:
+ write
+ clears buffer counter
+ read bit:
+ 7: 0 - indicates an interrupt request from the disk controller
+ 1 - no interrupt
+ 3: 0 - disable CART / FIRQ (masked)
+ 1 - enable CART / FIRQ
+ 2: 0 - normal NMI
+ 1 - masked NMI
+ 1: 0 - compatible I/O mode
+ 1 - buffered I/O mode
+ 0: 0 - buffered write operation
+ 1 - buffered read operation
+ There was a jumper to set the addresses to be FF58 or FF5B. Not implemented.
*********************************************************************/
#include "emu.h"
-#include "cococart.h"
#include "coco_fdc.h"
+
+#include "meb_intrf.h"
+
#include "imagedev/floppy.h"
-#include "machine/msm6242.h"
#include "machine/ds1315.h"
+#include "machine/input_merger.h"
+#include "machine/msm6242.h"
#include "machine/wd_fdc.h"
-#include "machine/ram.h"
+
#include "formats/dmk_dsk.h"
+#include "formats/flex_dsk.h"
+#include "formats/fs_coco_os9.h"
+#include "formats/fs_coco_rsdos.h"
#include "formats/jvc_dsk.h"
-#include "formats/vdk_dsk.h"
-#include "formats/sdf_dsk.h"
#include "formats/os9_dsk.h"
-#include "formats/fs_coco_rsdos.h"
-#include "formats/fs_coco_os9.h"
-
+#include "formats/sdf_dsk.h"
+#include "formats/vdk_dsk.h"
-//#define LOG_GENERAL (1U << 0) //defined in logmacro.h already
#define LOG_WDFDC (1U << 1) // Shows register setup
-#define LOG_WDIO (1U << 2) // Shows Data read and write
+#define LOG_WDIO (1U << 2) // Shows data read and write
+#define LOG_WDSCII (1U << 3) // Shows SCII register setup
-//#define VERBOSE (LOG_GENERAL | LOG_WDFDC)
+//#define VERBOSE (LOG_GENERAL|LOG_WDFDC|LOG_WDSCII)
#include "logmacro.h"
-#define LOGWDFDC(...) LOGMASKED(LOG_WDFDC, __VA_ARGS__)
-#define LOGWDIO(...) LOGMASKED(LOG_WDIO, __VA_ARGS__)
+#define LOGWDFDC(...) LOGMASKED(LOG_WDFDC, __VA_ARGS__)
+#define LOGWDIO(...) LOGMASKED(LOG_WDIO, __VA_ARGS__)
+#define LOGWDSCII(...) LOGMASKED(LOG_WDSCII, __VA_ARGS__)
+
/***************************************************************************
PARAMETERS
@@ -101,9 +110,7 @@
#define WD_TAG "wd17xx"
#define WD2797_TAG "wd2797"
-#define DISTO_TAG "disto"
-#define CLOUD9_TAG "cloud9"
-
+#define MEB_TAG "meb"
template class device_finder<coco_family_fdc_device_base, false>;
template class device_finder<coco_family_fdc_device_base, true>;
@@ -119,17 +126,6 @@ protected:
// construction/destruction
coco_fdc_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
- enum class rtc_type
- {
- DISTO = 0x00,
- CLOUD9 = 0x01,
- NONE = 0xFF
- };
-
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
-
// device-level overrides
virtual u8 cts_read(offs_t offset) override;
virtual u8 scs_read(offs_t offset) override;
@@ -139,31 +135,13 @@ protected:
// methods
virtual void update_lines() override;
void dskreg_w(u8 data);
- rtc_type real_time_clock();
// devices
required_device<wd1773_device> m_wd17xx;
- required_device<ds1315_device> m_ds1315;
required_device_array<floppy_connector, 4> m_floppies;
-
- // Disto RTC
- required_device<msm6242_device> m_disto_msm6242; // 6242 RTC on Disto interface
- offs_t m_msm6242_rtc_address;
- optional_ioport m_rtc;
-
- // Protected
- u8 ff74_read(offs_t offset);
- void ff74_write(offs_t offset, u8 data);
-
-private:
- // registers
- u8 m_cache_controler;
- u8 m_cache_pointer;
- required_device<ram_device> m_cache_buffer;
};
-
/***************************************************************************
LOCAL VARIABLES
***************************************************************************/
@@ -171,10 +149,11 @@ private:
void coco_family_fdc_device_base::floppy_formats(format_registration &fr)
{
fr.add_mfm_containers();
+ fr.add(FLOPPY_FLEX_FORMAT);
fr.add(FLOPPY_DMK_FORMAT);
+ fr.add(FLOPPY_SDF_FORMAT);
fr.add(FLOPPY_JVC_FORMAT);
fr.add(FLOPPY_VDK_FORMAT);
- fr.add(FLOPPY_SDF_FORMAT);
fr.add(FLOPPY_OS9_FORMAT);
fr.add(fs::COCO_RSDOS);
fr.add(fs::COCO_OS9);
@@ -199,12 +178,6 @@ void coco_fdc_device_base::device_add_mconfig(machine_config &config)
FLOPPY_CONNECTOR(config, m_floppies[1], coco_fdc_floppies, "525dd", coco_fdc_device_base::floppy_formats).enable_sound(true);
FLOPPY_CONNECTOR(config, m_floppies[2], coco_fdc_floppies, nullptr, coco_fdc_device_base::floppy_formats).enable_sound(true);
FLOPPY_CONNECTOR(config, m_floppies[3], coco_fdc_floppies, nullptr, coco_fdc_device_base::floppy_formats).enable_sound(true);
-
- MSM6242(config, m_disto_msm6242, 32.768_kHz_XTAL);
-
- DS1315(config, CLOUD9_TAG, 0);
-
- RAM(config, "cachebuffer").set_default_size("256").set_default_value(0);
}
@@ -267,125 +240,8 @@ memory_region *coco_family_fdc_device_base::get_cart_memregion()
coco_fdc_device_base::coco_fdc_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
: coco_family_fdc_device_base(mconfig, type, tag, owner, clock)
, m_wd17xx(*this, WD_TAG)
- , m_ds1315(*this, CLOUD9_TAG)
, m_floppies(*this, WD_TAG ":%u", 0)
- , m_disto_msm6242(*this, DISTO_TAG)
- , m_msm6242_rtc_address(0)
- , m_rtc(*this, ":real_time_clock")
- , m_cache_buffer(*this, "cachebuffer")
-{
-}
-
-
-//-------------------------------------------------
-// device_start - device-specific start
-//-------------------------------------------------
-
-void coco_fdc_device_base::device_start()
-{
- coco_family_fdc_device_base::device_start();
-
- install_readwrite_handler(0xFF74, 0xFF76,
- read8sm_delegate(*this, FUNC(coco_fdc_device_base::ff74_read)),
- write8sm_delegate(*this, FUNC(coco_fdc_device_base::ff74_write)));
-
- save_item(NAME(m_cache_controler));
- save_item(NAME(m_cache_pointer));
-}
-
-
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
-void coco_fdc_device_base::device_reset()
-{
- coco_family_fdc_device_base::device_reset();
-
- m_cache_controler = 0x80;
- m_cache_pointer = 0;
-}
-
-
-//-------------------------------------------------
-// ff74_read - no halt registers
-//-------------------------------------------------
-
-u8 coco_fdc_device_base::ff74_read(offs_t offset)
-{
- u8 data = 0x0;
-
- switch(offset)
- {
- case 0x0:
- data = m_cache_buffer->read(m_cache_pointer++);
- LOG( "CachDat_A read: %2.2x\n", data );
- break;
- case 0x1:
- data = m_cache_buffer->read(m_cache_pointer++);
- LOG( "CachDat_B read: %2.2x\n", data );
- break;
- case 0x2:
- data = m_cache_controler;
- LOG( "CachCtrl read: %2.2x\n", data );
- break;
- }
-
- return data;
-}
-
-
-//-------------------------------------------------
-// ff74_write - no halt registers
-//-------------------------------------------------
-
-void coco_fdc_device_base::ff74_write(offs_t offset, u8 data)
-{
- switch(offset)
- {
- case 0x0:
- LOG( "CachDat_A write: %2.2x\n", data );
- m_cache_buffer->write(m_cache_pointer++, data);
- break;
- case 0x1:
- LOG( "CachDat_B write: %2.2x\n", data );
- m_cache_buffer->write(m_cache_pointer++, data);
- break;
- case 0x2:
- LOG( "CachCtrl write: %2.2x\n", data );
-
- // reset static ram buffer pointer on any write
- m_cache_pointer = 0;
-
- if(data == 0)
- {
- // Clear interrupt when caching is turned off
- set_line_value(line::CART, CLEAR_LINE);
- m_cache_controler |= 0x80;
- }
-
- m_cache_controler = (m_cache_controler & 0x80) | (data & 0x7f);
- break;
- }
-}
-
-
-//-------------------------------------------------
-// real_time_clock
-//-------------------------------------------------
-
-coco_fdc_device_base::rtc_type coco_fdc_device_base::real_time_clock()
{
- rtc_type result = (rtc_type) m_rtc.read_safe((ioport_value) rtc_type::NONE);
-
- // check to make sure we don't have any invalid values
- if (((result == rtc_type::DISTO) && (m_disto_msm6242 == nullptr))
- || ((result == rtc_type::CLOUD9) && (m_ds1315 == nullptr)))
- {
- result = rtc_type::NONE;
- }
-
- return result;
}
@@ -396,60 +252,15 @@ coco_fdc_device_base::rtc_type coco_fdc_device_base::real_time_clock()
void coco_fdc_device_base::update_lines()
{
- if( (m_cache_controler & 0x7f) == 0) /* cache disabled */
- {
- // clear HALT enable under certain circumstances
- if (intrq() && (dskreg() & 0x20))
- set_dskreg(dskreg() & ~0x80); // clear halt enable
+ // clear HALT enable under certain circumstances
+ if (intrq())
+ set_dskreg(dskreg() & ~0x80); // clear halt enable
- // set the NMI line
- set_line_value(line::NMI, intrq() && (dskreg() & 0x20));
+ // set the NMI line
+ set_line_value(line::NMI, intrq() && (dskreg() & 0x20));
- // set the HALT line
- set_line_value(line::HALT, !drq() && (dskreg() & 0x80));
- }
- else
- {
- if( drq() == ASSERT_LINE)
- {
- if( (m_cache_controler & 0x07) == 0x07) /* Read cache on */
- {
- u8 data = m_wd17xx->data_r();
- LOG("Cached drq read: %2.2x\n", data );
- m_cache_buffer->write(m_cache_pointer++, data);
- }
- else if( (m_cache_controler & 0x07) == 0x04 ) /* Write cache on */
- {
- u8 data = m_cache_buffer->read(m_cache_pointer++);
- LOG("Cached drq write: %2.2x\n", data );
- m_wd17xx->data_w(data);
- }
- else if( (m_cache_controler & 0x07) == 0x06 ) /* Copy Write cache to controller */
- {
- u8 data = m_cache_buffer->read(m_cache_pointer++);
- LOG("Cached copy drq write: %2.2x\n", data );
- m_wd17xx->data_w(data);
- }
- else
- {
- LOG("illegal DRQ cached assert mode\n" );
- }
- }
-
- if( (m_cache_controler & 0x08) == 0x08)
- {
- set_line_value(line::CART, intrq());
- }
-
- if( intrq() == ASSERT_LINE)
- {
- m_cache_controler &= 0x7f;
- }
- else
- {
- m_cache_controler |= 0x80;
- }
- }
+ // set the HALT line
+ set_line_value(line::HALT, !drq() && (dskreg() & 0x80));
}
@@ -475,7 +286,7 @@ void coco_fdc_device_base::dskreg_w(u8 data)
// An email from John Kowalski informed me that if the DS3 is
// high, and one of the other drive bits is selected (DS0-DS2), then the
- // second side of DS0, DS1, or DS2 is selected. If multiple bits are
+ // second side of DS0, DS1, or DS2 is selected. If multiple bits are
// selected in other situations, then both drives are selected, and any
// read signals get yucky.
@@ -534,43 +345,19 @@ u8 coco_fdc_device_base::scs_read(offs_t offset)
{
case 8:
result = m_wd17xx->status_r();
- LOGWDFDC("m_wd17xx->status_r: %2.2x\n", result );
+ LOGWDFDC("m_wd17xx->status_r: %02x\n", result );
break;
case 9:
result = m_wd17xx->track_r();
- LOGWDFDC("m_wd17xx->track_r: %2.2x\n", result );
+ LOGWDFDC("m_wd17xx->track_r: %02x\n", result );
break;
case 10:
result = m_wd17xx->sector_r();
- LOGWDFDC("m_wd17xx->sector_r: %2.2x\n", result );
+ LOGWDFDC("m_wd17xx->sector_r: %02x\n", result );
break;
case 11:
result = m_wd17xx->data_r();
- LOGWDIO("m_wd17xx->data_r: %2.2x\n", result );
- break;
- }
-
- /* other stuff for RTCs */
- switch (offset)
- {
- case 0x10: /* FF50 */
- if (real_time_clock() == rtc_type::DISTO)
- result = m_disto_msm6242->read(m_msm6242_rtc_address);
- break;
-
- case 0x38: /* FF78 */
- if (real_time_clock() == rtc_type::CLOUD9)
- m_ds1315->read_0();
- break;
-
- case 0x39: /* FF79 */
- if (real_time_clock() == rtc_type::CLOUD9)
- m_ds1315->read_1();
- break;
-
- case 0x3C: /* FF7C */
- if (real_time_clock() == rtc_type::CLOUD9)
- result = m_ds1315->read_data();
+ LOGWDIO("m_wd17xx->data_r: %02x\n", result );
break;
}
@@ -591,48 +378,122 @@ void coco_fdc_device_base::scs_write(offs_t offset, u8 data)
dskreg_w(data);
break;
case 8:
- LOGWDFDC("m_wd17xx->cmd_w: %2.2x\n", data );
+ LOGWDFDC("m_wd17xx->cmd_w: %02x\n", data );
m_wd17xx->cmd_w(data);
break;
case 9:
- LOGWDFDC("m_wd17xx->track_w: %2.2x\n", data );
+ LOGWDFDC("m_wd17xx->track_w: %02x\n", data );
m_wd17xx->track_w(data);
break;
case 10:
- LOGWDFDC("m_wd17xx->sector_w: %2.2x\n", data );
+ LOGWDFDC("m_wd17xx->sector_w: %02x\n", data );
m_wd17xx->sector_w(data);
break;
case 11:
- LOGWDIO("m_wd17xx->data_w: %2.2x\n", data );
+ LOGWDIO("m_wd17xx->data_w: %02x\n", data );
m_wd17xx->data_w(data);
break;
};
-
- /* other stuff for RTCs */
- switch(offset)
- {
- case 0x10: /* FF50 */
- if (real_time_clock() == rtc_type::DISTO)
- m_disto_msm6242->write(m_msm6242_rtc_address, data);
- break;
-
- case 0x11: /* FF51 */
- if (real_time_clock() == rtc_type::DISTO)
- m_msm6242_rtc_address = data & 0x0f;
- break;
- }
}
//**************************************************************************
-// COCO FDC
+// CoCo DOS ROMs
//**************************************************************************
ROM_START(coco_fdc)
+ ROM_REGION(0x8000, "eprom", ROMREGION_ERASE00)
+ ROM_DEFAULT_BIOS("v11")
+
+ ROM_SYSTEM_BIOS(0, "v10", "RSDOS v1.0")
+ ROMX_LOAD("disk10.rom", 0x0000, 0x2000, CRC(b4f9968e) SHA1(04115be3f97952b9d9310b52f806d04f80b40d03), ROM_BIOS(0))
+ ROM_RELOAD(0x2000,0x2000)
+ ROM_RELOAD(0x4000,0x2000)
+ ROM_RELOAD(0x6000,0x2000)
+
+ ROM_SYSTEM_BIOS(1, "v11", "RSDOS v1.1")
+ ROMX_LOAD("disk11.rom", 0x0000, 0x2000, CRC(0b9c5415) SHA1(10bdc5aa2d7d7f205f67b47b19003a4bd89defd1), ROM_BIOS(1))
+ ROM_RELOAD(0x2000,0x2000)
+ ROM_RELOAD(0x4000,0x2000)
+ ROM_RELOAD(0x6000,0x2000)
+
+ ROM_SYSTEM_BIOS(2, "ados", "ADOS v1.02 for CoCo 1/2")
+ ROMX_LOAD("ados.rom", 0x0000, 0x2000, CRC(24e807cf) SHA1(a935ea11af4c600a771e4540b661cbb4258a21d6), ROM_BIOS(2))
+ ROM_RELOAD(0x2000,0x2000)
+ ROM_RELOAD(0x4000,0x2000)
+ ROM_RELOAD(0x6000,0x2000)
+
+ ROM_SYSTEM_BIOS(3, "ados2b", "ADOS v1.02 for CoCo 2B")
+ ROMX_LOAD("ados2b.rom", 0x0000, 0x2000, CRC(47a59ad4) SHA1(66bd3cf08e7f1b318e82e8c4a9848233f38f1a56), ROM_BIOS(3))
+ ROM_RELOAD(0x2000,0x2000)
+ ROM_RELOAD(0x4000,0x2000)
+ ROM_RELOAD(0x6000,0x2000)
+
+ ROM_SYSTEM_BIOS(4, "ados3", "ADOS3 v1.01.01")
+ ROMX_LOAD("ados3.rom", 0x0000, 0x2000, CRC(6f824cd1) SHA1(de602d8d219094f1237d37a4f80032c25808b358), ROM_BIOS(4))
+ ROM_RELOAD(0x2000,0x2000)
+ ROM_RELOAD(0x4000,0x2000)
+ ROM_RELOAD(0x6000,0x2000)
+
+ ROM_SYSTEM_BIOS(5, "ados340", "ADOS3 v1.01.01, 40 track disk drives")
+ ROMX_LOAD("ados3-40.rom", 0x0000, 0x2000, CRC(8afe1a04) SHA1(a8dcc6fc0aa5589612cea2a318e7fae58d930c6c), ROM_BIOS(5))
+ ROM_RELOAD(0x2000,0x2000)
+ ROM_RELOAD(0x4000,0x2000)
+ ROM_RELOAD(0x6000,0x2000)
+
+ ROM_SYSTEM_BIOS(6, "ados380", "ADOS3 v1.01.01, 80 track disk drives")
+ ROMX_LOAD("ados3-80.rom", 0x0000, 0x2000, CRC(859762f5) SHA1(957f7d5a10e61266193b636dbf642002bcedfaa3), ROM_BIOS(6))
+ ROM_RELOAD(0x2000,0x2000)
+ ROM_RELOAD(0x4000,0x2000)
+ ROM_RELOAD(0x6000,0x2000)
+
+ ROM_SYSTEM_BIOS(7, "rgbdos", "Hard Disk Basic for Emudsk")
+ ROMX_LOAD("rgbdos_mess.rom", 0x0000, 0x2000, CRC(0b0e64db) SHA1(062ffab14dc788ec7744e528bf9bb425c3ec60ed), ROM_BIOS(7))
+ ROM_RELOAD(0x2000,0x2000)
+ ROM_RELOAD(0x4000,0x2000)
+ ROM_RELOAD(0x6000,0x2000)
+
+ ROM_SYSTEM_BIOS(8, "hdbk12", "Hard Disk Basic for Becker Port and DriveWire 3, CoCo 1/2")
+ ROMX_LOAD("hdbdw3bck.rom", 0x0000, 0x2000, CRC(867a3f42) SHA1(8fd64f1c246489e0bf2b3743ae76332ff324716a), ROM_BIOS(8))
+ ROM_RELOAD(0x2000,0x2000)
+ ROM_RELOAD(0x4000,0x2000)
+ ROM_RELOAD(0x6000,0x2000)
+
+ ROM_SYSTEM_BIOS(9, "hdbk3", "Hard Disk Basic for Becker Port and DriveWire 3, CoCo 3")
+ ROMX_LOAD("hdbdw3bc3.rom", 0x0000, 0x2000, CRC(309a9efd) SHA1(671605d61811953860466f771c1594bbade331f4), ROM_BIOS(9))
+ ROM_RELOAD(0x2000,0x2000)
+ ROM_RELOAD(0x4000,0x2000)
+ ROM_RELOAD(0x6000,0x2000)
+ROM_END
+
+ROM_START(coco_scii)
+ ROM_REGION(0x8000, "eprom", ROMREGION_ERASE00)
+ ROM_DEFAULT_BIOS("cdos3")
+
+ ROM_SYSTEM_BIOS(0, "cdos", "Disto C-DOS v4.0 for the CoCo 1/2")
+ ROMX_LOAD("cdos 4 4-6-89 cc1.bin", 0x0000, 0x4000, CRC(9da6db28) SHA1(2cc6e275178ca8d8f281d845792fb0ae069aaeda), ROM_BIOS(0))
+ ROM_RELOAD(0x4000,0x4000)
+
+ ROM_SYSTEM_BIOS(1, "cdos3", "Disto C-DOS 3 v1.2 for the CoCo 3")
+ ROMX_LOAD("cdos 1_2 3-30-89 cc3.bin", 0x0000, 0x4000, CRC(891c0094) SHA1(c1fa0fcbf1202a9b63aafd98dce777b502584230), ROM_BIOS(1))
+ ROM_RELOAD(0x4000,0x4000)
+ROM_END
+
+ROM_START(cp450_fdc)
+ ROM_REGION(0x4000, "eprom", ROMREGION_ERASE00)
+ ROM_LOAD("cp450_basic_disco_v1.0.rom", 0x0000, 0x2000, CRC(e9ad60a0) SHA1(827697fa5b755f5dc1efb054cdbbeb04e405405b))
+ROM_END
+
+ROM_START(cd6809_fdc)
ROM_REGION(0x4000, "eprom", ROMREGION_ERASE00)
- ROM_LOAD("disk10.rom", 0x0000, 0x2000, CRC(b4f9968e) SHA1(04115be3f97952b9d9310b52f806d04f80b40d03))
+ ROM_LOAD("cd6809dsk.u16", 0x0000, 0x2000, CRC(3c35bda8) SHA1(9b2eec25188bed4326b84739a666435884e4ddf4))
ROM_END
+
+//**************************************************************************
+// COCO Floppy Disk Controller
+//**************************************************************************
+
namespace
{
class coco_fdc_device : public coco_fdc_device_base
@@ -645,121 +506,267 @@ namespace
}
protected:
- // optional information overrides
+ // device_t implementation
virtual const tiny_rom_entry *device_rom_region() const override
{
return ROM_NAME(coco_fdc);
}
-
};
-}
-
-DEFINE_DEVICE_TYPE_PRIVATE(COCO_FDC, coco_family_fdc_device_base, coco_fdc_device, "coco_fdc", "CoCo FDC")
-
//**************************************************************************
-// COCO FDC v1.1
+// Disto / CRC Super Controller II Base
//**************************************************************************
-ROM_START(coco_fdc_v11)
- ROM_REGION(0x8000, "eprom", ROMREGION_ERASE00)
- ROM_LOAD("disk11.rom", 0x0000, 0x2000, CRC(0b9c5415) SHA1(10bdc5aa2d7d7f205f67b47b19003a4bd89defd1))
- ROM_RELOAD(0x2000, 0x2000)
- ROM_RELOAD(0x4000, 0x2000)
- ROM_RELOAD(0x6000, 0x2000)
-ROM_END
-
-namespace
-{
- class coco_fdc_v11_device : public coco_fdc_device_base
+ class coco_scii_device
+ : public coco_fdc_device_base
{
public:
// construction/destruction
- coco_fdc_v11_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
- : coco_fdc_device_base(mconfig, COCO_FDC_V11, tag, owner, clock)
+ // construction/destruction
+ coco_scii_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : coco_fdc_device_base(mconfig, COCO_SCII, tag, owner, clock)
+ , m_slot(*this, MEB_TAG)
+ , m_carts(*this, "cart_line")
{
}
protected:
- // optional information overrides
+ // device_t implementation
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual u8 scs_read(offs_t offset) override;
+ virtual void scs_write(offs_t offset, u8 data) override;
+
+ virtual void device_add_mconfig(machine_config &config) override;
+
virtual const tiny_rom_entry *device_rom_region() const override
{
- return ROM_NAME(coco_fdc_v11);
+ return ROM_NAME(coco_scii);
}
+
+ // methods
+ virtual void update_lines() override;
+
+ // Disto no halt registers
+ u8 ff74_read(offs_t offset);
+ void ff74_write(offs_t offset, u8 data);
+
+ // device references
+ required_device<distomeb_slot_device> m_slot;
+ required_device<input_merger_device> m_carts;
+
+ private:
+ // registers
+ std::unique_ptr<uint8_t[]> m_cache;
+ u8 m_cache_pointer;
+ u8 m_cache_controler;
};
-}
-DEFINE_DEVICE_TYPE_PRIVATE(COCO_FDC_V11, coco_family_fdc_device_base, coco_fdc_v11_device, "coco_fdc_v11", "CoCo FDC v1.1")
+//-------------------------------------------------
+// device_start - device-specific start
+//-------------------------------------------------
-//**************************************************************************
-// COCO-3 HDB-DOS
-//**************************************************************************
+ void coco_scii_device::device_start()
+ {
+ coco_family_fdc_device_base::device_start();
-ROM_START(coco3_hdb1)
- ROM_REGION(0x8000, "eprom", ROMREGION_ERASE00)
- ROM_LOAD("hdbdw3bc3.rom", 0x0000, 0x2000, CRC(309a9efd) SHA1(671605d61811953860466f771c1594bbade331f4))
- ROM_RELOAD(0x2000, 0x2000)
- ROM_RELOAD(0x4000, 0x2000)
- ROM_RELOAD(0x6000, 0x2000)
-ROM_END
+ m_cache = std::make_unique<uint8_t[]>(0x200);
-namespace
-{
- class coco3_hdb1_device : public coco_fdc_device_base
+ install_readwrite_handler(0xFF74, 0xFF77,
+ read8sm_delegate(*this, FUNC(coco_scii_device::ff74_read)),
+ write8sm_delegate(*this, FUNC(coco_scii_device::ff74_write)));
+
+ save_pointer(NAME(m_cache), 0x200);
+ save_item(NAME(m_cache_pointer));
+ save_item(NAME(m_cache_controler));
+ }
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+ void coco_scii_device::device_reset()
{
- public:
- // construction/destruction
- coco3_hdb1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
- : coco_fdc_device_base(mconfig, COCO3_HDB1, tag, owner, clock)
+ coco_family_fdc_device_base::device_reset();
+
+ m_cache_controler = 0x80;
+ m_cache_pointer = 0;
+ }
+
+ static void disto_meb_slot(device_slot_interface &device)
+ {
+ disto_meb_add_basic_devices(device);
+ }
+
+
+//-------------------------------------------------
+// device_add_mconfig - device-specific machine config
+//-------------------------------------------------
+
+ void coco_scii_device::device_add_mconfig(machine_config &config)
+ {
+ coco_fdc_device_base::device_add_mconfig(config);
+
+ INPUT_MERGER_ANY_HIGH(config, m_carts).output_handler().set([this](int state) { set_line_value(line::CART, state); });
+
+ DISTOMEB_SLOT(config, m_slot, DERIVED_CLOCK(1, 1), disto_meb_slot, "rtime");
+ m_slot->cart_callback().set(m_carts, FUNC(input_merger_device::in_w<1>));
+ }
+
+
+//-------------------------------------------------
+// scs_read
+//-------------------------------------------------
+
+ u8 coco_scii_device::scs_read(offs_t offset)
+ {
+ if (offset > 0x0f && offset < 0x18)
+ return m_slot->meb_read(offset - 0x10);
+
+ return coco_fdc_device_base::scs_read(offset);
+ }
+
+
+//-------------------------------------------------
+// scs_write
+//-------------------------------------------------
+
+ void coco_scii_device::scs_write(offs_t offset, u8 data)
+ {
+ if (offset > 0x0f && offset < 0x18)
+ m_slot->meb_write(offset - 0x10, data);
+ else
+ {
+ coco_fdc_device_base::scs_write(offset, data);
+ }
+ }
+
+
+//-------------------------------------------------
+// update_lines - SCII controller lines
+//-------------------------------------------------
+
+ void coco_scii_device::update_lines()
+ {
+ // clear HALT enable under certain circumstances
+ if (intrq())
+ set_dskreg(dskreg() & ~0x80); // clear halt enable
+
+ if ((m_cache_controler & 0x02) == 0) /* cache disabled */
{
+ // set the HALT line
+ set_line_value(line::HALT, !drq() && (dskreg() & 0x80));
}
+ else
+ {
+ set_line_value(line::HALT, CLEAR_LINE);
- protected:
- // optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override
+ if (drq() == ASSERT_LINE)
+ {
+ if ((m_cache_controler & 0x01) == 0x01) /* Read cache on */
+ {
+ u8 data = m_wd17xx->data_r();
+ LOGWDSCII("cache drq read: %02x\n", data );
+ m_cache[m_cache_pointer++] = data;
+ }
+ else /* Write cache on */
+ {
+ u8 data = m_cache[m_cache_pointer++];
+ LOGWDSCII("cache drq write: %02x\n", data );
+ m_wd17xx->data_w(data);
+ }
+
+ m_cache_pointer &= 0x1ff;
+ }
+ }
+
+ if ((m_cache_controler & 0x08) == 0x08)
{
- return ROM_NAME(coco3_hdb1);
+ m_carts->in_w<0>(intrq());
+ }
+ else
+ {
+ m_carts->in_w<0>(CLEAR_LINE);
}
- };
-}
-DEFINE_DEVICE_TYPE_PRIVATE(COCO3_HDB1, coco_family_fdc_device_base, coco3_hdb1_device, "coco3_hdb1", "CoCo3 HDB-DOS")
+ if ((m_cache_controler & 0x04) == 0x00)
+ {
+ set_line_value(line::NMI, intrq() && (dskreg() & 0x20));
+ }
+ else
+ {
+ set_line_value(line::NMI, CLEAR_LINE);
+ }
+ }
-//**************************************************************************
-// COCO-2 HDB-DOS
-//**************************************************************************
-ROM_START(coco2_hdb1)
- ROM_REGION(0x8000, "eprom", ROMREGION_ERASE00)
- ROM_LOAD("hdbdw3bck.rom", 0x0000, 0x2000, CRC(867a3f42) SHA1(8fd64f1c246489e0bf2b3743ae76332ff324716a))
- ROM_RELOAD(0x2000, 0x2000)
- ROM_RELOAD(0x4000, 0x2000)
- ROM_RELOAD(0x6000, 0x2000)
-ROM_END
+//-------------------------------------------------
+// ff74_read - no halt registers
+//-------------------------------------------------
-namespace
-{
- class coco2_hdb1_device : public coco_fdc_device_base
+ u8 coco_scii_device::ff74_read(offs_t offset)
{
- public:
- // construction/destruction
- coco2_hdb1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
- : coco_fdc_device_base(mconfig, COCO2_HDB1, tag, owner, clock)
+ u8 data = 0x0;
+
+ switch(offset)
{
+ case 0x0:
+ case 0x1:
+ data = m_cache[m_cache_pointer++];
+ LOGWDSCII("cache read: %04x = %02x\n", m_cache_pointer, data);
+ m_cache_pointer &= 0x1ff;
+ break;
+
+ case 0x2:
+ case 0x3:
+ if (intrq() == ASSERT_LINE)
+ {
+ m_cache_controler &= 0x7f;
+ }
+ else
+ {
+ m_cache_controler |= 0x80;
+ }
+
+ data = m_cache_controler;
+ LOGWDSCII("control read: %02x\n", data);
+ break;
}
- protected:
- // optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override
+ return data;
+ }
+
+
+//-------------------------------------------------
+// ff74_write - no halt registers
+//-------------------------------------------------
+
+ void coco_scii_device::ff74_write(offs_t offset, u8 data)
+ {
+ switch(offset)
{
- return ROM_NAME(coco2_hdb1);
+ case 0x0:
+ case 0x1:
+ LOGWDSCII("cache write: %04x = %02x\n", m_cache_pointer, data);
+ m_cache[m_cache_pointer++] = data;
+ m_cache_pointer &= 0x1ff;
+ break;
+ case 0x2:
+ case 0x3:
+ LOGWDSCII("control write: %02x\n", data);
+
+ // reset static ram buffer pointer on any write
+ m_cache_pointer = 0;
+
+ m_cache_controler = data;
+ update_lines();
+ break;
}
- };
-}
+ }
-DEFINE_DEVICE_TYPE_PRIVATE(COCO2_HDB1, coco_family_fdc_device_base, coco2_hdb1_device, "coco2_hdb1", "CoCo2 HDB-DOS")
//**************************************************************************
// Prológica CP-450 BASIC Disco V. 1.0 (1984)
@@ -770,13 +777,6 @@ DEFINE_DEVICE_TYPE_PRIVATE(COCO2_HDB1, coco_family_fdc_device_base, coco2_hdb1_d
//
//**************************************************************************
-ROM_START(cp450_fdc)
- ROM_REGION(0x4000, "eprom", ROMREGION_ERASE00)
- ROM_LOAD("cp450_basic_disco_v1.0.rom", 0x0000, 0x2000, CRC(e9ad60a0) SHA1(827697fa5b755f5dc1efb054cdbbeb04e405405b))
-ROM_END
-
-namespace
-{
class cp450_fdc_device : public coco_fdc_device_base
{
public:
@@ -793,9 +793,7 @@ namespace
return ROM_NAME(cp450_fdc);
}
};
-}
-DEFINE_DEVICE_TYPE_PRIVATE(CP450_FDC, coco_family_fdc_device_base, cp450_fdc_device, "cp450_fdc", "Prológica CP-450 BASIC Disco V. 1.0 (1984)")
//**************************************************************************
// Codimex CD-6809 FDC (1986)
@@ -804,13 +802,6 @@ DEFINE_DEVICE_TYPE_PRIVATE(CP450_FDC, coco_family_fdc_device_base, cp450_fdc_dev
// More ifo at: http://amxproject.com/?p=2747
//**************************************************************************
-ROM_START(cd6809_fdc)
- ROM_REGION(0x4000, "eprom", ROMREGION_ERASE00)
- ROM_LOAD("cd6809dsk.u16", 0x0000, 0x2000, CRC(3c35bda8) SHA1(9b2eec25188bed4326b84739a666435884e4ddf4))
-ROM_END
-
-namespace
-{
class cd6809_fdc_device : public coco_fdc_device_base
{
public:
@@ -827,6 +818,9 @@ namespace
return ROM_NAME(cd6809_fdc);
}
};
-}
+} // Anonymous namepace
+DEFINE_DEVICE_TYPE_PRIVATE(COCO_FDC, coco_family_fdc_device_base, coco_fdc_device, "coco_fdc", "CoCo Floppy Disk Controller")
+DEFINE_DEVICE_TYPE_PRIVATE(COCO_SCII, coco_family_fdc_device_base, coco_scii_device, "coco_scii", "Disto Super Controller II")
+DEFINE_DEVICE_TYPE_PRIVATE(CP450_FDC, coco_family_fdc_device_base, cp450_fdc_device, "cp450_fdc", "Prológica CP-450 BASIC Disco V. 1.0 (1984)")
DEFINE_DEVICE_TYPE_PRIVATE(CD6809_FDC, coco_family_fdc_device_base, cd6809_fdc_device, "cd6809_fdc", "Codimex CD-6809 Disk BASIC (1986)")
diff --git a/src/devices/bus/coco/coco_fdc.h b/src/devices/bus/coco/coco_fdc.h
index 786d30c2f68..f5279fe445b 100644
--- a/src/devices/bus/coco/coco_fdc.h
+++ b/src/devices/bus/coco/coco_fdc.h
@@ -12,6 +12,7 @@
#define MAME_BUS_COCO_COCO_FDC_H
#include "cococart.h"
+
#include "imagedev/floppy.h"
@@ -26,8 +27,8 @@ class coco_family_fdc_device_base :
public device_cococart_interface
{
public:
- DECLARE_WRITE_LINE_MEMBER(fdc_intrq_w) { m_intrq = state; update_lines(); }
- DECLARE_WRITE_LINE_MEMBER(fdc_drq_w) { m_drq = state; update_lines(); }
+ void fdc_intrq_w(int state) { m_intrq = state; update_lines(); }
+ void fdc_drq_w(int state) { m_drq = state; update_lines(); }
static void floppy_formats(format_registration &fr);
@@ -62,11 +63,9 @@ private:
};
// device type definitions - CoCo FDC
-DECLARE_DEVICE_TYPE(COCO_FDC, coco_family_fdc_device_base)
-DECLARE_DEVICE_TYPE(COCO_FDC_V11, coco_family_fdc_device_base)
-DECLARE_DEVICE_TYPE(COCO3_HDB1, coco_family_fdc_device_base)
-DECLARE_DEVICE_TYPE(COCO2_HDB1, coco_family_fdc_device_base)
-DECLARE_DEVICE_TYPE(CP450_FDC, coco_family_fdc_device_base)
-DECLARE_DEVICE_TYPE(CD6809_FDC, coco_family_fdc_device_base)
+DECLARE_DEVICE_TYPE(COCO_FDC, coco_family_fdc_device_base)
+DECLARE_DEVICE_TYPE(COCO_SCII, coco_family_fdc_device_base)
+DECLARE_DEVICE_TYPE(CP450_FDC, coco_family_fdc_device_base)
+DECLARE_DEVICE_TYPE(CD6809_FDC, coco_family_fdc_device_base)
#endif // MAME_BUS_COCO_COCO_FDC_H
diff --git a/src/devices/bus/coco/coco_midi.cpp b/src/devices/bus/coco/coco_midi.cpp
index 0e6e38b839b..965ca3d261a 100644
--- a/src/devices/bus/coco/coco_midi.cpp
+++ b/src/devices/bus/coco/coco_midi.cpp
@@ -35,7 +35,7 @@ class coco_midi_device :
// optional information overrides
virtual void device_add_mconfig(machine_config &config) override;
required_device<acia6850_device> m_acia;
- DECLARE_WRITE_LINE_MEMBER( acia_irq_w );
+ void acia_irq_w(int state);
private:
required_device<midi_port_device> m_mdthru;
@@ -88,7 +88,7 @@ void coco_midi_device::device_start()
write8sm_delegate(m_acia, FUNC(acia6850_device::write)));
}
-WRITE_LINE_MEMBER(coco_midi_device::acia_irq_w)
+void coco_midi_device::acia_irq_w(int state)
{
set_line_value(line::CART, state == 0);
}
diff --git a/src/devices/bus/coco/coco_multi.cpp b/src/devices/bus/coco/coco_multi.cpp
index 2061c905b3f..1e385dab107 100644
--- a/src/devices/bus/coco/coco_multi.cpp
+++ b/src/devices/bus/coco/coco_multi.cpp
@@ -65,7 +65,6 @@
#define SWITCH_CONFIG_TAG "switch"
-//#define LOG_GENERAL (1U << 0) //defined in logmacro.h already
#define LOG_CART (1U << 1) // shows cart line changes
#define LOG_SWITCH (1U << 2) // shows switch changes
//#define VERBOSE (LOG_CART|LOG_SWITCH)
@@ -190,7 +189,7 @@ void coco_multipak_device::device_add_mconfig(machine_config &config)
m_slots[2]->cart_callback().set([this](int state) { update_line(3, line::CART); });
m_slots[2]->nmi_callback().set([this](int state) { update_line(3, line::NMI); });
m_slots[2]->halt_callback().set([this](int state) { update_line(3, line::HALT); });
- COCOCART_SLOT(config, m_slots[3], DERIVED_CLOCK(1, 1), coco_cart_slot4, "fdcv11");
+ COCOCART_SLOT(config, m_slots[3], DERIVED_CLOCK(1, 1), coco_cart_slot4, "fdc");
m_slots[3]->cart_callback().set([this](int state) { update_line(4, line::CART); });
m_slots[3]->nmi_callback().set([this](int state) { update_line(4, line::NMI); });
m_slots[3]->halt_callback().set([this](int state) { update_line(4, line::HALT); });
diff --git a/src/devices/bus/coco/coco_ram.cpp b/src/devices/bus/coco/coco_ram.cpp
index 885cc55a34d..0fc1736f387 100644
--- a/src/devices/bus/coco/coco_ram.cpp
+++ b/src/devices/bus/coco/coco_ram.cpp
@@ -7,25 +7,20 @@
Code for emulating the Disto RAM cartridge
This cartridge came in several forms: 256K, 512K, 768K, and 1024K.
+ It also includes a mini expansion bus.
***************************************************************************/
#include "emu.h"
#include "coco_ram.h"
+#include "meb_intrf.h"
-#include "machine/ram.h"
-
-#define STATICRAM_TAG "static_ram"
-
-
-// #define VERBOSE (LOG_GENERAL )
+//#define VERBOSE (LOG_GENERAL)
#include "logmacro.h"
-#define RAM_SIZE_IN_K 1024
-#define BUFFER_SIZE (RAM_SIZE_IN_K * 1024)
+#define RAM_SIZE 1024 * 1024
+#define MEB_TAG "meb"
-#define STRINGIZE_HELPER(expr) #expr
-#define STRINGIZE(expr) STRINGIZE_HELPER(expr)
//**************************************************************************
// TYPE DECLARATIONS
@@ -33,27 +28,28 @@
namespace
{
- // ======================> coco_pak_device
+ // ======================> coco_pak_ram_device
- class coco_pak_ram_device :
- public device_t,
- public device_cococart_interface
+ class coco_pak_ram_device
+ : public device_t
+ , public device_cococart_interface
{
- public:
- // construction/destruction
- coco_pak_ram_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual void device_add_mconfig(machine_config &config) override;
-
- protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void scs_write(offs_t offset, u8 data) override;
- virtual u8 scs_read(offs_t offset) override;
-
- private:
- required_device<ram_device> m_staticram;
- u32 m_offset;
+ public:
+ // construction/destruction
+ coco_pak_ram_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+ virtual void device_add_mconfig(machine_config &config) override;
+
+ protected:
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void scs_write(offs_t offset, u8 data) override;
+ virtual u8 scs_read(offs_t offset) override;
+ required_device<distomeb_slot_device> m_slot;
+
+ private:
+ std::unique_ptr<uint8_t[]> m_staticram;
+ u32 m_offset;
};
};
@@ -63,19 +59,18 @@ namespace
// GLOBAL VARIABLES
//**************************************************************************
-DEFINE_DEVICE_TYPE_PRIVATE(COCO_PAK_RAM, device_cococart_interface, coco_pak_ram_device, "cocopakram", "Disto " STRINGIZE(RAM_SIZE_IN_K) "K RAM Cartridge")
+DEFINE_DEVICE_TYPE_PRIVATE(COCO_PAK_RAM, device_cococart_interface, coco_pak_ram_device, "cocopakram", "Disto RAM Cartridge")
//-------------------------------------------------
-// coco_pak_device - constructor
+// coco_pak_ram_device - constructor
//-------------------------------------------------
coco_pak_ram_device::coco_pak_ram_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: device_t(mconfig, COCO_PAK_RAM, tag, owner, clock)
, device_cococart_interface(mconfig, *this)
- , m_staticram(*this, STATICRAM_TAG)
- , m_offset(0)
+ , m_slot(*this, MEB_TAG)
{
}
@@ -85,9 +80,15 @@ coco_pak_ram_device::coco_pak_ram_device(const machine_config &mconfig, const ch
// MACHINE FRAGMENTS AND ADDRESS MAPS
//**************************************************************************
+static void disto_meb_slot(device_slot_interface &device)
+{
+ disto_meb_add_basic_devices(device);
+}
+
void coco_pak_ram_device::device_add_mconfig(machine_config &config)
{
- RAM(config, STATICRAM_TAG).set_default_size(STRINGIZE(RAM_SIZE_IN_K) "K").set_default_value(0);
+ DISTOMEB_SLOT(config, m_slot, DERIVED_CLOCK(1, 1), disto_meb_slot, "rtime");
+ m_slot->cart_callback().set([this](int state) { set_line_value(line::CART, state); });
}
@@ -100,9 +101,11 @@ void coco_pak_ram_device::device_start()
{
// initial state
m_offset = 0;
+ m_staticram = std::make_unique<uint8_t[]>(RAM_SIZE);
// save state
save_item(NAME(m_offset));
+ save_pointer(NAME(m_staticram), RAM_SIZE);
}
@@ -124,28 +127,31 @@ void coco_pak_ram_device::device_reset()
void coco_pak_ram_device::scs_write(offs_t offset, u8 data)
{
-// int idata = data;
-
- switch (offset)
+ if (offset > 0x0f && offset < 0x18)
+ m_slot->meb_write(offset - 0x10, data);
+ else
{
- case 0:
- m_offset = (m_offset & 0xffff00) | u32(data);
- break;
- case 1:
- m_offset = (m_offset & 0xff00ff) | (u32(data) << 8);
- break;
- case 2:
- m_offset = (m_offset & 0x00ffff) | (u32(data) << 16);
- break;
- case 3:
- if (m_offset < BUFFER_SIZE)
- {
- m_staticram->write(m_offset, data);
- }
- break;
+ switch (offset)
+ {
+ case 0:
+ m_offset = (m_offset & 0xffff00) | u32(data);
+ break;
+ case 1:
+ m_offset = (m_offset & 0xff00ff) | (u32(data) << 8);
+ break;
+ case 2:
+ m_offset = (m_offset & 0x00ffff) | (u32(data) << 16);
+ break;
+ case 3:
+ if (m_offset < RAM_SIZE)
+ {
+ m_staticram[m_offset] = data;
+ }
+ break;
+ }
+
+ LOG("scs_write: %s: %06x, %02x, %02x\n", machine().describe_context(), m_offset, offset, data);
}
-
- LOG("scs_write: %s: %06x, %02x, %02x\n", machine().describe_context(), m_offset, offset, data);
}
@@ -158,25 +164,33 @@ u8 coco_pak_ram_device::scs_read(offs_t offset)
{
u8 data = 0x00;
- switch (offset)
+ if (offset > 0x0f && offset < 0x18)
+ {
+ data = m_slot->meb_read(offset - 0x10);
+ }
+ else
{
- case 0:
- data = u8(m_offset & 0x00ff);
- break;
- case 1:
- data = u8((m_offset >> 8) & 0x00ff);
- break;
- case 2:
- data = u8((m_offset >> 16) & 0x00ff);
- break;
- case 3:
- if (m_offset < BUFFER_SIZE)
- {
- data = m_staticram->read(m_offset);
- }
- break;
+ switch (offset)
+ {
+ case 0:
+ data = u8(m_offset & 0x00ff);
+ break;
+ case 1:
+ data = u8((m_offset >> 8) & 0x00ff);
+ break;
+ case 2:
+ data = u8((m_offset >> 16) & 0x00ff);
+ break;
+ case 3:
+ if (m_offset < RAM_SIZE)
+ {
+ data = m_staticram[m_offset];
+ }
+ break;
+ }
+
+ LOG("scs_read:\t%s: %06x, %02x, %02x\n", machine().describe_context(), m_offset, offset, data);
}
- LOG("scs_read: %s: %06x, %02x, %02x\n", machine().describe_context(), m_offset, offset, data);
return data;
}
diff --git a/src/devices/bus/coco/coco_rs232.cpp b/src/devices/bus/coco/coco_rs232.cpp
index 90f7c6f7be7..2c747caf6a8 100644
--- a/src/devices/bus/coco/coco_rs232.cpp
+++ b/src/devices/bus/coco/coco_rs232.cpp
@@ -47,7 +47,7 @@ namespace
// optional information overrides
virtual void device_add_mconfig(machine_config &config) override;
- WRITE_LINE_MEMBER(uart_irq_w)
+ void uart_irq_w(int state)
{
set_line_value(line::CART, state != 0);
}
diff --git a/src/devices/bus/coco/coco_ssc.cpp b/src/devices/bus/coco/coco_ssc.cpp
index 7c8d497a224..b99d8e2af40 100644
--- a/src/devices/bus/coco/coco_ssc.cpp
+++ b/src/devices/bus/coco/coco_ssc.cpp
@@ -40,8 +40,8 @@
#include "speaker.h"
-#define LOG_INTERFACE (1U << 1)
-#define LOG_INTERNAL (1U << 2)
+#define LOG_INTERFACE (1U << 1)
+#define LOG_INTERNAL (1U << 2)
#define VERBOSE (0)
// #define VERBOSE (LOG_INTERFACE)
// #define VERBOSE (LOG_INTERFACE|LOG_INTERNAL)
diff --git a/src/devices/bus/coco/coco_stecomp.cpp b/src/devices/bus/coco/coco_stecomp.cpp
index 412f4e3f865..079fe481d35 100644
--- a/src/devices/bus/coco/coco_stecomp.cpp
+++ b/src/devices/bus/coco/coco_stecomp.cpp
@@ -70,10 +70,10 @@ namespace
{
SPEAKER(config, "sc_lspeaker").front_left();
SPEAKER(config, "sc_rspeaker").front_right();
- DAC_8BIT_R2R(config, m_ldac, 0).add_route(ALL_OUTPUTS, "sc_lspeaker", 0.5);
- DAC_8BIT_R2R(config, m_rdac, 0).add_route(ALL_OUTPUTS, "sc_rspeaker", 0.5);
+ DAC_8BIT_R2R(config, m_ldac).add_route(ALL_OUTPUTS, "sc_lspeaker", 0.5);
+ DAC_8BIT_R2R(config, m_rdac).add_route(ALL_OUTPUTS, "sc_rspeaker", 0.5);
- pia6821_device &pia(PIA6821(config, "sc_pia", 0));
+ pia6821_device &pia(PIA6821(config, "sc_pia"));
pia.writepa_handler().set("sc_ldac", FUNC(dac_byte_interface::data_w));
pia.writepb_handler().set("sc_rdac", FUNC(dac_byte_interface::data_w));
}
diff --git a/src/devices/bus/coco/coco_sym12.cpp b/src/devices/bus/coco/coco_sym12.cpp
index 1edbb27fccc..cf9cc15bd0e 100644
--- a/src/devices/bus/coco/coco_sym12.cpp
+++ b/src/devices/bus/coco/coco_sym12.cpp
@@ -72,7 +72,7 @@ namespace
void coco_symphony_twelve_device::device_add_mconfig(machine_config &config)
{
- pia6821_device &pia(PIA6821(config, "s12_pia", 0));
+ pia6821_device &pia(PIA6821(config, "s12_pia"));
pia.writepa_handler().set(*this, FUNC(coco_symphony_twelve_device::write_porta));
pia.readpa_handler().set(*this, FUNC(coco_symphony_twelve_device::read_porta));
pia.writepb_handler().set(*this, FUNC(coco_symphony_twelve_device::write_portb));
diff --git a/src/devices/bus/coco/coco_t4426.cpp b/src/devices/bus/coco/coco_t4426.cpp
index bf236f5b7b8..b0f3b73d54c 100644
--- a/src/devices/bus/coco/coco_t4426.cpp
+++ b/src/devices/bus/coco/coco_t4426.cpp
@@ -50,10 +50,9 @@
#include "machine/mc14411.h"
#include "machine/6821pia.h"
-//#define LOG_GENERAL (1U << 0)
-#define LOG_SETUP (1U << 1)
-#define LOG_PIA (1U << 2)
-#define LOG_ACIA (1U << 3)
+#define LOG_SETUP (1U << 1)
+#define LOG_PIA (1U << 2)
+#define LOG_ACIA (1U << 3)
//#define VERBOSE (LOG_PIA) // (LOG_PIA | LOG_GENERAL | LOG_SETUP)
//#define LOG_OUTPUT_STREAM std::cout
@@ -107,15 +106,15 @@ namespace
// Clocks
void write_acia_clocks(int id, int state);
- DECLARE_WRITE_LINE_MEMBER (write_f1_clock){ write_acia_clocks(mc14411_device::TIMER_F1, state); }
- DECLARE_WRITE_LINE_MEMBER (write_f3_clock){ write_acia_clocks(mc14411_device::TIMER_F3, state); }
- DECLARE_WRITE_LINE_MEMBER (write_f5_clock){ write_acia_clocks(mc14411_device::TIMER_F5, state); }
- DECLARE_WRITE_LINE_MEMBER (write_f7_clock){ write_acia_clocks(mc14411_device::TIMER_F7, state); }
- DECLARE_WRITE_LINE_MEMBER (write_f8_clock){ write_acia_clocks(mc14411_device::TIMER_F8, state); }
- DECLARE_WRITE_LINE_MEMBER (write_f9_clock){ write_acia_clocks(mc14411_device::TIMER_F9, state); }
- DECLARE_WRITE_LINE_MEMBER (write_f11_clock){ write_acia_clocks(mc14411_device::TIMER_F11, state); }
- DECLARE_WRITE_LINE_MEMBER (write_f13_clock){ write_acia_clocks(mc14411_device::TIMER_F13, state); }
- DECLARE_WRITE_LINE_MEMBER (write_f15_clock){ write_acia_clocks(mc14411_device::TIMER_F15, state); }
+ void write_f1_clock(int state) { write_acia_clocks(mc14411_device::TIMER_F1, state); }
+ void write_f3_clock(int state) { write_acia_clocks(mc14411_device::TIMER_F3, state); }
+ void write_f5_clock(int state) { write_acia_clocks(mc14411_device::TIMER_F5, state); }
+ void write_f7_clock(int state) { write_acia_clocks(mc14411_device::TIMER_F7, state); }
+ void write_f8_clock(int state) { write_acia_clocks(mc14411_device::TIMER_F8, state); }
+ void write_f9_clock(int state) { write_acia_clocks(mc14411_device::TIMER_F9, state); }
+ void write_f11_clock(int state) { write_acia_clocks(mc14411_device::TIMER_F11, state); }
+ void write_f13_clock(int state) { write_acia_clocks(mc14411_device::TIMER_F13, state); }
+ void write_f15_clock(int state) { write_acia_clocks(mc14411_device::TIMER_F15, state); }
protected:
coco_t4426_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
@@ -151,7 +150,7 @@ namespace
void coco_t4426_device::device_add_mconfig(machine_config &config)
{
- PIA6821(config, m_pia, 0);
+ PIA6821(config, m_pia);
m_pia->writepa_handler().set(FUNC(coco_t4426_device::pia_A_w));
ACIA6850(config, m_uart, 0);
diff --git a/src/devices/bus/coco/cococart.cpp b/src/devices/bus/coco/cococart.cpp
index ec387378fb8..2c385890311 100644
--- a/src/devices/bus/coco/cococart.cpp
+++ b/src/devices/bus/coco/cococart.cpp
@@ -73,7 +73,6 @@
PARAMETERS
***************************************************************************/
-//#define LOG_GENERAL (1U << 0) //defined in logmacro.h already
#define LOG_CART (1U << 1) // shows cart line changes
#define LOG_NMI (1U << 2) // shows switch changes
#define LOG_HALT (1U << 3) // shows switch changes
@@ -153,7 +152,6 @@ void cococart_slot_device::device_start()
m_cart_line.value = line_value::CLEAR;
m_cart_line.line = 0;
m_cart_line.q_count = 0;
- m_cart_callback.resolve();
m_cart_line.callback = &m_cart_callback;
m_nmi_line.timer_index = 0;
@@ -161,7 +159,6 @@ void cococart_slot_device::device_start()
m_nmi_line.value = line_value::CLEAR;
m_nmi_line.line = 0;
m_nmi_line.q_count = 0;
- m_nmi_callback.resolve();
m_nmi_line.callback = &m_nmi_callback;
m_halt_line.timer_index = 0;
@@ -169,7 +166,6 @@ void cococart_slot_device::device_start()
m_halt_line.value = line_value::CLEAR;
m_halt_line.line = 0;
m_halt_line.q_count = 0;
- m_halt_callback.resolve();
m_halt_line.callback = &m_halt_callback;
m_cart = get_card_device();
@@ -346,9 +342,8 @@ void cococart_slot_device::set_line(line ln, coco_cartridge_line &line, cococart
break;
}
- /* invoke the callback, if present */
- if (!(*line.callback).isnull())
- (*line.callback)(line.line);
+ /* invoke the callback */
+ (*line.callback)(line.line);
}
}
@@ -575,7 +570,7 @@ static std::error_condition read_coco_rpk(std::unique_ptr<util::random_read> &&s
// call_load
//-------------------------------------------------
-image_init_result cococart_slot_device::call_load()
+std::pair<std::error_condition, std::string> cococart_slot_device::call_load()
{
if (m_cart)
{
@@ -597,7 +592,7 @@ image_init_result cococart_slot_device::call_load()
if (!err)
err = read_coco_rpk(std::move(proxy), base, cart_length, read_length);
if (err)
- return image_init_result::FAIL;
+ return std::make_pair(err, std::string());
}
else
{
@@ -612,7 +607,7 @@ image_init_result cococart_slot_device::call_load()
read_length += len;
}
}
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
@@ -657,7 +652,7 @@ template class device_finder<device_cococart_interface, true>;
device_cococart_interface::device_cococart_interface(const machine_config &mconfig, device_t &device)
: device_interface(device, "cococart")
- , m_owning_slot(nullptr)
+ , m_owning_slot(dynamic_cast<cococart_slot_device *>(device.owner()))
, m_host(nullptr)
{
}
@@ -678,7 +673,6 @@ device_cococart_interface::~device_cococart_interface()
void device_cococart_interface::interface_config_complete()
{
- m_owning_slot = dynamic_cast<cococart_slot_device *>(device().owner());
m_host = m_owning_slot
? dynamic_cast<device_cococart_host_interface *>(m_owning_slot->owner())
: nullptr;
@@ -861,12 +855,10 @@ void coco_cart_add_fdcs(device_slot_interface &device)
{
// FDCs are optional because if they are on a Multi-Pak interface, they must
// be on Slot 4
- device.option_add("cc2hdb1", COCO2_HDB1);
- device.option_add("cc3hdb1", COCO3_HDB1);
device.option_add("cd6809_fdc", CD6809_FDC);
device.option_add("cp450_fdc", CP450_FDC);
device.option_add("fdc", COCO_FDC);
- device.option_add("fdcv11", COCO_FDC_V11);
+ device.option_add("scii", COCO_SCII);
}
diff --git a/src/devices/bus/coco/cococart.h b/src/devices/bus/coco/cococart.h
index b686ac0748d..3056bfeed62 100644
--- a/src/devices/bus/coco/cococart.h
+++ b/src/devices/bus/coco/cococart.h
@@ -67,17 +67,17 @@ public:
auto nmi_callback() { return m_nmi_callback.bind(); }
auto halt_callback() { return m_halt_callback.bind(); }
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
- // image-level overrides
- virtual image_init_result call_load() override;
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
virtual bool is_reset_on_load() const noexcept override { return true; }
virtual const char *image_interface() const noexcept override { return "coco_cart"; }
virtual const char *file_extensions() const noexcept override { return "ccc,rom"; }
- // slot interface overrides
+ // device_slot_interface implementation
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
// reading and writing to $C000-$FFEF
@@ -221,7 +221,7 @@ protected:
private:
cococart_base_update_delegate m_update;
- cococart_slot_device * m_owning_slot;
+ cococart_slot_device * const m_owning_slot;
device_cococart_host_interface * m_host;
};
diff --git a/src/devices/bus/coco/dragon_claw.cpp b/src/devices/bus/coco/dragon_claw.cpp
index a4c00b0f71a..54d99c6dc9a 100644
--- a/src/devices/bus/coco/dragon_claw.cpp
+++ b/src/devices/bus/coco/dragon_claw.cpp
@@ -123,7 +123,7 @@ void dragon_claw_device::device_add_mconfig(machine_config &config)
m_slot->halt_callback().set([this](int state) { set_line_value(line::HALT, state); });
}
-WRITE_LINE_MEMBER(dragon_claw_device::irq_w)
+void dragon_claw_device::irq_w(int state)
{
if (m_links->read() & 0x04)
set_line_value(line::CART, state);
diff --git a/src/devices/bus/coco/dragon_claw.h b/src/devices/bus/coco/dragon_claw.h
index 9743b5b0b3c..69df7b2e303 100644
--- a/src/devices/bus/coco/dragon_claw.h
+++ b/src/devices/bus/coco/dragon_claw.h
@@ -45,7 +45,7 @@ protected:
virtual address_space &cartridge_space() override;
private:
- DECLARE_WRITE_LINE_MEMBER(irq_w);
+ void irq_w(int state);
required_device<via6522_device> m_via;
required_device<cococart_slot_device> m_slot;
diff --git a/src/devices/bus/coco/dragon_fdc.cpp b/src/devices/bus/coco/dragon_fdc.cpp
index 5a70433e559..671126191e2 100644
--- a/src/devices/bus/coco/dragon_fdc.cpp
+++ b/src/devices/bus/coco/dragon_fdc.cpp
@@ -82,8 +82,9 @@
PARAMETERS
***************************************************************************/
-#define LOG_FDC 0
-
+#define LOG_FDC (1U << 1)
+#define VERBOSE (0)
+#include "logmacro.h"
/***************************************************************************
@@ -221,19 +222,16 @@ void premier_fdc_device_base::update_lines()
void dragon_fdc_device_base::dskreg_w(u8 data)
{
- if (LOG_FDC)
- {
- logerror("fdc_dragon_dskreg_w(): %c%c%c%c%c%c%c%c ($%02x)\n",
- BIT(data, 7) ? 'X' : 'x',
- BIT(data, 6) ? 'X' : 'x',
- BIT(data, 5) ? 'N' : 'n',
- BIT(data, 4) ? 'P' : 'p',
- BIT(data, 3) ? 'S' : 'D',
- BIT(data, 2) ? 'M' : 'm',
- BIT(data, 1) ? '1' : '0',
- BIT(data, 0) ? '1' : '0',
- data);
- }
+ LOGMASKED(LOG_FDC, "fdc_dragon_dskreg_w(): %c%c%c%c%c%c%c%c ($%02x)\n",
+ BIT(data, 7) ? 'X' : 'x',
+ BIT(data, 6) ? 'X' : 'x',
+ BIT(data, 5) ? 'N' : 'n',
+ BIT(data, 4) ? 'P' : 'p',
+ BIT(data, 3) ? 'S' : 'D',
+ BIT(data, 2) ? 'M' : 'm',
+ BIT(data, 1) ? '1' : '0',
+ BIT(data, 0) ? '1' : '0',
+ data);
// update the motor on each floppy
for (int i = 0; i < 4; i++)
@@ -253,19 +251,16 @@ void dragon_fdc_device_base::dskreg_w(u8 data)
void premier_fdc_device_base::dskreg_w(u8 data)
{
- if (LOG_FDC)
- {
- logerror("fdc_premier_dskreg_w(): %c%c%c%c%c%c%c%c ($%02x)\n",
- BIT(data, 7) ? 'X' : 'x',
- BIT(data, 6) ? 'X' : 'x',
- BIT(data, 5) ? 'X' : 'x',
- BIT(data, 4) ? 'D' : 'S',
- BIT(data, 3) ? '8' : '5',
- BIT(data, 2) ? '1' : '0',
- BIT(data, 1) ? '1' : '0',
- BIT(data, 0) ? '1' : '0',
- data);
- }
+ LOGMASKED(LOG_FDC, "fdc_premier_dskreg_w(): %c%c%c%c%c%c%c%c ($%02x)\n",
+ BIT(data, 7) ? 'X' : 'x',
+ BIT(data, 6) ? 'X' : 'x',
+ BIT(data, 5) ? 'X' : 'x',
+ BIT(data, 4) ? 'D' : 'S',
+ BIT(data, 3) ? '8' : '5',
+ BIT(data, 2) ? '1' : '0',
+ BIT(data, 1) ? '1' : '0',
+ BIT(data, 0) ? '1' : '0',
+ data);
floppy_image_device *floppy = nullptr;
// update the motor on each floppy
diff --git a/src/devices/bus/coco/dragon_jcbspch.cpp b/src/devices/bus/coco/dragon_jcbspch.cpp
index a82d122d275..71ba15ce267 100644
--- a/src/devices/bus/coco/dragon_jcbspch.cpp
+++ b/src/devices/bus/coco/dragon_jcbspch.cpp
@@ -83,7 +83,7 @@ memory_region *dragon_jcbspch_device::get_cart_memregion()
void dragon_jcbspch_device::device_add_mconfig(machine_config &config)
{
- PIA6821(config, m_pia, 0);
+ PIA6821(config, m_pia);
m_pia->writepb_handler().set(m_nsp, FUNC(sp0256_device::ald_w)).mask(0x3f);
m_pia->cb2_handler().set(FUNC(dragon_jcbspch_device::pia_cb2_w));
m_pia->irqb_handler().set(FUNC(dragon_jcbspch_device::nmi_w));
@@ -143,12 +143,12 @@ void dragon_jcbspch_device::scs_write(offs_t offset, u8 data)
}
}
-WRITE_LINE_MEMBER(dragon_jcbspch_device::pia_cb2_w)
+void dragon_jcbspch_device::pia_cb2_w(int state)
{
// TODO: what does this do?
}
-WRITE_LINE_MEMBER(dragon_jcbspch_device::nmi_w)
+void dragon_jcbspch_device::nmi_w(int state)
{
// set the NMI line
set_line_value(line::NMI, state);
diff --git a/src/devices/bus/coco/dragon_jcbspch.h b/src/devices/bus/coco/dragon_jcbspch.h
index e8761dec2d8..b94c10f6915 100644
--- a/src/devices/bus/coco/dragon_jcbspch.h
+++ b/src/devices/bus/coco/dragon_jcbspch.h
@@ -37,8 +37,8 @@ protected:
virtual void scs_write(offs_t offset, u8 data) override;
private:
- DECLARE_WRITE_LINE_MEMBER(pia_cb2_w);
- DECLARE_WRITE_LINE_MEMBER(nmi_w);
+ void pia_cb2_w(int state);
+ void nmi_w(int state);
required_memory_region m_eprom;
required_device<pia6821_device> m_pia;
diff --git a/src/devices/bus/coco/dragon_serial.cpp b/src/devices/bus/coco/dragon_serial.cpp
index 8967bed816c..85a5808ca91 100644
--- a/src/devices/bus/coco/dragon_serial.cpp
+++ b/src/devices/bus/coco/dragon_serial.cpp
@@ -8,75 +8,64 @@
includes a through port for DOS cartridges.
TODO:
- - RX/TX rate set by dipswitches (default 100001/001001?), for use with a 1200/75 modem.
- add throughport, not known how CTS/SCS lines are switched between slots.
***************************************************************************/
#include "emu.h"
#include "dragon_serial.h"
+#include "machine/6850acia.h"
#include "machine/clock.h"
#include "bus/rs232/rs232.h"
-//-------------------------------------------------
-// ROM( dragon_serial )
-//-------------------------------------------------
+namespace {
-ROM_START(dragon_serial)
- ROM_REGION(0x2000, "eprom", 0)
- ROM_LOAD("comron_peaksoft.rom", 0x0000, 0x2000, CRC(9d18cf46) SHA1(14124dfb4bd78d1907e80d779cd7f3bae30564c9))
-ROM_END
+class dragon_serial_device : public device_t, public device_cococart_interface
+{
+public:
+ dragon_serial_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, DRAGON_SERIAL, tag, owner, clock)
+ , device_cococart_interface(mconfig, *this )
+ , m_eprom(*this, "eprom")
+ , m_acia(*this, "acia")
+ {
+ }
-//**************************************************************************
-// GLOBAL VARIABLES
-//**************************************************************************
+protected:
+ // device_t overrides
+ virtual void device_start() override { }
+ virtual u8 *get_cart_base() override { return m_eprom->base(); }
+ virtual memory_region *get_cart_memregion() override { return m_eprom; }
-DEFINE_DEVICE_TYPE(DRAGON_SERIAL, dragon_serial_device, "dragon_serial", "Dragon Peaksoft Prestel Module")
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual u8 cts_read(offs_t offset) override;
+ virtual u8 scs_read(offs_t offset) override;
+ virtual void scs_write(offs_t offset, u8 data) override;
-//**************************************************************************
-// LIVE DEVICE
-//**************************************************************************
+private:
+ required_memory_region m_eprom;
+ required_device<acia6850_device> m_acia;
+};
-//-------------------------------------------------
-// dragon_serial_device - constructor
-//-------------------------------------------------
-
-dragon_serial_device::dragon_serial_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
- : device_t(mconfig, DRAGON_SERIAL, tag, owner, clock)
- , device_cococart_interface(mconfig, *this )
- , m_eprom(*this, "eprom")
- , m_acia(*this, "acia")
-{
-}
//-------------------------------------------------
-// device_start - device-specific startup
+// ROM( dragon_serial )
//-------------------------------------------------
-void dragon_serial_device::device_start()
-{
- set_line_value(line::CART, line_value::Q);
-}
-
-//-------------------------------------------------
-// dragon_serial_device::get_cart_base
-//-------------------------------------------------
+ROM_START(dragon_serial)
+ ROM_REGION(0x2000, "eprom", 0)
+ ROM_LOAD("comron_peaksoft.rom", 0x0000, 0x2000, CRC(9d18cf46) SHA1(14124dfb4bd78d1907e80d779cd7f3bae30564c9))
+ROM_END
-u8 *dragon_serial_device::get_cart_base()
+const tiny_rom_entry *dragon_serial_device::device_rom_region() const
{
- return m_eprom->base();
+ return ROM_NAME( dragon_serial );
}
-//-------------------------------------------------
-// dragon_serial_device::get_cart_memregion
-//-------------------------------------------------
-
-memory_region *dragon_serial_device::get_cart_memregion()
-{
- return m_eprom;
-}
//-------------------------------------------------
// device_add_mconfig - add device configuration
@@ -89,23 +78,18 @@ void dragon_serial_device::device_add_mconfig(machine_config &config)
m_acia->rts_handler().set("rs232", FUNC(rs232_port_device::write_rts));
m_acia->irq_handler().set([this](int state) { set_line_value(line::NMI, state); });
- clock_device &acia_clock(CLOCK(config, "acia_clock", 2.4576_MHz_XTAL));
- acia_clock.signal_handler().set(FUNC(dragon_serial_device::write_acia_clock));
+ clock_device &rx_clock(CLOCK(config, "rx_clock", 2.4576_MHz_XTAL / 32)); // 1200 baud
+ rx_clock.signal_handler().set(m_acia, FUNC(acia6850_device::write_rxc));
+
+ clock_device &tx_clock(CLOCK(config, "tx_clock", 2.4576_MHz_XTAL / 512)); // 75 baud
+ tx_clock.signal_handler().set(m_acia, FUNC(acia6850_device::write_txc));
rs232_port_device &rs232(RS232_PORT(config, "rs232", default_rs232_devices, "null_modem"));
rs232.rxd_handler().set(m_acia, FUNC(acia6850_device::write_rxd));
rs232.cts_handler().set(m_acia, FUNC(acia6850_device::write_cts));
- rs232.dcd_handler().set(m_acia, FUNC(acia6850_device::write_dcd));
+ rs232.dcd_handler().set(m_acia, FUNC(acia6850_device::write_dcd)).invert();
}
-//-------------------------------------------------
-// rom_region - device-specific ROM region
-//-------------------------------------------------
-
-const tiny_rom_entry *dragon_serial_device::device_rom_region() const
-{
- return ROM_NAME( dragon_serial );
-}
//-------------------------------------------------
// cts_read
@@ -130,6 +114,7 @@ u8 dragon_serial_device::scs_read(offs_t offset)
result = m_acia->read(offset & 1);
break;
}
+
return result;
}
@@ -147,8 +132,7 @@ void dragon_serial_device::scs_write(offs_t offset, u8 data)
}
}
-WRITE_LINE_MEMBER(dragon_serial_device::write_acia_clock)
-{
- m_acia->write_txc(state);
- m_acia->write_rxc(state);
-}
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(DRAGON_SERIAL, device_cococart_interface, dragon_serial_device, "dragon_serial", "Dragon Peaksoft Prestel Module")
diff --git a/src/devices/bus/coco/dragon_serial.h b/src/devices/bus/coco/dragon_serial.h
index 7f33a61de67..5bd93f7e930 100644
--- a/src/devices/bus/coco/dragon_serial.h
+++ b/src/devices/bus/coco/dragon_serial.h
@@ -6,47 +6,8 @@
#pragma once
#include "cococart.h"
-#include "machine/6850acia.h"
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-// ======================> dragon_serial_device
-
-class dragon_serial_device :
- public device_t,
- public device_cococart_interface
-{
-public:
- // construction/destruction
- dragon_serial_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
-
- static constexpr feature_type imperfect_features() { return feature::COMMS; }
-
-protected:
- // device-level overrides
- virtual void device_start() override;
- virtual u8 *get_cart_base() override;
- virtual memory_region *get_cart_memregion() override;
-
- // optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
-
- virtual u8 cts_read(offs_t offset) override;
- virtual u8 scs_read(offs_t offset) override;
- virtual void scs_write(offs_t offset, u8 data) override;
-
-private:
- DECLARE_WRITE_LINE_MEMBER(write_acia_clock);
-
- required_memory_region m_eprom;
- required_device<acia6850_device> m_acia;
-};
-
-
-// device type definition
-DECLARE_DEVICE_TYPE(DRAGON_SERIAL, dragon_serial_device)
+DECLARE_DEVICE_TYPE(DRAGON_SERIAL, device_cococart_interface)
#endif // MAME_BUS_COCO_DRAGON_SERIAL_H
diff --git a/src/devices/bus/coco/dragon_sprites.cpp b/src/devices/bus/coco/dragon_sprites.cpp
index a33d9648715..c04167d8b03 100644
--- a/src/devices/bus/coco/dragon_sprites.cpp
+++ b/src/devices/bus/coco/dragon_sprites.cpp
@@ -111,7 +111,7 @@ void dragon_sprites_device::cts_write(offs_t offset, u8 data)
}
-WRITE_LINE_MEMBER(dragon_sprites_device::nmi_w)
+void dragon_sprites_device::nmi_w(int state)
{
// set the NMI line
set_line_value(line::NMI, state);
diff --git a/src/devices/bus/coco/dragon_sprites.h b/src/devices/bus/coco/dragon_sprites.h
index 1236912396e..032c8531e9e 100644
--- a/src/devices/bus/coco/dragon_sprites.h
+++ b/src/devices/bus/coco/dragon_sprites.h
@@ -38,7 +38,7 @@ private:
required_memory_region m_eprom;
required_device<tms9929a_device> m_vdp;
- DECLARE_WRITE_LINE_MEMBER(nmi_w);
+ void nmi_w(int state);
};
diff --git a/src/devices/bus/coco/meb_intrf.cpp b/src/devices/bus/coco/meb_intrf.cpp
new file mode 100644
index 00000000000..4a70daf9cb0
--- /dev/null
+++ b/src/devices/bus/coco/meb_intrf.cpp
@@ -0,0 +1,187 @@
+// license:BSD-3-Clause
+// copyright-holders:tim lindner
+/*********************************************************************
+
+ meb_intrf.h
+
+ CRC / Disto Mini Expansion Bus management
+
+ Mini Expansion Bus
+ 17 pin in-line header
+ pin
+ 1 reset
+ 2 e clock
+ 3 address 0
+ 4 address 1
+ 5 data 0
+ 6 data 1
+ 7 data 2
+ 8 data 3
+ 9 data 4
+ 10 data 5
+ 11 data 6
+ 12 data 7
+ 13 chip enable*
+ 14 ground
+ 15 r/w*
+ 16 +5v
+ 17 address 2
+
+ There is also one additional pin for the CART signal
+
+ Addresses active: $FF50 to $FF57
+
+ This was implemented in the Super (floppy) Controller I and II,
+ and in the ram disk expansion pak.
+
+*********************************************************************/
+
+#include "emu.h"
+#include "meb_intrf.h"
+
+#include "meb_rtime.h"
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(DISTOMEB_SLOT, distomeb_slot_device, "distomeb_slot", "Disto Mini Expansion Bus")
+
+
+//-------------------------------------------------
+// distomeb_slot_device - constructor
+//-------------------------------------------------
+distomeb_slot_device::distomeb_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, DISTOMEB_SLOT, tag, owner, clock)
+ , device_single_card_slot_interface<device_distomeb_interface>(mconfig, *this)
+ , m_cart_callback(*this)
+ , m_cart(nullptr)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void distomeb_slot_device::device_start()
+{
+ m_cart = get_card_device();
+
+ save_item(NAME(m_cart_line));
+}
+
+
+//-------------------------------------------------
+// meb_read
+//-------------------------------------------------
+
+u8 distomeb_slot_device::meb_read(offs_t offset)
+{
+ u8 result = 0x00;
+ if (m_cart)
+ result = m_cart->meb_read(offset);
+ return result;
+}
+
+
+//-------------------------------------------------
+// meb_write
+//-------------------------------------------------
+
+
+void distomeb_slot_device::meb_write(offs_t offset, u8 data)
+{
+ if (m_cart)
+ m_cart->meb_write(offset, data);
+}
+
+//-------------------------------------------------
+// set_cart_line
+//-------------------------------------------------
+
+void distomeb_slot_device::set_cart_line(int state)
+{
+ m_cart_line = state;
+ m_cart_callback(state);
+}
+
+
+//**************************************************************************
+// DEVICE DISTO MEB INTERFACE - Implemented by devices that plug into
+// Disto Mini Expansion Bus
+//**************************************************************************
+
+template class device_finder<device_distomeb_interface, false>;
+template class device_finder<device_distomeb_interface, true>;
+
+
+//-------------------------------------------------
+// device_distomeb_interface - constructor
+//-------------------------------------------------
+
+device_distomeb_interface::device_distomeb_interface(const machine_config &mconfig, device_t &device)
+ : device_interface(device, "distomeb")
+ , m_owning_slot(dynamic_cast<distomeb_slot_device *>(device.owner()))
+{
+}
+
+
+//-------------------------------------------------
+// ~device_distomeb_interface - destructor
+//-------------------------------------------------
+
+device_distomeb_interface::~device_distomeb_interface()
+{
+}
+
+
+//-------------------------------------------------
+// interface_pre_start
+//-------------------------------------------------
+
+void device_distomeb_interface::interface_pre_start()
+{
+ if (!m_owning_slot)
+ throw emu_fatalerror("Expected device().owner() to be of type distomeb_slot_device");
+}
+
+
+//-------------------------------------------------
+// meb_read - Addresses active: $FF50 to $FF57
+//-------------------------------------------------
+
+u8 device_distomeb_interface::meb_read(offs_t offset)
+{
+ return 0x00;
+}
+
+
+//-------------------------------------------------
+// cts_write - Addresses active: $FF50 to $FF57
+//-------------------------------------------------
+
+void device_distomeb_interface::meb_write(offs_t offset, u8 data)
+{
+}
+
+
+//-------------------------------------------------
+// set_cart_value
+//-------------------------------------------------
+
+void device_distomeb_interface::set_cart_value(int value)
+{
+ m_owning_slot->set_cart_line(value);
+}
+
+
+//-------------------------------------------------
+// disto_meb_add_basic_devices
+//-------------------------------------------------
+
+void disto_meb_add_basic_devices(device_slot_interface &device)
+{
+ // basic devices
+ device.option_add("rtime", DISTOMEB_RTIME);
+}
diff --git a/src/devices/bus/coco/meb_intrf.h b/src/devices/bus/coco/meb_intrf.h
new file mode 100644
index 00000000000..e1b99d4d818
--- /dev/null
+++ b/src/devices/bus/coco/meb_intrf.h
@@ -0,0 +1,90 @@
+// license:BSD-3-Clause
+// copyright-holders:tim lindner
+/*********************************************************************
+
+ intrf.h
+
+ CRC / Disto Mini Expansion Bus management
+
+*********************************************************************/
+
+#ifndef MAME_BUS_COCO_DISTOMEB_H
+#define MAME_BUS_COCO_DISTOMEB_H
+
+#pragma once
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+// ======================> distomeb_slot_device
+class device_distomeb_interface;
+
+class distomeb_slot_device final
+ : public device_t
+ , public device_single_card_slot_interface<device_distomeb_interface>
+{
+public:
+ // construction/destruction
+ template <typename T>
+ distomeb_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock, T &&opts, const char *dflt)
+ : distomeb_slot_device(mconfig, tag, owner, clock)
+ {
+ option_reset();
+ opts(*this);
+ set_default_option(dflt);
+ set_fixed(false);
+ }
+ distomeb_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ auto cart_callback() { return m_cart_callback.bind(); }
+
+ // reading and writing to $FF50-$FF57
+ u8 meb_read(offs_t offset);
+ void meb_write(offs_t offset, u8 data);
+
+ // manipulation of CART signal
+ void set_cart_line(int state);
+ int get_cart_line() { return m_cart_line; }
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+
+private:
+ u8 m_cart_line;
+ devcb_write_line m_cart_callback;
+ device_distomeb_interface *m_cart;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(DISTOMEB_SLOT, distomeb_slot_device)
+
+
+// ======================> device_distomeb_interface
+
+class device_distomeb_interface : public device_interface
+{
+public:
+ // destruction
+ virtual ~device_distomeb_interface();
+
+ virtual u8 meb_read(offs_t offset);
+ virtual void meb_write(offs_t offset, u8 data);
+
+protected:
+ device_distomeb_interface(const machine_config &mconfig, device_t &device);
+
+ virtual void interface_pre_start() override;
+
+ // setting cart values
+ void set_cart_value(int value);
+ void set_cart_value(bool value) { set_cart_value(value ? 1 : 0); }
+
+private:
+ distomeb_slot_device *const m_owning_slot;
+};
+
+void disto_meb_add_basic_devices(device_slot_interface &device);
+
+#endif // MAME_BUS_COCO_DISTOMEB_H
diff --git a/src/devices/bus/coco/meb_rtime.cpp b/src/devices/bus/coco/meb_rtime.cpp
new file mode 100644
index 00000000000..496072eb86e
--- /dev/null
+++ b/src/devices/bus/coco/meb_rtime.cpp
@@ -0,0 +1,173 @@
+// license:BSD-3-Clause
+// copyright-holders:tim lindner
+/***************************************************************************
+
+ meb_rtime.cpp
+
+ Real time clock for Disto mini expansion bus
+
+ Includes a Centronics parallel port interface
+
+***************************************************************************/
+
+#include "emu.h"
+#include "meb_rtime.h"
+#include "machine/msm6242.h"
+#include "bus/centronics/ctronics.h"
+
+#define VERBOSE (LOG_GENERAL)
+#include "logmacro.h"
+
+// ======================> disto_rtime_device
+
+namespace
+{
+ class disto_rtime_device
+ : public device_t
+ , public device_distomeb_interface
+ {
+ public:
+ // construction/destruction
+ disto_rtime_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ protected:
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual u8 meb_read(offs_t offset) override;
+ virtual void meb_write(offs_t offset, u8 data) override;
+
+ private:
+ void busy_w(int state);
+
+ required_device<msm6242_device> m_rtc;
+ u8 m_rtc_address;
+ u8 m_double_write;
+ required_device<centronics_device> m_centronics;
+ required_device<output_latch_device> m_latch;
+ u8 m_centronics_busy;
+ };
+
+
+ /***************************************************************************
+ IMPLEMENTATION
+ ***************************************************************************/
+
+ //-------------------------------------------------
+ // disto_rtime_device - constructor
+ //-------------------------------------------------
+
+ disto_rtime_device::disto_rtime_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, DISTOMEB_RTIME, tag, owner, clock)
+ , device_distomeb_interface(mconfig, *this)
+ , m_rtc(*this, "rtc")
+ , m_rtc_address(0)
+ , m_double_write(0)
+ , m_centronics(*this, "centronics")
+ , m_latch(*this, "latch")
+ , m_centronics_busy(0)
+ {
+ }
+
+ //-------------------------------------------------
+ // device_start - device-specific startup
+ //-------------------------------------------------
+
+ void disto_rtime_device::device_start()
+ {
+ // save state
+ save_item(NAME(m_rtc_address));
+ save_item(NAME(m_double_write));
+ save_item(NAME(m_centronics_busy));
+ }
+
+ //-------------------------------------------------
+ // device_add_mconfig - add device configuration
+ //-------------------------------------------------
+
+ void disto_rtime_device::device_add_mconfig(machine_config &config)
+ {
+ MSM6242(config, m_rtc, XTAL(32'768));
+
+ CENTRONICS(config, m_centronics, centronics_devices, "printer");
+ m_centronics->busy_handler().set(FUNC(disto_rtime_device::busy_w));
+
+ OUTPUT_LATCH(config, m_latch);
+ m_centronics->set_output_latch(*m_latch);
+ }
+
+ //-------------------------------------------------
+ // meb_read
+ //-------------------------------------------------
+
+ u8 disto_rtime_device::meb_read(offs_t offset)
+ {
+ u8 result = 0;
+
+ switch(offset)
+ {
+ case 0x00: /* FF50 */
+ result = m_rtc->read(m_rtc_address & 0x0f);
+ break;
+
+ case 0x02: /* FF52 */
+ case 0x03: /* FF53 */
+ result = m_centronics_busy << 7;
+ }
+
+ return result;
+ }
+
+
+ //-------------------------------------------------
+ // meb_write
+ //-------------------------------------------------
+
+ void disto_rtime_device::meb_write(offs_t offset, u8 data)
+ {
+ LOG("meb write: %02x %02x\n", offset, data);
+
+ switch(offset)
+ {
+ case 0x00: /* FF50 */
+ m_rtc->write(m_rtc_address & 0x0f, data);
+ break;
+
+ case 0x01: /* FF51 */
+ m_rtc_address = data;
+ break;
+
+ case 0x02: /* FF52 */
+ case 0x03: /* FF53 */
+ if ((m_rtc_address == data) && !m_double_write)
+ {
+ m_double_write = 1;
+ m_latch->write(data);
+ m_centronics->write_strobe(1);
+ m_centronics->write_strobe(0);
+ }
+
+ m_rtc_address = data;
+ break;
+ }
+
+ m_double_write = 0;
+ }
+
+
+ //-------------------------------------------------
+ // busy_w - centronics busy call back
+ //-------------------------------------------------
+
+ void disto_rtime_device::busy_w(int state)
+ {
+ m_centronics_busy = state;
+ }
+} // Anonymous namespace
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(DISTOMEB_RTIME, device_distomeb_interface, disto_rtime_device, "distomeb_rtime", "Disto Real Time Clock Card")
diff --git a/src/devices/bus/coco/meb_rtime.h b/src/devices/bus/coco/meb_rtime.h
new file mode 100644
index 00000000000..54c35f8d4d2
--- /dev/null
+++ b/src/devices/bus/coco/meb_rtime.h
@@ -0,0 +1,13 @@
+// license:BSD-3-Clause
+// copyright-holders:tim lindner
+#ifndef MAME_BUS_COCO_MEB_RTIME_H
+#define MAME_BUS_COCO_MEB_RTIME_H
+
+#pragma once
+
+#include "meb_intrf.h"
+
+// device type definition
+DECLARE_DEVICE_TYPE(DISTOMEB_RTIME, device_distomeb_interface)
+
+#endif // MAME_BUS_COCO_MEB_RTIME_H
diff --git a/src/devices/bus/coleco/cartridge/activision.cpp b/src/devices/bus/coleco/cartridge/activision.cpp
new file mode 100644
index 00000000000..4741efc11b4
--- /dev/null
+++ b/src/devices/bus/coleco/cartridge/activision.cpp
@@ -0,0 +1,132 @@
+// license: BSD-3-Clause
+// copyright-holders: Dirk Best
+/**********************************************************************
+
+ ColecoVision 'Activision' cartridge emulation
+
+**********************************************************************/
+
+#include "emu.h"
+#include "activision.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(COLECOVISION_ACTIVISION, colecovision_activision_cartridge_device, "coleco_activision", "ColecoVision Activision Cartridge")
+DEFINE_DEVICE_TYPE(COLECOVISION_ACTIVISION_256B, colecovision_activision_256b_cartridge_device, "coleco_activision_256b", "ColecoVision Activision Cartridge (256B EEPROM)")
+DEFINE_DEVICE_TYPE(COLECOVISION_ACTIVISION_32K, colecovision_activision_32k_cartridge_device, "coleco_activision_32k", "ColecoVision Activision Cartridge (32K EEPROM)")
+
+colecovision_activision_cartridge_device::colecovision_activision_cartridge_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, COLECOVISION_ACTIVISION, tag, owner, clock),
+ device_colecovision_cartridge_interface(mconfig, *this),
+ m_eeprom(*this, "eeprom"),
+ m_active_bank(0)
+{
+}
+
+colecovision_activision_cartridge_device::colecovision_activision_cartridge_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, type, tag, owner, clock),
+ device_colecovision_cartridge_interface(mconfig, *this),
+ m_eeprom(*this, "eeprom"),
+ m_active_bank(0)
+{
+}
+
+colecovision_activision_256b_cartridge_device::colecovision_activision_256b_cartridge_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ colecovision_activision_cartridge_device(mconfig, COLECOVISION_ACTIVISION_256B, tag, owner, clock)
+{
+}
+
+colecovision_activision_32k_cartridge_device::colecovision_activision_32k_cartridge_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ colecovision_activision_cartridge_device(mconfig, COLECOVISION_ACTIVISION_32K, tag, owner, clock)
+{
+}
+
+
+//**************************************************************************
+// MACHINE DEFINITIONS
+//**************************************************************************
+
+void colecovision_activision_256b_cartridge_device::device_add_mconfig(machine_config &config)
+{
+ I2C_24C02(config, m_eeprom, 0);
+}
+
+void colecovision_activision_32k_cartridge_device::device_add_mconfig(machine_config &config)
+{
+ I2C_24C256(config, m_eeprom, 0);
+}
+
+
+//**************************************************************************
+// MACHINE EMULATION
+//**************************************************************************
+
+void colecovision_activision_cartridge_device::device_start()
+{
+ // register for save states
+ save_item(NAME(m_active_bank));
+}
+
+uint8_t colecovision_activision_cartridge_device::read(offs_t offset, int _8000, int _a000, int _c000, int _e000)
+{
+ uint8_t data = 0xff;
+
+ if (!_8000 || !_a000 || !_c000 || !_e000)
+ {
+ if (offset < 0x4000)
+ {
+ // fixed first rom bank
+ data = m_rom[offset];
+ }
+ else if (offset == 0x7f80)
+ {
+ // eeprom data
+ if (m_eeprom.found())
+ data = m_eeprom->read_sda();
+ else
+ data = 0xff;
+ }
+ else if (offset > 0x7f80)
+ {
+ // "dead" area
+ data = 0xff;
+ }
+ else
+ {
+ // bankswitched rom
+ data = m_rom[(m_active_bank << 14) | (offset & 0x3fff)];
+ }
+ }
+
+ return data;
+}
+
+void colecovision_activision_cartridge_device::write(offs_t offset, uint8_t data, int _8000, int _a000, int _c000, int _e000)
+{
+ switch (offset)
+ {
+ // bankswitch
+ case 0x7f90:
+ case 0x7fa0:
+ case 0x7fb0:
+ m_active_bank = (offset >> 4) & 0x03;
+ break;
+
+ // eeprom scl
+ case 0x7fc0:
+ case 0x7fd0:
+ if (m_eeprom.found())
+ m_eeprom->write_scl(BIT(offset, 4));
+ break;
+
+ // eeprom sda
+ case 0x7fe0:
+ case 0x7ff0:
+ if (m_eeprom.found())
+ m_eeprom->write_sda(BIT(offset, 4));
+ break;
+ }
+}
diff --git a/src/devices/bus/coleco/cartridge/activision.h b/src/devices/bus/coleco/cartridge/activision.h
new file mode 100644
index 00000000000..c36a77880ac
--- /dev/null
+++ b/src/devices/bus/coleco/cartridge/activision.h
@@ -0,0 +1,65 @@
+// license: BSD-3-Clause
+// copyright-holders: Dirk Best
+/**********************************************************************
+
+ ColecoVision 'Activision' cartridge emulation
+
+**********************************************************************/
+
+#ifndef MAME_BUS_COLECO_CARTRIDGE_ACTIVISION_H
+#define MAME_BUS_COLECO_CARTRIDGE_ACTIVISION_H
+
+#pragma once
+
+#include "exp.h"
+#include "machine/i2cmem.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class colecovision_activision_cartridge_device : public device_t, public device_colecovision_cartridge_interface
+{
+public:
+ colecovision_activision_cartridge_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ colecovision_activision_cartridge_device(const machine_config &mconfig, device_type type, const char* tag, device_t* owner, uint32_t clock);
+
+ optional_device<i2cmem_device> m_eeprom;
+
+ virtual void device_start() override;
+
+ // cartridge interface
+ virtual uint8_t read(offs_t offset, int _8000, int _a000, int _c000, int _e000) override;
+ virtual void write(offs_t offset, uint8_t data, int _8000, int _a000, int _c000, int _e000) override;
+
+private:
+ uint8_t m_active_bank;
+};
+
+class colecovision_activision_256b_cartridge_device : public colecovision_activision_cartridge_device
+{
+public:
+ colecovision_activision_256b_cartridge_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override;
+};
+
+class colecovision_activision_32k_cartridge_device : public colecovision_activision_cartridge_device
+{
+public:
+ colecovision_activision_32k_cartridge_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override;
+};
+
+// device type declaration
+DECLARE_DEVICE_TYPE(COLECOVISION_ACTIVISION, colecovision_activision_cartridge_device)
+DECLARE_DEVICE_TYPE(COLECOVISION_ACTIVISION_256B, colecovision_activision_256b_cartridge_device)
+DECLARE_DEVICE_TYPE(COLECOVISION_ACTIVISION_32K, colecovision_activision_32k_cartridge_device)
+
+#endif // MAME_BUS_COLECO_CARTRIDGE_ACTIVISION_H
diff --git a/src/devices/bus/coleco/cartridge/exp.cpp b/src/devices/bus/coleco/cartridge/exp.cpp
index 6a73d73efb6..21fcfd9708a 100644
--- a/src/devices/bus/coleco/cartridge/exp.cpp
+++ b/src/devices/bus/coleco/cartridge/exp.cpp
@@ -76,11 +76,11 @@ void colecovision_cartridge_slot_device::device_start()
// call_load -
//-------------------------------------------------
-image_init_result colecovision_cartridge_slot_device::call_load()
+std::pair<std::error_condition, std::string> colecovision_cartridge_slot_device::call_load()
{
if (m_card)
{
- size_t size = !loaded_through_softlist() ? length() : get_software_region_length("rom");
+ size_t const size = !loaded_through_softlist() ? length() : get_software_region_length("rom");
m_card->rom_alloc(size);
if (!loaded_through_softlist())
@@ -94,7 +94,7 @@ image_init_result colecovision_cartridge_slot_device::call_load()
}
}
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
@@ -121,23 +121,36 @@ std::string colecovision_cartridge_slot_device::get_default_card_software(get_de
//-------------------------------------------------
-// bd_r - cartridge data read
+// read - cartridge data read
//-------------------------------------------------
-
-uint8_t colecovision_cartridge_slot_device::bd_r(offs_t offset, uint8_t data, int _8000, int _a000, int _c000, int _e000)
+uint8_t colecovision_cartridge_slot_device::read(offs_t offset, int _8000, int _a000, int _c000, int _e000)
{
+ uint8_t data = 0xff;
+
if (m_card)
- data = m_card->bd_r(offset , data, _8000, _a000, _c000, _e000);
+ data = m_card->read(offset, _8000, _a000, _c000, _e000);
return data;
}
//-------------------------------------------------
+// write - cartridge data write
+//-------------------------------------------------
+
+void colecovision_cartridge_slot_device::write(offs_t offset, uint8_t data, int _8000, int _a000, int _c000, int _e000)
+{
+ if (m_card)
+ m_card->write(offset, data, _8000, _a000, _c000, _e000);
+}
+
+
+//-------------------------------------------------
// SLOT_INTERFACE( colecovision_cartridges )
//-------------------------------------------------
+#include "activision.h"
#include "megacart.h"
#include "std.h"
#include "xin1.h"
@@ -145,6 +158,9 @@ uint8_t colecovision_cartridge_slot_device::bd_r(offs_t offset, uint8_t data, in
void colecovision_cartridges(device_slot_interface &device)
{
// the following need ROMs from the software list
+ device.option_add_internal("activision", COLECOVISION_ACTIVISION);
+ device.option_add_internal("activision_256b", COLECOVISION_ACTIVISION_256B);
+ device.option_add_internal("activision_32k", COLECOVISION_ACTIVISION_32K);
device.option_add_internal("megacart", COLECOVISION_MEGACART);
device.option_add_internal("standard", COLECOVISION_STANDARD);
device.option_add_internal("xin1", COLECOVISION_XIN1);
diff --git a/src/devices/bus/coleco/cartridge/exp.h b/src/devices/bus/coleco/cartridge/exp.h
index 5e7eaa252d2..0861f9f39b1 100644
--- a/src/devices/bus/coleco/cartridge/exp.h
+++ b/src/devices/bus/coleco/cartridge/exp.h
@@ -65,20 +65,21 @@ public:
colecovision_cartridge_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// computer interface
- uint8_t bd_r(offs_t offset, uint8_t data, int _8000, int _a000, int _c000, int _e000);
+ uint8_t read(offs_t offset, int _8000, int _a000, int _c000, int _e000);
+ void write(offs_t offset, uint8_t data, int _8000, int _a000, int _c000, int _e000);
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
- // image-level overrides
- virtual image_init_result call_load() override;
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
virtual bool is_reset_on_load() const noexcept override { return true; }
virtual const char *image_interface() const noexcept override { return "coleco_cart"; }
virtual const char *file_extensions() const noexcept override { return "rom,col,bin"; }
- // slot interface overrides
+ // device_slot_interface implementation
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
device_colecovision_cartridge_interface *m_card;
@@ -92,7 +93,8 @@ class device_colecovision_cartridge_interface : public device_interface
friend class colecovision_cartridge_slot_device;
public:
- virtual uint8_t bd_r(offs_t offset, uint8_t data, int _8000, int _a000, int _c000, int _e000) { return 0xff; }
+ virtual uint8_t read(offs_t offset, int _8000, int _a000, int _c000, int _e000) { return 0xff; }
+ virtual void write(offs_t offset, uint8_t data, int _8000, int _a000, int _c000, int _e000) { }
void rom_alloc(size_t size);
diff --git a/src/devices/bus/coleco/cartridge/megacart.cpp b/src/devices/bus/coleco/cartridge/megacart.cpp
index 68b84af653b..1cb6b471bb0 100644
--- a/src/devices/bus/coleco/cartridge/megacart.cpp
+++ b/src/devices/bus/coleco/cartridge/megacart.cpp
@@ -62,15 +62,17 @@ void colecovision_megacart_cartridge_device::device_reset()
// read - cartridge data read
//-------------------------------------------------
-uint8_t colecovision_megacart_cartridge_device::bd_r(offs_t offset, uint8_t data, int _8000, int _a000, int _c000, int _e000)
+uint8_t colecovision_megacart_cartridge_device::read(offs_t offset, int _8000, int _a000, int _c000, int _e000)
{
+ uint8_t data = 0xff;
+
if (!_8000 || !_a000 || !_c000 || !_e000)
{
if (m_bankcount > 2)
{
// offset as passed to us is a delta from address 0x8000.
- if (offset >= 0x7FC0)
+ if (offset >= 0x7fc0)
{
// Reads within the final 64 bytes select which megacart bank is active.
m_activebank = offset & (m_bankcount - 1);
diff --git a/src/devices/bus/coleco/cartridge/megacart.h b/src/devices/bus/coleco/cartridge/megacart.h
index 6a0b73f5124..7d259ef50f4 100644
--- a/src/devices/bus/coleco/cartridge/megacart.h
+++ b/src/devices/bus/coleco/cartridge/megacart.h
@@ -34,7 +34,7 @@ protected:
virtual void device_reset() override;
// device_colecovision_cartridge_interface overrides
- virtual uint8_t bd_r(offs_t offset, uint8_t data, int _8000, int _a000, int _c000, int _e000) override;
+ virtual uint8_t read(offs_t offset, int _8000, int _a000, int _c000, int _e000) override;
private:
uint32_t m_bankcount;
diff --git a/src/devices/bus/coleco/cartridge/std.cpp b/src/devices/bus/coleco/cartridge/std.cpp
index 24bb815834e..638a1b36fd5 100644
--- a/src/devices/bus/coleco/cartridge/std.cpp
+++ b/src/devices/bus/coleco/cartridge/std.cpp
@@ -47,14 +47,14 @@ void colecovision_standard_cartridge_device::device_start()
// read - cartridge data read
//-------------------------------------------------
-uint8_t colecovision_standard_cartridge_device::bd_r(offs_t offset, uint8_t data, int _8000, int _a000, int _c000, int _e000)
+uint8_t colecovision_standard_cartridge_device::read(offs_t offset, int _8000, int _a000, int _c000, int _e000)
{
+ uint8_t data = 0xff;
+
if (!_8000 || !_a000 || !_c000 || !_e000)
{
if (offset < m_rom_size)
data = m_rom[offset];
- else
- data = 0xff;
}
return data;
diff --git a/src/devices/bus/coleco/cartridge/std.h b/src/devices/bus/coleco/cartridge/std.h
index 6e0c5206ada..fc39e94acdc 100644
--- a/src/devices/bus/coleco/cartridge/std.h
+++ b/src/devices/bus/coleco/cartridge/std.h
@@ -33,7 +33,7 @@ protected:
virtual void device_start() override;
// device_colecovision_expansion_card_interface overrides
- virtual uint8_t bd_r(offs_t offset, uint8_t data, int _8000, int _a000, int _c000, int _e000) override;
+ virtual uint8_t read(offs_t offset, int _8000, int _a000, int _c000, int _e000) override;
};
diff --git a/src/devices/bus/coleco/cartridge/xin1.cpp b/src/devices/bus/coleco/cartridge/xin1.cpp
index 954c4a6e483..6a3ba70d512 100644
--- a/src/devices/bus/coleco/cartridge/xin1.cpp
+++ b/src/devices/bus/coleco/cartridge/xin1.cpp
@@ -59,8 +59,10 @@ void colecovision_xin1_cartridge_device::device_reset()
// read - cartridge data read
//-------------------------------------------------
-uint8_t colecovision_xin1_cartridge_device::bd_r(offs_t offset, uint8_t data, int _8000, int _a000, int _c000, int _e000)
+uint8_t colecovision_xin1_cartridge_device::read(offs_t offset, int _8000, int _a000, int _c000, int _e000)
{
+ uint8_t data = 0xff;
+
if (!_8000 || !_a000 || !_c000 || !_e000)
{
data = m_rom[m_current_offset + offset];
diff --git a/src/devices/bus/coleco/cartridge/xin1.h b/src/devices/bus/coleco/cartridge/xin1.h
index 0e8a7813c9f..c5ce426ff4c 100644
--- a/src/devices/bus/coleco/cartridge/xin1.h
+++ b/src/devices/bus/coleco/cartridge/xin1.h
@@ -34,7 +34,7 @@ protected:
virtual void device_reset() override;
// device_colecovision_expansion_card_interface overrides
- virtual uint8_t bd_r(offs_t offset, uint8_t data, int _8000, int _a000, int _c000, int _e000) override;
+ virtual uint8_t read(offs_t offset, int _8000, int _a000, int _c000, int _e000) override;
private:
uint32_t m_current_offset;
diff --git a/src/devices/bus/coleco/controller/ctrl.cpp b/src/devices/bus/coleco/controller/ctrl.cpp
index 80b5968eb03..2a9cb9baadd 100644
--- a/src/devices/bus/coleco/controller/ctrl.cpp
+++ b/src/devices/bus/coleco/controller/ctrl.cpp
@@ -61,8 +61,6 @@ colecovision_control_port_device::colecovision_control_port_device(const machine
void colecovision_control_port_device::device_start()
{
m_device = get_card_device();
-
- m_write_irq.resolve_safe();
}
diff --git a/src/devices/bus/coleco/controller/ctrl.h b/src/devices/bus/coleco/controller/ctrl.h
index 3d87a19b355..7c10ad1321a 100644
--- a/src/devices/bus/coleco/controller/ctrl.h
+++ b/src/devices/bus/coleco/controller/ctrl.h
@@ -65,8 +65,8 @@ public:
// computer interface
uint8_t read() { uint8_t data = 0xff; if (exists()) data = m_device->joy_r(); return data; }
- DECLARE_WRITE_LINE_MEMBER( common0_w ) { if (exists()) m_device->common0_w(state); }
- DECLARE_WRITE_LINE_MEMBER( common1_w ) { if (exists()) m_device->common1_w(state); }
+ void common0_w(int state) { if (exists()) m_device->common0_w(state); }
+ void common1_w(int state) { if (exists()) m_device->common1_w(state); }
bool exists() { return m_device != nullptr; }
diff --git a/src/devices/bus/coleco/expansion/cards.cpp b/src/devices/bus/coleco/expansion/cards.cpp
new file mode 100644
index 00000000000..5789b370456
--- /dev/null
+++ b/src/devices/bus/coleco/expansion/cards.cpp
@@ -0,0 +1,18 @@
+// license: BSD-3-Clause
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ Colecovision Expansion Slot cards
+
+***************************************************************************/
+
+#include "emu.h"
+#include "cards.h"
+
+#include "sgm.h"
+
+
+void coleco_expansion_cards(device_slot_interface &device)
+{
+ device.option_add("sgm", COLECO_SGM);
+}
diff --git a/src/devices/bus/coleco/expansion/cards.h b/src/devices/bus/coleco/expansion/cards.h
new file mode 100644
index 00000000000..08577a2cba9
--- /dev/null
+++ b/src/devices/bus/coleco/expansion/cards.h
@@ -0,0 +1,16 @@
+// license: BSD-3-Clause
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ Colecovision Expansion Slot cards
+
+***************************************************************************/
+
+#ifndef MAME_BUS_COlECO_EXPANSION_CARDS_H
+#define MAME_BUS_COlECO_EXPANSION_CARDS_H
+
+#pragma once
+
+void coleco_expansion_cards(device_slot_interface &device);
+
+#endif // MAME_BUS_COlECO_EXPANSION_CARDS_H
diff --git a/src/devices/bus/coleco/expansion/expansion.cpp b/src/devices/bus/coleco/expansion/expansion.cpp
new file mode 100644
index 00000000000..30b9c831dfb
--- /dev/null
+++ b/src/devices/bus/coleco/expansion/expansion.cpp
@@ -0,0 +1,61 @@
+// license: BSD-3-Clause
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ Colecovision Expansion Slot
+
+ 60-pin slot
+
+***************************************************************************/
+
+#include "emu.h"
+#include "expansion.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(COLECO_EXPANSION, coleco_expansion_device, "coleco_expansion", "Colecovision Expansion Bus")
+
+
+//**************************************************************************
+// SLOT DEVICE
+//**************************************************************************
+
+coleco_expansion_device::coleco_expansion_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, COLECO_EXPANSION, tag, owner, clock),
+ device_single_card_slot_interface<device_coleco_expansion_interface>(mconfig, *this),
+ device_mixer_interface(mconfig, *this),
+ m_program(*this, finder_base::DUMMY_TAG, -1),
+ m_io(*this, finder_base::DUMMY_TAG, -1),
+ m_int_handler(*this),
+ m_nmi_handler(*this),
+ m_card(nullptr)
+{
+}
+
+coleco_expansion_device::~coleco_expansion_device()
+{
+}
+
+void coleco_expansion_device::device_start()
+{
+ // get inserted card
+ m_card = get_card_device();
+}
+
+
+//**************************************************************************
+// CARD INTERFACE
+//**************************************************************************
+
+device_coleco_expansion_interface::device_coleco_expansion_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "colecoexp")
+{
+ m_expansion = dynamic_cast<coleco_expansion_device *>(device.owner());
+}
+
+device_coleco_expansion_interface::~device_coleco_expansion_interface()
+{
+}
diff --git a/src/devices/bus/coleco/expansion/expansion.h b/src/devices/bus/coleco/expansion/expansion.h
new file mode 100644
index 00000000000..74dadfe57f3
--- /dev/null
+++ b/src/devices/bus/coleco/expansion/expansion.h
@@ -0,0 +1,126 @@
+// license: BSD-3-Clause
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ Colecovision Expansion Slot
+
+ 60-pin slot
+
+ 1 GND 60 -5V
+ 2 GND 59 +5V
+ 3 D3 58 +5V
+ 4 A14 57 +12V
+ 5 EN40 56 AUDOUT
+ 6 EN20 55 IORQ
+ 7 HALT 54 MREQ
+ 8 WR 53 RD
+ 9 NMI 52 BUSACK
+ 10 FX-9 51 INT
+ 11 BUSREQ 50 WAIT
+ 12 D1 49 RFSH
+ 13 RESET 48 D5
+ 14 D0 47 A0
+ 15 M1 46 D5
+ 16 D2 45 CPUCLK
+ 17 D6 44 A3
+ 18 A1 43 A15
+ 19 D4 42 N/C
+ 20 A2 41 N/C
+ 21 A4 40 CPUCLK
+ 22 A13 39 EXVDCRST
+ 23 A5 38 A12
+ 24 A8 37 A11
+ 25 A7 36 EXRES2
+ 26 A8 35 AUDCLK
+ 27 A9 34 EXRES1
+ 28 A10 33 EXVID
+ 29 N/C 32 EXVIDEN
+ 30 N/C 31 EXAUD
+
+***************************************************************************/
+
+#ifndef MAME_BUS_COlECO_EXPANSION_EXPANSION_H
+#define MAME_BUS_COlECO_EXPANSION_EXPANSION_H
+
+#pragma once
+
+// include here so drivers don't need to
+#include "cards.h"
+
+// forward declaration
+class device_coleco_expansion_interface;
+
+
+//**************************************************************************
+// BUS DEVICE
+//**************************************************************************
+
+class coleco_expansion_device :
+ public device_t,
+ public device_single_card_slot_interface<device_coleco_expansion_interface>,
+ public device_mixer_interface
+{
+public:
+ // construction/destruction
+ coleco_expansion_device(machine_config const &mconfig, char const *tag, device_t *owner, const char *dflt) :
+ coleco_expansion_device(mconfig, tag, owner, uint32_t(0))
+ {
+ option_reset();
+ coleco_expansion_cards(*this);
+ set_default_option(dflt);
+ set_fixed(false);
+ }
+
+ coleco_expansion_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ virtual ~coleco_expansion_device();
+
+ template <typename T> void set_program_space(T &&tag, int spacenum) { m_program.set_tag(std::forward<T>(tag), spacenum); }
+ template <typename T> void set_io_space(T &&tag, int spacenum) { m_io.set_tag(std::forward<T>(tag), spacenum); }
+
+ // callbacks
+ auto int_handler() { return m_int_handler.bind(); }
+ auto nmi_handler() { return m_nmi_handler.bind(); }
+
+ // called from card device
+ void int_w(int state) { m_int_handler(state); }
+ void nmi_w(int state) { m_nmi_handler(state); }
+
+ address_space &mem_space() { return *m_program; }
+ address_space &io_space() { return *m_io; }
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+
+private:
+ required_address_space m_program;
+ required_address_space m_io;
+
+ devcb_write_line m_int_handler;
+ devcb_write_line m_nmi_handler;
+
+ device_coleco_expansion_interface *m_card;
+};
+
+
+//**************************************************************************
+// CARD INTERFACE
+//**************************************************************************
+
+class device_coleco_expansion_interface : public device_interface
+{
+public:
+ virtual ~device_coleco_expansion_interface();
+
+protected:
+ device_coleco_expansion_interface(const machine_config &mconfig, device_t &device);
+
+ coleco_expansion_device *m_expansion;
+};
+
+
+// device type declaration
+DECLARE_DEVICE_TYPE(COLECO_EXPANSION, coleco_expansion_device)
+
+
+#endif // MAME_BUS_COlECO_EXPANSION_EXPANSION_H
diff --git a/src/devices/bus/coleco/expansion/sgm.cpp b/src/devices/bus/coleco/expansion/sgm.cpp
new file mode 100644
index 00000000000..d52d91f5b47
--- /dev/null
+++ b/src/devices/bus/coleco/expansion/sgm.cpp
@@ -0,0 +1,98 @@
+// license: BSD-3-Clause
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ Opcode Super Game Module
+
+***************************************************************************/
+
+#include "emu.h"
+#include "sgm.h"
+#include "sound/ay8910.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(COLECO_SGM, coleco_sgm_device, "coleco_sgm", "Opcode Super Game Module")
+
+coleco_sgm_device::coleco_sgm_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, COLECO_SGM, tag, owner, clock),
+ device_coleco_expansion_interface(mconfig, *this),
+ m_view_lower(*this, "view_lower"),
+ m_view_upper(*this, "view_upper")
+{
+}
+
+
+//**************************************************************************
+// ADDRESS MAPS
+//**************************************************************************
+
+void coleco_sgm_device::io_map(address_map &map)
+{
+ map(0x50, 0x50).w("ay", FUNC(ay8910_device::address_w));
+ map(0x51, 0x51).w("ay", FUNC(ay8910_device::data_w));
+ map(0x52, 0x52).r("ay", FUNC(ay8910_device::data_r));
+ map(0x53, 0x53).w(FUNC(coleco_sgm_device::upper_enable_w));
+ map(0x7f, 0x7f).w(FUNC(coleco_sgm_device::lower_enable_w));
+}
+
+
+//**************************************************************************
+// MACHINE DEFINITIONS
+//**************************************************************************
+
+void coleco_sgm_device::device_add_mconfig(machine_config &config)
+{
+ ay8910_device &ay(AY8910(config, "ay", 7.15909_MHz_XTAL / 4));
+ ay.add_route(ALL_OUTPUTS, DEVICE_SELF_OWNER, 1.0);
+}
+
+
+//**************************************************************************
+// MACHINE EMULATION
+//**************************************************************************
+
+void coleco_sgm_device::device_start()
+{
+ // allocate memory for ram
+ m_ram_lower = std::make_unique<uint8_t []>(0x2000);
+ m_ram_upper = std::make_unique<uint8_t []>(0x6000);
+
+ // register for save states
+ save_pointer(NAME(m_ram_lower), 0x2000);
+ save_pointer(NAME(m_ram_upper), 0x6000);
+
+ // install device into memory map
+ m_expansion->io_space().install_device(0x00, 0x7f, *this, &coleco_sgm_device::io_map);
+
+ m_expansion->mem_space().install_view(0x0000, 0x1fff, m_view_lower);
+ m_view_lower[0].install_ram(0x0000, 0x1fff, &m_ram_lower[0]);
+
+ m_expansion->mem_space().install_view(0x2000, 0x7fff, m_view_upper);
+ m_view_upper[0].install_ram(0x2000, 0x7fff, &m_ram_upper[0]);
+}
+
+void coleco_sgm_device::device_reset()
+{
+ m_view_lower.disable();
+ m_view_upper.disable();
+}
+
+void coleco_sgm_device::upper_enable_w(uint8_t data)
+{
+ if (BIT(data, 0))
+ m_view_upper.select(0);
+ else
+ m_view_upper.disable();
+}
+
+void coleco_sgm_device::lower_enable_w(uint8_t data)
+{
+ if (BIT(data, 1))
+ m_view_lower.disable();
+ else
+ m_view_lower.select(0);
+}
diff --git a/src/devices/bus/coleco/expansion/sgm.h b/src/devices/bus/coleco/expansion/sgm.h
new file mode 100644
index 00000000000..cd77dbaa78e
--- /dev/null
+++ b/src/devices/bus/coleco/expansion/sgm.h
@@ -0,0 +1,48 @@
+// license: BSD-3-Clause
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ Colecovision Super Game Module
+
+***************************************************************************/
+
+#ifndef MAME_BUS_COLECO_EXPANSION_SGM_H
+#define MAME_BUS_COLECO_EXPANSION_SGM_H
+
+#pragma once
+
+#include "expansion.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class coleco_sgm_device : public device_t, public device_coleco_expansion_interface
+{
+public:
+ // construction/destruction
+ coleco_sgm_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+private:
+ memory_view m_view_lower;
+ memory_view m_view_upper;
+
+ std::unique_ptr<uint8_t []> m_ram_lower;
+ std::unique_ptr<uint8_t []> m_ram_upper;
+
+ void io_map(address_map &map);
+
+ void upper_enable_w(uint8_t data);
+ void lower_enable_w(uint8_t data);
+};
+
+// device type declaration
+DECLARE_DEVICE_TYPE(COLECO_SGM, coleco_sgm_device)
+
+#endif // MAME_BUS_COLECO_EXPANSION_SGM_H
diff --git a/src/devices/bus/compis/graphics.cpp b/src/devices/bus/compis/graphics.cpp
index ad9291dee65..059f19b6517 100644
--- a/src/devices/bus/compis/graphics.cpp
+++ b/src/devices/bus/compis/graphics.cpp
@@ -54,9 +54,6 @@ compis_graphics_slot_device::compis_graphics_slot_device(const machine_config &m
void compis_graphics_slot_device::device_start()
{
m_card = get_card_device();
-
- // resolve callbacks
- m_write_dma_request.resolve_safe();
}
diff --git a/src/devices/bus/compis/graphics.h b/src/devices/bus/compis/graphics.h
index 3f0c8e41cb9..0509fb8746c 100644
--- a/src/devices/bus/compis/graphics.h
+++ b/src/devices/bus/compis/graphics.h
@@ -75,7 +75,7 @@ public:
void dma_ack_w(offs_t offset, uint8_t data) { if (m_card) m_card->dma_ack_w(offset, data); }
// card interface
- DECLARE_WRITE_LINE_MEMBER( dma_request_w ) { m_write_dma_request(state); }
+ void dma_request_w(int state) { m_write_dma_request(state); }
protected:
// device-level overrides
diff --git a/src/devices/bus/compucolor/floppy.cpp b/src/devices/bus/compucolor/floppy.cpp
index 9c8a33870c1..1c599115db4 100644
--- a/src/devices/bus/compucolor/floppy.cpp
+++ b/src/devices/bus/compucolor/floppy.cpp
@@ -9,6 +9,8 @@
#include "emu.h"
#include "floppy.h"
+#include "formats/ccvf_dsk.h"
+
//**************************************************************************
diff --git a/src/devices/bus/compucolor/floppy.h b/src/devices/bus/compucolor/floppy.h
index 66247ac9601..96d1d9841fa 100644
--- a/src/devices/bus/compucolor/floppy.h
+++ b/src/devices/bus/compucolor/floppy.h
@@ -12,7 +12,6 @@
#pragma once
#include "bus/rs232/rs232.h"
-#include "formats/ccvf_dsk.h"
#include "imagedev/floppy.h"
@@ -50,9 +49,9 @@ public:
}
compucolor_floppy_port_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_WRITE_LINE_MEMBER( rw_w ) { if (m_dev) m_dev->rw_w(state); }
+ void rw_w(int state) { if (m_dev) m_dev->rw_w(state); }
void stepper_w(uint8_t data) { if (m_dev) m_dev->stepper_w(data); }
- DECLARE_WRITE_LINE_MEMBER( select_w ) { if (m_dev) m_dev->select_w(state); }
+ void select_w(int state) { if (m_dev) m_dev->select_w(state); }
protected:
// device-level overrides
diff --git a/src/devices/bus/comx35/exp.cpp b/src/devices/bus/comx35/exp.cpp
index 9c5095e5fd1..6848ade4f92 100644
--- a/src/devices/bus/comx35/exp.cpp
+++ b/src/devices/bus/comx35/exp.cpp
@@ -58,9 +58,6 @@ comx_expansion_slot_device::comx_expansion_slot_device(const machine_config &mco
void comx_expansion_slot_device::device_start()
{
m_card = get_card_device();
-
- // resolve callbacks
- m_write_irq.resolve_safe();
}
@@ -120,7 +117,7 @@ void comx_expansion_slot_device::io_w(offs_t offset, uint8_t data)
// ds_w - device select write
//-------------------------------------------------
-WRITE_LINE_MEMBER(comx_expansion_slot_device::ds_w)
+void comx_expansion_slot_device::ds_w(int state)
{
if (m_card != nullptr)
m_card->comx_ds_w(state);
@@ -131,7 +128,7 @@ WRITE_LINE_MEMBER(comx_expansion_slot_device::ds_w)
// q_w - Q write
//-------------------------------------------------
-WRITE_LINE_MEMBER(comx_expansion_slot_device::q_w)
+void comx_expansion_slot_device::q_w(int state)
{
if (m_card != nullptr)
m_card->comx_q_w(state);
@@ -142,7 +139,7 @@ WRITE_LINE_MEMBER(comx_expansion_slot_device::q_w)
// ef4_r - EF4 poll
//-------------------------------------------------
-READ_LINE_MEMBER(comx_expansion_slot_device::ef4_r)
+int comx_expansion_slot_device::ef4_r()
{
int state = CLEAR_LINE;
@@ -168,7 +165,7 @@ void comx_expansion_slot_device::sc_w(offs_t offset, uint8_t data)
// tpb_w - TPB write
//-------------------------------------------------
-WRITE_LINE_MEMBER(comx_expansion_slot_device::tpb_w)
+void comx_expansion_slot_device::tpb_w(int state)
{
if (m_card != nullptr)
m_card->comx_tpb_w(state);
diff --git a/src/devices/bus/comx35/exp.h b/src/devices/bus/comx35/exp.h
index 8f99edae4fd..fbb104a4ab4 100644
--- a/src/devices/bus/comx35/exp.h
+++ b/src/devices/bus/comx35/exp.h
@@ -66,15 +66,15 @@ public:
uint8_t io_r(offs_t offset);
void io_w(offs_t offset, uint8_t data);
- DECLARE_READ_LINE_MEMBER(ef4_r);
+ int ef4_r();
- DECLARE_WRITE_LINE_MEMBER(ds_w);
- DECLARE_WRITE_LINE_MEMBER(q_w);
+ void ds_w(int state);
+ void q_w(int state);
- DECLARE_WRITE_LINE_MEMBER(irq_w) { m_write_irq(state); }
+ void irq_w(int state) { m_write_irq(state); }
void sc_w(offs_t offset, uint8_t data);
- DECLARE_WRITE_LINE_MEMBER(tpb_w);
+ void tpb_w(int state);
protected:
// device-level overrides
diff --git a/src/devices/bus/comx35/expbox.h b/src/devices/bus/comx35/expbox.h
index c4c89b4f2bc..b53ae5a885f 100644
--- a/src/devices/bus/comx35/expbox.h
+++ b/src/devices/bus/comx35/expbox.h
@@ -56,10 +56,10 @@ protected:
void set_irq() { m_slot->irq_w(m_irq[0] || m_irq[1] || m_irq[2] || m_irq[3]); }
private:
- DECLARE_WRITE_LINE_MEMBER( slot1_irq_w ) { m_irq[0] = state; set_irq(); }
- DECLARE_WRITE_LINE_MEMBER( slot2_irq_w ) { m_irq[1] = state; set_irq(); }
- DECLARE_WRITE_LINE_MEMBER( slot3_irq_w ) { m_irq[2] = state; set_irq(); }
- DECLARE_WRITE_LINE_MEMBER( slot4_irq_w ) { m_irq[3] = state; set_irq(); }
+ void slot1_irq_w(int state) { m_irq[0] = state; set_irq(); }
+ void slot2_irq_w(int state) { m_irq[1] = state; set_irq(); }
+ void slot3_irq_w(int state) { m_irq[2] = state; set_irq(); }
+ void slot4_irq_w(int state) { m_irq[3] = state; set_irq(); }
required_memory_region m_rom;
diff --git a/src/devices/bus/comx35/fdc.cpp b/src/devices/bus/comx35/fdc.cpp
index 077de3e2c4d..e277d5003a9 100644
--- a/src/devices/bus/comx35/fdc.cpp
+++ b/src/devices/bus/comx35/fdc.cpp
@@ -44,6 +44,8 @@ Notes:
#include "emu.h"
#include "fdc.h"
+#include "formats/comx35_dsk.h"
+
//**************************************************************************
diff --git a/src/devices/bus/comx35/fdc.h b/src/devices/bus/comx35/fdc.h
index 6f2b5ea60bd..24847194004 100644
--- a/src/devices/bus/comx35/fdc.h
+++ b/src/devices/bus/comx35/fdc.h
@@ -12,7 +12,6 @@
#pragma once
#include "exp.h"
-#include "formats/comx35_dsk.h"
#include "imagedev/floppy.h"
#include "machine/wd_fdc.h"
diff --git a/src/devices/bus/cpc/cpc_rom.cpp b/src/devices/bus/cpc/cpc_rom.cpp
index 014d4600858..fee8cf3fdca 100644
--- a/src/devices/bus/cpc/cpc_rom.cpp
+++ b/src/devices/bus/cpc/cpc_rom.cpp
@@ -9,6 +9,9 @@
#include "emu.h"
#include "cpc_rom.h"
+#include <tuple>
+
+
DEFINE_DEVICE_TYPE(CPC_ROM, cpc_rom_device, "cpc_rom", "CPC ROM Box")
void cpc_exp_cards(device_slot_interface &device);
@@ -101,23 +104,18 @@ void cpc_rom_image_device::device_start()
/*-------------------------------------------------
DEVICE_IMAGE_LOAD( rom )
-------------------------------------------------*/
-image_init_result cpc_rom_image_device::call_load()
+std::pair<std::error_condition, std::string> cpc_rom_image_device::call_load()
{
- device_image_interface* image = this;
- uint64_t size = image->length();
-
- m_base = std::make_unique<uint8_t[]>(16384);
- if(size <= 16384)
- {
- image->fread(m_base,size);
- }
- else
- {
- image->fseek(size-16384,SEEK_SET);
- image->fread(m_base,16384);
- }
-
- return image_init_result::PASS;
+ uint64_t const total = length();
+ size_t const size = std::min<uint64_t>(total, 16384);
+
+ std::error_condition err;
+ size_t actual;
+ std::tie(err, m_base, actual) = read_at(image_core_file(), total - size, size);
+ if (!err && (actual != size))
+ err = std::errc::io_error;
+
+ return std::make_pair(err, std::string());
}
diff --git a/src/devices/bus/cpc/cpc_rom.h b/src/devices/bus/cpc/cpc_rom.h
index a9932dd57a8..d0786f6ddbd 100644
--- a/src/devices/bus/cpc/cpc_rom.h
+++ b/src/devices/bus/cpc/cpc_rom.h
@@ -25,8 +25,8 @@ public:
cpc_rom_image_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual ~cpc_rom_image_device();
- // image-level overrides
- virtual image_init_result call_load() override;
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
virtual void call_unload() override;
virtual bool is_reset_on_load() const noexcept override { return true; }
@@ -36,7 +36,7 @@ public:
uint8_t* base() { return m_base.get(); }
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
private:
diff --git a/src/devices/bus/cpc/cpc_rs232.cpp b/src/devices/bus/cpc/cpc_rs232.cpp
index 4e387f9ab85..e3be3af93d3 100644
--- a/src/devices/bus/cpc/cpc_rs232.cpp
+++ b/src/devices/bus/cpc/cpc_rs232.cpp
@@ -119,17 +119,17 @@ void cpc_rs232_device::device_reset()
}
-WRITE_LINE_MEMBER(cpc_rs232_device::pit_out0_w)
+void cpc_rs232_device::pit_out0_w(int state)
{
m_dart->txca_w(state);
}
-WRITE_LINE_MEMBER(cpc_rs232_device::pit_out1_w)
+void cpc_rs232_device::pit_out1_w(int state)
{
m_dart->rxca_w(state);
}
-WRITE_LINE_MEMBER(cpc_rs232_device::pit_out2_w)
+void cpc_rs232_device::pit_out2_w(int state)
{
m_dart->txcb_w(state);
m_dart->rxcb_w(state);
diff --git a/src/devices/bus/cpc/cpc_rs232.h b/src/devices/bus/cpc/cpc_rs232.h
index fabbbd2001b..1e577e8008e 100644
--- a/src/devices/bus/cpc/cpc_rs232.h
+++ b/src/devices/bus/cpc/cpc_rs232.h
@@ -43,9 +43,9 @@ protected:
required_device<rs232_port_device> m_rs232;
private:
- DECLARE_WRITE_LINE_MEMBER(pit_out0_w);
- DECLARE_WRITE_LINE_MEMBER(pit_out1_w);
- DECLARE_WRITE_LINE_MEMBER(pit_out2_w);
+ void pit_out0_w(int state);
+ void pit_out1_w(int state);
+ void pit_out2_w(int state);
cpc_expansion_slot_device *m_slot;
};
diff --git a/src/devices/bus/cpc/cpc_ssa1.cpp b/src/devices/bus/cpc/cpc_ssa1.cpp
index 40cfcccf0da..eab90d6831d 100644
--- a/src/devices/bus/cpc/cpc_ssa1.cpp
+++ b/src/devices/bus/cpc/cpc_ssa1.cpp
@@ -30,10 +30,10 @@ uint8_t cpc_ssa1_device::ssa1_r()
{
uint8_t ret = 0xff;
- if(get_sby() == 0)
+ if(!m_sp0256_device->sby_r())
ret &= ~0x80;
- if(get_lrq() != 0)
+ if(m_sp0256_device->lrq_r())
ret &= ~0x40;
return ret;
@@ -50,7 +50,7 @@ uint8_t cpc_dkspeech_device::dkspeech_r()
// SBY is not connected
- if(get_lrq() != 0)
+ if(m_sp0256_device->lrq_r())
ret &= ~0x80;
return ret;
@@ -61,26 +61,6 @@ void cpc_dkspeech_device::dkspeech_w(uint8_t data)
m_sp0256_device->ald_w(data & 0x3f);
}
-WRITE_LINE_MEMBER(cpc_ssa1_device::lrq_cb)
-{
- set_lrq(state);
-}
-
-WRITE_LINE_MEMBER(cpc_ssa1_device::sby_cb)
-{
- set_sby(state);
-}
-
-WRITE_LINE_MEMBER(cpc_dkspeech_device::lrq_cb)
-{
- set_lrq(state);
-}
-
-WRITE_LINE_MEMBER(cpc_dkspeech_device::sby_cb)
-{
- set_sby(state);
-}
-
//-------------------------------------------------
// Device ROM definition
//-------------------------------------------------
@@ -119,8 +99,6 @@ void cpc_ssa1_device::device_add_mconfig(machine_config &config)
{
SPEAKER(config, "mono").front_center();
SP0256(config, m_sp0256_device, XTAL(3'120'000));
- m_sp0256_device->data_request_callback().set(FUNC(cpc_ssa1_device::lrq_cb));
- m_sp0256_device->standby_callback().set(FUNC(cpc_ssa1_device::sby_cb));
m_sp0256_device->add_route(ALL_OUTPUTS, "mono", 1.00);
// pass-through
@@ -134,8 +112,6 @@ void cpc_dkspeech_device::device_add_mconfig(machine_config &config)
{
SPEAKER(config, "mono").front_center();
SP0256(config, m_sp0256_device, DERIVED_CLOCK(1, 1)); // uses the CPC's clock from pin 50 of the expansion port
- m_sp0256_device->data_request_callback().set(FUNC(cpc_dkspeech_device::lrq_cb));
- m_sp0256_device->standby_callback().set(FUNC(cpc_dkspeech_device::sby_cb));
m_sp0256_device->add_route(ALL_OUTPUTS, "mono", 1.00);
// pass-through
@@ -153,7 +129,6 @@ void cpc_dkspeech_device::device_add_mconfig(machine_config &config)
cpc_ssa1_device::cpc_ssa1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, CPC_SSA1, tag, owner, clock),
device_cpc_expansion_card_interface(mconfig, *this), m_slot(nullptr), m_rom(nullptr),
- m_lrq(1), m_sby(0),
m_sp0256_device(*this,"sp0256")
{
}
@@ -161,7 +136,6 @@ cpc_ssa1_device::cpc_ssa1_device(const machine_config &mconfig, const char *tag,
cpc_dkspeech_device::cpc_dkspeech_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, CPC_DKSPEECH, tag, owner, clock),
device_cpc_expansion_card_interface(mconfig, *this), m_slot(nullptr), m_rom(nullptr),
- m_lrq(1), m_sby(0),
m_sp0256_device(*this,"sp0256")
{
}
diff --git a/src/devices/bus/cpc/cpc_ssa1.h b/src/devices/bus/cpc/cpc_ssa1.h
index 7157d9a0475..9c89be6067d 100644
--- a/src/devices/bus/cpc/cpc_ssa1.h
+++ b/src/devices/bus/cpc/cpc_ssa1.h
@@ -56,11 +56,6 @@ public:
// construction/destruction
cpc_ssa1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- void set_lrq(uint8_t state) { m_lrq = state; }
- uint8_t get_lrq() { return m_lrq; }
- void set_sby(uint8_t state) { m_sby = state; }
- uint8_t get_sby() { return m_sby; }
-
uint8_t ssa1_r();
void ssa1_w(uint8_t data);
@@ -74,15 +69,8 @@ protected:
virtual void device_add_mconfig(machine_config &config) override;
private:
- DECLARE_WRITE_LINE_MEMBER(lrq_cb);
- DECLARE_WRITE_LINE_MEMBER(sby_cb);
-
cpc_expansion_slot_device *m_slot;
-
uint8_t *m_rom;
- uint8_t m_lrq;
- uint8_t m_sby;
-
required_device<sp0256_device> m_sp0256_device;
};
@@ -93,11 +81,6 @@ public:
// construction/destruction
cpc_dkspeech_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- void set_lrq(uint8_t state) { m_lrq = state; }
- uint8_t get_lrq() { return m_lrq; }
- void set_sby(uint8_t state) { m_sby = state; }
- uint8_t get_sby() { return m_sby; }
-
uint8_t dkspeech_r();
void dkspeech_w(uint8_t data);
@@ -111,15 +94,8 @@ protected:
virtual void device_add_mconfig(machine_config &config) override;
private:
- DECLARE_WRITE_LINE_MEMBER(lrq_cb);
- DECLARE_WRITE_LINE_MEMBER(sby_cb);
-
cpc_expansion_slot_device *m_slot;
-
uint8_t *m_rom;
- uint8_t m_lrq;
- uint8_t m_sby;
-
required_device<sp0256_device> m_sp0256_device;
};
diff --git a/src/devices/bus/cpc/cpcexp.cpp b/src/devices/bus/cpc/cpcexp.cpp
index a8e1420f22d..c625ed4689e 100644
--- a/src/devices/bus/cpc/cpcexp.cpp
+++ b/src/devices/bus/cpc/cpcexp.cpp
@@ -65,13 +65,6 @@ cpc_expansion_slot_device::~cpc_expansion_slot_device()
void cpc_expansion_slot_device::device_start()
{
m_card = get_card_device();
-
- // resolve callbacks
- m_out_irq_cb.resolve_safe();
- m_out_nmi_cb.resolve_safe();
- m_out_reset_cb.resolve_safe();
- m_out_romdis_cb.resolve_safe();
- m_out_rom_select.resolve_safe();
}
//-------------------------------------------------
@@ -92,8 +85,8 @@ void cpc_expansion_slot_device::device_config_complete()
}
-WRITE_LINE_MEMBER( cpc_expansion_slot_device::irq_w ) { m_out_irq_cb(state); }
-WRITE_LINE_MEMBER( cpc_expansion_slot_device::nmi_w ) { m_out_nmi_cb(state); }
-WRITE_LINE_MEMBER( cpc_expansion_slot_device::reset_w ) { m_out_reset_cb(state); }
-WRITE_LINE_MEMBER( cpc_expansion_slot_device::romdis_w ) { m_out_romdis_cb(state); }
+void cpc_expansion_slot_device::irq_w(int state) { m_out_irq_cb(state); }
+void cpc_expansion_slot_device::nmi_w(int state) { m_out_nmi_cb(state); }
+void cpc_expansion_slot_device::reset_w(int state) { m_out_reset_cb(state); }
+void cpc_expansion_slot_device::romdis_w(int state) { m_out_romdis_cb(state); }
void cpc_expansion_slot_device::rom_select(uint8_t data) { m_out_rom_select(data); }
diff --git a/src/devices/bus/cpc/cpcexp.h b/src/devices/bus/cpc/cpcexp.h
index 6793a116e6e..9f83c10eb75 100644
--- a/src/devices/bus/cpc/cpcexp.h
+++ b/src/devices/bus/cpc/cpcexp.h
@@ -71,8 +71,8 @@ public:
// reset
virtual void cpc_reset_w() { }
- virtual WRITE_LINE_MEMBER( cursor_w ) { }
- virtual WRITE_LINE_MEMBER( romen_w ) { }
+ virtual void cursor_w(int state) { }
+ virtual void romen_w(int state) { }
void set_rom_bank(uint8_t sel) { m_rom_sel = sel; } // tell device the currently selected ROM
uint8_t get_rom_bank() { return m_rom_sel; }
@@ -112,16 +112,16 @@ public:
auto romdis_callback() { return m_out_romdis_cb.bind(); }
auto rom_select_callback() { return m_out_rom_select.bind(); }
- DECLARE_WRITE_LINE_MEMBER( irq_w );
- DECLARE_WRITE_LINE_MEMBER( nmi_w );
- DECLARE_WRITE_LINE_MEMBER( reset_w );
- DECLARE_WRITE_LINE_MEMBER( romdis_w );
+ void irq_w(int state);
+ void nmi_w(int state);
+ void reset_w(int state);
+ void romdis_w(int state);
void rom_select(uint8_t data);
void set_rom_bank(uint8_t sel) { if(m_card) m_card->set_rom_bank(sel); } // tell device the currently selected ROM
void set_mapping(uint8_t type) { if(m_card) m_card->set_mapping(type); } // tell device to enable any ROM or RAM mapping
- DECLARE_WRITE_LINE_MEMBER( cursor_w ) { if(m_card) m_card->cursor_w(state); } // pass on CRTC Cursor signal
- DECLARE_WRITE_LINE_MEMBER( romen_w ) { if(m_card) m_card->romen_w(state); } // pass on /ROMEN signal
+ void cursor_w(int state) { if(m_card) m_card->cursor_w(state); } // pass on CRTC Cursor signal
+ void romen_w(int state) { if(m_card) m_card->romen_w(state); } // pass on /ROMEN signal
cpu_device &cpu() const { return *m_cpu; }
diff --git a/src/devices/bus/cpc/ddi1.h b/src/devices/bus/cpc/ddi1.h
index ab25ce454d3..6ec347224e7 100644
--- a/src/devices/bus/cpc/ddi1.h
+++ b/src/devices/bus/cpc/ddi1.h
@@ -37,7 +37,7 @@ protected:
virtual const tiny_rom_entry *device_rom_region() const override;
virtual void device_add_mconfig(machine_config &config) override;
virtual void set_mapping(uint8_t type) override;
- virtual WRITE_LINE_MEMBER( romen_w ) override { m_romen = state; }
+ virtual void romen_w(int state) override { m_romen = state; }
private:
cpc_expansion_slot_device *m_slot;
diff --git a/src/devices/bus/cpc/doubler.cpp b/src/devices/bus/cpc/doubler.cpp
index 3a30f6b5449..68c7a51899e 100644
--- a/src/devices/bus/cpc/doubler.cpp
+++ b/src/devices/bus/cpc/doubler.cpp
@@ -9,6 +9,8 @@
#include "emu.h"
#include "doubler.h"
+#include "formats/tzx_cas.h"
+
//**************************************************************************
// DEVICE DEFINITIONS
//**************************************************************************
diff --git a/src/devices/bus/cpc/doubler.h b/src/devices/bus/cpc/doubler.h
index 13e3370dd99..051f5ec5e62 100644
--- a/src/devices/bus/cpc/doubler.h
+++ b/src/devices/bus/cpc/doubler.h
@@ -15,7 +15,6 @@
#include "cpcexp.h"
#include "imagedev/cassette.h"
-#include "formats/tzx_cas.h"
class cpc_doubler_device : public device_t,
public device_cpc_expansion_card_interface
diff --git a/src/devices/bus/cpc/hd20.cpp b/src/devices/bus/cpc/hd20.cpp
index 81fa6d90c43..ae9751f3c51 100644
--- a/src/devices/bus/cpc/hd20.cpp
+++ b/src/devices/bus/cpc/hd20.cpp
@@ -117,7 +117,7 @@ void cpc_hd20_device::hdc_w(offs_t offset, uint8_t data)
}
}
-WRITE_LINE_MEMBER(cpc_hd20_device::irq_w)
+void cpc_hd20_device::irq_w(int state)
{
// if(state)
// m_hdc->set_ready();
diff --git a/src/devices/bus/cpc/hd20.h b/src/devices/bus/cpc/hd20.h
index 684f7c90901..de7d2ba5cef 100644
--- a/src/devices/bus/cpc/hd20.h
+++ b/src/devices/bus/cpc/hd20.h
@@ -39,7 +39,7 @@ protected:
virtual const tiny_rom_entry *device_rom_region() const override;
private:
- DECLARE_WRITE_LINE_MEMBER(irq_w);
+ void irq_w(int state);
cpc_expansion_slot_device *m_slot;
diff --git a/src/devices/bus/cpc/magicsound.cpp b/src/devices/bus/cpc/magicsound.cpp
index 194791f4a38..23828254aac 100644
--- a/src/devices/bus/cpc/magicsound.cpp
+++ b/src/devices/bus/cpc/magicsound.cpp
@@ -138,22 +138,22 @@ void al_magicsound_device::mapper_w(offs_t offset, uint8_t data)
set_timer_gate(true);
}
-WRITE_LINE_MEMBER(al_magicsound_device::da0_w)
+void al_magicsound_device::da0_w(int state)
{
m_dac->write(m_output[m_current_output++]);
if(m_current_output > 3)
m_current_output = 0;
}
-WRITE_LINE_MEMBER(al_magicsound_device::dack0_w) { m_dack[0] = state; }
-WRITE_LINE_MEMBER(al_magicsound_device::dack1_w) { m_dack[1] = state; }
-WRITE_LINE_MEMBER(al_magicsound_device::dack2_w) { m_dack[2] = state; }
-WRITE_LINE_MEMBER(al_magicsound_device::dack3_w) { m_dack[3] = state; }
+void al_magicsound_device::dack0_w(int state) { m_dack[0] = state; }
+void al_magicsound_device::dack1_w(int state) { m_dack[1] = state; }
+void al_magicsound_device::dack2_w(int state) { m_dack[2] = state; }
+void al_magicsound_device::dack3_w(int state) { m_dack[3] = state; }
-WRITE_LINE_MEMBER(al_magicsound_device::sam0_w) { m_current_channel = 0; if(m_dack[0] && state) m_dmac->dreq0_w(1); }
-WRITE_LINE_MEMBER(al_magicsound_device::sam1_w) { m_current_channel = 1; if(m_dack[1] && state) m_dmac->dreq1_w(1); }
-WRITE_LINE_MEMBER(al_magicsound_device::sam2_w) { m_current_channel = 2; if(m_dack[2] && state) m_dmac->dreq2_w(1); }
-WRITE_LINE_MEMBER(al_magicsound_device::sam3_w) { m_current_channel = 3; if(m_dack[3] && state) m_dmac->dreq3_w(1); }
+void al_magicsound_device::sam0_w(int state) { m_current_channel = 0; if(m_dack[0] && state) m_dmac->dreq0_w(1); }
+void al_magicsound_device::sam1_w(int state) { m_current_channel = 1; if(m_dack[1] && state) m_dmac->dreq1_w(1); }
+void al_magicsound_device::sam2_w(int state) { m_current_channel = 2; if(m_dack[2] && state) m_dmac->dreq2_w(1); }
+void al_magicsound_device::sam3_w(int state) { m_current_channel = 3; if(m_dack[3] && state) m_dmac->dreq3_w(1); }
uint8_t al_magicsound_device::dma_read_byte(offs_t offset)
{
diff --git a/src/devices/bus/cpc/magicsound.h b/src/devices/bus/cpc/magicsound.h
index e40b6230d41..f3e41275e56 100644
--- a/src/devices/bus/cpc/magicsound.h
+++ b/src/devices/bus/cpc/magicsound.h
@@ -56,17 +56,17 @@ protected:
virtual void device_add_mconfig(machine_config &config) override;
private:
- DECLARE_WRITE_LINE_MEMBER(da0_w);
+ void da0_w(int state);
uint8_t dma_read_byte(offs_t offset);
void dma_write_byte(uint8_t data);
- DECLARE_WRITE_LINE_MEMBER(dack0_w);
- DECLARE_WRITE_LINE_MEMBER(dack1_w);
- DECLARE_WRITE_LINE_MEMBER(dack2_w);
- DECLARE_WRITE_LINE_MEMBER(dack3_w);
- DECLARE_WRITE_LINE_MEMBER(sam0_w);
- DECLARE_WRITE_LINE_MEMBER(sam1_w);
- DECLARE_WRITE_LINE_MEMBER(sam2_w);
- DECLARE_WRITE_LINE_MEMBER(sam3_w);
+ void dack0_w(int state);
+ void dack1_w(int state);
+ void dack2_w(int state);
+ void dack3_w(int state);
+ void sam0_w(int state);
+ void sam1_w(int state);
+ void sam2_w(int state);
+ void sam3_w(int state);
cpc_expansion_slot_device *m_slot;
diff --git a/src/devices/bus/cpc/musicmachine.cpp b/src/devices/bus/cpc/musicmachine.cpp
index a02be0c70b7..a513e9d5fd3 100644
--- a/src/devices/bus/cpc/musicmachine.cpp
+++ b/src/devices/bus/cpc/musicmachine.cpp
@@ -116,7 +116,7 @@ void cpc_musicmachine_device::irqsel_w(uint8_t data)
m_irq_select = false;
}
-WRITE_LINE_MEMBER(cpc_musicmachine_device::irq_w)
+void cpc_musicmachine_device::irq_w(int state)
{
if(m_irq_select)
m_slot->nmi_w(state);
diff --git a/src/devices/bus/cpc/musicmachine.h b/src/devices/bus/cpc/musicmachine.h
index 57c1b6f5273..46f7f5cbc40 100644
--- a/src/devices/bus/cpc/musicmachine.h
+++ b/src/devices/bus/cpc/musicmachine.h
@@ -27,7 +27,7 @@ public:
uint8_t acia_r(offs_t offset);
void acia_w(offs_t offset, uint8_t data);
void irqsel_w(uint8_t data);
- DECLARE_WRITE_LINE_MEMBER(irq_w);
+ void irq_w(int state);
void write_acia_clock(u8 data) { m_acia->write_txc(data); m_acia->write_rxc(data); }
diff --git a/src/devices/bus/cpc/playcity.h b/src/devices/bus/cpc/playcity.h
index 5dd8459e986..684268e9707 100644
--- a/src/devices/bus/cpc/playcity.h
+++ b/src/devices/bus/cpc/playcity.h
@@ -39,7 +39,7 @@ public:
uint8_t ymz1_data_r();
uint8_t ymz2_data_r();
- virtual WRITE_LINE_MEMBER(cursor_w) override { m_ctc->trg1(state); }
+ virtual void cursor_w(int state) override { m_ctc->trg1(state); }
protected:
// device-level overrides
@@ -50,8 +50,8 @@ protected:
virtual void device_add_mconfig(machine_config &config) override;
private:
- DECLARE_WRITE_LINE_MEMBER(ctc_zc1_cb) { if(state) { m_slot->nmi_w(1); m_slot->nmi_w(0); } }
- DECLARE_WRITE_LINE_MEMBER(ctc_intr_cb) { m_slot->irq_w(state); }
+ void ctc_zc1_cb(int state) { if(state) { m_slot->nmi_w(1); m_slot->nmi_w(0); } }
+ void ctc_intr_cb(int state) { m_slot->irq_w(state); }
cpc_expansion_slot_device *m_slot;
diff --git a/src/devices/bus/cpc/symbfac2.cpp b/src/devices/bus/cpc/symbfac2.cpp
index bffadf99f2a..8b18c94aab3 100644
--- a/src/devices/bus/cpc/symbfac2.cpp
+++ b/src/devices/bus/cpc/symbfac2.cpp
@@ -93,7 +93,8 @@ void cpc_symbiface2_device::device_start()
space.install_readwrite_handler(0xfd00,0xfd07, read8sm_delegate(*this, FUNC(cpc_symbiface2_device::ide_cs1_r)), write8sm_delegate(*this, FUNC(cpc_symbiface2_device::ide_cs1_w)));
space.install_readwrite_handler(0xfd08,0xfd0f, read8sm_delegate(*this, FUNC(cpc_symbiface2_device::ide_cs0_r)), write8sm_delegate(*this, FUNC(cpc_symbiface2_device::ide_cs0_w)));
space.install_read_handler(0xfd10,0xfd10, read8smo_delegate(*this, FUNC(cpc_symbiface2_device::mouse_r)));
- space.install_readwrite_handler(0xfd14,0xfd15, read8sm_delegate(*this, FUNC(cpc_symbiface2_device::rtc_r)), write8sm_delegate(*this, FUNC(cpc_symbiface2_device::rtc_w)));
+ space.install_readwrite_handler(0xfd14,0xfd14, read8smo_delegate(m_rtc, FUNC(mc146818_device::data_r)), write8smo_delegate(m_rtc, FUNC(mc146818_device::data_w)));
+ space.install_write_handler(0xfd15,0xfd15, write8smo_delegate(m_rtc, FUNC(mc146818_device::address_w)));
space.install_readwrite_handler(0xfd17,0xfd17, read8smo_delegate(*this, FUNC(cpc_symbiface2_device::rom_rewrite_r)), write8smo_delegate(*this, FUNC(cpc_symbiface2_device::rom_rewrite_w)));
// set up ROM space (these can be writable, when mapped to &4000, or completely disabled, allowing the built-in ROMs to be visible)
@@ -159,15 +160,6 @@ void cpc_symbiface2_device::ide_cs1_w(offs_t offset, uint8_t data)
// RTC (Dallas DS1287A)
// #FD15 (write only) register select
// #FD14 (read/write) read from or write into selected register
-uint8_t cpc_symbiface2_device::rtc_r(offs_t offset)
-{
- return m_rtc->read(~offset & 0x01);
-}
-
-void cpc_symbiface2_device::rtc_w(offs_t offset, uint8_t data)
-{
- m_rtc->write(~offset & 0x01, data);
-}
// PS/2 Mouse connector
// #FD10 (read only) read mouse status
diff --git a/src/devices/bus/cpc/symbfac2.h b/src/devices/bus/cpc/symbfac2.h
index 4bc59e8a5e6..5b5bb2e7e43 100644
--- a/src/devices/bus/cpc/symbfac2.h
+++ b/src/devices/bus/cpc/symbfac2.h
@@ -27,8 +27,6 @@ public:
void ide_cs0_w(offs_t offset, uint8_t data);
uint8_t ide_cs1_r(offs_t offset);
void ide_cs1_w(offs_t offset, uint8_t data);
- uint8_t rtc_r(offs_t offset);
- void rtc_w(offs_t offset, uint8_t data);
uint8_t mouse_r();
uint8_t rom_rewrite_r();
void rom_rewrite_w(uint8_t data);
diff --git a/src/devices/bus/cpc/transtape.h b/src/devices/bus/cpc/transtape.h
index 451c3b1bd2a..15ccf0db4fc 100644
--- a/src/devices/bus/cpc/transtape.h
+++ b/src/devices/bus/cpc/transtape.h
@@ -26,7 +26,7 @@ public:
virtual ioport_constructor device_input_ports() const override;
virtual void set_mapping(uint8_t type) override;
- virtual WRITE_LINE_MEMBER( romen_w ) override { m_romen = state; }
+ virtual void romen_w(int state) override { m_romen = state; }
uint8_t input_r();
void output_w(uint8_t data);
diff --git a/src/devices/bus/crvision/slot.cpp b/src/devices/bus/crvision/slot.cpp
index e0776bec33b..0b28124eb5b 100644
--- a/src/devices/bus/crvision/slot.cpp
+++ b/src/devices/bus/crvision/slot.cpp
@@ -44,11 +44,11 @@ device_crvision_cart_interface::~device_crvision_cart_interface()
// rom_alloc - alloc the space for the cart
//-------------------------------------------------
-void device_crvision_cart_interface::rom_alloc(uint32_t size, const char *tag)
+void device_crvision_cart_interface::rom_alloc(uint32_t size)
{
if (m_rom == nullptr)
{
- m_rom = device().machine().memory().region_alloc(std::string(tag).append(CRVSLOT_ROM_REGION_TAG).c_str(), size, 1, ENDIANNESS_LITTLE)->base();
+ m_rom = device().machine().memory().region_alloc(device().subtag("^cart:rom"), size, 1, ENDIANNESS_LITTLE)->base();
m_rom_size = size;
}
}
@@ -137,19 +137,16 @@ static const char *crvision_get_slot(int type)
call load
-------------------------------------------------*/
-image_init_result crvision_cart_slot_device::call_load()
+std::pair<std::error_condition, std::string> crvision_cart_slot_device::call_load()
{
if (m_cart)
{
- uint32_t size = !loaded_through_softlist() ? length() : get_software_region_length("rom");
+ uint32_t const size = !loaded_through_softlist() ? length() : get_software_region_length("rom");
if (size > 0x4800)
- {
- seterror(image_error::INVALIDIMAGE, "Image extends beyond the expected size for an APF cart");
- return image_init_result::FAIL;
- }
+ return std::make_pair(image_error::INVALIDLENGTH, "Image exceeds the expected size for a CreatiVision cartridge (18K)");
- m_cart->rom_alloc(size, tag());
+ m_cart->rom_alloc(size);
if (!loaded_through_softlist())
fread(m_cart->get_rom_base(), size);
@@ -192,12 +189,10 @@ image_init_result crvision_cart_slot_device::call_load()
m_type = crvision_get_pcb_id(pcb_name);
}
- printf("Type: %s\n", crvision_get_slot(m_type));
-
- return image_init_result::PASS;
+ logerror("Type: %s\n", crvision_get_slot(m_type));
}
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
diff --git a/src/devices/bus/crvision/slot.h b/src/devices/bus/crvision/slot.h
index ec0a626f994..dcb1f65edb7 100644
--- a/src/devices/bus/crvision/slot.h
+++ b/src/devices/bus/crvision/slot.h
@@ -12,8 +12,6 @@
TYPE DEFINITIONS
***************************************************************************/
-#define CRVSLOT_ROM_REGION_TAG ":cart:rom"
-
/* PCB */
enum
{
@@ -39,7 +37,7 @@ public:
virtual uint8_t read_rom40(offs_t offset) { return 0xff; }
virtual uint8_t read_rom80(offs_t offset) { return 0xff; }
- void rom_alloc(uint32_t size, const char *tag);
+ void rom_alloc(uint32_t size);
uint8_t* get_rom_base() { return m_rom; }
uint32_t get_rom_size() { return m_rom_size; }
@@ -72,15 +70,15 @@ public:
crvision_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual ~crvision_cart_slot_device();
- // image-level overrides
- virtual image_init_result call_load() override;
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
virtual void call_unload() override { }
virtual bool is_reset_on_load() const noexcept override { return true; }
virtual const char *image_interface() const noexcept override { return "crvision_cart"; }
virtual const char *file_extensions() const noexcept override { return "bin,rom"; }
- // slot interface overrides
+ // device_slot_interface implementation
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
int get_type() { return m_type; }
@@ -90,11 +88,11 @@ public:
uint8_t read_rom80(offs_t offset);
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
int m_type;
- device_crvision_cart_interface* m_cart;
+ device_crvision_cart_interface *m_cart;
};
// device type definition
diff --git a/src/devices/bus/dmv/dmvbus.cpp b/src/devices/bus/dmv/dmvbus.cpp
index 3b828de41a1..a2a51092f81 100644
--- a/src/devices/bus/dmv/dmvbus.cpp
+++ b/src/devices/bus/dmv/dmvbus.cpp
@@ -199,7 +199,7 @@ device_dmvslot_interface::~device_dmvslot_interface()
dmvcart_slot_device::dmvcart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, DMVCART_SLOT, tag, owner, clock),
device_single_card_slot_interface<device_dmvslot_interface>(mconfig, *this),
- m_prog_read_cb(*this),
+ m_prog_read_cb(*this, 0),
m_prog_write_cb(*this),
m_out_int_cb(*this),
m_out_irq_cb(*this),
@@ -226,13 +226,6 @@ dmvcart_slot_device::~dmvcart_slot_device()
void dmvcart_slot_device::device_start()
{
m_cart = get_card_device();
-
- // resolve callbacks
- m_prog_read_cb.resolve_safe(0);
- m_prog_write_cb.resolve_safe();
- m_out_int_cb.resolve_safe();
- m_out_irq_cb.resolve_safe();
- m_out_thold_cb.resolve_safe();
}
/*-------------------------------------------------
diff --git a/src/devices/bus/dmv/k012.h b/src/devices/bus/dmv/k012.h
index b450b5f125b..0f262b6ca74 100644
--- a/src/devices/bus/dmv/k012.h
+++ b/src/devices/bus/dmv/k012.h
@@ -38,7 +38,7 @@ protected:
virtual void io_read(int ifsel, offs_t offset, uint8_t &data) override;
virtual void io_write(int ifsel, offs_t offset, uint8_t data) override;
- DECLARE_WRITE_LINE_MEMBER(hdc_intrq_w);
+ void hdc_intrq_w(int state);
private:
required_device<wd1000_device> m_hdc;
diff --git a/src/devices/bus/dmv/k210.cpp b/src/devices/bus/dmv/k210.cpp
index 90f39e5bf0e..0f2371fedea 100644
--- a/src/devices/bus/dmv/k210.cpp
+++ b/src/devices/bus/dmv/k210.cpp
@@ -158,11 +158,11 @@ void dmv_k210_device::portc_w(uint8_t data)
out_irq(BIT(data, 3));
}
-WRITE_LINE_MEMBER( dmv_k210_device::cent_ack_w ) { if (state) m_portb |= 0x04; else m_portb &= ~0x04; m_ppi->pc6_w(state); }
-WRITE_LINE_MEMBER( dmv_k210_device::cent_slct_w ) { if (state) m_portb |= 0x10; else m_portb &= ~0x10; }
-WRITE_LINE_MEMBER( dmv_k210_device::cent_busy_w ) { if (state) m_portb |= 0x20; else m_portb &= ~0x20; }
-WRITE_LINE_MEMBER( dmv_k210_device::cent_pe_w ) { if (state) m_portb |= 0x40; else m_portb &= ~0x40; }
-WRITE_LINE_MEMBER( dmv_k210_device::cent_fault_w ) { if (state) m_portb |= 0x80; else m_portb &= ~0x80; }
-
-WRITE_LINE_MEMBER( dmv_k210_device::cent_autofd_w ) { if (state) m_portc |= 0x02; else m_portc &= ~0x02; }
-WRITE_LINE_MEMBER( dmv_k210_device::cent_init_w ) { if (state) m_portc |= 0x04; else m_portc &= ~0x04; }
+void dmv_k210_device::cent_ack_w(int state) { if (state) m_portb |= 0x04; else m_portb &= ~0x04; m_ppi->pc6_w(state); }
+void dmv_k210_device::cent_slct_w(int state) { if (state) m_portb |= 0x10; else m_portb &= ~0x10; }
+void dmv_k210_device::cent_busy_w(int state) { if (state) m_portb |= 0x20; else m_portb &= ~0x20; }
+void dmv_k210_device::cent_pe_w(int state) { if (state) m_portb |= 0x40; else m_portb &= ~0x40; }
+void dmv_k210_device::cent_fault_w(int state) { if (state) m_portb |= 0x80; else m_portb &= ~0x80; }
+
+void dmv_k210_device::cent_autofd_w(int state) { if (state) m_portc |= 0x02; else m_portc &= ~0x02; }
+void dmv_k210_device::cent_init_w(int state) { if (state) m_portc |= 0x04; else m_portc &= ~0x04; }
diff --git a/src/devices/bus/dmv/k210.h b/src/devices/bus/dmv/k210.h
index d49673b2415..6d69aa93511 100644
--- a/src/devices/bus/dmv/k210.h
+++ b/src/devices/bus/dmv/k210.h
@@ -44,13 +44,13 @@ private:
void portb_w(uint8_t data);
void portc_w(uint8_t data);
- DECLARE_WRITE_LINE_MEMBER(cent_ack_w);
- DECLARE_WRITE_LINE_MEMBER(cent_busy_w);
- DECLARE_WRITE_LINE_MEMBER(cent_slct_w);
- DECLARE_WRITE_LINE_MEMBER(cent_pe_w);
- DECLARE_WRITE_LINE_MEMBER(cent_fault_w);
- DECLARE_WRITE_LINE_MEMBER(cent_autofd_w);
- DECLARE_WRITE_LINE_MEMBER(cent_init_w);
+ void cent_ack_w(int state);
+ void cent_busy_w(int state);
+ void cent_slct_w(int state);
+ void cent_pe_w(int state);
+ void cent_fault_w(int state);
+ void cent_autofd_w(int state);
+ void cent_init_w(int state);
TIMER_CALLBACK_MEMBER(strobe_tick);
diff --git a/src/devices/bus/dmv/k220.cpp b/src/devices/bus/dmv/k220.cpp
index 64df90c21d8..89f579ccf27 100644
--- a/src/devices/bus/dmv/k220.cpp
+++ b/src/devices/bus/dmv/k220.cpp
@@ -264,18 +264,18 @@ void dmv_k220_device::portc_w(uint8_t data)
}
-WRITE_LINE_MEMBER( dmv_k220_device::write_out0 )
+void dmv_k220_device::write_out0(int state)
{
m_pit->write_clk1(state);
m_pit->write_clk2(state);
}
-WRITE_LINE_MEMBER( dmv_k220_device::write_out1 )
+void dmv_k220_device::write_out1(int state)
{
}
-WRITE_LINE_MEMBER( dmv_k220_device::write_out2 )
+void dmv_k220_device::write_out2(int state)
{
}
diff --git a/src/devices/bus/dmv/k220.h b/src/devices/bus/dmv/k220.h
index b58777df15e..3ab23800bae 100644
--- a/src/devices/bus/dmv/k220.h
+++ b/src/devices/bus/dmv/k220.h
@@ -41,9 +41,9 @@ protected:
private:
void porta_w(uint8_t data);
void portc_w(uint8_t data);
- DECLARE_WRITE_LINE_MEMBER(write_out0);
- DECLARE_WRITE_LINE_MEMBER(write_out1);
- DECLARE_WRITE_LINE_MEMBER(write_out2);
+ void write_out0(int state);
+ void write_out1(int state);
+ void write_out2(int state);
required_device<pit8253_device> m_pit;
required_device<i8255_device> m_ppi;
diff --git a/src/devices/bus/dmv/k230.h b/src/devices/bus/dmv/k230.h
index fd8d759c137..c260ad70504 100644
--- a/src/devices/bus/dmv/k230.h
+++ b/src/devices/bus/dmv/k230.h
@@ -10,7 +10,7 @@
#include "cpu/i86/i86.h"
// K234
-#include "cpu/m68000/m68000.h"
+#include "cpu/m68000/m68008.h"
// K235
#include "cpu/nec/nec.h"
diff --git a/src/devices/bus/dmv/k801.cpp b/src/devices/bus/dmv/k801.cpp
index 4465a45227b..02bb59aa662 100644
--- a/src/devices/bus/dmv/k801.cpp
+++ b/src/devices/bus/dmv/k801.cpp
@@ -206,7 +206,7 @@ ioport_constructor dmv_k213_device::device_input_ports() const
return INPUT_PORTS_NAME( dmv_k213 );
}
-WRITE_LINE_MEMBER(dmv_k801_device::pci_irq_w)
+void dmv_k801_device::pci_irq_w(int state)
{
out_irq(state);
}
diff --git a/src/devices/bus/dmv/k801.h b/src/devices/bus/dmv/k801.h
index 41f72aaacf8..d03e6d0b786 100644
--- a/src/devices/bus/dmv/k801.h
+++ b/src/devices/bus/dmv/k801.h
@@ -47,7 +47,7 @@ protected:
required_ioport m_dsw;
private:
- DECLARE_WRITE_LINE_MEMBER(pci_irq_w);
+ void pci_irq_w(int state);
};
diff --git a/src/devices/bus/dmv/k803.cpp b/src/devices/bus/dmv/k803.cpp
index d2a72f22441..87d7ef6bcbd 100644
--- a/src/devices/bus/dmv/k803.cpp
+++ b/src/devices/bus/dmv/k803.cpp
@@ -119,7 +119,7 @@ void dmv_k803_device::io_write(int ifsel, offs_t offset, uint8_t data)
}
}
-WRITE_LINE_MEMBER(dmv_k803_device::rtc_irq_w)
+void dmv_k803_device::rtc_irq_w(int state)
{
m_rtc_int = state;
update_int();
diff --git a/src/devices/bus/dmv/k803.h b/src/devices/bus/dmv/k803.h
index 60a8cd91ced..2e9df0c07ec 100644
--- a/src/devices/bus/dmv/k803.h
+++ b/src/devices/bus/dmv/k803.h
@@ -38,7 +38,7 @@ protected:
void update_int();
private:
- DECLARE_WRITE_LINE_MEMBER(rtc_irq_w);
+ void rtc_irq_w(int state);
required_device<mm58167_device> m_rtc;
required_ioport m_dsw;
diff --git a/src/devices/bus/dmv/k806.cpp b/src/devices/bus/dmv/k806.cpp
index 89802ca43bd..5f160dd6809 100644
--- a/src/devices/bus/dmv/k806.cpp
+++ b/src/devices/bus/dmv/k806.cpp
@@ -175,7 +175,7 @@ uint8_t dmv_k806_device::port1_r()
return data;
}
-READ_LINE_MEMBER( dmv_k806_device::portt1_r )
+int dmv_k806_device::portt1_r()
{
return BIT(m_jumpers->read(), 7) ? 0 : 1;
}
diff --git a/src/devices/bus/dmv/k806.h b/src/devices/bus/dmv/k806.h
index 8c7c3618f69..36a859d1346 100644
--- a/src/devices/bus/dmv/k806.h
+++ b/src/devices/bus/dmv/k806.h
@@ -40,7 +40,7 @@ protected:
virtual void io_write(int ifsel, offs_t offset, uint8_t data) override;
private:
- DECLARE_READ_LINE_MEMBER(portt1_r);
+ int portt1_r();
uint8_t port1_r();
void port2_w(uint8_t data);
diff --git a/src/devices/bus/ecbbus/ecbbus.cpp b/src/devices/bus/ecbbus/ecbbus.cpp
index 5eaeda9f284..a59c0eede84 100644
--- a/src/devices/bus/ecbbus/ecbbus.cpp
+++ b/src/devices/bus/ecbbus/ecbbus.cpp
@@ -96,9 +96,6 @@ ecbbus_device::ecbbus_device(const machine_config &mconfig, const char *tag, dev
void ecbbus_device::device_start()
{
- // resolve callbacks
- m_write_irq.resolve_safe();
- m_write_nmi.resolve_safe();
}
diff --git a/src/devices/bus/ecbbus/ecbbus.h b/src/devices/bus/ecbbus/ecbbus.h
index bee5201a2fc..6f655a7b7f1 100644
--- a/src/devices/bus/ecbbus/ecbbus.h
+++ b/src/devices/bus/ecbbus/ecbbus.h
@@ -116,8 +116,8 @@ public:
uint8_t io_r(offs_t offset);
void io_w(offs_t offset, uint8_t data);
- DECLARE_WRITE_LINE_MEMBER( irq_w ) { m_write_irq(state); }
- DECLARE_WRITE_LINE_MEMBER( nmi_w ) { m_write_nmi(state); }
+ void irq_w(int state) { m_write_irq(state); }
+ void nmi_w(int state) { m_write_nmi(state); }
protected:
// device-level overrides
diff --git a/src/devices/bus/ecbbus/grip.cpp b/src/devices/bus/ecbbus/grip.cpp
index 6de51191cd5..d4f83e61edd 100644
--- a/src/devices/bus/ecbbus/grip.cpp
+++ b/src/devices/bus/ecbbus/grip.cpp
@@ -317,7 +317,7 @@ void ecb_grip21_device::ppi_pc_w(uint8_t data)
// Z80STI_INTERFACE( sti_intf )
//-------------------------------------------------
-WRITE_LINE_MEMBER(ecb_grip21_device::write_centronics_busy)
+void ecb_grip21_device::write_centronics_busy(int state)
{
m_centronics_busy = state;
}
@@ -359,7 +359,7 @@ uint8_t ecb_grip21_device::sti_gpio_r()
return data;
}
-WRITE_LINE_MEMBER( ecb_grip21_device::speaker_w )
+void ecb_grip21_device::speaker_w(int state)
{
int level = state && ((m_vol1 << 1) | m_vol0);
@@ -680,7 +680,7 @@ void ecb_grip21_device::page_w(uint8_t data)
// stat_r -
//-------------------------------------------------
-WRITE_LINE_MEMBER(ecb_grip21_device::write_centronics_fault)
+void ecb_grip21_device::write_centronics_fault(int state)
{
m_centronics_fault = state;
}
diff --git a/src/devices/bus/ecbbus/grip.h b/src/devices/bus/ecbbus/grip.h
index 024a820e4e3..289b91eb850 100644
--- a/src/devices/bus/ecbbus/grip.h
+++ b/src/devices/bus/ecbbus/grip.h
@@ -57,12 +57,12 @@ private:
uint8_t ppi_pb_r();
void ppi_pc_w(uint8_t data);
uint8_t sti_gpio_r();
- DECLARE_WRITE_LINE_MEMBER( speaker_w );
+ void speaker_w(int state);
void kb_w(uint8_t data);
- DECLARE_WRITE_LINE_MEMBER( write_centronics_busy );
- DECLARE_WRITE_LINE_MEMBER( write_centronics_fault );
+ void write_centronics_busy(int state);
+ void write_centronics_fault(int state);
MC6845_UPDATE_ROW( crtc_update_row );
diff --git a/src/devices/bus/econet/e01.cpp b/src/devices/bus/econet/e01.cpp
index 256e545c702..0e2d723d4a2 100644
--- a/src/devices/bus/econet/e01.cpp
+++ b/src/devices/bus/econet/e01.cpp
@@ -53,8 +53,11 @@
#include "emu.h"
#include "e01.h"
+
#include "bus/scsi/scsihd.h"
-#include "softlist.h"
+#include "softlist_dev.h"
+
+#include "formats/afs_dsk.h"
//**************************************************************************
@@ -133,7 +136,7 @@ const tiny_rom_entry *econet_e01_device::device_rom_region() const
// MC146818_INTERFACE( rtc_intf )
//-------------------------------------------------
-WRITE_LINE_MEMBER(econet_e01_device::rtc_irq_w)
+void econet_e01_device::rtc_irq_w(int state)
{
m_rtc_irq = state;
@@ -145,26 +148,26 @@ WRITE_LINE_MEMBER(econet_e01_device::rtc_irq_w)
// mc6854_interface adlc_intf
//-------------------------------------------------
-WRITE_LINE_MEMBER( econet_e01_device::adlc_irq_w )
+void econet_e01_device::adlc_irq_w(int state)
{
m_adlc_irq = state;
update_interrupts();
}
-WRITE_LINE_MEMBER( econet_e01_device::econet_data_w )
+void econet_e01_device::econet_data_w(int state)
{
m_econet->data_w(this, state);
}
-WRITE_LINE_MEMBER(econet_e01_device::via_irq_w)
+void econet_e01_device::via_irq_w(int state)
{
m_via_irq = state;
update_interrupts();
}
-WRITE_LINE_MEMBER( econet_e01_device::clk_en_w )
+void econet_e01_device::clk_en_w(int state)
{
m_clk_en = state;
}
@@ -174,21 +177,21 @@ void econet_e01_device::floppy_formats_afs(format_registration &fr)
fr.add(FLOPPY_AFS_FORMAT);
}
-WRITE_LINE_MEMBER( econet_e01_device::fdc_irq_w )
+void econet_e01_device::fdc_irq_w(int state)
{
m_fdc_irq = state;
update_interrupts();
}
-WRITE_LINE_MEMBER( econet_e01_device::fdc_drq_w )
+void econet_e01_device::fdc_drq_w(int state)
{
m_fdc_drq = state;
update_interrupts();
}
-WRITE_LINE_MEMBER( econet_e01_device::scsi_bsy_w )
+void econet_e01_device::scsi_bsy_w(int state)
{
m_scsi_ctrl_in->write_bit1(state);
@@ -198,7 +201,7 @@ WRITE_LINE_MEMBER( econet_e01_device::scsi_bsy_w )
}
}
-WRITE_LINE_MEMBER( econet_e01_device::scsi_req_w )
+void econet_e01_device::scsi_req_w(int state)
{
m_scsi_ctrl_in->write_bit5(state);
@@ -219,8 +222,8 @@ WRITE_LINE_MEMBER( econet_e01_device::scsi_req_w )
void econet_e01_device::e01_mem(address_map &map)
{
map(0x0000, 0xffff).rw(FUNC(econet_e01_device::read), FUNC(econet_e01_device::write));
- map(0xfc00, 0xfc00).mirror(0x00c3).rw(FUNC(econet_e01_device::rtc_address_r), FUNC(econet_e01_device::rtc_address_w));
- map(0xfc04, 0xfc04).mirror(0x00c3).rw(FUNC(econet_e01_device::rtc_data_r), FUNC(econet_e01_device::rtc_data_w));
+ map(0xfc00, 0xfc00).mirror(0x00c3).w(m_rtc, FUNC(mc146818_device::address_w));
+ map(0xfc04, 0xfc04).mirror(0x00c3).rw(m_rtc, FUNC(mc146818_device::data_r), FUNC(mc146818_device::data_w));
map(0xfc08, 0xfc08).mirror(0x00c0).r(FUNC(econet_e01_device::ram_select_r)).w(FUNC(econet_e01_device::floppy_w));
map(0xfc0c, 0xfc0f).mirror(0x00c0).rw(WD2793_TAG, FUNC(wd2793_device::read), FUNC(wd2793_device::write));
map(0xfc10, 0xfc1f).mirror(0x00c0).m(R6522_TAG, FUNC(via6522_device::map));
@@ -650,46 +653,6 @@ void econet_e01_device::hdc_irq_enable_w(uint8_t data)
//-------------------------------------------------
-// rtc_address_r -
-//-------------------------------------------------
-
-uint8_t econet_e01_device::rtc_address_r()
-{
- return m_rtc->read(0);
-}
-
-
-//-------------------------------------------------
-// rtc_address_w -
-//-------------------------------------------------
-
-void econet_e01_device::rtc_address_w(uint8_t data)
-{
- m_rtc->write(0, data);
-}
-
-
-//-------------------------------------------------
-// rtc_data_r -
-//-------------------------------------------------
-
-uint8_t econet_e01_device::rtc_data_r()
-{
- return m_rtc->read(1);
-}
-
-
-//-------------------------------------------------
-// rtc_data_w -
-//-------------------------------------------------
-
-void econet_e01_device::rtc_data_w(uint8_t data)
-{
- m_rtc->write(1, data);
-}
-
-
-//-------------------------------------------------
// econet_clk_w -
//-------------------------------------------------
diff --git a/src/devices/bus/econet/e01.h b/src/devices/bus/econet/e01.h
index 695e18c47cd..9a83fd0568c 100644
--- a/src/devices/bus/econet/e01.h
+++ b/src/devices/bus/econet/e01.h
@@ -23,7 +23,6 @@
#include "machine/mc6854.h"
#include "machine/ram.h"
#include "machine/wd_fdc.h"
-#include "formats/afs_dsk.h"
class econet_e01_device : public device_t,
public device_econet_interface
@@ -55,15 +54,15 @@ protected:
virtual void econet_clk(int state) override;
private:
- DECLARE_WRITE_LINE_MEMBER( rtc_irq_w );
- DECLARE_WRITE_LINE_MEMBER( adlc_irq_w );
- DECLARE_WRITE_LINE_MEMBER( econet_data_w );
- DECLARE_WRITE_LINE_MEMBER( via_irq_w );
- DECLARE_WRITE_LINE_MEMBER( clk_en_w );
- DECLARE_WRITE_LINE_MEMBER( fdc_irq_w );
- DECLARE_WRITE_LINE_MEMBER( fdc_drq_w );
- DECLARE_WRITE_LINE_MEMBER( scsi_bsy_w );
- DECLARE_WRITE_LINE_MEMBER( scsi_req_w );
+ void rtc_irq_w(int state);
+ void adlc_irq_w(int state);
+ void econet_data_w(int state);
+ void via_irq_w(int state);
+ void clk_en_w(int state);
+ void fdc_irq_w(int state);
+ void fdc_drq_w(int state);
+ void scsi_bsy_w(int state);
+ void scsi_req_w(int state);
TIMER_CALLBACK_MEMBER(clk_tick);
@@ -79,10 +78,6 @@ private:
void hdc_data_w(uint8_t data);
void hdc_select_w(uint8_t data);
void hdc_irq_enable_w(uint8_t data);
- uint8_t rtc_address_r();
- void rtc_address_w(uint8_t data);
- uint8_t rtc_data_r();
- void rtc_data_w(uint8_t data);
static void floppy_formats_afs(format_registration &fr);
diff --git a/src/devices/bus/econet/econet.cpp b/src/devices/bus/econet/econet.cpp
index e9afc9c0d49..5571dd3a505 100644
--- a/src/devices/bus/econet/econet.cpp
+++ b/src/devices/bus/econet/econet.cpp
@@ -40,7 +40,7 @@ DEFINE_DEVICE_TYPE(ECONET_SLOT, econet_slot_device, "econet_slot", "Econet stati
//-------------------------------------------------
device_econet_interface::device_econet_interface(const machine_config &mconfig, device_t &device) :
- device_interface(device, "econet"), m_econet(nullptr), m_address(0), m_next(nullptr)
+ device_interface(device, "econet"), m_econet(nullptr), m_address(0)
{
}
@@ -56,8 +56,9 @@ device_econet_interface::device_econet_interface(const machine_config &mconfig,
econet_slot_device::econet_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, ECONET_SLOT, tag, owner, clock),
- device_slot_interface(mconfig, *this),
- m_address(0), m_econet(*this, finder_base::DUMMY_TAG)
+ device_single_card_slot_interface<device_econet_interface>(mconfig, *this),
+ m_address(0),
+ m_econet(*this, finder_base::DUMMY_TAG)
{
}
@@ -68,8 +69,9 @@ econet_slot_device::econet_slot_device(const machine_config &mconfig, const char
void econet_slot_device::device_start()
{
- device_econet_interface *dev = dynamic_cast<device_econet_interface *>(get_card_device());
- if (dev) m_econet->add_device(get_card_device(), m_address);
+ device_econet_interface *dev = get_card_device();
+ if (dev)
+ m_econet->add_device(*dev, m_address);
}
@@ -97,21 +99,17 @@ inline void econet_device::set_signal(device_t *device, int signal, int state)
}
else
{
- daisy_entry *entry = m_device_list.first();
-
- while (entry)
+ for (auto &entry : m_device_list)
{
- if (!strcmp(entry->m_device->tag(), device->tag()))
+ if (!strcmp(entry.device().tag(), device->tag()))
{
- if (entry->m_line[signal] != state)
+ if (entry.m_line[signal] != state)
{
if (LOG) logerror("Econet: '%s' %s %u\n", device->tag(), SIGNAL_NAME[signal], state);
- entry->m_line[signal] = state;
+ entry.m_line[signal] = state;
changed = true;
}
}
-
- entry = entry->next();
}
}
@@ -123,22 +121,18 @@ inline void econet_device::set_signal(device_t *device, int signal, int state)
case DATA: m_write_data(state); break;
}
- daisy_entry *entry = m_device_list.first();
-
- while (entry)
+ for (auto &entry : m_device_list)
{
switch (signal)
{
case CLK:
- entry->m_interface->econet_clk(state);
+ entry.interface().econet_clk(state);
break;
case DATA:
- entry->m_interface->econet_data(state);
+ entry.interface().econet_data(state);
break;
}
-
- entry = entry->next();
}
if (LOG) logerror("Econet: CLK %u DATA %u\n", get_signal(CLK), get_signal(DATA));
@@ -156,17 +150,13 @@ inline int econet_device::get_signal(int signal)
if (state)
{
- daisy_entry *entry = m_device_list.first();
-
- while (entry)
+ for (auto &entry : m_device_list)
{
- if (!entry->m_line[signal])
+ if (!entry.m_line[signal])
{
state = 0;
break;
}
-
- entry = entry->next();
}
}
@@ -201,9 +191,6 @@ econet_device::econet_device(const machine_config &mconfig, const char *tag, dev
void econet_device::device_start()
{
- // resolve callbacks
- m_write_clk.resolve_safe();
- m_write_data.resolve_safe();
}
@@ -213,7 +200,7 @@ void econet_device::device_start()
void econet_device::device_stop()
{
- m_device_list.reset();
+ m_device_list.clear();
}
@@ -221,14 +208,12 @@ void econet_device::device_stop()
// add_device -
//-------------------------------------------------
-void econet_device::add_device(device_t *target, int address)
+void econet_device::add_device(device_econet_interface &target, int address)
{
- auto entry = new daisy_entry(target);
+ target.m_econet = this;
+ target.m_address = address;
- entry->m_interface->m_econet = this;
- entry->m_interface->m_address = address;
-
- m_device_list.append(*entry);
+ m_device_list.emplace_back(target);
}
@@ -236,17 +221,12 @@ void econet_device::add_device(device_t *target, int address)
// daisy_entry - constructor
//-------------------------------------------------
-econet_device::daisy_entry::daisy_entry(device_t *device) :
- m_next(nullptr),
- m_device(device),
- m_interface(nullptr)
+econet_device::daisy_entry::daisy_entry(device_econet_interface &device) :
+ m_device(&device.device()),
+ m_interface(&device)
{
- for (auto & elem : m_line)
- {
+ for (auto &elem : m_line)
elem = 1;
- }
-
- device->interface(m_interface);
}
@@ -254,7 +234,7 @@ econet_device::daisy_entry::daisy_entry(device_t *device) :
// clk_w -
//-------------------------------------------------
-WRITE_LINE_MEMBER( econet_device::host_clk_w )
+void econet_device::host_clk_w(int state)
{
set_signal(this, CLK, state);
}
@@ -264,7 +244,7 @@ WRITE_LINE_MEMBER( econet_device::host_clk_w )
// data_w -
//-------------------------------------------------
-WRITE_LINE_MEMBER( econet_device::host_data_w )
+void econet_device::host_data_w(int state)
{
set_signal(this, DATA, state);
}
diff --git a/src/devices/bus/econet/econet.h b/src/devices/bus/econet/econet.h
index 1aab9da8095..063ca8b78c7 100644
--- a/src/devices/bus/econet/econet.h
+++ b/src/devices/bus/econet/econet.h
@@ -11,6 +11,7 @@
#pragma once
+#include <vector>
@@ -31,11 +32,11 @@ public:
auto clk_wr_callback() { return m_write_clk.bind(); }
auto data_wr_callback() { return m_write_data.bind(); }
- void add_device(device_t *target, int address);
+ void add_device(device_econet_interface &target, int address);
// writes for host (driver_device)
- DECLARE_WRITE_LINE_MEMBER( host_clk_w );
- DECLARE_WRITE_LINE_MEMBER( host_data_w );
+ void host_clk_w(int state);
+ void host_data_w(int state);
// writes for peripherals (device_t)
void clk_w(device_t *device, int state);
@@ -49,31 +50,33 @@ protected:
SIGNAL_COUNT
};
- // device-level overrides
- virtual void device_start() override;
- virtual void device_stop() override;
-
class daisy_entry
{
public:
- daisy_entry(device_t *device);
- daisy_entry *next() const { return m_next; }
+ daisy_entry(device_econet_interface &device);
- daisy_entry * m_next; // next device
- device_t * m_device; // associated device
- device_econet_interface * m_interface; // associated device's daisy interface
+ device_t &device() { return *m_device; }
+ device_econet_interface &interface() { return *m_interface; }
int m_line[SIGNAL_COUNT];
+
+ private:
+ device_t * m_device; // associated device
+ device_econet_interface * m_interface; // associated device's daisy interface
};
- simple_list<daisy_entry> m_device_list;
+ // device_t implementation
+ virtual void device_start() override;
+ virtual void device_stop() override;
+
+ std::vector<daisy_entry> m_device_list;
private:
devcb_write_line m_write_clk;
devcb_write_line m_write_data;
- inline void set_signal(device_t *device, int signal, int state);
- inline int get_signal(int signal);
+ void set_signal(device_t *device, int signal, int state);
+ int get_signal(int signal);
int m_line[SIGNAL_COUNT];
};
@@ -81,8 +84,7 @@ private:
// ======================> econet_slot_device
-class econet_slot_device : public device_t,
- public device_slot_interface
+class econet_slot_device : public device_t, public device_single_card_slot_interface<device_econet_interface>
{
public:
// construction/destruction
@@ -115,11 +117,8 @@ private:
class device_econet_interface : public device_interface
{
friend class econet_device;
- template <class ElementType> friend class simple_list;
public:
- device_econet_interface *next() const { return m_next; }
-
virtual void econet_clk(int state) = 0;
virtual void econet_data(int state) = 0;
@@ -129,9 +128,6 @@ protected:
econet_device *m_econet;
uint8_t m_address;
-
-private:
- device_econet_interface *m_next;
};
diff --git a/src/devices/bus/einstein/pipe/pipe.cpp b/src/devices/bus/einstein/pipe/pipe.cpp
index f54092e9587..05196ac2d49 100644
--- a/src/devices/bus/einstein/pipe/pipe.cpp
+++ b/src/devices/bus/einstein/pipe/pipe.cpp
@@ -80,18 +80,13 @@ void tatung_pipe_device::device_start()
{
// get inserted module
m_card = get_card_device();
-
- // resolve callbacks
- m_int_handler.resolve_safe();
- m_nmi_handler.resolve_safe();
- m_reset_handler.resolve_safe();
}
//-------------------------------------------------
// host to module interface
//-------------------------------------------------
-WRITE_LINE_MEMBER( tatung_pipe_device::host_int_w )
+void tatung_pipe_device::host_int_w(int state)
{
if (m_card)
m_card->int_w(state);
diff --git a/src/devices/bus/einstein/pipe/pipe.h b/src/devices/bus/einstein/pipe/pipe.h
index 7b2a2fdcbad..6adb988a018 100644
--- a/src/devices/bus/einstein/pipe/pipe.h
+++ b/src/devices/bus/einstein/pipe/pipe.h
@@ -77,12 +77,12 @@ public:
auto reset_handler() { return m_reset_handler.bind(); }
// called from host
- DECLARE_WRITE_LINE_MEMBER( host_int_w );
+ void host_int_w(int state);
// called from card device
- DECLARE_WRITE_LINE_MEMBER( int_w ) { m_int_handler(state); }
- DECLARE_WRITE_LINE_MEMBER( nmi_w ) { m_nmi_handler(state); }
- DECLARE_WRITE_LINE_MEMBER( reset_w ) { m_reset_handler(state); }
+ void int_w(int state) { m_int_handler(state); }
+ void nmi_w(int state) { m_nmi_handler(state); }
+ void reset_w(int state) { m_reset_handler(state); }
protected:
// device-level overrides
diff --git a/src/devices/bus/einstein/pipe/speculator.cpp b/src/devices/bus/einstein/pipe/speculator.cpp
index e99d3978cb4..ae73b030577 100644
--- a/src/devices/bus/einstein/pipe/speculator.cpp
+++ b/src/devices/bus/einstein/pipe/speculator.cpp
@@ -116,7 +116,7 @@ void einstein_speculator_device::device_reset()
// IMPLEMENTATION
//**************************************************************************
-WRITE_LINE_MEMBER( einstein_speculator_device::ic5a_q_w )
+void einstein_speculator_device::ic5a_q_w(int state)
{
m_ic5b->a_w(state);
@@ -127,7 +127,7 @@ WRITE_LINE_MEMBER( einstein_speculator_device::ic5a_q_w )
}
}
-WRITE_LINE_MEMBER( einstein_speculator_device::ic5b_q_w )
+void einstein_speculator_device::ic5b_q_w(int state)
{
if (m_nmisel == 0)
{
diff --git a/src/devices/bus/einstein/pipe/speculator.h b/src/devices/bus/einstein/pipe/speculator.h
index c66b2e0122e..b542edf9fd5 100644
--- a/src/devices/bus/einstein/pipe/speculator.h
+++ b/src/devices/bus/einstein/pipe/speculator.h
@@ -39,8 +39,8 @@ public:
uint8_t tape_r();
void nmi_w(uint8_t data);
- DECLARE_WRITE_LINE_MEMBER(ic5a_q_w);
- DECLARE_WRITE_LINE_MEMBER(ic5b_q_w);
+ void ic5a_q_w(int state);
+ void ic5b_q_w(int state);
protected:
virtual void device_add_mconfig(machine_config &config) override;
diff --git a/src/devices/bus/einstein/pipe/tk02.cpp b/src/devices/bus/einstein/pipe/tk02.cpp
index 74cd880e151..4b14e9b3391 100644
--- a/src/devices/bus/einstein/pipe/tk02.cpp
+++ b/src/devices/bus/einstein/pipe/tk02.cpp
@@ -196,7 +196,7 @@ MC6845_UPDATE_ROW( tk02_device::crtc_update_row )
}
}
-WRITE_LINE_MEMBER( tk02_device::de_w )
+void tk02_device::de_w(int state)
{
m_de = state;
}
diff --git a/src/devices/bus/einstein/pipe/tk02.h b/src/devices/bus/einstein/pipe/tk02.h
index 3834585ed2a..2c78bd97834 100644
--- a/src/devices/bus/einstein/pipe/tk02.h
+++ b/src/devices/bus/einstein/pipe/tk02.h
@@ -38,7 +38,7 @@ protected:
private:
void map(address_map &map);
- DECLARE_WRITE_LINE_MEMBER(de_w);
+ void de_w(int state);
uint8_t ram_r(offs_t offset);
void ram_w(offs_t offset, uint8_t data);
diff --git a/src/devices/bus/einstein/userport/userport.cpp b/src/devices/bus/einstein/userport/userport.cpp
index e2fdd06acd2..dac68cc1181 100644
--- a/src/devices/bus/einstein/userport/userport.cpp
+++ b/src/devices/bus/einstein/userport/userport.cpp
@@ -51,9 +51,6 @@ einstein_userport_device::~einstein_userport_device()
void einstein_userport_device::device_start()
{
- // resolve callbacks
- m_bstb_handler.resolve_safe();
-
m_card = get_card_device();
}
@@ -76,7 +73,7 @@ void einstein_userport_device::write(uint8_t data)
m_card->write(data);
}
-WRITE_LINE_MEMBER( einstein_userport_device::brdy_w )
+void einstein_userport_device::brdy_w(int state)
{
if (m_card)
m_card->brdy_w(state);
diff --git a/src/devices/bus/einstein/userport/userport.h b/src/devices/bus/einstein/userport/userport.h
index d543f14d7c6..ced90c8dad7 100644
--- a/src/devices/bus/einstein/userport/userport.h
+++ b/src/devices/bus/einstein/userport/userport.h
@@ -52,11 +52,11 @@ public:
auto bstb_handler() { return m_bstb_handler.bind(); }
// called from card device
- DECLARE_WRITE_LINE_MEMBER( bstb_w ) { m_bstb_handler(state); }
+ void bstb_w(int state) { m_bstb_handler(state); }
uint8_t read();
void write(uint8_t data);
- DECLARE_WRITE_LINE_MEMBER( brdy_w );
+ void brdy_w(int state);
protected:
// device-level overrides
diff --git a/src/devices/bus/ekara/rom.cpp b/src/devices/bus/ekara/rom.cpp
index e29f7d03ae6..b08f5cc2fc4 100644
--- a/src/devices/bus/ekara/rom.cpp
+++ b/src/devices/bus/ekara/rom.cpp
@@ -14,6 +14,7 @@ DEFINE_DEVICE_TYPE(EKARA_ROM_I2C_24C08_EPITCH, ekara_rom_i2c_24c08_epitch_de
DEFINE_DEVICE_TYPE(EKARA_ROM_I2C_24LC04, ekara_rom_i2c_24lc04_device, "ekara_rom_i2c_24lc04", "EKARA Cartridge with I2C 24LC04")
DEFINE_DEVICE_TYPE(EKARA_ROM_I2C_24LC02, ekara_rom_i2c_24lc02_device, "ekara_rom_i2c_24lc02", "EKARA Cartridge with I2C 24LC02")
DEFINE_DEVICE_TYPE(EKARA_ROM_I2C_24LC02_GC0010, ekara_rom_i2c_24lc02_gc0010_device, "ekara_rom_i2c_24lc02_gc0010", "EKARA Cartridge with I2C 24LC02 (GC0010 direct access)")
+DEFINE_DEVICE_TYPE(EKARA_ROM_I2C_24LC08_EVIO, ekara_rom_i2c_24lc08_evio_device, "ekara_rom_i2c_24lc08_evio", "EKARA Cartridge with I2C 24LC08 (evio direct access)")
ekara_rom_plain_device::ekara_rom_plain_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
@@ -56,7 +57,17 @@ ekara_rom_i2c_24lc02_device::ekara_rom_i2c_24lc02_device(const machine_config &m
}
ekara_rom_i2c_24lc02_gc0010_device::ekara_rom_i2c_24lc02_gc0010_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- ekara_rom_i2c_base_device(mconfig, EKARA_ROM_I2C_24LC02_GC0010, tag, owner, clock)
+ ekara_rom_i2c_24lc02_gc0010_device(mconfig, EKARA_ROM_I2C_24LC02_GC0010, tag, owner, clock)
+{
+}
+
+ekara_rom_i2c_24lc02_gc0010_device::ekara_rom_i2c_24lc02_gc0010_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
+ ekara_rom_i2c_base_device(mconfig, type, tag, owner, clock)
+{
+}
+
+ekara_rom_i2c_24lc08_evio_device::ekara_rom_i2c_24lc08_evio_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ ekara_rom_i2c_24lc02_gc0010_device(mconfig, EKARA_ROM_I2C_24LC08_EVIO, tag, owner, clock)
{
}
@@ -187,17 +198,17 @@ void ekara_rom_i2c_24lc02_gc0010_device::write_extra(offs_t offset, uint8_t data
}
-WRITE_LINE_MEMBER(ekara_rom_i2c_24lc02_gc0010_device::write_sda)
+void ekara_rom_i2c_24lc02_gc0010_device::write_sda(int state)
{
m_i2cmem->write_sda(state);
}
-WRITE_LINE_MEMBER(ekara_rom_i2c_24lc02_gc0010_device::write_scl)
+void ekara_rom_i2c_24lc02_gc0010_device::write_scl(int state)
{
m_i2cmem->write_scl(state);
}
-READ_LINE_MEMBER(ekara_rom_i2c_24lc02_gc0010_device::read_sda )
+int ekara_rom_i2c_24lc02_gc0010_device::read_sda()
{
return m_i2cmem->read_sda();
}
@@ -210,6 +221,11 @@ void ekara_rom_i2c_24lc02_gc0010_device::device_add_mconfig(machine_config &conf
}
+void ekara_rom_i2c_24lc08_evio_device::device_add_mconfig(machine_config &config)
+{
+ I2C_24C08(config, "i2cmem", 0);
+}
+
/*-------------------------------------------------
slot interface
-------------------------------------------------*/
@@ -221,5 +237,5 @@ void ekara_cart(device_slot_interface &device)
device.option_add_internal("rom_24lc04", EKARA_ROM_I2C_24LC04);
device.option_add_internal("rom_24lc02", EKARA_ROM_I2C_24LC02);
device.option_add_internal("rom_24lc02_gc0010", EKARA_ROM_I2C_24LC02_GC0010);
-
+ device.option_add_internal("rom_24lc08_evio", EKARA_ROM_I2C_24LC08_EVIO);
}
diff --git a/src/devices/bus/ekara/rom.h b/src/devices/bus/ekara/rom.h
index 19dcca1fb36..d28584cf2a0 100644
--- a/src/devices/bus/ekara/rom.h
+++ b/src/devices/bus/ekara/rom.h
@@ -114,17 +114,31 @@ public:
ekara_rom_i2c_24lc02_gc0010_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
+ ekara_rom_i2c_24lc02_gc0010_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
virtual void device_add_mconfig(machine_config &config) override;
bool is_read_access_not_rom(void) override;
bool is_write_access_not_rom(void) override;
uint8_t read_extra(offs_t offset) override;
void write_extra(offs_t offset, uint8_t data) override;
- DECLARE_WRITE_LINE_MEMBER(write_sda) override;
- DECLARE_WRITE_LINE_MEMBER(write_scl) override;
- DECLARE_READ_LINE_MEMBER(read_sda ) override;
+ void write_sda(int state) override;
+ void write_scl(int state) override;
+ int read_sda() override;
};
+class ekara_rom_i2c_24lc08_evio_device : public ekara_rom_i2c_24lc02_gc0010_device
+{
+public:
+ // construction/destruction
+ ekara_rom_i2c_24lc08_evio_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override;
+
+};
+
+
// device type definition
DECLARE_DEVICE_TYPE(EKARA_ROM_PLAIN, ekara_rom_plain_device)
DECLARE_DEVICE_TYPE(EKARA_ROM_I2C_BASE, ekara_rom_i2c_base_device)
@@ -132,5 +146,6 @@ DECLARE_DEVICE_TYPE(EKARA_ROM_I2C_24C08_EPITCH, ekara_rom_i2c_24c08_epitch_dev
DECLARE_DEVICE_TYPE(EKARA_ROM_I2C_24LC04, ekara_rom_i2c_24lc04_device)
DECLARE_DEVICE_TYPE(EKARA_ROM_I2C_24LC02, ekara_rom_i2c_24lc02_device)
DECLARE_DEVICE_TYPE(EKARA_ROM_I2C_24LC02_GC0010, ekara_rom_i2c_24lc02_gc0010_device)
+DECLARE_DEVICE_TYPE(EKARA_ROM_I2C_24LC08_EVIO, ekara_rom_i2c_24lc08_evio_device)
#endif // MAME_BUS_EKARA_ROM_H
diff --git a/src/devices/bus/ekara/slot.cpp b/src/devices/bus/ekara/slot.cpp
index 198d6c35519..33f4e087fa4 100644
--- a/src/devices/bus/ekara/slot.cpp
+++ b/src/devices/bus/ekara/slot.cpp
@@ -38,11 +38,11 @@ device_ekara_cart_interface::~device_ekara_cart_interface()
// rom_alloc - alloc the space for the cart
//-------------------------------------------------
-void device_ekara_cart_interface::rom_alloc(uint32_t size, const char *tag)
+void device_ekara_cart_interface::rom_alloc(uint32_t size)
{
if (m_rom == nullptr)
{
- m_rom = device().machine().memory().region_alloc(std::string(tag).append(EKARASLOT_ROM_REGION_TAG).c_str(), size, 1, ENDIANNESS_BIG)->base();
+ m_rom = device().machine().memory().region_alloc(device().subtag("^cart:rom"), size, 1, ENDIANNESS_BIG)->base();
m_rom_size = size;
}
}
@@ -127,16 +127,15 @@ static const char *ekara_get_slot(int type)
call load
-------------------------------------------------*/
-image_init_result ekara_cart_slot_device::call_load()
+std::pair<std::error_condition, std::string> ekara_cart_slot_device::call_load()
{
if (m_cart)
{
- uint8_t *ROM;
- uint32_t len = !loaded_through_softlist() ? length() : get_software_region_length("rom");
+ uint32_t const len = !loaded_through_softlist() ? length() : get_software_region_length("rom");
- m_cart->rom_alloc(len, tag());
+ m_cart->rom_alloc(len);
- ROM = m_cart->get_rom_base();
+ uint8_t *const ROM = m_cart->get_rom_base();
if (!loaded_through_softlist())
fread(ROM, len);
@@ -155,11 +154,9 @@ image_init_result ekara_cart_slot_device::call_load()
if (pcb_name)
m_type = ekara_get_pcb_id(pcb_name);
}
-
- return image_init_result::PASS;
}
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
@@ -188,8 +185,7 @@ std::string ekara_cart_slot_device::get_default_card_software(get_default_card_s
hook.image_file()->length(len); // FIXME: check error return, guard against excessively large files
std::vector<uint8_t> rom(len);
- size_t actual;
- hook.image_file()->read(&rom[0], len, actual); // FIXME: check error return or read returning short
+ /*auto const [err, actual] =*/ read(*hook.image_file(), &rom[0], len); // FIXME: check error return or read returning short
int const type = get_cart_type(&rom[0], len);
char const *const slot_string = ekara_get_slot(type);
@@ -261,17 +257,17 @@ bool ekara_cart_slot_device::is_write_access_not_rom(void)
direct seeprom access (popira2, gc0010)
-------------------------------------------------*/
-WRITE_LINE_MEMBER(ekara_cart_slot_device::write_sda)
+void ekara_cart_slot_device::write_sda(int state)
{
m_cart->write_sda(state);
}
-WRITE_LINE_MEMBER(ekara_cart_slot_device::write_scl)
+void ekara_cart_slot_device::write_scl(int state)
{
m_cart->write_scl(state);
}
-READ_LINE_MEMBER(ekara_cart_slot_device::read_sda )
+int ekara_cart_slot_device::read_sda()
{
return m_cart->read_sda();
}
diff --git a/src/devices/bus/ekara/slot.h b/src/devices/bus/ekara/slot.h
index 6efbd5962e7..b4248bf6fbd 100644
--- a/src/devices/bus/ekara/slot.h
+++ b/src/devices/bus/ekara/slot.h
@@ -36,17 +36,17 @@ public:
virtual uint8_t read_extra(offs_t offset) { return 0xff; }
virtual void write_extra(offs_t offset, uint8_t data) { }
- virtual DECLARE_WRITE_LINE_MEMBER(write_sda) { }
- virtual DECLARE_WRITE_LINE_MEMBER(write_scl) { }
- //virtual DECLARE_WRITE_LINE_MEMBER( write_wc )
- virtual DECLARE_READ_LINE_MEMBER( read_sda ) { return 0; }
+ virtual void write_sda(int state) { }
+ virtual void write_scl(int state) { }
+ //virtual void write_wc(int state)
+ virtual int read_sda() { return 0; }
virtual void write_bus_control(offs_t offset, uint8_t data) { }
virtual bool is_read_access_not_rom(void) { return false; }
virtual bool is_write_access_not_rom(void) { return false; }
- void rom_alloc(uint32_t size, const char *tag);
+ void rom_alloc(uint32_t size);
uint8_t* get_rom_base() { return m_rom; }
uint32_t get_rom_size() { return m_rom_size; }
@@ -80,15 +80,15 @@ public:
virtual ~ekara_cart_slot_device();
- // image-level overrides
- virtual image_init_result call_load() override;
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
virtual void call_unload() override {}
virtual bool is_reset_on_load() const noexcept override { return true; }
virtual const char *image_interface() const noexcept override { return "ekara_cart"; }
virtual const char *file_extensions() const noexcept override { return "bin,u1"; }
- // slot interface overrides
+ // device_slot_interface implementation
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
int get_type() { return m_type; }
@@ -101,10 +101,10 @@ public:
uint8_t read_extra(offs_t offset);
void write_extra(offs_t offset, uint8_t data);
- DECLARE_WRITE_LINE_MEMBER(write_sda);
- DECLARE_WRITE_LINE_MEMBER(write_scl);
- //DECLARE_WRITE_LINE_MEMBER( write_wc );
- DECLARE_READ_LINE_MEMBER( read_sda );
+ void write_sda(int state);
+ void write_scl(int state);
+ //void write_wc(int state);
+ int read_sda();
void write_bus_control(offs_t offset, uint8_t data);
@@ -114,7 +114,7 @@ public:
bool has_cart() { return m_cart ? true : false; }
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
int m_type;
@@ -128,8 +128,6 @@ DECLARE_DEVICE_TYPE(EKARA_CART_SLOT, ekara_cart_slot_device)
DEVICE CONFIGURATION MACROS
***************************************************************************/
-#define EKARASLOT_ROM_REGION_TAG ":cart:rom"
-
void ekara_cart(device_slot_interface &device);
#endif // MAME_BUS_EKARA_SLOT_H
diff --git a/src/devices/bus/electron/cart/ap34.cpp b/src/devices/bus/electron/cart/ap34.cpp
index ecb3b9da30c..ac1188b8f54 100644
--- a/src/devices/bus/electron/cart/ap34.cpp
+++ b/src/devices/bus/electron/cart/ap34.cpp
@@ -11,10 +11,11 @@
**********************************************************************/
-
#include "emu.h"
#include "ap34.h"
+#include "formats/acorn_dsk.h"
+
//**************************************************************************
// DEVICE DEFINITIONS
diff --git a/src/devices/bus/electron/cart/ap34.h b/src/devices/bus/electron/cart/ap34.h
index ac84e7cd58f..4ae651a7e74 100644
--- a/src/devices/bus/electron/cart/ap34.h
+++ b/src/devices/bus/electron/cart/ap34.h
@@ -14,7 +14,6 @@
#include "slot.h"
#include "imagedev/floppy.h"
#include "machine/wd_fdc.h"
-#include "formats/acorn_dsk.h"
//**************************************************************************
// TYPE DEFINITIONS
diff --git a/src/devices/bus/electron/cart/ap5.cpp b/src/devices/bus/electron/cart/ap5.cpp
index 90c4188d7b1..82d83bfe611 100644
--- a/src/devices/bus/electron/cart/ap5.cpp
+++ b/src/devices/bus/electron/cart/ap5.cpp
@@ -154,23 +154,21 @@ void electron_ap5_device::write(offs_t offset, uint8_t data, int infc, int infd,
// IMPLEMENTATION
//**************************************************************************
-image_init_result electron_ap5_device::load_rom(device_image_interface &image, generic_slot_device *slot)
+std::pair<std::error_condition, std::string> electron_ap5_device::load_rom(device_image_interface &image, generic_slot_device *slot)
{
- uint32_t size = slot->common_get_size("rom");
+ uint32_t const size = slot->common_get_size("rom");
// socket accepts 8K and 16K ROM only
if (size != 0x2000 && size != 0x4000)
- {
- image.seterror(image_error::INVALIDIMAGE, "Invalid size: Only 8K/16K is supported");
- return image_init_result::FAIL;
- }
+ return std::make_pair(image_error::INVALIDLENGTH, "Invalid size: Only 8K/16K is supported");
slot->rom_alloc(0x4000, GENERIC_ROM8_WIDTH, ENDIANNESS_LITTLE);
slot->common_load_rom(slot->get_rom_base(), size, "rom");
// mirror 8K ROMs
- uint8_t *crt = slot->get_rom_base();
- if (size <= 0x2000) memcpy(crt + 0x2000, crt, 0x2000);
+ uint8_t *const crt = slot->get_rom_base();
+ if (size <= 0x2000)
+ memcpy(crt + 0x2000, crt, 0x2000);
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
diff --git a/src/devices/bus/electron/cart/ap5.h b/src/devices/bus/electron/cart/ap5.h
index 9e69c775c63..259a3e48812 100644
--- a/src/devices/bus/electron/cart/ap5.h
+++ b/src/devices/bus/electron/cart/ap5.h
@@ -31,18 +31,18 @@ public:
electron_ap5_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
// optional information overrides
virtual void device_add_mconfig(machine_config &config) override;
- // electron_cart_interface overrides
+ // electron_cart_interface implementation
virtual uint8_t read(offs_t offset, int infc, int infd, int romqa, int oe, int oe2) override;
virtual void write(offs_t offset, uint8_t data, int infc, int infd, int romqa, int oe, int oe2) override;
private:
- image_init_result load_rom(device_image_interface &image, generic_slot_device *slot);
+ std::pair<std::error_condition, std::string> load_rom(device_image_interface &image, generic_slot_device *slot);
DECLARE_DEVICE_IMAGE_LOAD_MEMBER(rom1_load) { return load_rom(image, m_romslot[0]); }
DECLARE_DEVICE_IMAGE_LOAD_MEMBER(rom2_load) { return load_rom(image, m_romslot[1]); }
diff --git a/src/devices/bus/electron/cart/click.cpp b/src/devices/bus/electron/cart/click.cpp
index 46bb123c9e4..31537949a4f 100644
--- a/src/devices/bus/electron/cart/click.cpp
+++ b/src/devices/bus/electron/cart/click.cpp
@@ -96,9 +96,8 @@ uint8_t electron_click_device::read(offs_t offset, int infc, int infd, int romqa
{
switch (offset & 0xff)
{
- case 0xf8:
case 0xf9:
- data = m_rtc->read(offset & 0x01);
+ data = m_rtc->data_r();
break;
case 0xfc:
data = m_page_register;
@@ -134,8 +133,10 @@ void electron_click_device::write(offs_t offset, uint8_t data, int infc, int inf
switch (offset & 0xff)
{
case 0xf8:
+ m_rtc->address_w(data);
+ break;
case 0xf9:
- m_rtc->write(offset & 0x01, data);
+ m_rtc->data_w(data);
break;
case 0xfc:
m_page_register = data;
diff --git a/src/devices/bus/electron/cart/cumana.cpp b/src/devices/bus/electron/cart/cumana.cpp
index 9b854871e59..2452feffc6b 100644
--- a/src/devices/bus/electron/cart/cumana.cpp
+++ b/src/devices/bus/electron/cart/cumana.cpp
@@ -7,16 +7,16 @@
http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Cumana_FDsystem.html
TODO:
- - add floppy format CDFS, and find original utilities disc
- - confirm whether DRQ and INTRQ are connected
+ - find original utilities disc
- add spare ROM slot
**********************************************************************/
-
#include "emu.h"
#include "cumana.h"
+#include "formats/acorn_dsk.h"
+
//**************************************************************************
// DEVICE DEFINITIONS
@@ -32,6 +32,7 @@ DEFINE_DEVICE_TYPE(ELECTRON_CUMANA, electron_cumana_device, "electron_cumana", "
void electron_cumana_device::floppy_formats(format_registration &fr)
{
fr.add_mfm_containers();
+ fr.add(FLOPPY_CUMANA_DFS_FORMAT);
fr.add(FLOPPY_ACORN_SSD_FORMAT);
fr.add(FLOPPY_ACORN_DSD_FORMAT);
fr.add(FLOPPY_ACORN_ADFS_OLD_FORMAT);
@@ -49,12 +50,10 @@ void cumana_floppies(device_slot_interface &device)
void electron_cumana_device::device_add_mconfig(machine_config &config)
{
- /* fdc */
- FD1793(config, m_fdc, DERIVED_CLOCK(1, 16)); // TODO: Not known whether DRQ and INTRQ are connected
- FLOPPY_CONNECTOR(config, m_floppy0, cumana_floppies, "525qd", electron_cumana_device::floppy_formats).enable_sound(true);
- FLOPPY_CONNECTOR(config, m_floppy1, cumana_floppies, nullptr, electron_cumana_device::floppy_formats).enable_sound(true);
+ FD1793(config, m_fdc, DERIVED_CLOCK(1, 16));
+ FLOPPY_CONNECTOR(config, m_floppy[0], cumana_floppies, "525qd", electron_cumana_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[1], cumana_floppies, nullptr, electron_cumana_device::floppy_formats).enable_sound(true);
- /* rtc */
MC146818(config, m_rtc, 32.768_kHz_XTAL);
m_rtc->irq().set(DEVICE_SELF_OWNER, FUNC(electron_cartslot_device::irq_w));
}
@@ -71,8 +70,7 @@ electron_cumana_device::electron_cumana_device(const machine_config &mconfig, co
: device_t(mconfig, ELECTRON_CUMANA, tag, owner, clock)
, device_electron_cart_interface(mconfig, *this)
, m_fdc(*this, "fdc")
- , m_floppy0(*this, "fdc:0")
- , m_floppy1(*this, "fdc:1")
+ , m_floppy(*this, "fdc:%u", 0)
, m_rtc(*this, "rtc")
{
}
@@ -85,6 +83,7 @@ void electron_cumana_device::device_start()
{
}
+
//-------------------------------------------------
// read - cartridge data read
//-------------------------------------------------
@@ -101,10 +100,10 @@ uint8_t electron_cumana_device::read(offs_t offset, int infc, int infd, int romq
data = m_fdc->read(offset & 0x03);
break;
case 0x94:
- break;
case 0x98:
+ break;
case 0x9c:
- data = m_rtc->read(BIT(offset, 2));
+ data = m_rtc->data_r();
break;
}
}
@@ -145,11 +144,13 @@ void electron_cumana_device::write(offs_t offset, uint8_t data, int infc, int in
m_fdc->write(offset & 0x03, data);
break;
case 0x94:
- wd1793_control_w(data);
+ control_w(data);
break;
case 0x98:
+ m_rtc->address_w(data);
+ break;
case 0x9c:
- m_rtc->write(BIT(offset, 2), data);
+ m_rtc->data_w(data);
break;
}
}
@@ -167,13 +168,13 @@ void electron_cumana_device::write(offs_t offset, uint8_t data, int infc, int in
// IMPLEMENTATION
//**************************************************************************
-void electron_cumana_device::wd1793_control_w(uint8_t data)
+void electron_cumana_device::control_w(uint8_t data)
{
floppy_image_device *floppy = nullptr;
// bit 1, 2: drive select
- if (BIT(data, 1)) floppy = m_floppy0->get_device();
- if (BIT(data, 2)) floppy = m_floppy1->get_device();
+ if (BIT(data, 1)) floppy = m_floppy[0]->get_device();
+ if (BIT(data, 2)) floppy = m_floppy[1]->get_device();
m_fdc->set_floppy(floppy);
// bit 0: side select
@@ -187,5 +188,6 @@ void electron_cumana_device::wd1793_control_w(uint8_t data)
if (floppy)
floppy->mon_w(!BIT(data, 4));
- // bit 5: head load
+ // bit 5: head load timing
+ m_fdc->hlt_w(BIT(data, 5));
}
diff --git a/src/devices/bus/electron/cart/cumana.h b/src/devices/bus/electron/cart/cumana.h
index 2dce4bbc78c..4717cb57d7b 100644
--- a/src/devices/bus/electron/cart/cumana.h
+++ b/src/devices/bus/electron/cart/cumana.h
@@ -15,7 +15,6 @@
#include "imagedev/floppy.h"
#include "machine/wd_fdc.h"
#include "machine/mc146818.h"
-#include "formats/acorn_dsk.h"
//**************************************************************************
// TYPE DEFINITIONS
@@ -41,12 +40,11 @@ protected:
virtual void write(offs_t offset, uint8_t data, int infc, int infd, int romqa, int oe, int oe2) override;
private:
- void wd1793_control_w(uint8_t data);
+ void control_w(uint8_t data);
static void floppy_formats(format_registration &fr);
required_device<fd1793_device> m_fdc;
- required_device<floppy_connector> m_floppy0;
- required_device<floppy_connector> m_floppy1;
+ required_device_array<floppy_connector, 2> m_floppy;
required_device<mc146818_device> m_rtc;
};
diff --git a/src/devices/bus/electron/cart/peg400.cpp b/src/devices/bus/electron/cart/peg400.cpp
index cba69099613..82c348cf2f8 100644
--- a/src/devices/bus/electron/cart/peg400.cpp
+++ b/src/devices/bus/electron/cart/peg400.cpp
@@ -9,10 +9,11 @@
**********************************************************************/
-
#include "emu.h"
#include "peg400.h"
+#include "formats/acorn_dsk.h"
+
//**************************************************************************
// DEVICE DEFINITIONS
@@ -171,7 +172,7 @@ void electron_peg400_device::wd1770_control_w(uint8_t data)
// bit 5: head load
}
-WRITE_LINE_MEMBER(electron_peg400_device::fdc_drq_w)
+void electron_peg400_device::fdc_drq_w(int state)
{
m_slot->nmi_w((state && m_fdc_ie) ? ASSERT_LINE : CLEAR_LINE);
}
diff --git a/src/devices/bus/electron/cart/peg400.h b/src/devices/bus/electron/cart/peg400.h
index 141cc1fe02f..c2920dc08d7 100644
--- a/src/devices/bus/electron/cart/peg400.h
+++ b/src/devices/bus/electron/cart/peg400.h
@@ -12,7 +12,6 @@
#include "slot.h"
#include "imagedev/floppy.h"
#include "machine/wd_fdc.h"
-#include "formats/acorn_dsk.h"
//**************************************************************************
// TYPE DEFINITIONS
@@ -40,7 +39,7 @@ protected:
private:
void wd1770_control_w(uint8_t data);
static void floppy_formats(format_registration &fr);
- DECLARE_WRITE_LINE_MEMBER(fdc_drq_w);
+ void fdc_drq_w(int state);
required_device<wd1770_device> m_fdc;
required_device<floppy_connector> m_floppy0;
diff --git a/src/devices/bus/electron/cart/romp144.cpp b/src/devices/bus/electron/cart/romp144.cpp
index 8bdeab7cc34..e570074a7f2 100644
--- a/src/devices/bus/electron/cart/romp144.cpp
+++ b/src/devices/bus/electron/cart/romp144.cpp
@@ -140,23 +140,21 @@ void electron_romp144_device::write(offs_t offset, uint8_t data, int infc, int i
// IMPLEMENTATION
//**************************************************************************
-image_init_result electron_romp144_device::load_rom(device_image_interface &image, generic_slot_device *slot)
+std::pair<std::error_condition, std::string> electron_romp144_device::load_rom(device_image_interface &image, generic_slot_device *slot)
{
- uint32_t size = slot->common_get_size("rom");
+ uint32_t const size = slot->common_get_size("rom");
// socket accepts 8K and 16K ROM only
if (size != 0x2000 && size != 0x4000)
- {
- image.seterror(image_error::INVALIDIMAGE, "Invalid size: Only 8K/16K is supported");
- return image_init_result::FAIL;
- }
+ return std::make_pair(image_error::INVALIDLENGTH, "Invalid size: Only 8K/16K is supported");
slot->rom_alloc(0x4000, GENERIC_ROM8_WIDTH, ENDIANNESS_LITTLE);
slot->common_load_rom(slot->get_rom_base(), size, "rom");
// mirror 8K ROMs
- uint8_t *crt = slot->get_rom_base();
- if (size <= 0x2000) memcpy(crt + 0x2000, crt, 0x2000);
+ uint8_t *const crt = slot->get_rom_base();
+ if (size <= 0x2000)
+ memcpy(crt + 0x2000, crt, 0x2000);
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
diff --git a/src/devices/bus/electron/cart/romp144.h b/src/devices/bus/electron/cart/romp144.h
index 45916a3ab38..1cd9cf90180 100644
--- a/src/devices/bus/electron/cart/romp144.h
+++ b/src/devices/bus/electron/cart/romp144.h
@@ -26,18 +26,18 @@ public:
electron_romp144_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
// optional information overrides
virtual void device_add_mconfig(machine_config &config) override;
- // electron_cart_interface overrides
+ // electron_cart_interface implementation
virtual uint8_t read(offs_t offset, int infc, int infd, int romqa, int oe, int oe2) override;
virtual void write(offs_t offset, uint8_t data, int infc, int infd, int romqa, int oe, int oe2) override;
private:
- image_init_result load_rom(device_image_interface &image, generic_slot_device *slot);
+ std::pair<std::error_condition, std::string> load_rom(device_image_interface &image, generic_slot_device *slot);
DECLARE_DEVICE_IMAGE_LOAD_MEMBER(rom0) { return load_rom(image, m_romslot[0]); }
DECLARE_DEVICE_IMAGE_LOAD_MEMBER(rom1) { return load_rom(image, m_romslot[1]); }
DECLARE_DEVICE_IMAGE_LOAD_MEMBER(rom2) { return load_rom(image, m_romslot[2]); }
diff --git a/src/devices/bus/electron/cart/slot.cpp b/src/devices/bus/electron/cart/slot.cpp
index 6502fb7d4ac..76ea4a63cdc 100644
--- a/src/devices/bus/electron/cart/slot.cpp
+++ b/src/devices/bus/electron/cart/slot.cpp
@@ -52,12 +52,12 @@ void device_electron_cart_interface::rom_alloc(uint32_t size, const char *tag)
{
if (size <= 0x8000)
{
- m_rom = device().machine().memory().region_alloc(std::string(tag).append(ELECTRON_CART_ROM_REGION_TAG).c_str(), 0x8000, 1, ENDIANNESS_LITTLE)->base();
+ m_rom = device().machine().memory().region_alloc(std::string(tag).append(ELECTRON_CART_ROM_REGION_TAG), 0x8000, 1, ENDIANNESS_LITTLE)->base();
m_rom_size = 0x8000;
}
else
{
- m_rom = device().machine().memory().region_alloc(std::string(tag).append(ELECTRON_CART_ROM_REGION_TAG).c_str(), size, 1, ENDIANNESS_LITTLE)->base();
+ m_rom = device().machine().memory().region_alloc(std::string(tag).append(ELECTRON_CART_ROM_REGION_TAG), size, 1, ENDIANNESS_LITTLE)->base();
m_rom_size = size;
}
}
@@ -111,10 +111,6 @@ electron_cartslot_device::electron_cartslot_device(const machine_config &mconfig
void electron_cartslot_device::device_start()
{
m_cart = get_card_device();
-
- // resolve callbacks
- m_irq_handler.resolve_safe();
- m_nmi_handler.resolve_safe();
}
@@ -122,19 +118,16 @@ void electron_cartslot_device::device_start()
// call load
//-------------------------------------------------
-image_init_result electron_cartslot_device::call_load()
+std::pair<std::error_condition, std::string> electron_cartslot_device::call_load()
{
if (m_cart)
{
if (!loaded_through_softlist())
{
- uint32_t size = length();
+ uint32_t const size = length();
if (size % 0x2000)
- {
- seterror(image_error::INVALIDIMAGE, "Unsupported cartridge size");
- return image_init_result::FAIL;
- }
+ return std::make_pair(image_error::INVALIDLENGTH, "Unsupported cartridge size (must be a multiple of 8K)");
m_cart->rom_alloc(size, tag());
fread(m_cart->get_rom_base(), size);
@@ -150,11 +143,8 @@ image_init_result electron_cartslot_device::call_load()
uint32_t ramsize = get_software_region_length("ram");
uint32_t nvramsize = get_software_region_length("nvram");
- if ((upsize % 0x2000 && upsize != 0) || (losize % 0x2000 && losize != 0) || (romsize % 0x2000 && romsize != 0))
- {
- seterror(image_error::INVALIDIMAGE, "Unsupported cartridge size");
- return image_init_result::FAIL;
- }
+ if ((upsize % 0x2000) || (losize % 0x2000) || (romsize % 0x2000))
+ return std::make_pair(image_error::INVALIDLENGTH, "Unsupported ROM size (must be a multiple of 8K)");
// load standard 2x16K ROM cartridges
if (losize != 0 || upsize != 0)
@@ -197,7 +187,7 @@ image_init_result electron_cartslot_device::call_load()
}
}
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
diff --git a/src/devices/bus/electron/cart/slot.h b/src/devices/bus/electron/cart/slot.h
index b71da09d5ae..0da6bf10610 100644
--- a/src/devices/bus/electron/cart/slot.h
+++ b/src/devices/bus/electron/cart/slot.h
@@ -136,8 +136,8 @@ public:
auto irq_handler() { return m_irq_handler.bind(); }
auto nmi_handler() { return m_nmi_handler.bind(); }
- // image-level overrides
- virtual image_init_result call_load() override;
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
virtual void call_unload() override;
virtual bool is_writeable() const noexcept override { return true; }
@@ -145,7 +145,7 @@ public:
virtual const char *image_interface() const noexcept override { return "electron_cart"; }
virtual const char *file_extensions() const noexcept override { return "rom,bin"; }
- // slot interface overrides
+ // device_image_interface implementation
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
// reading and writing
@@ -154,13 +154,13 @@ public:
virtual bool present() { return is_loaded() || loaded_through_softlist(); }
- DECLARE_WRITE_LINE_MEMBER(irq_w) { m_irq_handler(state); }
- DECLARE_WRITE_LINE_MEMBER(nmi_w) { m_nmi_handler(state); }
+ void irq_w(int state) { m_irq_handler(state); }
+ void nmi_w(int state) { m_nmi_handler(state); }
protected:
electron_cartslot_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
device_electron_cart_interface *m_cart;
diff --git a/src/devices/bus/electron/cart/stlefs.cpp b/src/devices/bus/electron/cart/stlefs.cpp
index 462ead401d1..3aeb1ddac04 100644
--- a/src/devices/bus/electron/cart/stlefs.cpp
+++ b/src/devices/bus/electron/cart/stlefs.cpp
@@ -11,10 +11,11 @@
**********************************************************************/
-
#include "emu.h"
#include "stlefs.h"
+#include "formats/acorn_dsk.h"
+
//**************************************************************************
// DEVICE DEFINITIONS
diff --git a/src/devices/bus/electron/cart/stlefs.h b/src/devices/bus/electron/cart/stlefs.h
index 2ff8e53ea87..ba99b0f5d62 100644
--- a/src/devices/bus/electron/cart/stlefs.h
+++ b/src/devices/bus/electron/cart/stlefs.h
@@ -16,7 +16,6 @@
#include "machine/input_merger.h"
#include "machine/wd_fdc.h"
#include "imagedev/floppy.h"
-#include "formats/acorn_dsk.h"
//**************************************************************************
// TYPE DEFINITIONS
diff --git a/src/devices/bus/electron/elksd128.cpp b/src/devices/bus/electron/elksd128.cpp
index 302144bb343..d57fb07dfff 100644
--- a/src/devices/bus/electron/elksd128.cpp
+++ b/src/devices/bus/electron/elksd128.cpp
@@ -274,7 +274,7 @@ void electron_elksd128_device::expbus_w(offs_t offset, uint8_t data)
break;
case 0xfe:
- if (offset == 0xfe05)
+ if ((offset == 0xfe05) && !(data & 0xf0))
{
m_romsel = data & 0x0f;
}
diff --git a/src/devices/bus/electron/elksd64.cpp b/src/devices/bus/electron/elksd64.cpp
index c76c9a8c685..033f0aceb4d 100644
--- a/src/devices/bus/electron/elksd64.cpp
+++ b/src/devices/bus/electron/elksd64.cpp
@@ -151,7 +151,7 @@ void electron_elksd64_device::expbus_w(offs_t offset, uint8_t data)
break;
case 0xfe:
- if (offset == 0xfe05)
+ if ((offset == 0xfe05) && !(data & 0xf0))
{
m_romsel = data & 0x0f;
}
diff --git a/src/devices/bus/electron/exp.cpp b/src/devices/bus/electron/exp.cpp
index 6198b1abd0f..794e2e0df96 100644
--- a/src/devices/bus/electron/exp.cpp
+++ b/src/devices/bus/electron/exp.cpp
@@ -57,10 +57,6 @@ electron_expansion_slot_device::electron_expansion_slot_device(const machine_con
void electron_expansion_slot_device::device_start()
{
m_card = get_card_device();
-
- // resolve callbacks
- m_irq_handler.resolve_safe();
- m_nmi_handler.resolve_safe();
}
@@ -114,7 +110,7 @@ void electron_expansion_slot_device::expbus_w(offs_t offset, uint8_t data)
#include "romboxp.h"
#include "sidewndr.h"
#include "m2105.h"
-//#include "voxbox.h"
+#include "voxbox.h"
void electron_expansion_devices(device_slot_interface &device)
@@ -136,5 +132,5 @@ void electron_expansion_devices(device_slot_interface &device)
device.option_add("romboxp", ELECTRON_ROMBOXP);
device.option_add("sidewndr", ELECTRON_SIDEWNDR);
device.option_add("m2105", ELECTRON_M2105);
- //device.option_add("voxbox", ELECTRON_VOXBOX);
+ device.option_add("voxbox", ELECTRON_VOXBOX);
}
diff --git a/src/devices/bus/electron/exp.h b/src/devices/bus/electron/exp.h
index ea0c435a4be..12b98356e14 100644
--- a/src/devices/bus/electron/exp.h
+++ b/src/devices/bus/electron/exp.h
@@ -120,8 +120,8 @@ public:
uint8_t expbus_r(offs_t offset);
void expbus_w(offs_t offset, uint8_t data);
- DECLARE_WRITE_LINE_MEMBER( irq_w ) { m_irq_handler(state); }
- DECLARE_WRITE_LINE_MEMBER( nmi_w ) { m_nmi_handler(state); }
+ void irq_w(int state) { m_irq_handler(state); }
+ void nmi_w(int state) { m_nmi_handler(state); }
protected:
// device-level overrides
diff --git a/src/devices/bus/electron/m2105.cpp b/src/devices/bus/electron/m2105.cpp
index 35ba1e40e13..25f9e60a73f 100644
--- a/src/devices/bus/electron/m2105.cpp
+++ b/src/devices/bus/electron/m2105.cpp
@@ -49,8 +49,8 @@ ROM_START( m2105 )
ROMX_LOAD("sk01-pc-207l-1.ic24", 0x8000, 0x4000, CRC(0850bcea) SHA1(270e7a31e69e1454cfb70ced23a50f5d97efe4d5), ROM_BIOS(2))
ROMX_LOAD("sk02-pc-207l-1.ic24", 0xc000, 0x4000, CRC(d8b9143f) SHA1(4e132c7a6dae4caf7203139b51882706d508c449), ROM_BIOS(2))
- ROM_REGION(0x4000, "tms6100", 0)
- ROM_LOAD("phroma.bin", 0x0000, 0x4000, CRC(98e1bf9e) SHA1(b369809275cb67dfd8a749265e91adb2d2558ae6))
+ ROM_REGION(0x40000, "vsm", ROMREGION_ERASE00)
+ ROM_LOAD("cm62024.bin", 0x3c000, 0x4000, CRC(98e1bf9e) SHA1(b369809275cb67dfd8a749265e91adb2d2558ae6))
ROM_END
@@ -65,9 +65,9 @@ void electron_m2105_device::device_add_mconfig(machine_config &config)
INPUT_MERGER_ANY_HIGH(config, "irqs").output_handler().set(DEVICE_SELF_OWNER, FUNC(electron_expansion_slot_device::irq_w));
MOS6522(config, m_via[0], DERIVED_CLOCK(1, 16));
- m_via[0]->readpa_handler().set("tms5220", FUNC(tms5220_device::status_r));
- m_via[0]->writepa_handler().set("tms5220", FUNC(tms5220_device::data_w));
- m_via[0]->writepb_handler().set("tms5220", FUNC(tms5220_device::combined_rsq_wsq_w)).mask(0x03);
+ m_via[0]->readpa_handler().set("vsp", FUNC(tms5220_device::status_r));
+ m_via[0]->writepa_handler().set("vsp", FUNC(tms5220_device::data_w));
+ m_via[0]->writepb_handler().set("vsp", FUNC(tms5220_device::combined_rsq_wsq_w)).mask(0x03);
//m_via[0]->writepb_handler().set().bit(5); SPK ENABLE
//m_via[0]->writepb_handler().set().bit(6); SND ENABLE
m_via[0]->cb1_handler().set(m_via[0], FUNC(via6522_device::write_pb4));
@@ -114,19 +114,15 @@ void electron_m2105_device::device_add_mconfig(machine_config &config)
output_latch_device &latch(OUTPUT_LATCH(config, "cent_data_out"));
centronics.set_output_latch(latch);
- TMS6100(config, "tms6100", 640000/4);
+ SPEECHROM(config, "vsm", 0).set_reverse_bit_order(true);
- tms5220_device &tms(TMS5220(config, "tms5220", 640000));
+ tms5220_device &tms(TMS5220(config, "vsp", 640000));
+ tms.set_speechrom_tag("vsm");
tms.ready_cb().set(m_via[0], FUNC(via6522_device::write_ca1));
tms.ready_cb().append(m_via[0], FUNC(via6522_device::write_pb2));
tms.irq_cb().set(m_via[0], FUNC(via6522_device::write_ca2));
tms.irq_cb().append(m_via[0], FUNC(via6522_device::write_pb3));
- tms.m0_cb().set("tms6100", FUNC(tms6100_device::m0_w));
- tms.m1_cb().set("tms6100", FUNC(tms6100_device::m1_w));
- tms.addr_cb().set("tms6100", FUNC(tms6100_device::add_w));
- tms.data_cb().set("tms6100", FUNC(tms6100_device::data_line_r));
- tms.romclk_cb().set("tms6100", FUNC(tms6100_device::clk_w));
- tms.add_route(ALL_OUTPUTS, "mono", 1.0);
+ tms.add_route(ALL_OUTPUTS, "mono", 0.5);
SPEAKER(config, "mono").front_center();
}
@@ -261,7 +257,7 @@ void electron_m2105_device::expbus_w(offs_t offset, uint8_t data)
break;
case 0xfe:
- if (offset == 0xfe05)
+ if ((offset == 0xfe05) && !(data & 0xf0))
{
m_romsel = data & 0x0f;
}
diff --git a/src/devices/bus/electron/mc68k.cpp b/src/devices/bus/electron/mc68k.cpp
index 06e39350977..8963527c19b 100644
--- a/src/devices/bus/electron/mc68k.cpp
+++ b/src/devices/bus/electron/mc68k.cpp
@@ -84,7 +84,7 @@ void electron_mc68k_device::device_add_mconfig(machine_config &config)
{
M68000(config, m_maincpu, 10_MHz_XTAL);
m_maincpu->set_addrmap(AS_PROGRAM, &electron_mc68k_device::mem_map);
- m_maincpu->disable_interrupt_mixer();
+ m_maincpu->set_interrupt_mixer(false);
INPUT_MERGER_ANY_HIGH(config, "irq_ipl0").output_handler().set_inputline(m_maincpu, M68K_IRQ_IPL0);
INPUT_MERGER_ANY_HIGH(config, "irq_ipl1").output_handler().set_inputline(m_maincpu, M68K_IRQ_IPL1);
@@ -92,14 +92,14 @@ void electron_mc68k_device::device_add_mconfig(machine_config &config)
RAM(config, m_ram).set_default_size("256K").set_extra_options("64K,128K,192K");
- PIA6821(config, m_pia[0], 0);
+ PIA6821(config, m_pia[0]);
m_pia[0]->writepb_handler().set(m_pia[1], FUNC(pia6821_device::set_a_input));
m_pia[0]->ca2_handler().set(m_pia[1], FUNC(pia6821_device::cb1_w));
m_pia[0]->cb2_handler().set(m_pia[1], FUNC(pia6821_device::ca1_w));
m_pia[0]->irqa_handler().set("irq_ipl0", FUNC(input_merger_device::in_w<0>));
m_pia[0]->irqb_handler().set("irq_ipl0", FUNC(input_merger_device::in_w<1>));
- PIA6821(config, m_pia[1], 0);
+ PIA6821(config, m_pia[1]);
m_pia[1]->writepb_handler().set(m_pia[0], FUNC(pia6821_device::set_a_input));
m_pia[1]->ca2_handler().set(m_pia[0], FUNC(pia6821_device::cb1_w));
m_pia[1]->cb2_handler().set(m_pia[0], FUNC(pia6821_device::ca1_w));
diff --git a/src/devices/bus/electron/mode7.cpp b/src/devices/bus/electron/mode7.cpp
index 408b6a92300..056883d78b1 100644
--- a/src/devices/bus/electron/mode7.cpp
+++ b/src/devices/bus/electron/mode7.cpp
@@ -223,7 +223,7 @@ MC6845_UPDATE_ROW(electron_mode7_device::crtc_update_row)
}
}
-WRITE_LINE_MEMBER(electron_mode7_device::vsync_changed)
+void electron_mode7_device::vsync_changed(int state)
{
m_trom->dew_w(state);
}
diff --git a/src/devices/bus/electron/mode7.h b/src/devices/bus/electron/mode7.h
index b3c447ee87d..e4551e10bfe 100644
--- a/src/devices/bus/electron/mode7.h
+++ b/src/devices/bus/electron/mode7.h
@@ -53,7 +53,7 @@ private:
std::unique_ptr<uint8_t[]> m_videoram;
MC6845_UPDATE_ROW(crtc_update_row);
- DECLARE_WRITE_LINE_MEMBER(vsync_changed);
+ void vsync_changed(int state);
uint8_t m_romsel;
};
diff --git a/src/devices/bus/electron/plus1.cpp b/src/devices/bus/electron/plus1.cpp
index 4b2c3ba9dad..349dcf9e5c7 100644
--- a/src/devices/bus/electron/plus1.cpp
+++ b/src/devices/bus/electron/plus1.cpp
@@ -71,27 +71,7 @@ ROM_END
// INPUT_PORTS( plus1 )
//-------------------------------------------------
-static INPUT_PORTS_START( plus1 )
- PORT_START("JOY1")
- PORT_BIT(0xff, 0x80, IPT_AD_STICK_X) PORT_SENSITIVITY(100) PORT_KEYDELTA(100) PORT_CENTERDELTA(100) PORT_MINMAX(0x00, 0xff) PORT_PLAYER(1) PORT_REVERSE
-
- PORT_START("JOY2")
- PORT_BIT(0xff, 0x80, IPT_AD_STICK_Y) PORT_SENSITIVITY(100) PORT_KEYDELTA(100) PORT_CENTERDELTA(100) PORT_MINMAX(0x00, 0xff) PORT_PLAYER(1) PORT_REVERSE
-
- PORT_START("JOY3")
- PORT_BIT(0xff, 0x80, IPT_AD_STICK_X) PORT_SENSITIVITY(100) PORT_KEYDELTA(100) PORT_CENTERDELTA(100) PORT_MINMAX(0x00, 0xff) PORT_PLAYER(2) PORT_REVERSE
-
- PORT_START("JOY4")
- PORT_BIT(0xff, 0x80, IPT_AD_STICK_Y) PORT_SENSITIVITY(100) PORT_KEYDELTA(100) PORT_CENTERDELTA(100) PORT_MINMAX(0x00, 0xff) PORT_PLAYER(2) PORT_REVERSE
-
- PORT_START("BUTTONS")
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_PLAYER(1)
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_PLAYER(2)
-INPUT_PORTS_END
-
static INPUT_PORTS_START( ap6 )
- PORT_INCLUDE(plus1)
-
PORT_START("LINKS")
PORT_CONFNAME(0x01, 0x01, "J1 ROM 13")
PORT_CONFSETTING(0x00, "Disabled")
@@ -108,11 +88,6 @@ INPUT_PORTS_END
// input_ports - device-specific input ports
//-------------------------------------------------
-ioport_constructor electron_plus1_device::device_input_ports() const
-{
- return INPUT_PORTS_NAME( plus1 );
-}
-
ioport_constructor electron_ap6_device::device_input_ports() const
{
return INPUT_PORTS_NAME( ap6 );
@@ -135,10 +110,12 @@ void electron_plus1_device::device_add_mconfig(machine_config &config)
/* adc */
ADC0844(config, m_adc);
m_adc->intr_callback().set([this](int state) { m_adc_ready = !state; });
- m_adc->ch1_callback().set_ioport("JOY1");
- m_adc->ch2_callback().set_ioport("JOY2");
- m_adc->ch3_callback().set_ioport("JOY3");
- m_adc->ch4_callback().set_ioport("JOY4");
+ m_adc->ch1_callback().set([this]() { return m_analogue->ch_r(0); });
+ m_adc->ch2_callback().set([this]() { return m_analogue->ch_r(1); });
+ m_adc->ch3_callback().set([this]() { return m_analogue->ch_r(2); });
+ m_adc->ch4_callback().set([this]() { return m_analogue->ch_r(3); });
+
+ BBC_ANALOGUE_SLOT(config, m_analogue, bbc_analogue_devices, "acornjoy");
/* cartridges */
ELECTRON_CARTSLOT(config, m_cart_sk1, DERIVED_CLOCK(1, 1), electron_cart, nullptr);
@@ -204,9 +181,8 @@ electron_plus1_device::electron_plus1_device(const machine_config &mconfig, devi
, m_cart_sk2(*this, "cart_sk2")
, m_centronics(*this, "centronics")
, m_cent_data_out(*this, "cent_data_out")
+ , m_analogue(*this, "analogue")
, m_adc(*this, "adc")
- , m_joy(*this, "JOY%u", 1)
- , m_buttons(*this, "BUTTONS")
, m_romsel(0)
, m_centronics_busy(0)
, m_adc_ready(0)
@@ -223,7 +199,7 @@ electron_ap1_device::electron_ap1_device(const machine_config &mconfig, const ch
{
}
-electron_ap6_device::electron_ap6_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock)
+electron_ap6_device::electron_ap6_device(const machine_config &mconfig, const char* tag, device_t* owner, uint32_t clock)
: electron_plus1_device(mconfig, ELECTRON_AP6, tag, owner, clock)
, m_rom(*this, "rom%u", 1)
, m_links(*this, "LINKS")
@@ -305,7 +281,7 @@ uint8_t electron_plus1_device::expbus_r(offs_t offset)
// b6: ADC conversion end
// b5: Fire Button 1
// b4: Fire Button 2
- data &= (m_centronics_busy << 7) | (m_adc_ready << 6) | m_buttons->read() | 0x0f;
+ data &= (m_centronics_busy << 7) | (m_adc_ready << 6) | m_analogue->pb_r() | 0x0f;
}
break;
@@ -428,7 +404,7 @@ void electron_plus1_device::expbus_w(offs_t offset, uint8_t data)
break;
case 0xfe:
- if (offset == 0xfe05)
+ if ((offset == 0xfe05) && !(data & 0xf0))
{
m_romsel = data & 0x0f;
}
@@ -515,23 +491,21 @@ void electron_ap6_device::expbus_w(offs_t offset, uint8_t data)
// IMPLEMENTATION
//**************************************************************************
-image_init_result electron_ap6_device::load_rom(device_image_interface &image, generic_slot_device *slot)
+std::pair<std::error_condition, std::string> electron_ap6_device::load_rom(device_image_interface &image, generic_slot_device *slot)
{
- uint32_t size = slot->common_get_size("rom");
+ uint32_t const size = slot->common_get_size("rom");
// socket accepts 8K and 16K ROM only
if (size != 0x2000 && size != 0x4000)
- {
- image.seterror(image_error::INVALIDIMAGE, "Invalid size: Only 8K/16K is supported");
- return image_init_result::FAIL;
- }
+ return std::make_pair(image_error::INVALIDLENGTH, "Invalid size: Only 8K/16K is supported");
slot->rom_alloc(0x4000, GENERIC_ROM8_WIDTH, ENDIANNESS_LITTLE);
slot->common_load_rom(slot->get_rom_base(), size, "rom");
// mirror 8K ROMs
- uint8_t *crt = slot->get_rom_base();
- if (size <= 0x2000) memcpy(crt + 0x2000, crt, 0x2000);
+ uint8_t *const crt = slot->get_rom_base();
+ if (size <= 0x2000)
+ memcpy(crt + 0x2000, crt, 0x2000);
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
diff --git a/src/devices/bus/electron/plus1.h b/src/devices/bus/electron/plus1.h
index 36a403b960c..1ec722d066d 100644
--- a/src/devices/bus/electron/plus1.h
+++ b/src/devices/bus/electron/plus1.h
@@ -13,6 +13,7 @@
#include "exp.h"
#include "machine/adc0844.h"
#include "machine/input_merger.h"
+#include "bus/bbc/analogue/analogue.h"
#include "bus/centronics/ctronics.h"
#include "bus/electron/cart/slot.h"
#include "bus/generic/slot.h"
@@ -33,13 +34,12 @@ public:
protected:
electron_plus1_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
// optional information overrides
virtual void device_add_mconfig(machine_config &config) override;
virtual const tiny_rom_entry *device_rom_region() const override;
- virtual ioport_constructor device_input_ports() const override;
virtual uint8_t expbus_r(offs_t offset) override;
virtual void expbus_w(offs_t offset, uint8_t data) override;
@@ -50,9 +50,8 @@ protected:
required_device<electron_cartslot_device> m_cart_sk2;
required_device<centronics_device> m_centronics;
required_device<output_latch_device> m_cent_data_out;
+ required_device<bbc_analogue_slot_device> m_analogue;
required_device<adc0844_device> m_adc;
- required_ioport_array<4> m_joy;
- required_ioport m_buttons;
uint8_t m_romsel;
int m_centronics_busy;
@@ -63,7 +62,7 @@ protected:
class electron_ap1_device : public electron_plus1_device
{
public:
- electron_ap1_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock);
+ electron_ap1_device(const machine_config &mconfig, const char* tag, device_t* owner, uint32_t clock);
protected:
// optional information overrides
@@ -74,14 +73,14 @@ protected:
class electron_ap6_device : public electron_plus1_device
{
public:
- electron_ap6_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock);
+ electron_ap6_device(const machine_config &mconfig, const char* tag, device_t* owner, uint32_t clock);
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
// optional information overrides
- virtual void device_add_mconfig(machine_config& config) override;
+ virtual void device_add_mconfig(machine_config &config) override;
virtual const tiny_rom_entry* device_rom_region() const override;
virtual ioport_constructor device_input_ports() const override;
@@ -89,7 +88,7 @@ protected:
virtual void expbus_w(offs_t offset, uint8_t data) override;
private:
- image_init_result load_rom(device_image_interface &image, generic_slot_device *slot);
+ std::pair<std::error_condition, std::string> load_rom(device_image_interface &image, generic_slot_device *slot);
DECLARE_DEVICE_IMAGE_LOAD_MEMBER(rom1_load) { return load_rom(image, m_rom[0]); }
DECLARE_DEVICE_IMAGE_LOAD_MEMBER(rom2_load) { return load_rom(image, m_rom[1]); }
DECLARE_DEVICE_IMAGE_LOAD_MEMBER(rom3_load) { return load_rom(image, m_rom[2]); }
diff --git a/src/devices/bus/electron/plus2.cpp b/src/devices/bus/electron/plus2.cpp
index 7a75524ed5c..92a9599dfb0 100644
--- a/src/devices/bus/electron/plus2.cpp
+++ b/src/devices/bus/electron/plus2.cpp
@@ -208,7 +208,7 @@ void electron_plus2_device::expbus_w(offs_t offset, uint8_t data)
break;
case 0xfe:
- if (offset == 0xfe05)
+ if ((offset == 0xfe05) && !(data & 0xf0))
{
m_romsel = data & 0x0f;
}
@@ -224,23 +224,21 @@ void electron_plus2_device::expbus_w(offs_t offset, uint8_t data)
// IMPLEMENTATION
//**************************************************************************
-image_init_result electron_plus2_device::load_rom(device_image_interface &image, generic_slot_device *slot)
+std::pair<std::error_condition, std::string> electron_plus2_device::load_rom(device_image_interface &image, generic_slot_device *slot)
{
- uint32_t size = slot->common_get_size("rom");
+ uint32_t const size = slot->common_get_size("rom");
// socket accepts 8K and 16K ROM only
if (size != 0x2000 && size != 0x4000)
- {
- image.seterror(image_error::INVALIDIMAGE, "Invalid size: Only 8K/16K is supported");
- return image_init_result::FAIL;
- }
+ return std::make_pair(image_error::INVALIDLENGTH, "Invalid size: Only 8K/16K is supported");
slot->rom_alloc(0x4000, GENERIC_ROM8_WIDTH, ENDIANNESS_LITTLE);
slot->common_load_rom(slot->get_rom_base(), size, "rom");
// mirror 8K ROMs
- uint8_t *crt = slot->get_rom_base();
- if (size <= 0x2000) memcpy(crt + 0x2000, crt, 0x2000);
+ uint8_t *const crt = slot->get_rom_base();
+ if (size <= 0x2000)
+ memcpy(crt + 0x2000, crt, 0x2000);
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
diff --git a/src/devices/bus/electron/plus2.h b/src/devices/bus/electron/plus2.h
index 04e3a280377..3257bd08d5b 100644
--- a/src/devices/bus/electron/plus2.h
+++ b/src/devices/bus/electron/plus2.h
@@ -31,7 +31,7 @@ public:
electron_plus2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
// optional information overrides
@@ -41,7 +41,7 @@ protected:
virtual void expbus_w(offs_t offset, uint8_t data) override;
private:
- image_init_result load_rom(device_image_interface &image, generic_slot_device *slot);
+ std::pair<std::error_condition, std::string> load_rom(device_image_interface &image, generic_slot_device *slot);
DECLARE_DEVICE_IMAGE_LOAD_MEMBER(rom1_load) { return load_rom(image, m_rom[0]); }
DECLARE_DEVICE_IMAGE_LOAD_MEMBER(rom2_load) { return load_rom(image, m_rom[1]); }
DECLARE_DEVICE_IMAGE_LOAD_MEMBER(rom3_load) { return load_rom(image, m_rom[2]); }
diff --git a/src/devices/bus/electron/plus3.cpp b/src/devices/bus/electron/plus3.cpp
index 1589bc722b9..b378fc5d4cc 100644
--- a/src/devices/bus/electron/plus3.cpp
+++ b/src/devices/bus/electron/plus3.cpp
@@ -14,10 +14,11 @@
**********************************************************************/
-
#include "emu.h"
#include "plus3.h"
+#include "formats/acorn_dsk.h"
+
//**************************************************************************
// DEVICE DEFINITIONS
@@ -164,7 +165,7 @@ void electron_plus3_device::expbus_w(offs_t offset, uint8_t data)
{
m_fdc->write(offset & 0x03, data);
}
- else if (offset == 0xfe05)
+ else if ((offset == 0xfe05) && !(data & 0xf0))
{
m_romsel = data & 0x0f;
}
diff --git a/src/devices/bus/electron/plus3.h b/src/devices/bus/electron/plus3.h
index 2854557675b..88180c6e964 100644
--- a/src/devices/bus/electron/plus3.h
+++ b/src/devices/bus/electron/plus3.h
@@ -12,7 +12,6 @@
#include "exp.h"
#include "imagedev/floppy.h"
#include "machine/wd_fdc.h"
-#include "formats/acorn_dsk.h"
//**************************************************************************
// TYPE DEFINITIONS
diff --git a/src/devices/bus/electron/pwrjoy.cpp b/src/devices/bus/electron/pwrjoy.cpp
index 1ff7ab79566..5848edae648 100644
--- a/src/devices/bus/electron/pwrjoy.cpp
+++ b/src/devices/bus/electron/pwrjoy.cpp
@@ -104,7 +104,7 @@ uint8_t electron_pwrjoy_device::expbus_r(offs_t offset)
void electron_pwrjoy_device::expbus_w(offs_t offset, uint8_t data)
{
- if (offset == 0xfe05)
+ if ((offset == 0xfe05) && !(data & 0xf0))
{
m_romsel = data & 0x0f;
}
diff --git a/src/devices/bus/electron/rombox.cpp b/src/devices/bus/electron/rombox.cpp
index 47040271e7f..704a7eeb7e4 100644
--- a/src/devices/bus/electron/rombox.cpp
+++ b/src/devices/bus/electron/rombox.cpp
@@ -168,7 +168,7 @@ void electron_rombox_device::expbus_w(offs_t offset, uint8_t data)
{
m_exp->expbus_w(offset, data);
- if (offset == 0xfe05)
+ if ((offset == 0xfe05) && !(data & 0xf0))
{
m_romsel = data & 0x0f;
}
@@ -178,23 +178,21 @@ void electron_rombox_device::expbus_w(offs_t offset, uint8_t data)
// IMPLEMENTATION
//**************************************************************************
-image_init_result electron_rombox_device::load_rom(device_image_interface &image, generic_slot_device *slot)
+std::pair<std::error_condition, std::string> electron_rombox_device::load_rom(device_image_interface &image, generic_slot_device *slot)
{
- uint32_t size = slot->common_get_size("rom");
+ uint32_t const size = slot->common_get_size("rom");
// socket accepts 8K and 16K ROM only
if (size != 0x2000 && size != 0x4000)
- {
- image.seterror(image_error::INVALIDIMAGE, "Invalid size: Only 8K/16K is supported");
- return image_init_result::FAIL;
- }
+ return std::make_pair(image_error::INVALIDLENGTH, "Invalid size: Only 8K/16K is supported");
slot->rom_alloc(0x4000, GENERIC_ROM8_WIDTH, ENDIANNESS_LITTLE);
slot->common_load_rom(slot->get_rom_base(), size, "rom");
// mirror 8K ROMs
- uint8_t *crt = slot->get_rom_base();
- if (size <= 0x2000) memcpy(crt + 0x2000, crt, 0x2000);
+ uint8_t *const crt = slot->get_rom_base();
+ if (size <= 0x2000)
+ memcpy(crt + 0x2000, crt, 0x2000);
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
diff --git a/src/devices/bus/electron/rombox.h b/src/devices/bus/electron/rombox.h
index 65ed2fa80d8..244f551087e 100644
--- a/src/devices/bus/electron/rombox.h
+++ b/src/devices/bus/electron/rombox.h
@@ -27,7 +27,7 @@ public:
electron_rombox_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
virtual void device_reset() override;
@@ -39,7 +39,7 @@ protected:
virtual void expbus_w(offs_t offset, uint8_t data) override;
private:
- image_init_result load_rom(device_image_interface &image, generic_slot_device *slot);
+ std::pair<std::error_condition, std::string> load_rom(device_image_interface &image, generic_slot_device *slot);
DECLARE_DEVICE_IMAGE_LOAD_MEMBER(rom1_load) { return load_rom(image, m_rom[0]); }
DECLARE_DEVICE_IMAGE_LOAD_MEMBER(rom2_load) { return load_rom(image, m_rom[1]); }
DECLARE_DEVICE_IMAGE_LOAD_MEMBER(rom3_load) { return load_rom(image, m_rom[2]); }
diff --git a/src/devices/bus/electron/romboxp.cpp b/src/devices/bus/electron/romboxp.cpp
index 59d83bc4121..e489849ec73 100644
--- a/src/devices/bus/electron/romboxp.cpp
+++ b/src/devices/bus/electron/romboxp.cpp
@@ -308,7 +308,7 @@ void electron_romboxp_device::expbus_w(offs_t offset, uint8_t data)
break;
case 0xfe:
- if (offset == 0xfe05)
+ if ((offset == 0xfe05) && !(data & 0xf0))
{
m_romsel = data & 0x0f;
}
@@ -321,23 +321,21 @@ void electron_romboxp_device::expbus_w(offs_t offset, uint8_t data)
// IMPLEMENTATION
//**************************************************************************
-image_init_result electron_romboxp_device::load_rom(device_image_interface &image, generic_slot_device *slot)
+std::pair<std::error_condition, std::string> electron_romboxp_device::load_rom(device_image_interface &image, generic_slot_device *slot)
{
- uint32_t size = slot->common_get_size("rom");
+ uint32_t const size = slot->common_get_size("rom");
// socket accepts 8K and 16K ROM only
if (size != 0x2000 && size != 0x4000)
- {
- image.seterror(image_error::INVALIDIMAGE, "Invalid size: Only 8K/16K is supported");
- return image_init_result::FAIL;
- }
+ return std::make_pair(image_error::INVALIDLENGTH, "Invalid size: Only 8K/16K is supported");
slot->rom_alloc(0x4000, GENERIC_ROM8_WIDTH, ENDIANNESS_LITTLE);
slot->common_load_rom(slot->get_rom_base(), size, "rom");
// mirror 8K ROMs
- uint8_t *crt = slot->get_rom_base();
- if (size <= 0x2000) memcpy(crt + 0x2000, crt, 0x2000);
+ uint8_t *const crt = slot->get_rom_base();
+ if (size <= 0x2000)
+ memcpy(crt + 0x2000, crt, 0x2000);
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
diff --git a/src/devices/bus/electron/romboxp.h b/src/devices/bus/electron/romboxp.h
index 62b2124c913..b4022d13053 100644
--- a/src/devices/bus/electron/romboxp.h
+++ b/src/devices/bus/electron/romboxp.h
@@ -32,7 +32,7 @@ public:
electron_romboxp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
virtual void device_reset() override;
@@ -45,7 +45,7 @@ protected:
virtual void expbus_w(offs_t offset, uint8_t data) override;
private:
- image_init_result load_rom(device_image_interface &image, generic_slot_device *slot);
+ std::pair<std::error_condition, std::string> load_rom(device_image_interface &image, generic_slot_device *slot);
DECLARE_DEVICE_IMAGE_LOAD_MEMBER(rom1_load) { return load_rom(image, m_rom[0]); }
DECLARE_DEVICE_IMAGE_LOAD_MEMBER(rom2_load) { return load_rom(image, m_rom[1]); }
DECLARE_DEVICE_IMAGE_LOAD_MEMBER(rom3_load) { return load_rom(image, m_rom[2]); }
diff --git a/src/devices/bus/electron/sidewndr.cpp b/src/devices/bus/electron/sidewndr.cpp
index a2ab8011b09..d3d0d61955e 100644
--- a/src/devices/bus/electron/sidewndr.cpp
+++ b/src/devices/bus/electron/sidewndr.cpp
@@ -157,7 +157,7 @@ void electron_sidewndr_device::expbus_w(offs_t offset, uint8_t data)
{
m_exp->expbus_w(offset, data);
- if (offset == 0xfe05)
+ if ((offset == 0xfe05) && !(data & 0xf0))
{
m_romsel = data & 0x0f;
}
@@ -167,23 +167,21 @@ void electron_sidewndr_device::expbus_w(offs_t offset, uint8_t data)
// IMPLEMENTATION
//**************************************************************************
-image_init_result electron_sidewndr_device::load_rom(device_image_interface &image, generic_slot_device *slot)
+std::pair<std::error_condition, std::string> electron_sidewndr_device::load_rom(device_image_interface &image, generic_slot_device *slot)
{
- uint32_t size = slot->common_get_size("rom");
+ uint32_t const size = slot->common_get_size("rom");
// socket accepts 8K and 16K ROM only
if (size != 0x2000 && size != 0x4000)
- {
- image.seterror(image_error::INVALIDIMAGE, "Invalid size: Only 8K/16K is supported");
- return image_init_result::FAIL;
- }
+ return std::make_pair(image_error::INVALIDLENGTH, "Invalid size: Only 8K/16K is supported");
slot->rom_alloc(0x4000, GENERIC_ROM8_WIDTH, ENDIANNESS_LITTLE);
slot->common_load_rom(slot->get_rom_base(), size, "rom");
// mirror 8K ROMs
- uint8_t *crt = slot->get_rom_base();
- if (size <= 0x2000) memcpy(crt + 0x2000, crt, 0x2000);
+ uint8_t *const crt = slot->get_rom_base();
+ if (size <= 0x2000)
+ memcpy(crt + 0x2000, crt, 0x2000);
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
diff --git a/src/devices/bus/electron/sidewndr.h b/src/devices/bus/electron/sidewndr.h
index 2e1dea53087..84e30d2e2a9 100644
--- a/src/devices/bus/electron/sidewndr.h
+++ b/src/devices/bus/electron/sidewndr.h
@@ -27,7 +27,7 @@ public:
electron_sidewndr_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
// optional information overrides
@@ -39,7 +39,7 @@ protected:
virtual void expbus_w(offs_t offset, uint8_t data) override;
private:
- image_init_result load_rom(device_image_interface &image, generic_slot_device *slot);
+ std::pair<std::error_condition, std::string> load_rom(device_image_interface &image, generic_slot_device *slot);
DECLARE_DEVICE_IMAGE_LOAD_MEMBER(rom1_load) { return load_rom(image, m_rom[0]); }
DECLARE_DEVICE_IMAGE_LOAD_MEMBER(rom2_load) { return load_rom(image, m_rom[1]); }
DECLARE_DEVICE_IMAGE_LOAD_MEMBER(rom3_load) { return load_rom(image, m_rom[2]); }
diff --git a/src/devices/bus/electron/voxbox.cpp b/src/devices/bus/electron/voxbox.cpp
new file mode 100644
index 00000000000..15cdb09437f
--- /dev/null
+++ b/src/devices/bus/electron/voxbox.cpp
@@ -0,0 +1,100 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Millsgrade Voxbox Speech Synthesiser
+
+**********************************************************************/
+
+#include "emu.h"
+#include "voxbox.h"
+#include "speaker.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(ELECTRON_VOXBOX, electron_voxbox_device, "electron_voxbox", "Millsgrade Voxbox Speech Synthesiser")
+
+
+//-------------------------------------------------
+// ROM( voxbox )
+//-------------------------------------------------
+
+ROM_START( voxbox )
+ ROM_REGION(0x10000, "sp0256", 0)
+ ROM_LOAD( "sp0256a-al2.bin", 0x1000, 0x0800, CRC(b504ac15) SHA1(e60fcb5fa16ff3f3b69d36c7a6e955744d3feafc) )
+ROM_END
+
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const tiny_rom_entry *electron_voxbox_device::device_rom_region() const
+{
+ return ROM_NAME( voxbox );
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void electron_voxbox_device::device_add_mconfig(machine_config &config)
+{
+ SPEAKER(config, "mono").front_center();
+ SP0256(config, m_nsp, DERIVED_CLOCK(1, 4));
+ m_nsp->data_request_callback().set(FUNC(electron_voxbox_device::lrq_cb));
+ m_nsp->add_route(ALL_OUTPUTS, "mono", 1.0);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// electron_voxbox_device - constructor
+//-------------------------------------------------
+
+electron_voxbox_device::electron_voxbox_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, ELECTRON_VOXBOX, tag, owner, clock)
+ , device_electron_expansion_interface(mconfig, *this)
+ , m_nsp(*this, "sp0256")
+ , m_nmi(1)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void electron_voxbox_device::device_start()
+{
+ save_item(NAME(m_nmi));
+}
+
+
+//-------------------------------------------------
+// expbus_w - expansion data write
+//-------------------------------------------------
+
+void electron_voxbox_device::expbus_w(offs_t offset, uint8_t data)
+{
+ if ((offset & 0xff00) == 0xc000)
+ {
+ m_nsp->ald_w(offset & 0x3f);
+ }
+}
+
+void electron_voxbox_device::lrq_cb(int state)
+{
+ if (state != m_nmi)
+ {
+ m_nmi = state;
+ m_slot->nmi_w(state);
+ }
+}
diff --git a/src/devices/bus/electron/voxbox.h b/src/devices/bus/electron/voxbox.h
new file mode 100644
index 00000000000..5bab288b8ca
--- /dev/null
+++ b/src/devices/bus/electron/voxbox.h
@@ -0,0 +1,54 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Millsgrade Voxbox Speech Synthesiser
+
+**********************************************************************/
+
+#ifndef MAME_BUS_ELECTRON_VOXBOX_H
+#define MAME_BUS_ELECTRON_VOXBOX_H
+
+#pragma once
+
+
+#include "exp.h"
+#include "sound/sp0256.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> electron_voxbox_device
+
+class electron_voxbox_device : public device_t, public device_electron_expansion_interface
+{
+public:
+ // construction/destruction
+ electron_voxbox_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ // optional information overrides
+ virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override;
+
+ virtual void expbus_w(offs_t offset, uint8_t data) override;
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+
+private:
+ required_device<sp0256_device> m_nsp;
+
+ void lrq_cb(int state);
+
+ int m_nmi;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(ELECTRON_VOXBOX, electron_voxbox_device)
+
+
+#endif // MAME_BUS_ELECTRON_VOXBOX_H
diff --git a/src/devices/bus/ep64/exdos.cpp b/src/devices/bus/ep64/exdos.cpp
index 37f382955eb..1f7b5d8af97 100644
--- a/src/devices/bus/ep64/exdos.cpp
+++ b/src/devices/bus/ep64/exdos.cpp
@@ -48,6 +48,8 @@ This PCB plugs into the external expansion connector on the right side of the ma
#include "emu.h"
#include "exdos.h"
+#include "formats/ep64_dsk.h"
+
//**************************************************************************
@@ -109,10 +111,9 @@ void ep64_exdos_device::device_add_mconfig(machine_config &config)
{
WD1770(config, m_fdc, 8_MHz_XTAL);
- FLOPPY_CONNECTOR(config, m_floppy0, ep64_exdos_floppies, "35dd", ep64_exdos_device::floppy_formats);
- FLOPPY_CONNECTOR(config, m_floppy1, ep64_exdos_floppies, nullptr, ep64_exdos_device::floppy_formats);
- FLOPPY_CONNECTOR(config, m_floppy2, ep64_exdos_floppies, nullptr, ep64_exdos_device::floppy_formats);
- FLOPPY_CONNECTOR(config, m_floppy3, ep64_exdos_floppies, nullptr, ep64_exdos_device::floppy_formats);
+ for (auto &floppy : m_floppy)
+ FLOPPY_CONNECTOR(config, floppy, ep64_exdos_floppies, nullptr, ep64_exdos_device::floppy_formats);
+ m_floppy[0]->set_default_option("35dd");
}
@@ -128,11 +129,8 @@ ep64_exdos_device::ep64_exdos_device(const machine_config &mconfig, const char *
device_t(mconfig, EP64_EXDOS, tag, owner, clock),
device_ep64_expansion_bus_card_interface(mconfig, *this),
m_fdc(*this, WD1770_TAG),
- m_floppy0(*this, WD1770_TAG":0"),
- m_floppy1(*this, WD1770_TAG":1"),
- m_floppy2(*this, WD1770_TAG":2"),
- m_floppy3(*this, WD1770_TAG":3"),
- m_floppy(nullptr),
+ m_floppy(*this, WD1770_TAG":%u", 0U),
+ m_selected_floppy(nullptr),
m_rom(*this, "rom")
{
}
@@ -159,8 +157,8 @@ void ep64_exdos_device::device_reset()
{
m_fdc->reset();
- m_floppy = nullptr;
- m_fdc->set_floppy(m_floppy);
+ m_selected_floppy = nullptr;
+ m_fdc->set_floppy(m_selected_floppy);
m_fdc->dden_w(0);
}
@@ -191,7 +189,7 @@ uint8_t ep64_exdos_device::read()
data |= m_fdc->intrq_r() << 1;
data |= m_fdc->drq_r() << 7;
- data |= (m_floppy ? m_floppy->dskchg_r() : 1) << 6;
+ data |= (m_selected_floppy ? m_selected_floppy->dskchg_r() : 1) << 6;
return data;
}
@@ -218,19 +216,18 @@ void ep64_exdos_device::write(uint8_t data)
*/
- m_floppy = nullptr;
-
- if (BIT(data, 0)) m_floppy = m_floppy0->get_device();
- if (BIT(data, 1)) m_floppy = m_floppy1->get_device();
- if (BIT(data, 2)) m_floppy = m_floppy2->get_device();
- if (BIT(data, 3)) m_floppy = m_floppy3->get_device();
-
- m_fdc->set_floppy(m_floppy);
+ m_selected_floppy = nullptr;
- if (m_floppy)
+ for (int n = 0; n < 4; n++)
{
- m_floppy->ss_w(BIT(data, 4));
+ if (BIT(data, n))
+ m_selected_floppy = m_floppy[n]->get_device();
}
+ m_fdc->set_floppy(m_selected_floppy);
+
+ if (m_selected_floppy)
+ m_selected_floppy->ss_w(BIT(data, 4));
+
m_fdc->dden_w(BIT(data, 5));
}
diff --git a/src/devices/bus/ep64/exdos.h b/src/devices/bus/ep64/exdos.h
index cb5f9d47cc7..1cbf5a346a7 100644
--- a/src/devices/bus/ep64/exdos.h
+++ b/src/devices/bus/ep64/exdos.h
@@ -12,7 +12,6 @@
#pragma once
#include "exp.h"
-#include "formats/ep64_dsk.h"
#include "imagedev/floppy.h"
#include "machine/wd_fdc.h"
@@ -47,11 +46,8 @@ private:
static void floppy_formats(format_registration &fr);
required_device<wd1770_device> m_fdc;
- required_device<floppy_connector> m_floppy0;
- required_device<floppy_connector> m_floppy1;
- required_device<floppy_connector> m_floppy2;
- required_device<floppy_connector> m_floppy3;
- floppy_image_device *m_floppy;
+ required_device_array<floppy_connector, 4> m_floppy;
+ floppy_image_device *m_selected_floppy;
required_memory_region m_rom;
};
diff --git a/src/devices/bus/ep64/exp.cpp b/src/devices/bus/ep64/exp.cpp
index ebd423cfc7f..aff87fc77cc 100644
--- a/src/devices/bus/ep64/exp.cpp
+++ b/src/devices/bus/ep64/exp.cpp
@@ -63,11 +63,6 @@ ep64_expansion_bus_slot_device::ep64_expansion_bus_slot_device(const machine_con
void ep64_expansion_bus_slot_device::device_start()
{
m_card = get_card_device();
-
- // resolve callbacks
- m_write_irq.resolve_safe();
- m_write_nmi.resolve_safe();
- m_write_wait.resolve_safe();
}
diff --git a/src/devices/bus/ep64/exp.h b/src/devices/bus/ep64/exp.h
index 354d6f0691e..8a39bf315f8 100644
--- a/src/devices/bus/ep64/exp.h
+++ b/src/devices/bus/ep64/exp.h
@@ -81,9 +81,9 @@ public:
auto nmi_wr() { return m_write_nmi.bind(); }
auto wait_wr() { return m_write_wait.bind(); }
- DECLARE_WRITE_LINE_MEMBER( irq_w ) { m_write_irq(state); }
- DECLARE_WRITE_LINE_MEMBER( nmi_w ) { m_write_nmi(state); }
- DECLARE_WRITE_LINE_MEMBER( wait_w ) { m_write_wait(state); }
+ void irq_w(int state) { m_write_irq(state); }
+ void nmi_w(int state) { m_write_nmi(state); }
+ void wait_w(int state) { m_write_wait(state); }
address_space &program() { return *m_program_space; }
address_space &io() { return *m_io_space; }
diff --git a/src/devices/bus/epson_qx/cqgmem.cpp b/src/devices/bus/epson_qx/cqgmem.cpp
new file mode 100644
index 00000000000..5a912aa8fb5
--- /dev/null
+++ b/src/devices/bus/epson_qx/cqgmem.cpp
@@ -0,0 +1,135 @@
+// license:BSD-3-Clause
+// copyright-holders:Brian Johnson
+/*******************************************************************
+ *
+ * commodity quote graphics 1 megabyte memory expansion
+ *
+ *******************************************************************/
+
+#include "emu.h"
+#include "cqgmem.h"
+
+//**************************************************************************
+// CQGMEM DEVICE
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(EPSON_QX_OPTION_CQGMEM, bus::epson_qx::cqgmem_device, "epson_qx_option_cqgmem", "Commodity Quote Graphics 1MB Memory Expansion")
+
+namespace bus::epson_qx {
+
+static INPUT_PORTS_START( cqgmem )
+ PORT_START("IOBASE")
+ PORT_CONFNAME(0xf0, 0xf0, "IO Base Address Selection")
+ PORT_CONFSETTING(0x80, "&80")
+ PORT_CONFSETTING(0x90, "&90")
+ PORT_CONFSETTING(0xa0, "&A0")
+ PORT_CONFSETTING(0xb0, "&B0")
+ PORT_CONFSETTING(0xc0, "&C0")
+ PORT_CONFSETTING(0xd0, "&D0")
+ PORT_CONFSETTING(0xe0, "&E0")
+ PORT_CONFSETTING(0xf0, "&F0")
+INPUT_PORTS_END
+
+//-------------------------------------------------
+// cqgmem_device - constructor
+//-------------------------------------------------
+cqgmem_device::cqgmem_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, EPSON_QX_OPTION_CQGMEM, tag, owner, clock),
+ device_option_expansion_interface(mconfig, *this),
+ device_memory_interface(mconfig, *this),
+ m_ram(*this, "xmem", 0x100000, ENDIANNESS_LITTLE),
+ m_banks(*this, "bank%u", 0U),
+ m_iobase(*this, "IOBASE"),
+ m_space_config("xmem", ENDIANNESS_LITTLE, 8, 20, 0, address_map_constructor(FUNC(cqgmem_device::xmem_map), this)),
+ m_installed(false)
+{
+}
+
+//-------------------------------------------------
+// device_input_ports - device-specific ports
+//-------------------------------------------------
+ioport_constructor cqgmem_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( cqgmem );
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+void cqgmem_device::device_start()
+{
+ m_installed = false;
+
+ for (int i = 0; i < m_banks.size(); ++i) {
+ m_banks[i]->configure_entries(0, 128, m_ram, 0x2000);
+ }
+
+ save_item(NAME(m_installed));
+ save_item(NAME(m_banks_enabled));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+void cqgmem_device::device_reset()
+{
+ if (!m_installed) {
+ address_space &space = m_bus->iospace();
+ offs_t iobase = m_iobase->read() & 0xf0;
+ space.install_device(iobase, iobase+0x07, *this, &cqgmem_device::io_map);
+ m_installed = true;
+ }
+
+ m_banks_enabled = 0; // FIXME: should probably unmap any enabled banks before clearing this on reset
+
+ for (int i = 0; i < m_banks.size(); ++i) {
+ m_banks[i]->set_entry(0);
+ }
+}
+
+//-------------------------------------------------
+// memory_space_config - return a description of
+// any address spaces owned by this device
+//-------------------------------------------------
+device_memory_interface::space_config_vector cqgmem_device::memory_space_config() const
+{
+ return space_config_vector {
+ std::make_pair(0, &m_space_config)
+ };
+}
+
+void cqgmem_device::xmem_map(address_map &map)
+{
+ map(0x00000, 0xfffff).ram().share("xmem");
+}
+
+void cqgmem_device::write(offs_t offset, uint8_t data)
+{
+ memory_view::memory_view_entry &view = m_bus->memview();
+
+ uint8_t const bank = offset & 0x07;
+ uint8_t const page = data & 0x7f;
+ uint8_t const enable = (m_banks_enabled & ~(0x80 >> bank)) | ((data & 0x80) >> bank);
+ uint16_t const bank_addr = bank * 0x2000;
+
+ m_banks[bank]->set_entry(page);
+
+ if (data & 0x80) {
+ if (enable != m_banks_enabled) {
+ view.unmap_readwrite(bank_addr, bank_addr + 0x1fff);
+ view.install_readwrite_bank(bank_addr, bank_addr + 0x1fff, m_banks[bank]);
+ }
+ } else {
+ if (enable != m_banks_enabled) {
+ view.unmap_readwrite(bank_addr, bank_addr + 0x1fff);
+ }
+ }
+ m_banks_enabled = enable;
+}
+
+void cqgmem_device::io_map(address_map &map)
+{
+ map(0x00, 0x06).w(FUNC(cqgmem_device::write));
+}
+
+} // namespace bus::epson_qx
diff --git a/src/devices/bus/epson_qx/cqgmem.h b/src/devices/bus/epson_qx/cqgmem.h
new file mode 100644
index 00000000000..ac5026c7cee
--- /dev/null
+++ b/src/devices/bus/epson_qx/cqgmem.h
@@ -0,0 +1,59 @@
+// license:BSD-3-Clause
+// copyright-holders:Brian Johnson
+/*******************************************************************
+ *
+ * commodity quote graphics 1 megabyte memory expansion
+ *
+ *******************************************************************/
+
+#ifndef MAME_BUS_EPSON_QX_CQGMEM_H
+#define MAME_BUS_EPSON_QX_CQGMEM_H
+
+#pragma once
+
+#include "option.h"
+
+namespace bus::epson_qx {
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+/* commodity quote graphics 1M memory expansion */
+
+class cqgmem_device : public device_t, public device_option_expansion_interface, public device_memory_interface
+{
+public:
+ // construction/destruction
+ cqgmem_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device_t implementation
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual ioport_constructor device_input_ports() const override;
+ virtual space_config_vector memory_space_config() const override;
+
+private:
+ void write(offs_t offset, uint8_t data);
+
+ void io_map(address_map &map);
+ void xmem_map(address_map &map);
+
+ uint8_t m_banks_enabled;
+
+ memory_share_creator<uint8_t> m_ram;
+ memory_bank_array_creator<7> m_banks;
+ required_ioport m_iobase;
+ const address_space_config m_space_config;
+
+ bool m_installed;
+};
+
+} // namespace bus::epson_qx
+
+// device type definition
+DECLARE_DEVICE_TYPE_NS(EPSON_QX_OPTION_CQGMEM, bus::epson_qx, cqgmem_device)
+
+
+#endif // MAME_BUS_EPSON_QX_CQGMEM_H
diff --git a/src/devices/bus/epson_qx/cr1510.cpp b/src/devices/bus/epson_qx/cr1510.cpp
new file mode 100644
index 00000000000..3506597a86e
--- /dev/null
+++ b/src/devices/bus/epson_qx/cr1510.cpp
@@ -0,0 +1,62 @@
+// license:BSD-3-Clause
+// copyright-holders:Brian Johnson
+/*******************************************************************
+ *
+ * Comrex ComFiler CR-1510 Card
+ *
+ *******************************************************************/
+
+#include "emu.h"
+#include "cr1510.h"
+
+
+//**************************************************************************
+// EPSON CR-1510 DEVICE
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(EPSON_QX_OPTION_CR1510, bus::epson_qx::cr1510_device, "epson_qx_option_cr1510", "Comrex ComFiler CR-1510")
+
+namespace bus::epson_qx {
+
+//-------------------------------------------------
+// cr1510_device - constructor
+//-------------------------------------------------
+cr1510_device::cr1510_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, EPSON_QX_OPTION_CR1510, tag, owner, clock),
+ device_option_expansion_interface(mconfig, *this),
+ m_hdd(*this, "hdd")
+{
+}
+
+//-------------------------------------------------
+// device_add_mconfig - device-specific config
+//-------------------------------------------------
+void cr1510_device::device_add_mconfig(machine_config &config)
+{
+ WD1000(config, m_hdd, 0);
+
+ HARDDISK(config, "hdd:0", 0);
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+void cr1510_device::device_start()
+{
+ address_space &space = m_bus->iospace();
+ space.install_device(0x80, 0x87, *this, &cr1510_device::map);
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+void cr1510_device::device_reset()
+{
+}
+
+void cr1510_device::map(address_map &map)
+{
+ map(0x00, 0x07).rw(m_hdd, FUNC(wd1000_device::read), FUNC(wd1000_device::write));
+}
+
+} // namespace bus::epson_qx
diff --git a/src/devices/bus/epson_qx/cr1510.h b/src/devices/bus/epson_qx/cr1510.h
new file mode 100644
index 00000000000..6078d536880
--- /dev/null
+++ b/src/devices/bus/epson_qx/cr1510.h
@@ -0,0 +1,50 @@
+// license:BSD-3-Clause
+// copyright-holders:Brian Johnson
+/*******************************************************************
+ *
+ * ComFiler CR-1510 Card
+ *
+ *******************************************************************/
+
+#ifndef MAME_BUS_EPSON_QX_CR1510_H
+#define MAME_BUS_EPSON_QX_CR1510_H
+
+#pragma once
+
+#include "option.h"
+
+#include "machine/wd1000.h"
+
+namespace bus::epson_qx {
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+/* Epson CR-1510 Device */
+
+class cr1510_device : public device_t, public bus::epson_qx::device_option_expansion_interface
+{
+public:
+ // construction/destruction
+ cr1510_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+
+ void map(address_map &map);
+private:
+ required_device<wd1000_device> m_hdd;
+};
+
+} // namespace bus::epson_qx
+
+// device type definition
+DECLARE_DEVICE_TYPE_NS(EPSON_QX_OPTION_CR1510, bus::epson_qx, cr1510_device)
+
+#endif // MAME_BUS_EPSON_QX_CR1510_H
diff --git a/src/devices/bus/epson_qx/ide.cpp b/src/devices/bus/epson_qx/ide.cpp
new file mode 100644
index 00000000000..7d709f442dc
--- /dev/null
+++ b/src/devices/bus/epson_qx/ide.cpp
@@ -0,0 +1,110 @@
+// license:BSD-3-Clause
+// copyright-holders:Brian Johnson
+/*******************************************************************
+ *
+ * IDE Compact Flash Adapter
+ *
+ * This implements a Compact flash adapter expansion card for QX-10
+ * systems. The boot disk necessary to support this card is listed below.
+ *
+ * Disk Image: https://github.com/brijohn/qx10/raw/master/diskimages/qx10cf.imd
+ * Board Design: https://github.com/brijohn/qx10/tree/master/kicad/cf_adapter
+ *
+ *******************************************************************/
+
+#include "emu.h"
+#include "ide.h"
+
+
+//**************************************************************************
+// EPSON IDE DEVICE
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(EPSON_QX_OPTION_IDE, bus::epson_qx::ide_device, "epson_qx_option_ide", "Epson QX-10 Compact Flash Adapter")
+
+namespace bus::epson_qx {
+
+static INPUT_PORTS_START( ide )
+ PORT_START("IOBASE")
+ PORT_CONFNAME(0xf0, 0xd0, "IO Base Address Selection")
+ PORT_CONFSETTING(0x80, "&80")
+ PORT_CONFSETTING(0x90, "&90")
+ PORT_CONFSETTING(0xa0, "&A0")
+ PORT_CONFSETTING(0xb0, "&B0")
+ PORT_CONFSETTING(0xc0, "&C0")
+ PORT_CONFSETTING(0xd0, "&D0")
+ PORT_CONFSETTING(0xe0, "&E0")
+ PORT_CONFSETTING(0xf0, "&F0")
+INPUT_PORTS_END
+
+//-------------------------------------------------
+// ide_device - constructor
+//-------------------------------------------------
+ide_device::ide_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ ide_hdd_device_base(mconfig, EPSON_QX_OPTION_IDE, tag, owner, clock),
+ device_option_expansion_interface(mconfig, *this),
+ m_iobase(*this, "IOBASE"),
+ m_installed(false)
+{
+}
+
+//-------------------------------------------------
+// device_input_ports - device-specific ports
+//-------------------------------------------------
+ioport_constructor ide_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( ide );
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+void ide_device::device_start()
+{
+ ide_hdd_device_base::device_start();
+
+ m_installed = false;
+
+ save_item(NAME(m_installed));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+void ide_device::device_reset()
+{
+ ide_hdd_device_base::device_reset();
+
+ if (!m_installed) {
+ address_space &space = m_bus->iospace();
+ offs_t iobase = m_iobase->read() & 0xf0;
+ space.install_device(iobase, iobase+0x0f, *this, &ide_device::map);
+ m_installed = true;
+ }
+}
+
+uint8_t ide_device::read(offs_t offset)
+{
+ if (offset < 8) {
+ return command_r(offset);
+ } else if (offset == 14 || offset == 15) {
+ return control_r(offset & 7);
+ }
+ return 0xff;
+}
+
+void ide_device::write(offs_t offset, uint8_t data)
+{
+ if (offset < 8) {
+ command_w(offset, data);
+ } else if (offset == 14) {
+ control_w(offset & 7, data);
+ }
+}
+
+void ide_device::map(address_map &map)
+{
+ map(0x00, 0x0f).rw(FUNC(ide_device::read), FUNC(ide_device::write));
+}
+
+} // namespace bus::epson_qx
diff --git a/src/devices/bus/epson_qx/ide.h b/src/devices/bus/epson_qx/ide.h
new file mode 100644
index 00000000000..19c8f2a3a5d
--- /dev/null
+++ b/src/devices/bus/epson_qx/ide.h
@@ -0,0 +1,61 @@
+// license:BSD-3-Clause
+// copyright-holders:Brian Johnson
+/*******************************************************************
+ *
+ * IDE Compact Flash Adapter
+ *
+ *******************************************************************/
+
+#ifndef MAME_BUS_EPSON_QX_IDE_H
+#define MAME_BUS_EPSON_QX_IDE_H
+
+#pragma once
+
+#include "option.h"
+
+#include "machine/atastorage.h"
+
+namespace bus::epson_qx {
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+/* Epson IDE Device */
+
+// TODO: this thing should probably implement the ATA controller interface rather than having an IDE hard disk with no slot
+class ide_device : public ide_hdd_device_base, public device_option_expansion_interface
+{
+public:
+ // construction/destruction
+ ide_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device_t implementation
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual ioport_constructor device_input_ports() const override;
+
+ uint8_t read(offs_t offset);
+ void write(offs_t offset, uint8_t data);
+
+ void map(address_map &map);
+
+private:
+ // ata_hle_device_base implementation
+ virtual void set_irq_out(int state) override { }
+ virtual void set_dmarq_out(int state) override { }
+ virtual void set_dasp_out(int state) override { }
+ virtual void set_pdiag_out(int state) override { }
+
+ required_ioport m_iobase;
+
+ bool m_installed;
+};
+
+} // namespace bus::epson_qx
+
+// device type definition
+DECLARE_DEVICE_TYPE_NS(EPSON_QX_OPTION_IDE, bus::epson_qx, ide_device)
+
+#endif // MAME_BUS_EPSON_QX_IDE_H
diff --git a/src/devices/bus/epson_qx/keyboard/keyboard.cpp b/src/devices/bus/epson_qx/keyboard/keyboard.cpp
new file mode 100644
index 00000000000..6316313fc9d
--- /dev/null
+++ b/src/devices/bus/epson_qx/keyboard/keyboard.cpp
@@ -0,0 +1,205 @@
+// license:BSD-3-Clause
+// copyright-holders:Carl, Brian Johnson
+/***************************************************************************
+
+ Epson QX-10 Keyboard Interface
+
+***************************************************************************/
+
+#include "emu.h"
+#include "keyboard.h"
+
+#include "matrix.h"
+
+#include "cpu/mcs48/mcs48.h"
+
+#include "qx10ascii.lh"
+#include "qx10hasci.lh"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(EPSON_QX_KEYBOARD_PORT, bus::epson_qx::keyboard::keyboard_port_device, "epson_qx_kbd", "Epson QX-10 Keyboard Port")
+DEFINE_DEVICE_TYPE(QX10_KEYBOARD_HASCI, bus::epson_qx::keyboard::qx10_keyboard_hasci, "qx10_keyboard_hasci", "Epson QX-10 Keyboard (HASCI)")
+DEFINE_DEVICE_TYPE(QX10_KEYBOARD_ASCII, bus::epson_qx::keyboard::qx10_keyboard_ascii, "qx10_keyboard_ascii", "Epson QX-10 Keyboard (ASCII)")
+
+
+namespace bus::epson_qx::keyboard {
+
+//**************************************************************************
+// SLOT DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// keyboard_port_device - constructor
+//-------------------------------------------------
+
+keyboard_port_device::keyboard_port_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, EPSON_QX_KEYBOARD_PORT, tag, owner, clock)
+ , device_single_card_slot_interface<keyboard_device>(mconfig, *this)
+ , m_kbd(nullptr)
+ , m_txd_handler(*this)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void keyboard_port_device::device_start()
+{
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void keyboard_port_device::device_reset()
+{
+ // get connected keyboard
+ m_kbd = get_card_device();
+}
+
+void keyboard_port_device::txd_w(int state)
+{
+ m_txd_handler(state);
+}
+
+//-------------------------------------------------
+//
+// host to module interface
+//-------------------------------------------------
+
+void keyboard_port_device::rxd_w(int state)
+{
+ if (m_kbd)
+ m_kbd->rxd_w(state);
+}
+
+void keyboard_port_device::clk_w(int state)
+{
+ if (m_kbd)
+ m_kbd->clk_w(state);
+}
+
+ROM_START(qx10kbd)
+ ROM_REGION(0x0800, "mcu", 0)
+ ROM_LOAD("mbl8049h.5a", 0x0000, 0x0800, CRC(8615e159) SHA1(26b7f447acfe2c605dbe0fc98e6c777f0fa8a94d))
+ROM_END
+
+//**************************************************************************
+// KEYBOARD DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// keyboard_device - constructor
+//-------------------------------------------------
+
+keyboard_device::keyboard_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, type, tag, owner, clock)
+ , device_interface(*this, "epson_qx_kbd")
+ , m_rows(*this, "LINE%X", 0U)
+ , m_mcu(*this, "mcu")
+ , m_leds(*this, "led%u", 0U)
+{
+ m_host = dynamic_cast<keyboard_port_device *>(this->owner());
+}
+
+tiny_rom_entry const *keyboard_device::device_rom_region() const
+{
+ return ROM_NAME(qx10kbd);
+}
+
+void keyboard_device::device_add_mconfig(machine_config &config)
+{
+ auto &mcu(I8049(config, "mcu", 11_MHz_XTAL));
+ mcu.p1_out_cb().set(FUNC(keyboard_device::mcu_p1_w));
+ mcu.p2_out_cb().set(FUNC(keyboard_device::mcu_p2_w));
+ mcu.bus_in_cb().set([this]() { return m_rows[m_row]->read(); });
+ mcu.t1_in_cb().set([this]() { return m_rxd; });
+ mcu.t0_in_cb().set([this]() { return m_clk_state; });
+
+ config.set_default_layout(layout());
+}
+
+void keyboard_device::device_start()
+{
+ m_leds.resolve();
+
+ m_clk_state = 0;
+
+ save_item(NAME(m_rxd));
+ save_item(NAME(m_row));
+ save_item(NAME(m_clk_state));
+}
+
+void keyboard_device::mcu_p1_w(uint8_t data)
+{
+ m_row = data & 0xf;
+ m_host->txd_w(BIT(data, 7));
+}
+
+void keyboard_device::mcu_p2_w(uint8_t data)
+{
+ for (int i = 0; i < 8; ++i) {
+ m_leds[i] = BIT(data, i);
+ }
+}
+
+void keyboard_device::rxd_w(int state)
+{
+ m_rxd = state;
+}
+
+void keyboard_device::clk_w(int state)
+{
+ m_clk_state = !state;
+}
+
+//**************************************************************************
+// HASCI KEYBOARD DEVICE
+//**************************************************************************
+
+qx10_keyboard_hasci::qx10_keyboard_hasci(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock)
+ : keyboard_device(mconfig, QX10_KEYBOARD_HASCI, tag, owner, clock)
+{
+}
+
+ioport_constructor qx10_keyboard_hasci::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(qx10_keyboard_hasci);
+}
+
+const internal_layout &qx10_keyboard_hasci::layout() const
+{
+ return layout_qx10hasci;
+}
+
+//**************************************************************************
+// ASCII KEYBOARD DEVICE
+//**************************************************************************
+
+qx10_keyboard_ascii::qx10_keyboard_ascii(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock)
+ : keyboard_device(mconfig, QX10_KEYBOARD_ASCII, tag, owner, clock)
+{
+}
+
+ioport_constructor qx10_keyboard_ascii::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(qx10_keyboard_ascii);
+}
+
+const internal_layout &qx10_keyboard_ascii::layout() const
+{
+ return layout_qx10ascii;
+}
+
+void keyboard_devices(device_slot_interface &device)
+{
+ device.option_add("qx10_hasci", QX10_KEYBOARD_HASCI);
+ device.option_add("qx10_ascii", QX10_KEYBOARD_ASCII);
+}
+
+}
diff --git a/src/devices/bus/epson_qx/keyboard/keyboard.h b/src/devices/bus/epson_qx/keyboard/keyboard.h
new file mode 100644
index 00000000000..d45bf4c0a62
--- /dev/null
+++ b/src/devices/bus/epson_qx/keyboard/keyboard.h
@@ -0,0 +1,114 @@
+// license:BSD-3-Clause
+// copyright-holders:Carl, Brian Johnson
+/***************************************************************************
+
+ Epson QX-10 Keyboard Interface
+
+ - TXD (transmit line)
+ - RXD (receive line)
+ - CLK (clock input)
+
+***************************************************************************/
+
+#ifndef MAME_BUS_EPSON_QX_KEYBOARD_H
+#define MAME_BUS_EPSON_QX_KEYBOARD_H
+
+#pragma once
+
+namespace bus::epson_qx::keyboard {
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class keyboard_device;
+
+class keyboard_port_device : public device_t, public device_single_card_slot_interface<keyboard_device>
+{
+public:
+ // construction/destruction
+ template <typename T>
+ keyboard_port_device(const machine_config &mconfig, const char *tag, device_t *owner, T &&opts, const char *dflt)
+ : keyboard_port_device(mconfig, tag, owner, 0)
+ {
+ option_reset();
+ opts(*this);
+ set_default_option(dflt);
+ set_fixed(false);
+ }
+ keyboard_port_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0U);
+
+ void txd_w(int state);
+
+ // callbacks
+ auto txd_handler() { return m_txd_handler.bind(); }
+
+ // called from host
+ void rxd_w(int state);
+ void clk_w(int state);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+private:
+ keyboard_device *m_kbd;
+
+ devcb_write_line m_txd_handler;
+};
+
+class keyboard_device : public device_t, public device_interface
+{
+
+public:
+ void rxd_w(int state);
+ void clk_w(int state);
+
+protected:
+ keyboard_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_start() override;
+ void mcu_p1_w(uint8_t data);
+ void mcu_p2_w(uint8_t data);
+
+ virtual const internal_layout &layout() const = 0;
+
+ keyboard_port_device *m_host;
+
+ required_ioport_array<16> m_rows;
+ required_device<cpu_device> m_mcu;
+ output_finder<8> m_leds;
+ uint8_t m_rxd;
+ int m_row;
+ int m_clk_state;
+};
+
+class qx10_keyboard_hasci : public keyboard_device
+{
+public:
+ qx10_keyboard_hasci(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ virtual ioport_constructor device_input_ports() const override;
+ virtual const internal_layout &layout() const override;
+};
+
+class qx10_keyboard_ascii : public keyboard_device
+{
+public:
+ qx10_keyboard_ascii(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ virtual ioport_constructor device_input_ports() const override;
+ virtual const internal_layout &layout() const override;
+};
+
+
+void keyboard_devices(device_slot_interface &device);
+
+
+} // namespace bus::epson_qx_keyboard
+
+DECLARE_DEVICE_TYPE_NS(EPSON_QX_KEYBOARD_PORT, bus::epson_qx::keyboard, keyboard_port_device)
+DECLARE_DEVICE_TYPE_NS(QX10_KEYBOARD_HASCI, bus::epson_qx::keyboard, qx10_keyboard_hasci)
+DECLARE_DEVICE_TYPE_NS(QX10_KEYBOARD_ASCII, bus::epson_qx::keyboard, qx10_keyboard_ascii)
+
+#endif
diff --git a/src/devices/bus/epson_qx/keyboard/matrix.cpp b/src/devices/bus/epson_qx/keyboard/matrix.cpp
new file mode 100644
index 00000000000..d05d155ba13
--- /dev/null
+++ b/src/devices/bus/epson_qx/keyboard/matrix.cpp
@@ -0,0 +1,300 @@
+// license:BSD-3-Clause
+// copyright-holders:Brian Johnson
+/***************************************************************************
+
+ Epson QX-10 Keyboard Matrix
+
+***************************************************************************/
+
+#include "emu.h"
+#include "matrix.h"
+
+namespace bus::epson_qx::keyboard {
+
+INPUT_PORTS_START( qx10_keyboard_common )
+ PORT_START("LINE0")
+ PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_UNUSED)
+ PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_UNUSED)
+ PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("RSHIFT") PORT_CODE(KEYCODE_RSHIFT) PORT_CHAR(UCHAR_SHIFT_1)
+ PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("LSHIFT") PORT_CODE(KEYCODE_LSHIFT) PORT_CHAR(UCHAR_SHIFT_1)
+ PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_UNUSED)
+ PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("GRPH SHIFT") PORT_CODE(KEYCODE_RALT) PORT_CHAR(UCHAR_MAMEKEY(RALT))
+
+ PORT_START("LINE1")
+ PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_UNUSED)
+ PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Q") PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q') PORT_CHAR(0x11)
+
+ PORT_START("LINE2")
+ PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_UNUSED)
+ PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_UNUSED)
+ PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("SPACE") PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ')
+ PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("W") PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W') PORT_CHAR(0x17)
+ PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("3") PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#')
+
+ PORT_START("LINE3")
+ PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_UNUSED)
+ PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_UNUSED)
+ PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Z") PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z') PORT_CHAR(0x1a)
+ PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("A") PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A') PORT_CHAR(0x01)
+ PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("E") PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E') PORT_CHAR(0x05)
+ PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("4") PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$')
+
+ PORT_START("LINE4")
+ PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_UNUSED)
+ PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("X") PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X') PORT_CHAR(0x18)
+ PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("S") PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S') PORT_CHAR(0x13)
+ PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("R") PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R') PORT_CHAR(0x12)
+ PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("5") PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%')
+
+ PORT_START("LINE5")
+ PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("ENTER (PAD)") PORT_CODE(KEYCODE_ENTER_PAD) PORT_CHAR(UCHAR_MAMEKEY(ENTER_PAD))
+ PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("3 (PAD)") PORT_CODE(KEYCODE_3_PAD) PORT_CHAR(UCHAR_MAMEKEY(3_PAD))
+ PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("C") PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C') PORT_CHAR(0x03)
+ PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("D") PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D') PORT_CHAR(0x04)
+ PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("T") PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T') PORT_CHAR(0x14)
+
+ PORT_START("LINE6")
+ PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME(". (PAD)") PORT_CODE(KEYCODE_DEL_PAD) PORT_CHAR(UCHAR_MAMEKEY(DEL_PAD))
+ PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("2 (PAD)") PORT_CODE(KEYCODE_2_PAD) PORT_CHAR(UCHAR_MAMEKEY(2_PAD))
+ PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("V") PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V') PORT_CHAR(0x16)
+ PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F") PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F') PORT_CHAR(0x06)
+ PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Y") PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y') PORT_CHAR(0x19)
+ PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("1") PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!')
+
+ PORT_START("LINE7")
+ PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("0 (PAD)") PORT_CODE(KEYCODE_0_PAD) PORT_CHAR(UCHAR_MAMEKEY(0_PAD))
+ PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("1 (PAD)") PORT_CODE(KEYCODE_1_PAD) PORT_CHAR(UCHAR_MAMEKEY(1_PAD))
+ PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("B") PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B') PORT_CHAR(0x02)
+ PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("G") PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G') PORT_CHAR(0x07)
+ PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("U") PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U') PORT_CHAR(0x15)
+ PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("TAB") PORT_CODE(KEYCODE_TAB) PORT_CHAR('\t')
+
+ PORT_START("LINE8")
+ PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_UNUSED)
+ PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("N") PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N') PORT_CHAR(0x0e)
+ PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("H") PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H') PORT_CHAR(0x08)
+ PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("I") PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I') PORT_CHAR(0x09)
+
+ PORT_START("LINE9")
+ PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("6 (PAD)") PORT_CODE(KEYCODE_6_PAD) PORT_CHAR(UCHAR_MAMEKEY(6_PAD))
+ PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("9 (PAD)") PORT_CODE(KEYCODE_9_PAD) PORT_CHAR(UCHAR_MAMEKEY(9_PAD))
+ PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("M") PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M') PORT_CHAR(0x0d)
+ PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("J") PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J') PORT_CHAR(0x0a)
+ PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("O") PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O') PORT_CHAR(0x0f)
+ PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_UNUSED)
+
+ PORT_START("LINEA")
+ PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("5 (PAD)") PORT_CODE(KEYCODE_5_PAD) PORT_CHAR(UCHAR_MAMEKEY(5_PAD))
+ PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("8 (PAD)") PORT_CODE(KEYCODE_8_PAD) PORT_CHAR(UCHAR_MAMEKEY(8_PAD))
+ PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("K") PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K') PORT_CHAR(0x0b)
+ PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("P") PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P') PORT_CHAR(0x10)
+ PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_UNUSED)
+
+ PORT_START("LINEB")
+ PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("4 (PAD)") PORT_CODE(KEYCODE_4_PAD) PORT_CHAR(UCHAR_MAMEKEY(4_PAD))
+ PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("7 (PAD)") PORT_CODE(KEYCODE_7_PAD) PORT_CHAR(UCHAR_MAMEKEY(7_PAD))
+ PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("L") PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L') PORT_CHAR(0x0c)
+ PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_UNUSED)
+
+ PORT_START("LINEC")
+ PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_UNUSED)
+ PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("UP") PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP))
+ PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_UNUSED)
+
+ PORT_START("LINED")
+ PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_UNUSED)
+ PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("* (PAD)") PORT_CODE(KEYCODE_ASTERISK) PORT_CHAR(UCHAR_MAMEKEY(ASTERISK))
+ PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("LEFT") PORT_CODE(KEYCODE_LEFT) PORT_CHAR(UCHAR_MAMEKEY(LEFT))
+ PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("BACKSPACE") PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(0x08)
+ PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_UNUSED)
+
+ PORT_START("LINEE")
+ PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("/ (PAD)") PORT_CODE(KEYCODE_SLASH_PAD) PORT_CHAR(UCHAR_MAMEKEY(SLASH_PAD))
+ PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("RIGHT") PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT))
+ PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("RETURN") PORT_CODE(KEYCODE_ENTER) PORT_CHAR(0x0d)
+ PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("INSERT") PORT_CODE(KEYCODE_INSERT) PORT_CHAR(UCHAR_MAMEKEY(INSERT))
+ PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_UNUSED)
+
+ PORT_START("LINEF")
+ PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("DOWN") PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN))
+ PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("/ ?") PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?')
+ PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_UNUSED)
+INPUT_PORTS_END
+
+INPUT_PORTS_START( qx10_keyboard_hasci )
+ PORT_INCLUDE(qx10_keyboard_common)
+
+ PORT_MODIFY("LINE0")
+ PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("RCTRL") PORT_CODE(KEYCODE_RCONTROL) PORT_CHAR(UCHAR_SHIFT_2)
+ PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("LCTRL") PORT_CODE(KEYCODE_LCONTROL) PORT_CHAR(UCHAR_SHIFT_2)
+
+ PORT_MODIFY("LINE1")
+ PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("UNDO") PORT_CODE(KEYCODE_F3) PORT_CHAR(UCHAR_MAMEKEY(F3))
+ PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_UNUSED)
+ PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_UNUSED)
+ PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("TAB REL")
+ PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("2") PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('@') PORT_CHAR(0x00)
+ PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("COPY DISK") PORT_CODE(KEYCODE_F2) PORT_CHAR(UCHAR_MAMEKEY(F2))
+
+ PORT_MODIFY("LINE2")
+ PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_UNUSED)
+ PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("SHIFT LOCK") PORT_CODE(KEYCODE_CAPSLOCK) PORT_CHAR(UCHAR_MAMEKEY(CAPSLOCK))
+ PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("HELP") PORT_CODE(KEYCODE_F1) PORT_CHAR(UCHAR_MAMEKEY(F1))
+
+ PORT_MODIFY("LINE3")
+ PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("STORE") PORT_CODE(KEYCODE_F4) PORT_CHAR(UCHAR_MAMEKEY(F4))
+ PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("STOP") PORT_CODE(KEYCODE_ESC) PORT_CHAR(UCHAR_MAMEKEY(ESC))
+
+ PORT_MODIFY("LINE4")
+ PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("RETRIEVE") PORT_CODE(KEYCODE_F5) PORT_CHAR(UCHAR_MAMEKEY(F5))
+ PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_UNUSED)
+ PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("MAR SEL")
+
+ PORT_MODIFY("LINE5")
+ PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("PRINT") PORT_CODE(KEYCODE_F6) PORT_CHAR(UCHAR_MAMEKEY(F6))
+ PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("6") PORT_CODE(KEYCODE_6) PORT_CHAR('6')
+ PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("± ^") PORT_CODE(KEYCODE_TILDE) PORT_CHAR('^') PORT_CHAR(0xb1) PORT_CHAR(0x1e)
+
+ PORT_MODIFY("LINE6")
+ PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("INDEX") PORT_CODE(KEYCODE_F7) PORT_CHAR(UCHAR_MAMEKEY(F7))
+ PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("7") PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('&')
+
+ PORT_MODIFY("LINE7")
+ PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("MAIL") PORT_CODE(KEYCODE_F8) PORT_CHAR(UCHAR_MAMEKEY(F8))
+ PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("8") PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('*')
+
+ PORT_MODIFY("LINE8")
+ PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("= (PAD)") PORT_CODE(KEYCODE_EQUALS_PAD) PORT_CHAR(UCHAR_MAMEKEY(EQUALS_PAD))
+ PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("+ (PAD)") PORT_CODE(KEYCODE_PLUS_PAD) PORT_CHAR(UCHAR_MAMEKEY(PLUS_PAD))
+ PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("9") PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR('(')
+ PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("TAB SET")
+
+ PORT_MODIFY("LINE9")
+ PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("MENU") PORT_CODE(KEYCODE_F9) PORT_CHAR(UCHAR_MAMEKEY(F9))
+ PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("0") PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR(')')
+
+ PORT_MODIFY("LINEA")
+ PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("CALC") PORT_CODE(KEYCODE_F10) PORT_CHAR(UCHAR_MAMEKEY(F10))
+ PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME(",") PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',')
+ PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("-") PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHAR('_') PORT_CHAR(0x1f)
+
+ PORT_MODIFY("LINEB")
+ PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("SCHED") PORT_CODE(KEYCODE_F11) PORT_CHAR(UCHAR_MAMEKEY(F11))
+ PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME(".") PORT_CODE(KEYCODE_STOP) PORT_CHAR('.')
+ PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("1/2 1/4")
+ PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("=") PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=') PORT_CHAR('+')
+
+ PORT_MODIFY("LINEC")
+ PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("DRAW") PORT_CODE(KEYCODE_F12) PORT_CHAR(UCHAR_MAMEKEY(F12))
+ PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("- (PAD)") PORT_CODE(KEYCODE_MINUS_PAD) PORT_CHAR(UCHAR_MAMEKEY(MINUS_PAD))
+ PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME(";") PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR(':')
+ PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("< [") PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('<') PORT_CHAR('[')
+ PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("\\") PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('\\') PORT_CHAR(0xb0) PORT_CHAR(0x1c)
+
+ PORT_MODIFY("LINED")
+ PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_UNUSED)
+ PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("'") PORT_CODE(KEYCODE_QUOTE) PORT_CHAR('\'') PORT_CHAR('"')
+ PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("> ]") PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR('>') PORT_CHAR(']') PORT_CHAR(0x1d)
+
+ PORT_MODIFY("LINEE")
+ PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("BOLD") PORT_CODE(KEYCODE_F13) PORT_CHAR(UCHAR_MAMEKEY(F13))
+ PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("STYLE") PORT_CODE(KEYCODE_F16) PORT_CHAR(UCHAR_MAMEKEY(F16))
+ PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("DELETE") PORT_CODE(KEYCODE_DEL) PORT_CHAR(UCHAR_MAMEKEY(DEL))
+
+ PORT_MODIFY("LINEF")
+ PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("ITALIC") PORT_CODE(KEYCODE_F14) PORT_CHAR(UCHAR_MAMEKEY(F14))
+ PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("SIZE") PORT_CODE(KEYCODE_F15) PORT_CHAR(UCHAR_MAMEKEY(F15))
+ PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("DEC TAB") PORT_CODE(KEYCODE_NUMLOCK) PORT_CHAR(UCHAR_MAMEKEY(NUMLOCK))
+ PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("WORD")
+ PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("LINE")
+INPUT_PORTS_END
+
+INPUT_PORTS_START( qx10_keyboard_ascii )
+ PORT_INCLUDE(qx10_keyboard_common)
+
+ PORT_MODIFY("LINE0")
+ PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("CTRL") PORT_CODE(KEYCODE_LCONTROL) PORT_CHAR(UCHAR_SHIFT_2)
+ PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_UNUSED)
+
+ PORT_MODIFY("LINE1")
+ PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F4") PORT_CODE(KEYCODE_F4) PORT_CHAR(UCHAR_MAMEKEY(F4))
+ PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("LF")
+ PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("CAPS LOCK") PORT_CODE(KEYCODE_CAPSLOCK) PORT_CHAR(UCHAR_MAMEKEY(CAPSLOCK))
+ PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_UNUSED)
+ PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("2") PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('"')
+ PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F3") PORT_CODE(KEYCODE_F3) PORT_CHAR(UCHAR_MAMEKEY(F3))
+
+ PORT_MODIFY("LINE2")
+ PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F5") PORT_CODE(KEYCODE_F5) PORT_CHAR(UCHAR_MAMEKEY(F5))
+ PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_UNUSED)
+ PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F2") PORT_CODE(KEYCODE_F2) PORT_CHAR(UCHAR_MAMEKEY(F2))
+
+ PORT_MODIFY("LINE3")
+ PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F6") PORT_CODE(KEYCODE_F6) PORT_CHAR(UCHAR_MAMEKEY(F6))
+ PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F1") PORT_CODE(KEYCODE_F1) PORT_CHAR(UCHAR_MAMEKEY(F1))
+
+ PORT_MODIFY("LINE4")
+ PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F7") PORT_CODE(KEYCODE_F7) PORT_CHAR(UCHAR_MAMEKEY(F7))
+ PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("000")
+ PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_UNUSED)
+
+ PORT_MODIFY("LINE5")
+ PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F8") PORT_CODE(KEYCODE_F8) PORT_CHAR(UCHAR_MAMEKEY(F8))
+ PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("6") PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('&')
+ PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("ESC") PORT_CODE(KEYCODE_ESC) PORT_CHAR(UCHAR_MAMEKEY(ESC))
+
+ PORT_MODIFY("LINE6")
+ PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F9") PORT_CODE(KEYCODE_F9) PORT_CHAR(UCHAR_MAMEKEY(F9))
+ PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("7") PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('\'')
+
+ PORT_MODIFY("LINE7")
+ PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F10") PORT_CODE(KEYCODE_F10) PORT_CHAR(UCHAR_MAMEKEY(F10))
+ PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("8") PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('(')
+
+ PORT_MODIFY("LINE8")
+ PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("+ (PAD)") PORT_CODE(KEYCODE_PLUS_PAD) PORT_CHAR(UCHAR_MAMEKEY(PLUS_PAD))
+ PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("- (PAD)") PORT_CODE(KEYCODE_MINUS_PAD) PORT_CHAR(UCHAR_MAMEKEY(MINUS_PAD))
+ PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("9") PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR(')')
+ PORT_BIT(0x80,IP_ACTIVE_HIGH,IPT_UNUSED)
+
+ PORT_MODIFY("LINE9")
+ PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("BREAK") PORT_CODE(KEYCODE_F11) PORT_CHAR(UCHAR_MAMEKEY(F11))
+ PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("0") PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR('_') PORT_CHAR(0x1f)
+
+ PORT_MODIFY("LINEA")
+ PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("PAUSE") PORT_CODE(KEYCODE_PAUSE) PORT_CHAR(UCHAR_MAMEKEY(PAUSE))
+ PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME(",") PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<')
+ PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("-") PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHAR('=')
+
+ PORT_MODIFY("LINEB")
+ PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("HELP") PORT_CODE(KEYCODE_F12) PORT_CHAR(UCHAR_MAMEKEY(F12))
+ PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME(".") PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>')
+ PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("@") PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('@') PORT_CHAR('`') PORT_CHAR(0x00)
+ PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("^ ~") PORT_CODE(KEYCODE_TILDE) PORT_CHAR('^') PORT_CHAR('~') PORT_CHAR(0x1e)
+
+ PORT_MODIFY("LINEC")
+ PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("SCRN DUMP") PORT_CODE(KEYCODE_PRTSCR) PORT_CHAR(UCHAR_MAMEKEY(PRTSCR))
+ PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("= (PAD)") PORT_CODE(KEYCODE_EQUALS_PAD) PORT_CHAR(UCHAR_MAMEKEY(EQUALS_PAD))
+ PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME(";") PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR('+')
+ PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("[ {") PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR('[') PORT_CHAR('{')
+ PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("\\") PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('\\') PORT_CHAR('|') PORT_CHAR(0x1c)
+
+ PORT_MODIFY("LINED")
+ PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("SF4") PORT_CODE(KEYCODE_F16) PORT_CHAR(UCHAR_MAMEKEY(F16))
+ PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("'") PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(':') PORT_CHAR('*')
+ PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("] }") PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR(']') PORT_CHAR('}') PORT_CHAR(0x1d)
+
+ PORT_MODIFY("LINEE")
+ PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_UNUSED)
+ PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("SF3") PORT_CODE(KEYCODE_F15) PORT_CHAR(UCHAR_MAMEKEY(F15))
+ PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("HOME") PORT_CODE(KEYCODE_HOME) PORT_CHAR(UCHAR_MAMEKEY(HOME))
+
+ PORT_MODIFY("LINEF")
+ PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("SF1") PORT_CODE(KEYCODE_F13) PORT_CHAR(UCHAR_MAMEKEY(F13))
+ PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("SF2") PORT_CODE(KEYCODE_F14) PORT_CHAR(UCHAR_MAMEKEY(F14))
+ PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME(",") PORT_CODE(KEYCODE_COMMA_PAD) PORT_CHAR(UCHAR_MAMEKEY(COMMA_PAD))
+ PORT_BIT(0x20,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("DEL") PORT_CODE(KEYCODE_DEL) PORT_CHAR(UCHAR_MAMEKEY(DEL))
+ PORT_BIT(0x40,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("CLS")
+INPUT_PORTS_END
+
+} //namespace bus::epson_qx::keyboard
diff --git a/src/devices/bus/epson_qx/keyboard/matrix.h b/src/devices/bus/epson_qx/keyboard/matrix.h
new file mode 100644
index 00000000000..1cefa143b52
--- /dev/null
+++ b/src/devices/bus/epson_qx/keyboard/matrix.h
@@ -0,0 +1,22 @@
+// license:BSD-3-Clause
+// copyright-holders:Brian Johnson
+/***************************************************************************
+
+ Epson QX-10 Keyboard Matrix
+
+***************************************************************************/
+
+#ifndef MAME_BUS_EPSON_QX_KEYBOARD_MATRIX_H
+#define MAME_BUS_EPSON_QX_KEYBOARD_MATRIX_H
+
+#pragma once
+
+namespace bus::epson_qx::keyboard {
+
+INPUT_PORTS_EXTERN(qx10_keyboard_hasci);
+INPUT_PORTS_EXTERN(qx10_keyboard_ascii);
+
+} // namespace bus::epson_qx::keyboard
+
+#endif // MAME_BUS_EPSON_QX_KEYBOARD_MATRIX_H
+
diff --git a/src/devices/bus/epson_qx/option.cpp b/src/devices/bus/epson_qx/option.cpp
index 8caf042cc36..a22a20236b3 100644
--- a/src/devices/bus/epson_qx/option.cpp
+++ b/src/devices/bus/epson_qx/option.cpp
@@ -7,7 +7,12 @@
*******************************************************************/
#include "emu.h"
#include "option.h"
+
+#include "cqgmem.h"
+#include "cr1510.h"
+#include "ide.h"
#include "multifont.h"
+#include "sound_card.h"
DEFINE_DEVICE_TYPE(EPSON_QX_OPTION_BUS_SLOT, bus::epson_qx::option_slot_device, "epson_qx_option_slot", "QX-10 Option slot")
DEFINE_DEVICE_TYPE(EPSON_QX_OPTION_BUS, bus::epson_qx::option_bus_device, "epson_qx_option_bus", "QX-10 Option Bus")
@@ -25,9 +30,9 @@ option_slot_device::option_slot_device(const machine_config &mconfig, const char
device_single_card_slot_interface<device_option_expansion_interface>(mconfig, *this),
m_bus(*this, finder_base::DUMMY_TAG),
m_dmas_w_cb(*this),
- m_dmas_r_cb(*this),
+ m_dmas_r_cb(*this, 0xff),
m_dmaf_w_cb(*this),
- m_dmaf_r_cb(*this),
+ m_dmaf_r_cb(*this, 0),
m_eopf_cb(*this),
m_eops_cb(*this),
m_slot(-1)
@@ -39,14 +44,6 @@ option_slot_device::option_slot_device(const machine_config &mconfig, const char
//-------------------------------------------------
void option_slot_device::device_start()
{
- m_dmas_w_cb.resolve_safe();
- m_dmas_r_cb.resolve_safe(0xff);
- m_dmaf_w_cb.resolve();
- m_dmaf_r_cb.resolve();
-
- m_eopf_cb.resolve_safe();
- m_eops_cb.resolve_safe();
-
device_option_expansion_interface *const intf(get_card_device());
if (intf) {
intf->set_option_bus(*m_bus, m_slot);
@@ -55,18 +52,18 @@ void option_slot_device::device_start()
m_bus->add_slot(*this);
}
-WRITE_LINE_MEMBER(option_slot_device::eopf) { m_eopf_cb(state); }
-WRITE_LINE_MEMBER(option_slot_device::eops) { m_eops_cb(state); }
+void option_slot_device::eopf(int state) { m_eopf_cb(state); }
+void option_slot_device::eops(int state) { m_eops_cb(state); }
-WRITE_LINE_MEMBER(option_slot_device::inth1_w) { (*m_bus).set_inth1_line(state, m_slot); }
-WRITE_LINE_MEMBER(option_slot_device::inth2_w) { (*m_bus).set_inth2_line(state, m_slot); }
-WRITE_LINE_MEMBER(option_slot_device::intl_w) { (*m_bus).set_intl_line(state, m_slot); }
+void option_slot_device::inth1_w(int state) { (*m_bus).set_inth1_line(state, m_slot); }
+void option_slot_device::inth2_w(int state) { (*m_bus).set_inth2_line(state, m_slot); }
+void option_slot_device::intl_w(int state) { (*m_bus).set_intl_line(state, m_slot); }
-WRITE_LINE_MEMBER(option_slot_device::drqf_w) { (*m_bus).set_drqf_line(state, m_slot); }
-WRITE_LINE_MEMBER(option_slot_device::drqs_w) { (*m_bus).set_drqs_line(state, m_slot); }
+void option_slot_device::drqf_w(int state) { (*m_bus).set_drqf_line(state, m_slot); }
+void option_slot_device::drqs_w(int state) { (*m_bus).set_drqs_line(state, m_slot); }
-WRITE_LINE_MEMBER(option_slot_device::rdyf_w) { (*m_bus).set_rdyf_line(state, m_slot); }
-WRITE_LINE_MEMBER(option_slot_device::rdys_w) { (*m_bus).set_rdys_line(state, m_slot); }
+void option_slot_device::rdyf_w(int state) { (*m_bus).set_rdyf_line(state, m_slot); }
+void option_slot_device::rdys_w(int state) { (*m_bus).set_rdys_line(state, m_slot); }
//**************************************************************************
// EPSON OPTION BUS DEVICE
@@ -103,13 +100,6 @@ void option_bus_device::add_slot(option_slot_device &slot)
//-------------------------------------------------
void option_bus_device::device_start()
{
- m_inth1_cb.resolve_safe();
- m_inth2_cb.resolve_safe();
- m_intl_cb.resolve_all_safe();
- m_drqf_cb.resolve_safe();
- m_drqs_cb.resolve_all_safe();
- m_rdyf_cb.resolve_safe();
- m_rdys_cb.resolve_safe();
}
//-------------------------------------------------
@@ -127,9 +117,7 @@ void option_bus_device::device_reset()
void option_bus_device::dackf_w(uint8_t data)
{
for (int i = 0; i < m_slot_list.size(); ++i) {
- if (!m_slot_list[i]->m_dmaf_w_cb.isnull()) {
- m_slot_list[i]->m_dmaf_w_cb(data);
- }
+ m_slot_list[i]->m_dmaf_w_cb(data);
}
}
@@ -138,7 +126,7 @@ uint8_t option_bus_device::dackf_r()
uint8_t value = 0;
bool found = false;
for (int i = 0; i < m_slot_list.size(); ++i) {
- if (!m_slot_list[i]->m_dmaf_r_cb.isnull()) {
+ if (!m_slot_list[i]->m_dmaf_r_cb.isunset()) {
found = true;
value |= m_slot_list[i]->m_dmaf_r_cb();
}
@@ -206,7 +194,11 @@ void device_option_expansion_interface::interface_pre_start()
void option_bus_devices(device_slot_interface &device)
{
+ device.option_add("cqgmem", EPSON_QX_OPTION_CQGMEM);
+ device.option_add("cr1510", EPSON_QX_OPTION_CR1510);
+ device.option_add("ide", EPSON_QX_OPTION_IDE);
device.option_add("multifont", EPSON_QX_OPTION_MULTIFONT);
+ device.option_add("ym2149", EPSON_QX_OPTION_YM2149);
}
} // namespace bus::epson_qx
diff --git a/src/devices/bus/epson_qx/option.h b/src/devices/bus/epson_qx/option.h
index db74d46deb3..5950a88ce79 100644
--- a/src/devices/bus/epson_qx/option.h
+++ b/src/devices/bus/epson_qx/option.h
@@ -138,18 +138,18 @@ public:
}
option_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_WRITE_LINE_MEMBER(inth1_w);
- DECLARE_WRITE_LINE_MEMBER(inth2_w);
- DECLARE_WRITE_LINE_MEMBER(intl_w);
+ void inth1_w(int state);
+ void inth2_w(int state);
+ void intl_w(int state);
- DECLARE_WRITE_LINE_MEMBER(drqf_w);
- DECLARE_WRITE_LINE_MEMBER(drqs_w);
+ void drqf_w(int state);
+ void drqs_w(int state);
- DECLARE_WRITE_LINE_MEMBER(rdyf_w);
- DECLARE_WRITE_LINE_MEMBER(rdys_w);
+ void rdyf_w(int state);
+ void rdys_w(int state);
- DECLARE_WRITE_LINE_MEMBER(eopf);
- DECLARE_WRITE_LINE_MEMBER(eops);
+ void eopf(int state);
+ void eops(int state);
auto dmas_w_callback() { m_dmas_w_cb.bind(); }
auto dmas_r_callback() { m_dmas_r_cb.bind(); }
diff --git a/src/devices/bus/epson_qx/sound_card.cpp b/src/devices/bus/epson_qx/sound_card.cpp
new file mode 100644
index 00000000000..95e833fac03
--- /dev/null
+++ b/src/devices/bus/epson_qx/sound_card.cpp
@@ -0,0 +1,125 @@
+// license:BSD-3-Clause
+// copyright-holders:Brian Johnson
+/*******************************************************************
+ *
+ * YM2149 based sound card with header for an external MPU401
+ *
+ * Board Design: https://github.com/brijohn/qx10/tree/master/kicad/ym2149_sound_card
+ *
+ *******************************************************************/
+
+#include "emu.h"
+#include "sound_card.h"
+
+#include "speaker.h"
+
+//**************************************************************************
+// YM2149 SOUND CARD DEVICE
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(EPSON_QX_OPTION_YM2149, bus::epson_qx::ym2149_sound_card_device, "epson_qx_option_sound_card", "Epson QX-10 YM2149 Sound Card")
+
+namespace bus::epson_qx {
+
+static INPUT_PORTS_START( ym2149_sound_card )
+ PORT_START("IOBASE")
+ PORT_CONFNAME(0xf0, 0xc0, "IO Base Address Selection")
+ PORT_CONFSETTING(0x80, "&80")
+ PORT_CONFSETTING(0x90, "&90")
+ PORT_CONFSETTING(0xa0, "&A0")
+ PORT_CONFSETTING(0xb0, "&B0")
+ PORT_CONFSETTING(0xc0, "&C0")
+ PORT_CONFSETTING(0xd0, "&D0")
+ PORT_CONFSETTING(0xe0, "&E0")
+ PORT_CONFSETTING(0xf0, "&F0")
+ PORT_START("IRQ")
+ PORT_CONFNAME(0x03, 0x03, "MPU IRQ")
+ PORT_CONFSETTING(0x00, "NONE")
+ PORT_CONFSETTING(0x01, "INTH1")
+ PORT_CONFSETTING(0x02, "INTH2")
+ PORT_CONFSETTING(0x03, "INTL")
+INPUT_PORTS_END
+
+//-------------------------------------------------
+// ym2149_sound_card_device - constructor
+//-------------------------------------------------
+ym2149_sound_card_device::ym2149_sound_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, EPSON_QX_OPTION_YM2149, tag, owner, clock),
+ device_option_expansion_interface(mconfig, *this),
+ m_mpu401(*this, "mpu401"),
+ m_ssg(*this, "ym2149"),
+ m_iobase(*this, "IOBASE"),
+ m_irq(*this, "IRQ"),
+ m_installed(false)
+{
+}
+
+//-------------------------------------------------
+// device_input_ports - device-specific ports
+//-------------------------------------------------
+ioport_constructor ym2149_sound_card_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( ym2149_sound_card );
+}
+
+//-------------------------------------------------
+// device_add_mconfig - device-specific config
+//-------------------------------------------------
+void ym2149_sound_card_device::device_add_mconfig(machine_config &config)
+{
+ MPU401(config, m_mpu401).irq_cb().set(FUNC(ym2149_sound_card_device::mpu_irq_out)).invert();
+ SPEAKER(config, "speaker").front_center();
+ YM2149(config, m_ssg, clock()).add_route(ALL_OUTPUTS, "speaker", 1.0);
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+void ym2149_sound_card_device::device_start()
+{
+ m_installed = false;
+
+ save_item(NAME(m_installed));
+ save_item(NAME(m_irqline));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+void ym2149_sound_card_device::device_reset()
+{
+ m_ssg->set_pin26_low_w();
+
+ m_irqline = m_irq->read() & 0x03;
+
+ if (!m_installed) {
+ address_space &space = m_bus->iospace();
+ offs_t iobase = m_iobase->read() & 0xf0;
+ space.install_device(iobase, iobase+0x03, *this, &ym2149_sound_card_device::map);
+ m_installed = true;
+ }
+}
+
+void ym2149_sound_card_device::map(address_map &map)
+{
+ map(0x01, 0x01).r(m_ssg, FUNC(ym2149_device::data_r));
+ map(0x00, 0x01).w(m_ssg, FUNC(ym2149_device::address_data_w));
+ map(0x02, 0x03).rw(m_mpu401, FUNC(mpu401_device::mpu_r), FUNC(mpu401_device::mpu_w));
+}
+
+void ym2149_sound_card_device::mpu_irq_out(int state)
+{
+ switch(m_irqline) {
+ case 1:
+ get_slot()->inth1_w(state);
+ break;
+ case 2:
+ get_slot()->inth2_w(state);
+ break;
+ case 3:
+ get_slot()->intl_w(state);
+ break;
+ }
+}
+
+} // namespace bus::epson_qx
diff --git a/src/devices/bus/epson_qx/sound_card.h b/src/devices/bus/epson_qx/sound_card.h
new file mode 100644
index 00000000000..e85e1e0b7da
--- /dev/null
+++ b/src/devices/bus/epson_qx/sound_card.h
@@ -0,0 +1,61 @@
+// license:BSD-3-Clause
+// copyright-holders:Brian Johnson
+/*******************************************************************
+ *
+ * YM2149 based sound card with header for an external MPU401
+ *
+ *******************************************************************/
+
+#ifndef MAME_BUS_EPSON_QX_YM2149_H
+#define MAME_BUS_EPSON_QX_YM2149_H
+
+#pragma once
+
+#include "option.h"
+
+#include "machine/mpu401.h"
+#include "sound/ay8910.h"
+
+namespace bus::epson_qx {
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+/* YM2149 Sound Card Device */
+
+class ym2149_sound_card_device : public device_t, public device_option_expansion_interface
+{
+public:
+ // construction/destruction
+ ym2149_sound_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual ioport_constructor device_input_ports() const override;
+
+ void map(address_map &map);
+
+private:
+ uint8_t m_irqline;
+ void mpu_irq_out(int state);
+
+ required_device<mpu401_device> m_mpu401;
+ required_device<ym2149_device> m_ssg;
+ required_ioport m_iobase;
+ required_ioport m_irq;
+ bool m_installed;
+};
+
+} // namespace bus::epson_qx
+
+// device type definition
+DECLARE_DEVICE_TYPE_NS(EPSON_QX_OPTION_YM2149, bus::epson_qx, ym2149_sound_card_device)
+
+
+#endif // MAME_BUS_EPSON_QX_YM2149_H
diff --git a/src/devices/bus/epson_sio/epson_sio.cpp b/src/devices/bus/epson_sio/epson_sio.cpp
index adb75b853b7..926c1080ec2 100644
--- a/src/devices/bus/epson_sio/epson_sio.cpp
+++ b/src/devices/bus/epson_sio/epson_sio.cpp
@@ -79,19 +79,16 @@ epson_sio_device::~epson_sio_device()
void epson_sio_device::device_start()
{
m_cart = get_card_device();
-
- m_write_rx.resolve_safe();
- m_write_pin.resolve_safe();
}
-WRITE_LINE_MEMBER( epson_sio_device::tx_w )
+void epson_sio_device::tx_w(int state)
{
if (m_cart != nullptr)
m_cart->tx_w(state);
}
-WRITE_LINE_MEMBER( epson_sio_device::pout_w )
+void epson_sio_device::pout_w(int state)
{
if (m_cart != nullptr)
m_cart->pout_w(state);
diff --git a/src/devices/bus/epson_sio/epson_sio.h b/src/devices/bus/epson_sio/epson_sio.h
index 99bf6bce7a3..9cdf940b9ac 100644
--- a/src/devices/bus/epson_sio/epson_sio.h
+++ b/src/devices/bus/epson_sio/epson_sio.h
@@ -42,12 +42,12 @@ public:
auto pin_callback() { return m_write_pin.bind(); }
// called from owner
- DECLARE_WRITE_LINE_MEMBER( tx_w );
- DECLARE_WRITE_LINE_MEMBER( pout_w );
+ void tx_w(int state);
+ void pout_w(int state);
// called from subdevice
- DECLARE_WRITE_LINE_MEMBER( rx_w ) { m_write_rx(state); }
- DECLARE_WRITE_LINE_MEMBER( pin_w ) { m_write_pin(state); }
+ void rx_w(int state) { m_write_rx(state); }
+ void pin_w(int state) { m_write_pin(state); }
protected:
// device-level overrides
diff --git a/src/devices/bus/epson_sio/pf10.cpp b/src/devices/bus/epson_sio/pf10.cpp
index 067931da4e8..bf78ee1ad23 100644
--- a/src/devices/bus/epson_sio/pf10.cpp
+++ b/src/devices/bus/epson_sio/pf10.cpp
@@ -27,8 +27,6 @@ DEFINE_DEVICE_TYPE(EPSON_PF10, epson_pf10_device, "epson_pf10", "EPSON PF-10 Por
void epson_pf10_device::cpu_mem(address_map &map)
{
- map(0x0000, 0x001f).m("maincpu", FUNC(hd6303y_cpu_device::m6801_io));
- map(0x0040, 0x00ff).ram(); /* 192 bytes internal ram */
map(0x0800, 0x0fff).ram(); /* external 2k ram */
map(0x1000, 0x17ff).rw(FUNC(epson_pf10_device::fdc_r), FUNC(epson_pf10_device::fdc_w));
map(0x1800, 0x1fff).w(FUNC(epson_pf10_device::fdc_tc_w));
@@ -62,7 +60,7 @@ static void pf10_floppies(device_slot_interface &device)
void epson_pf10_device::device_add_mconfig(machine_config &config)
{
- HD6303Y(config, m_cpu, XTAL(4'915'200)); // HD63A03XF
+ HD6303X(config, m_cpu, XTAL(4'915'200)); // HD63A03XF
m_cpu->set_addrmap(AS_PROGRAM, &epson_pf10_device::cpu_mem);
m_cpu->in_p1_cb().set(FUNC(epson_pf10_device::port1_r));
m_cpu->out_p1_cb().set(FUNC(epson_pf10_device::port1_w));
@@ -128,7 +126,7 @@ void epson_pf10_device::device_reset()
TIMER_CALLBACK_MEMBER( epson_pf10_device::serial_clk_tick )
{
- m_cpu->m6801_clock_serial();
+ m_cpu->clock_serial();
}
@@ -185,7 +183,7 @@ void epson_pf10_device::fdc_tc_w(uint8_t data)
// rxc_w - rx input
//-------------------------------------------------
-WRITE_LINE_MEMBER( epson_pf10_device::rxc_w )
+void epson_pf10_device::rxc_w(int state)
{
m_rxc = state;
m_sio_input->rx_w(m_hd6303_tx & m_rxc);
@@ -195,7 +193,7 @@ WRITE_LINE_MEMBER( epson_pf10_device::rxc_w )
// pinc_w - pin input
//-------------------------------------------------
-WRITE_LINE_MEMBER( epson_pf10_device::pinc_w )
+void epson_pf10_device::pinc_w(int state)
{
m_pinc = state;
m_sio_input->pin_w(m_pinc);
@@ -205,7 +203,7 @@ WRITE_LINE_MEMBER( epson_pf10_device::pinc_w )
// hd6303_tx_w - rx output
//-------------------------------------------------
-WRITE_LINE_MEMBER( epson_pf10_device::hd6303_tx_w )
+void epson_pf10_device::hd6303_tx_w(int state)
{
m_hd6303_tx = state;
m_sio_input->rx_w(m_hd6303_tx & m_rxc);
diff --git a/src/devices/bus/epson_sio/pf10.h b/src/devices/bus/epson_sio/pf10.h
index ce5f2ee6f3d..d49200c0c90 100644
--- a/src/devices/bus/epson_sio/pf10.h
+++ b/src/devices/bus/epson_sio/pf10.h
@@ -45,11 +45,11 @@ protected:
private:
// serial output from main cpu
- DECLARE_WRITE_LINE_MEMBER( hd6303_tx_w );
+ void hd6303_tx_w(int state);
// from sio output
- DECLARE_WRITE_LINE_MEMBER( rxc_w );
- DECLARE_WRITE_LINE_MEMBER( pinc_w );
+ void rxc_w(int state);
+ void pinc_w(int state);
// floppy disk controller
uint8_t fdc_r(offs_t offset);
@@ -66,7 +66,7 @@ private:
void cpu_mem(address_map &map);
- required_device<hd6303y_cpu_device> m_cpu;
+ required_device<hd6303x_cpu_device> m_cpu;
required_device<upd765a_device> m_fdc;
required_device<epson_sio_device> m_sio_output;
required_device<floppy_connector> m_floppy;
diff --git a/src/devices/bus/epson_sio/tf20.cpp b/src/devices/bus/epson_sio/tf20.cpp
index a2f9c2e9320..596b70021b9 100644
--- a/src/devices/bus/epson_sio/tf20.cpp
+++ b/src/devices/bus/epson_sio/tf20.cpp
@@ -262,7 +262,7 @@ void epson_tf20_device::fdc_control_w(uint8_t data)
// rxc_w - rx input
//-------------------------------------------------
-WRITE_LINE_MEMBER( epson_tf20_device::rxc_w )
+void epson_tf20_device::rxc_w(int state)
{
m_rxc = state;
m_sio_input->rx_w(m_txda && m_rxc);
@@ -272,7 +272,7 @@ WRITE_LINE_MEMBER( epson_tf20_device::rxc_w )
// pinc_w - pin input
//-------------------------------------------------
-WRITE_LINE_MEMBER( epson_tf20_device::pinc_w )
+void epson_tf20_device::pinc_w(int state)
{
m_pinc = state;
m_sio_input->pin_w(!m_dtra || m_pinc);
@@ -282,7 +282,7 @@ WRITE_LINE_MEMBER( epson_tf20_device::pinc_w )
// txda_w - rx output
//-------------------------------------------------
-WRITE_LINE_MEMBER( epson_tf20_device::txda_w )
+void epson_tf20_device::txda_w(int state)
{
m_txda = state;
m_sio_input->rx_w(m_txda && m_rxc);
@@ -292,7 +292,7 @@ WRITE_LINE_MEMBER( epson_tf20_device::txda_w )
// dtra_w - pin output
//-------------------------------------------------
-WRITE_LINE_MEMBER( epson_tf20_device::dtra_w )
+void epson_tf20_device::dtra_w(int state)
{
m_dtra = state;
m_sio_input->pin_w(!m_dtra || m_pinc);
diff --git a/src/devices/bus/epson_sio/tf20.h b/src/devices/bus/epson_sio/tf20.h
index 906ae0a4b9c..30dcc914f15 100644
--- a/src/devices/bus/epson_sio/tf20.h
+++ b/src/devices/bus/epson_sio/tf20.h
@@ -48,12 +48,12 @@ protected:
private:
IRQ_CALLBACK_MEMBER( irq_callback );
- DECLARE_WRITE_LINE_MEMBER( txda_w );
- DECLARE_WRITE_LINE_MEMBER( dtra_w );
+ void txda_w(int state);
+ void dtra_w(int state);
// from sio output
- DECLARE_WRITE_LINE_MEMBER( rxc_w );
- DECLARE_WRITE_LINE_MEMBER( pinc_w );
+ void rxc_w(int state);
+ void pinc_w(int state);
uint8_t rom_disable_r();
uint8_t upd765_tc_r();
diff --git a/src/devices/bus/fmt_scsi/fmt_scsi.cpp b/src/devices/bus/fmt_scsi/fmt_scsi.cpp
index b5d62fb3577..ccdab14f57e 100644
--- a/src/devices/bus/fmt_scsi/fmt_scsi.cpp
+++ b/src/devices/bus/fmt_scsi/fmt_scsi.cpp
@@ -60,8 +60,6 @@ void fmt_scsi_slot_device::device_resolve_objects()
void fmt_scsi_slot_device::device_start()
{
- m_irq_handler.resolve_safe();
- m_drq_handler.resolve_safe();
}
diff --git a/src/devices/bus/gamate/gamate_protection.cpp b/src/devices/bus/gamate/gamate_protection.cpp
index 4218a237a3f..263c4b8113d 100644
--- a/src/devices/bus/gamate/gamate_protection.cpp
+++ b/src/devices/bus/gamate/gamate_protection.cpp
@@ -46,7 +46,7 @@ bool gamate_protection_device::is_protection_passed()
return m_is_protection_passed;
}
-WRITE_LINE_MEMBER(gamate_protection_device::prot_w)
+void gamate_protection_device::prot_w(int state)
{
LOG("write to protection %01x\n", state);
@@ -88,7 +88,7 @@ WRITE_LINE_MEMBER(gamate_protection_device::prot_w)
}
}
-READ_LINE_MEMBER(gamate_protection_device::prot_r)
+int gamate_protection_device::prot_r()
{
if (m_passed_write)
diff --git a/src/devices/bus/gamate/gamate_protection.h b/src/devices/bus/gamate/gamate_protection.h
index 5ee37ff3e20..dd12764dd2c 100644
--- a/src/devices/bus/gamate/gamate_protection.h
+++ b/src/devices/bus/gamate/gamate_protection.h
@@ -16,8 +16,8 @@ public:
bool is_protection_passed();
- DECLARE_WRITE_LINE_MEMBER( prot_w );
- DECLARE_READ_LINE_MEMBER( prot_r );
+ void prot_w(int state);
+ int prot_r();
protected:
virtual void device_start() override;
diff --git a/src/devices/bus/gamate/slot.cpp b/src/devices/bus/gamate/slot.cpp
index cf75898e768..b627aee6d3e 100644
--- a/src/devices/bus/gamate/slot.cpp
+++ b/src/devices/bus/gamate/slot.cpp
@@ -38,11 +38,11 @@ device_gamate_cart_interface::~device_gamate_cart_interface()
// rom_alloc - alloc the space for the cart
//-------------------------------------------------
-void device_gamate_cart_interface::rom_alloc(uint32_t size, const char *tag)
+void device_gamate_cart_interface::rom_alloc(uint32_t size)
{
if (m_rom == nullptr)
{
- m_rom = device().machine().memory().region_alloc(std::string(tag).append(GAMATESLOT_ROM_REGION_TAG).c_str(), size, 1, ENDIANNESS_BIG)->base();
+ m_rom = device().machine().memory().region_alloc(device().subtag("^cart:rom"), size, 1, ENDIANNESS_BIG)->base();
m_rom_size = size;
}
}
@@ -125,22 +125,18 @@ static const char *gamate_get_slot(int type)
call load
-------------------------------------------------*/
-image_init_result gamate_cart_slot_device::call_load()
+std::pair<std::error_condition, std::string> gamate_cart_slot_device::call_load()
{
if (m_cart)
{
- uint8_t *ROM;
- uint32_t len = !loaded_through_softlist() ? length() : get_software_region_length("rom");
+ uint32_t const len = !loaded_through_softlist() ? length() : get_software_region_length("rom");
- if (len > 0x80000)
- {
- seterror(image_error::INVALIDIMAGE, "Unsupported cartridge size");
- return image_init_result::FAIL;
- }
+ if (len > 0x8'0000)
+ return std::make_pair(image_error::INVALIDLENGTH, "Unsupported cartridge size (must be no more than 512K)");
- m_cart->rom_alloc(len, tag());
+ m_cart->rom_alloc(len);
- ROM = m_cart->get_rom_base();
+ uint8_t *const ROM = m_cart->get_rom_base();
if (!loaded_through_softlist())
fread(ROM, len);
@@ -159,11 +155,9 @@ image_init_result gamate_cart_slot_device::call_load()
if (pcb_name)
m_type = gamate_get_pcb_id(pcb_name);
}
-
- return image_init_result::PASS;
}
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
@@ -207,8 +201,7 @@ std::string gamate_cart_slot_device::get_default_card_software(get_default_card_
hook.image_file()->length(len); // FIXME: check error return, guard against excessively large files
std::vector<uint8_t> rom(len);
- size_t actual;
- hook.image_file()->read(&rom[0], len, actual); // FIXME: check error return or read returning short
+ /*auto const [err, actual] =*/ read(*hook.image_file(), &rom[0], len); // FIXME: check error return or read returning short
int const type = get_cart_type(&rom[0], len);
char const *const slot_string = gamate_get_slot(type);
diff --git a/src/devices/bus/gamate/slot.h b/src/devices/bus/gamate/slot.h
index 333fd404e4a..54679ae0c23 100644
--- a/src/devices/bus/gamate/slot.h
+++ b/src/devices/bus/gamate/slot.h
@@ -31,7 +31,7 @@ public:
virtual uint8_t read_cart(offs_t offset) { return 0xff; }
virtual void write_cart(offs_t offset, uint8_t data) { }
- void rom_alloc(uint32_t size, const char *tag);
+ void rom_alloc(uint32_t size);
uint8_t* get_rom_base() { return m_rom; }
uint32_t get_rom_size() { return m_rom_size; }
@@ -64,15 +64,15 @@ public:
gamate_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
virtual ~gamate_cart_slot_device();
- // image-level overrides
- virtual image_init_result call_load() override;
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
virtual void call_unload() override { }
virtual bool is_reset_on_load() const noexcept override { return true; }
virtual const char *image_interface() const noexcept override { return "gamate_cart"; }
virtual const char *file_extensions() const noexcept override { return "bin"; }
- // slot interface overrides
+ // device_slot_interface implementation
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
int get_type() { return m_type; }
@@ -83,11 +83,11 @@ public:
void write_cart(offs_t offset, uint8_t data);
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
int m_type;
- device_gamate_cart_interface* m_cart;
+ device_gamate_cart_interface *m_cart;
};
// device type definition
@@ -97,8 +97,6 @@ DECLARE_DEVICE_TYPE(GAMATE_CART_SLOT, gamate_cart_slot_device)
DEVICE CONFIGURATION MACROS
***************************************************************************/
-#define GAMATESLOT_ROM_REGION_TAG ":cart:rom"
-
void gamate_cart(device_slot_interface &device);
#endif // MAME_BUS_GAMATE_SLOT_H
diff --git a/src/devices/bus/gameboy/camera.cpp b/src/devices/bus/gameboy/camera.cpp
new file mode 100644
index 00000000000..8325f9df943
--- /dev/null
+++ b/src/devices/bus/gameboy/camera.cpp
@@ -0,0 +1,620 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/***************************************************************************
+
+ Nintendo Game Boy Camera
+
+ Major components:
+ * U1 MAC-GBD Game Boy bus interface
+ * U2 program ROM
+ * U3 128K*8 static RAM
+ * U4 backup power controller
+ * CR2025 coin cell
+ * Mitsubishi M64282FP 128*123 pixel CMOS image sensor and processor
+
+ Static RAM is not accessible while image capture is in progress. Reads
+ will return 0x00 and writes will be ignored. Camera registers only respond
+ to A6-A0. Reading non-existent or write-only registers returns 0x00.
+
+ Note that unlike most MBC chips, only writing to cartridge RAM can be
+ disabled. It is still possible to read cartridge RAM while writing is
+ disabled (provided image capture is not in progress). Another unusual
+ feature is that ROM page 0 is selectable (it isn't automatically remapped
+ to page 1), but page 1 is initially selected.
+
+ 0x0000-3FFF R - Fixed ROM bank, always first page of ROM.
+ 0x4000-7FFF R - Selectable ROM bank, page 0-63 of ROM.
+ 0xA000-A1FF RW - Selectable static RAM page of camera registers.
+
+ 0x0000-1FFF W - Enable (0x0A) or disable (not 0x0A) writing to
+ cartridge RAM.
+ 0x2000-3FFF W - Select ROM page mapped at 0x4000.
+ 0x4000-5FFF W - ---X---- Select RAM (clear) or camera registers (set).
+ ----XXXX Select RAM page.
+
+ 0xA000 RW - -----XX- Select one-dimensional filter values (P, M).
+ R - -------X Capture in progress.
+ W - -------X Start capture.
+ 0xA001 W - X------- Exclusive edge enhancement mode (N).
+ W - -XX----- Vertical-horizontal edge operation mode (VH).
+ W - ---XXXXX Analog output gain (G).
+ 0xA002 W - XXXXXXXX Exposure most significant byte (C1).
+ 0xA003 W - XXXXXXXX Exposure least significant byte (C0).
+ 0xA004 W - X------- Edge enhancement (0) or extraction (1) (E3).
+ W - -XXX---- Edge enhancement ratio (E2-E0).
+ W - ----X--- Select inverted/non-inverted output (I).
+ W - -----XXX Output node bias voltage (V).
+ 0xA005 W - XX------ Zero point calibration (Z).
+ W - --XXXXXX Output reference voltage (O).
+ 0xA006-A035 W 4*4 matrix of three threshold values each.
+
+ TODO:
+ * Emulate more M64282FP processing modes.
+ * It's supposedly possible to cancel a capture before it completes.
+ * What do filters do at the edges of the image area?
+ * Adjust levels when it sweeps the parameters on start.
+
+ ***************************************************************************/
+
+#include "emu.h"
+#include "camera.h"
+
+#include "cartbase.ipp"
+
+#include "imagedev/picture.h"
+
+#include "bitmap.h"
+
+#include <algorithm>
+#include <iterator>
+#include <string>
+
+//#define VERBOSE 1
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+
+namespace bus::gameboy {
+
+namespace {
+
+class camera_device : public mbc_ram_device_base<mbc_device_base>
+{
+public:
+ static constexpr feature_type imperfect_features() { return feature::CAMERA; }
+
+ camera_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+ virtual std::error_condition load(std::string &message) override ATTR_COLD;
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+private:
+ static inline constexpr unsigned SENSOR_WIDTH{ 128U };
+ static inline constexpr unsigned SENSOR_HEIGHT{ 123U };
+ static inline constexpr unsigned OUTPUT_WIDTH{ 128U };
+ static inline constexpr unsigned OUTPUT_HEIGHT{ 112U };
+ static inline constexpr int EDGE_RATIO[8]{ 2U, 3U, 4U, 5U, 8U, 12U, 16U, 20U };
+ static inline constexpr u8 P_MASK[4]{ 0x00U, 0x01U, 0x01U, 0x01U };
+ static inline constexpr u8 M_MASK[4]{ 0x01U, 0x00U, 0x02U, 0x02U };
+
+ void enable_ram(u8 data);
+ void bank_switch_rom(u8 data);
+ void bank_switch_ram(u8 data);
+ u8 read_ram(offs_t offset);
+ void write_ram(offs_t offset, u8 data);
+ u8 read_camera(offs_t offset);
+ void write_camera(offs_t offset, u8 data);
+
+ TIMER_CALLBACK_MEMBER(capture_complete);
+
+ void start_capture()
+ {
+ // the controller shifts out the parameters and starts the capture
+ // we're over-simplifying the timings here
+ LOG("%s: Start capture\n", machine().describe_context());
+
+ // calculate total capture time
+ u32 cycles = 31'166; // time to start capture, read out image and apply thresholds
+ cycles += 5 * 256; // 256 cycles to set a register, registers 1, 2, 3, 7 and 0 always set
+ if (!m_n[0])
+ cycles += 2 * 256; // registers 4 and 5 also set if N is not clear
+ cycles += 16 * m_c[0]; // exposure units are 16 microseconds
+
+ // parameters are sent to the sensor serially - pretend it's instant
+ m_n[1] = m_n[0];
+ m_vh[1] = m_vh[0];
+ m_e[1] = m_e[0];
+ m_z[1] = m_z[0];
+ m_i[1] = m_i[0];
+ m_c[1] = m_c[0];
+ m_o[1] = m_o[0];
+ m_v[1] = m_v[0];
+ m_g[1] = m_g[0];
+ if (!m_n[0])
+ {
+ m_p = P_MASK[m_sel_pm];
+ m_m = M_MASK[m_sel_pm];
+ }
+
+ // set timer for when capture will finish
+ m_busy = 1U;
+ m_timer_capture->adjust(attotime::from_ticks(4 * cycles, 4.194304_MHz_XTAL)); // FIXME: actually from incoming phi clock
+ }
+
+ void acquire(s16 (&buffer)[SENSOR_HEIGHT][SENSOR_WIDTH])
+ {
+ bitmap_argb32 const &source(m_picture->get_bitmap());
+ if (source.valid())
+ {
+ LOG("Point-sampling %d*%d source bitmap\n", source.width(), source.height());
+ double const xstep(source.width() / double(SENSOR_WIDTH));
+ double const ystep(source.height() / double(SENSOR_HEIGHT));
+ for (unsigned y = 0U; SENSOR_HEIGHT > y; ++y)
+ {
+ u32 const *const srcline(&source.pix(s32((y * ystep) + 0.5)));
+ s16 *const dstline(buffer[y]);
+ for (unsigned x = 0U; SENSOR_WIDTH > x; ++x)
+ {
+ // extract luminance - output ranges from 0 to 31875
+ rgb_t const colour(srcline[s32((x * xstep) + 0.5)]);
+ u32 const mono((u32(299) * colour.r() + u32(587) * colour.g() + u32(114) * colour.b()) >> 3);
+
+ // starts with C = 0x1000 (65.536 ms) before auto exposure adjustment
+ // convert to 10-bit signed for processing
+ s16 const exposure(u16(std::min<u32>((mono * m_c[1]) / (u32(125) << 10), 0x03ff)));
+ dstline[x] = m_i[1] ? (511 - exposure) : (exposure - 512);
+ }
+ }
+ }
+ else
+ {
+ LOG("No source bitmap - filling sensor bitmap with pattern\n");
+ for (unsigned y = 0U; SENSOR_HEIGHT > y; ++y)
+ {
+ s16 *const dstline(buffer[y]);
+ for (unsigned x = 0U; SENSOR_WIDTH > x; ++x)
+ {
+ // values chosen to show dithering effects with default brightness/contrast
+ s16 mono = 0;
+ switch (((x >> 3) + (y >> 3)) & 0x03)
+ {
+ case 1: mono = 0x0240; break;
+ case 2: mono = 0x0340; break;
+ case 3: mono = 0x03ff; break;
+ }
+ dstline[x] = m_i[1] ? (511 - mono) : (mono - 512);
+ }
+ }
+ }
+ }
+
+ void apply_thresholds(s16 const (&buffer)[SENSOR_HEIGHT][SENSOR_WIDTH])
+ {
+ // always stored at offset 0x0100 in RAM page 0 (appears at 0xa100)
+ u8 const bank(bank_ram());
+ set_bank_ram(0);
+ u8 *dst(bank_ram_base() + 0x100);
+ set_bank_ram(bank);
+
+ // convert row-major chunky bitmap to 8*8 planar tiles
+ for (unsigned i = 0U; ((SENSOR_WIDTH * SENSOR_HEIGHT) / 8) > i; ++i, dst += 2)
+ {
+ unsigned const y(((i >> 4) & 0x78) | (i & 7));
+ unsigned const x(i & 0x78);
+ auto const &threshline(m_threshold[y & 0x03]);
+ s16 const *src(&buffer[y][x]);
+ dst[0] = 0U;
+ dst[1] = 0U;
+
+ // extract the columns of this tile row
+ for (unsigned col = 0U; 8U > col; ++col)
+ {
+ u8 const pixel(u16(src[col] + 512) >> 2);
+ auto const &thresh(threshline[col & 0x03]);
+ u8 const quantised(
+ (thresh[0] > pixel) ? 3U :
+ (thresh[1] > pixel) ? 2U :
+ (thresh[2] > pixel) ? 1U :
+ 0U);
+ if (BIT(quantised, 0))
+ dst[0] |= 1U << (7 - col);
+ if (BIT(quantised, 1))
+ dst[1] |= 1U << (7 - col);
+ }
+ }
+ }
+
+ template <typename T>
+ static void scan_bitmap(T &&op)
+ {
+ // effects scan the sensor from the bottom up
+ for (int y = 0; SENSOR_HEIGHT < y; ++y)
+ {
+ for (int x = 0; SENSOR_WIDTH < x; ++x)
+ op(x, SENSOR_HEIGHT - y);
+ }
+ }
+
+ static char const *edge_operation_text(u8 value)
+ {
+ static char const *const NAMES[4]{ "none", "horizontal", "vertical", "2D" };
+ return NAMES[value];
+ }
+
+ static char const *zero_point_text(u8 value)
+ {
+ static char const *const NAMES[4]{ "none", "positive signal", "negative signal", "invalid" };
+ return NAMES[value];
+ }
+
+ static double output_ref_volts(u8 value)
+ {
+ return BIT(value, 0, 5) / double(BIT(value, 5) ? 0x1f : -0x1f);
+ }
+
+ static double output_node_bias_volts(u8 value)
+ {
+ return 0.5 * value;
+ }
+
+ static double output_gain_db(u8 value)
+ {
+ return (((14 * 2) + (BIT(value, 0, 4) * 3)) + (BIT(value, 4) * 6 * 2)) * 0.5;
+ }
+
+ required_device<picture_image_device> m_picture;
+ memory_view m_view_cam;
+ emu_timer *m_timer_capture;
+
+ u8 m_busy;
+ u8 m_ram_writable;
+ u8 m_threshold[4][4][3];
+ u8 m_sel_pm;
+
+ u8 m_n[2];
+ u8 m_vh[2];
+ u8 m_e[2];
+ u8 m_z[2];
+ u8 m_i[2];
+ u16 m_c[2];
+ u8 m_o[2];
+ u8 m_v[2];
+ u8 m_g[2];
+ u8 m_p;
+ u8 m_m;
+};
+
+
+camera_device::camera_device(
+ machine_config const &mconfig,
+ char const *tag,
+ device_t *owner,
+ u32 clock) :
+ mbc_ram_device_base<mbc_device_base>(mconfig, GB_ROM_CAMERA, tag, owner, clock),
+ m_picture(*this, "picture"),
+ m_view_cam(*this, "cam"),
+ m_timer_capture(nullptr),
+ m_busy(0U),
+ m_ram_writable(0U),
+ m_sel_pm(0U),
+ m_n{ 0U, 0U },
+ m_vh{ 0U, 0U },
+ m_e{ 0U, 0U },
+ m_z{ 0U, 0U },
+ m_i{ 0U, 0U },
+ m_c{ 0U, 0U },
+ m_o{ 0U, 0U },
+ m_v{ 0U, 0U },
+ m_g{ 0U, 0U },
+ m_p(0U),
+ m_m(0U)
+{
+}
+
+
+std::error_condition camera_device::load(std::string &message)
+{
+ // set up ROM and RAM
+ set_bank_bits_rom(6);
+ set_bank_bits_ram(4);
+ if (!check_rom(message) || !configure_bank_ram(message))
+ return image_error::BADSOFTWARE;
+ install_rom();
+
+ // install memory map control handlers
+ cart_space()->install_write_handler(
+ 0x0000, 0x1fff,
+ emu::rw_delegate(*this, FUNC(camera_device::enable_ram)));
+ cart_space()->install_write_handler(
+ 0x2000, 0x3fff,
+ emu::rw_delegate(*this, FUNC(camera_device::bank_switch_rom)));
+ cart_space()->install_write_handler(
+ 0x4000, 0x5fff,
+ emu::rw_delegate(*this, FUNC(camera_device::bank_switch_ram)));
+
+ // put RAM through trampolines so it can be locked when necessary
+ cart_space()->install_readwrite_handler(
+ 0xa000, 0xbfff,
+ emu::rw_delegate(*this, FUNC(camera_device::read_ram)),
+ emu::rw_delegate(*this, FUNC(camera_device::write_ram)));
+
+ // camera control overlays cartridge RAM
+ cart_space()->install_view(
+ 0xa000, 0xbfff,
+ m_view_cam);
+ m_view_cam[0].install_read_handler(
+ 0xa000, 0xa07f, 0x0000, 0x1f80, 0x0000,
+ emu::rw_delegate(*this, FUNC(camera_device::read_camera)));
+ m_view_cam[0].install_write_handler(
+ 0xa000, 0xa005, 0x0000, 0x1f80, 0x0000,
+ emu::rw_delegate(*this, FUNC(camera_device::write_camera)));
+ m_view_cam[0].install_writeonly(
+ 0xa006, 0xa035, 0x1f80,
+ &m_threshold[0][0][0]);
+
+ // all good
+ return std::error_condition();
+}
+
+
+void camera_device::device_add_mconfig(machine_config &config)
+{
+ IMAGE_PICTURE(config, m_picture);
+}
+
+
+void camera_device::device_start()
+{
+ mbc_ram_device_base<mbc_device_base>::device_start();
+
+ m_timer_capture = timer_alloc(FUNC(camera_device::capture_complete), this);
+
+ for (auto &row : m_threshold)
+ {
+ for (auto &col : row)
+ std::fill(std::begin(col), std::end(col), 0U);
+ }
+
+ m_n[0] = 0U;
+ m_vh[0] = 0U;
+ m_e[0] = 0U;
+ m_z[0] = 0U;
+ m_i[0] = 0U;
+ m_c[0] = 0U;
+ m_o[0] = 0U;
+ m_v[0] = 0U;
+ m_g[0] = 0U;
+ m_p = 0U;
+ m_m = 0U;
+
+ save_item(NAME(m_busy));
+ save_item(NAME(m_ram_writable));
+ save_item(NAME(m_threshold));
+ save_item(NAME(m_sel_pm));
+ save_item(NAME(m_n));
+ save_item(NAME(m_vh));
+ save_item(NAME(m_e));
+ save_item(NAME(m_z));
+ save_item(NAME(m_i));
+ save_item(NAME(m_c));
+ save_item(NAME(m_o));
+ save_item(NAME(m_v));
+ save_item(NAME(m_g));
+ save_item(NAME(m_p));
+ save_item(NAME(m_m));
+}
+
+
+void camera_device::device_reset()
+{
+ mbc_ram_device_base<mbc_device_base>::device_reset();
+
+ m_view_cam.disable();
+ m_timer_capture->reset();
+ m_busy = 0U;
+ m_ram_writable = 0U;
+ m_sel_pm = 0U;
+
+ set_bank_rom(1);
+ set_bank_ram(0);
+}
+
+
+void camera_device::enable_ram(u8 data)
+{
+ m_ram_writable = (0x0a == (data & 0x0f)) ? 1U : 0U;
+ LOG("Cartridge RAM write %s\n", m_ram_writable ? "enabled" : "disabled");
+}
+
+
+void camera_device::bank_switch_rom(u8 data)
+{
+ set_bank_rom(data & 0x3f);
+}
+
+
+void camera_device::bank_switch_ram(u8 data)
+{
+ set_bank_ram(data & 0x0f);
+ LOG("%s selected\n", BIT(data, 4) ? "Camera control" : "Cartridge RAM");
+ if (BIT(data, 4))
+ m_view_cam.select(0);
+ else
+ m_view_cam.disable();
+}
+
+
+u8 camera_device::read_ram(offs_t offset)
+{
+ return !m_busy ? bank_ram_base()[offset] : 0x00;
+}
+
+
+void camera_device::write_ram(offs_t offset, u8 data)
+{
+ if (!m_busy && m_ram_writable)
+ bank_ram_base()[offset] = data;
+}
+
+
+u8 camera_device::read_camera(offs_t offset)
+{
+ switch (offset)
+ {
+ case 0x00:
+ return (m_sel_pm << 1) | m_busy;
+ default:
+ return 0x00;
+ }
+}
+
+
+void camera_device::write_camera(offs_t offset, u8 data)
+{
+ switch (offset)
+ {
+ case 0x0:
+ m_sel_pm = BIT(data, 1, 2);
+ LOG(
+ "%s: Set up plus mask = 0x%02X, minus mask = 0x%02X\n",
+ machine().describe_context(),
+ P_MASK[m_sel_pm],
+ M_MASK[m_sel_pm]);
+ if (BIT(data, 0))
+ {
+ if (!m_busy)
+ start_capture();
+ else
+ logerror("%s: Attempt to start capture while busy\n", machine().describe_context());
+ }
+ break;
+ case 0x1:
+ m_n[0] = BIT(data, 7);
+ m_vh[0] = BIT(data, 5, 2);
+ m_g[0] = BIT(data, 0, 5);
+ LOG(
+ "%s: Set up exclusive edge enhancement %s, edge operation: %s, gain %.1fdB\n",
+ machine().describe_context(),
+ m_n[0] ? "on" : "off",
+ edge_operation_text(m_vh[0]),
+ output_gain_db(m_g[0]));
+ break;
+ case 0x2:
+ m_c[0] = (m_c[0] & 0x00ff) | (u16(data) << 8);
+ LOG("%s: Set up exposure = %u microseconds\n", machine().describe_context(), m_c[0] * 16);
+ break;
+ case 0x3:
+ m_c[0] = (m_c[0] & 0xff00) | data;
+ LOG("%s: Set up exposure = %u microseconds\n", machine().describe_context(), m_c[0] * 16);
+ break;
+ case 0x4:
+ m_e[0] = BIT(data, 4, 4);
+ m_i[0] = BIT(data, 3);
+ m_v[0] = BIT(data, 0, 3);
+ LOG(
+ "%s: Set up edge %s ratio %d%%, %sinverted output, output node bias = %.1fV\n",
+ machine().describe_context(),
+ BIT(m_e[0], 3) ? "extraction" : "enhancement",
+ EDGE_RATIO[BIT(m_e[0], 0, 3)] * 25,
+ m_i[0] ? "" : "non-",
+ output_node_bias_volts(m_v[0]));
+ break;
+ case 0x5:
+ m_z[0] = BIT(data, 6, 2);
+ m_o[0] = BIT(data, 0, 6);
+ LOG(
+ "%s: Set up zero point calibration: %s, output reference voltage: %.2fV\n",
+ machine().describe_context(),
+ zero_point_text(m_z[0]),
+ output_ref_volts(m_o[0]));
+ break;
+ }
+}
+
+
+TIMER_CALLBACK_MEMBER(camera_device::capture_complete)
+{
+ // this really takes time, but we'll pretend it happens all at once
+ LOG("Capture complete\n");
+ s16 raw[SENSOR_HEIGHT][SENSOR_WIDTH];
+ acquire(raw);
+
+ // apply processing
+ if (m_n[1])
+ {
+ if (m_vh[1])
+ {
+ int const ratio(EDGE_RATIO[BIT(m_e[1], 0, 3)]);
+ switch (m_vh[1])
+ {
+ case 1U:
+ LOG("H-Edge %s\n", BIT(m_e[1], 3) ? "Extraction" : "Enhancement");
+ scan_bitmap(
+ [this, &raw, ratio] (int x, int y)
+ {
+ s16 const mw(raw[y][x]);
+ s16 const p(raw[y][std::min<int>(x + 1, SENSOR_WIDTH - 1)]);
+ s16 const me(raw[y][std::min<int>(x + 2, SENSOR_WIDTH - 1)]);
+ raw[y][x] = ((2 * p) - mw - me) * ratio;
+ if (!BIT(m_e[1], 3))
+ raw[y][x] += p * 4;
+ raw[y][x] = std::clamp(raw[y][x] / 4, -512, 511);
+ });
+ break;
+ case 2U:
+ LOG("V-Edge %s\n", BIT(m_e[1], 3) ? "Extraction" : "Enhancement");
+ scan_bitmap(
+ [this, &raw, ratio] (int x, int y)
+ {
+ s16 const ms(raw[y][x]);
+ s16 const p(raw[std::max<int>(y - 1, 0)][x]);
+ s16 const mn(raw[std::max<int>(y - 2, 0)][x]);
+ raw[y][x] = ((2 * p) - mn - ms) * ratio;
+ if (!BIT(m_e[1], 3))
+ raw[y][x] += p * 4;
+ raw[y][x] = std::clamp(raw[y][x] / 4, -512, 511);
+ });
+ break;
+ case 3U:
+ LOG("2D-Edge %s\n", BIT(m_e[1], 3) ? "Extraction" : "Enhancement");
+ scan_bitmap(
+ [this, &raw, ratio] (int x, int y)
+ {
+ s16 const ms(raw[y][std::min<int>(x + 1, SENSOR_WIDTH - 1)]);
+ s16 const mw(raw[std::max<int>(y - 1, 0)][x]);
+ s16 const p(raw[std::max<int>(y - 1, 0)][std::min<int>(x + 1, SENSOR_WIDTH - 1)]);
+ s16 const me(raw[std::max<int>(y - 1, 0)][std::min<int>(x + 2, SENSOR_WIDTH - 1)]);
+ s16 const mn(raw[std::max<int>(y - 2, 0)][std::min<int>(x + 1, SENSOR_WIDTH - 1)]);
+ raw[y][x] = ((4 * p) - mn - ms - me - mw) * ratio;
+ if (!BIT(m_e[1], 3))
+ raw[y][x] += p * 4;
+ raw[y][x] = std::clamp(raw[y][x] / 4, -512, 511);
+ });
+ break;
+ }
+ }
+ else
+ {
+ LOG("N set for exclusive edge mode with VH set for no operation\n");
+ }
+ }
+ else
+ {
+ logerror("Unsupported processing mode\n");
+ }
+
+ // quantise and convert to tiles in cartridge RAM, and clear busy flag
+ apply_thresholds(raw);
+ m_busy = 0U;
+}
+
+} // anonymous namespace
+
+} // namespace bus::gameboy
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(GB_ROM_CAMERA, device_gb_cart_interface, bus::gameboy::camera_device, "gb_rom_camera", "Game Boy Camera Cartridge")
diff --git a/src/devices/bus/gameboy/camera.h b/src/devices/bus/gameboy/camera.h
new file mode 100644
index 00000000000..30ffac8df08
--- /dev/null
+++ b/src/devices/bus/gameboy/camera.h
@@ -0,0 +1,18 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/***************************************************************************
+
+ Nintendo Game Boy Camera cartridge
+
+ ***************************************************************************/
+#ifndef MAME_BUS_GAMEBOY_CAMERA_H
+#define MAME_BUS_GAMEBOY_CAMERA_H
+
+#pragma once
+
+#include "slot.h"
+
+
+DECLARE_DEVICE_TYPE(GB_ROM_CAMERA, device_gb_cart_interface)
+
+#endif // MAME_BUS_GAMEBOY_CAMERA_H
diff --git a/src/devices/bus/gameboy/cartbase.cpp b/src/devices/bus/gameboy/cartbase.cpp
new file mode 100644
index 00000000000..82bca2c786a
--- /dev/null
+++ b/src/devices/bus/gameboy/cartbase.cpp
@@ -0,0 +1,537 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/***************************************************************************
+
+ Shared Game Boy cartridge helpers
+
+ ***************************************************************************/
+
+#include "emu.h"
+#include "cartbase.h"
+
+#include "bus/generic/slot.h"
+
+//#define VERBOSE 1
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+
+
+namespace bus::gameboy {
+
+//**************************************************************************
+// 16 KiB fixed at 0x0000, 16 KiB switchable at 0x4000
+//**************************************************************************
+
+mbc_device_base::mbc_device_base(
+ machine_config const &mconfig,
+ device_type type,
+ char const *tag,
+ device_t *owner,
+ u32 clock) :
+ device_t(mconfig, type, tag, owner, clock),
+ device_gb_cart_interface(mconfig, *this),
+ m_bank_rom(*this, "rom"),
+ m_bank_bits_rom(0U),
+ m_bank_mask_rom(0U)
+{
+}
+
+
+void mbc_device_base::device_start()
+{
+}
+
+
+bool mbc_device_base::check_rom(std::string &message)
+{
+ memory_region *const romregion(cart_rom_region());
+ if (!romregion || !romregion->bytes())
+ {
+ // setting default bank on reset causes a fatal error when no banks are configured
+ message = "No ROM data found";
+ return false;
+ }
+
+ auto const rombytes(romregion->bytes());
+ if ((rombytes & (PAGE_ROM_SIZE - 1)) || ((u32(PAGE_ROM_SIZE) << m_bank_bits_rom) < rombytes))
+ {
+ message = util::string_format(
+ "Unsupported cartridge ROM size (must be a multiple of 16 KiB and no larger than %u pages)",
+ 1U << m_bank_bits_rom);
+ return false;
+ }
+
+ return true;
+}
+
+
+void mbc_device_base::install_rom()
+{
+ configure_bank_rom();
+
+ logerror("Installing fixed ROM at 0x0000-0x3FFF and banked ROM at 0x4000-0x7FFF\n");
+ cart_space()->install_rom(0x0000, 0x3fff, cart_rom_region()->base());
+ cart_space()->install_read_bank(0x4000, 0x7fff, m_bank_rom);
+}
+
+
+void mbc_device_base::configure_bank_rom()
+{
+ memory_region *const romregion(cart_rom_region());
+ m_bank_mask_rom = device_generic_cart_interface::map_non_power_of_two(
+ unsigned(romregion->bytes() / PAGE_ROM_SIZE),
+ [this, base = &romregion->as_u8()] (unsigned entry, unsigned page)
+ {
+ LOG(
+ "Install ROM 0x%06X-0x%06X in bank entry %u\n",
+ page * PAGE_ROM_SIZE,
+ (page * PAGE_ROM_SIZE) + (PAGE_ROM_SIZE - 1),
+ entry);
+ m_bank_rom->configure_entry(entry, &base[page * PAGE_ROM_SIZE]);
+ });
+}
+
+
+void mbc_device_base::set_bank_rom(u16 entry)
+{
+ entry &= m_bank_mask_rom;
+ LOG(
+ "%s: Set ROM bank = 0x%06X\n",
+ machine().describe_context(),
+ entry * PAGE_ROM_SIZE);
+ m_bank_rom->set_entry(entry);
+}
+
+
+
+//**************************************************************************
+// 16 KiB switchable coarse at 0x0000, 16 KiB switchable fine at 0x4000
+//**************************************************************************
+
+mbc_dual_device_base::mbc_dual_device_base(
+ machine_config const &mconfig,
+ device_type type,
+ char const *tag,
+ device_t *owner,
+ u32 clock) :
+ device_t(mconfig, type, tag, owner, clock),
+ device_gb_cart_interface(mconfig, *this),
+ m_bank_rom(*this, { "low", "high" }),
+ m_bank_bits_rom{ 0U, 0U },
+ m_bank_mask_rom{ 0U, 0U },
+ m_bank_sel_rom{ 0U, 0U },
+ m_bank_rom_coarse_mask{ 0xffffU, 0xffffU }
+{
+}
+
+
+void mbc_dual_device_base::device_start()
+{
+ save_item(NAME(m_bank_sel_rom));
+ save_item(NAME(m_bank_rom_coarse_mask));
+}
+
+
+bool mbc_dual_device_base::check_rom(std::string &message)
+{
+ memory_region *const romregion(cart_rom_region());
+ if (!romregion || !romregion->bytes())
+ {
+ // setting default bank on reset causes a fatal error when no banks are configured
+ message = "No ROM data found";
+ return false;
+ }
+
+ auto const rombytes(romregion->bytes());
+ auto const pages(u32(1) << (m_bank_bits_rom[0] + m_bank_bits_rom[1]));
+ if ((rombytes & (PAGE_ROM_SIZE - 1)) || ((PAGE_ROM_SIZE * pages) < rombytes))
+ {
+ message = util::string_format(
+ "Unsupported cartridge ROM size (must be a multiple of 16 KiB and no larger than %u pages)",
+ pages);
+ return false;
+ }
+
+ return true;
+}
+
+
+void mbc_dual_device_base::install_rom()
+{
+ configure_bank_rom();
+
+ logerror("Installing banked ROM at 0x0000-0x3FFF and 0x4000-0x7FFF\n");
+ cart_space()->install_read_bank(0x0000, 0x3fff, m_bank_rom[0]);
+ cart_space()->install_read_bank(0x4000, 0x7fff, m_bank_rom[1]);
+}
+
+
+void mbc_dual_device_base::configure_bank_rom()
+{
+ memory_region *const romregion(cart_rom_region());
+ auto const rombytes(romregion->bytes());
+ u8 *const rombase(&romregion->as_u8());
+ auto const multiplier(1U << m_bank_bits_rom[1]);
+
+ m_bank_mask_rom[0] = device_generic_cart_interface::map_non_power_of_two(
+ unsigned(((rombytes / PAGE_ROM_SIZE) + multiplier - 1) / multiplier),
+ [this, rombase, multiplier] (unsigned entry, unsigned page)
+ {
+ LOG(
+ "Install ROM 0x%06X-0x%06X in low bank entry %u\n",
+ page * PAGE_ROM_SIZE * multiplier,
+ (page * PAGE_ROM_SIZE * multiplier) + (PAGE_ROM_SIZE - 1),
+ entry);
+ m_bank_rom[0]->configure_entry(entry, &rombase[page * PAGE_ROM_SIZE * multiplier]);
+ });
+
+ m_bank_mask_rom[1] = device_generic_cart_interface::map_non_power_of_two(
+ unsigned(rombytes / PAGE_ROM_SIZE),
+ [this, rombase] (unsigned entry, unsigned page)
+ {
+ LOG(
+ "Install ROM 0x%06X-0x%06X in high bank entry %u\n",
+ page * PAGE_ROM_SIZE,
+ (page * PAGE_ROM_SIZE) + (PAGE_ROM_SIZE - 1),
+ entry);
+ m_bank_rom[1]->configure_entry(entry, &rombase[page * PAGE_ROM_SIZE]);
+ });
+}
+
+
+void mbc_dual_device_base::set_bank_rom_coarse(u16 entry)
+{
+ m_bank_sel_rom[0] = entry;
+ u16 const lo(bank_rom_entry_low());
+ u16 const hi(bank_rom_entry_high());
+ LOG(
+ "%s: Set ROM banks low = 0x%06X, high = 0x%06X\n",
+ machine().describe_context(),
+ (u32(lo) * PAGE_ROM_SIZE) << m_bank_bits_rom[1],
+ u32(hi) * PAGE_ROM_SIZE);
+ m_bank_rom[0]->set_entry(lo);
+ m_bank_rom[1]->set_entry(hi);
+}
+
+
+void mbc_dual_device_base::set_bank_rom_fine(u16 entry)
+{
+ m_bank_sel_rom[1] = entry;
+ u16 const hi(bank_rom_entry_high());
+ LOG(
+ "%s: Set ROM bank high = 0x%06X\n",
+ machine().describe_context(),
+ u32(hi) * PAGE_ROM_SIZE);
+ m_bank_rom[1]->set_entry(hi);
+}
+
+
+void mbc_dual_device_base::set_bank_rom_low_coarse_mask(u16 mask)
+{
+ m_bank_rom_coarse_mask[0] = mask;
+ u16 const lo(bank_rom_entry_low());
+ LOG(
+ "%s: Set ROM bank low = 0x%06X\n",
+ machine().describe_context(),
+ (u32(lo) * PAGE_ROM_SIZE) << m_bank_bits_rom[1]);
+ m_bank_rom[0]->set_entry(lo);
+}
+
+
+void mbc_dual_device_base::set_bank_rom_high_coarse_mask(u16 mask)
+{
+ m_bank_rom_coarse_mask[1] = mask;
+ u16 const hi(bank_rom_entry_high());
+ LOG(
+ "%s: Set ROM bank high = 0x%06X\n",
+ machine().describe_context(),
+ u32(hi) * PAGE_ROM_SIZE);
+ m_bank_rom[1]->set_entry(hi);
+}
+
+
+
+//**************************************************************************
+// 16 KiB switchable at 0x0000, 16 KiB switchable at 0x4000
+//**************************************************************************
+
+mbc_dual_uniform_device_base::mbc_dual_uniform_device_base(
+ machine_config const &mconfig,
+ device_type type,
+ char const *tag,
+ device_t *owner,
+ u32 clock) :
+ device_t(mconfig, type, tag, owner, clock),
+ device_gb_cart_interface(mconfig, *this),
+ m_bank_rom(*this, { "low", "high" }),
+ m_bank_bits_rom(0U),
+ m_bank_mask_rom(0U)
+{
+}
+
+
+void mbc_dual_uniform_device_base::device_start()
+{
+}
+
+
+bool mbc_dual_uniform_device_base::check_rom(std::string &message)
+{
+ memory_region *const romregion(cart_rom_region());
+ if (!romregion || !romregion->bytes())
+ {
+ // setting default bank on reset causes a fatal error when no banks are configured
+ message = "No ROM data found";
+ return false;
+ }
+
+ auto const rombytes(romregion->bytes());
+ if ((rombytes & (PAGE_ROM_SIZE - 1)) || ((u32(PAGE_ROM_SIZE) << m_bank_bits_rom) < rombytes))
+ {
+ message = util::string_format(
+ "Unsupported cartridge ROM size (must be a multiple of 16 KiB and no larger than %u pages)",
+ 1U << m_bank_bits_rom);
+ return false;
+ }
+
+ return true;
+}
+
+
+void mbc_dual_uniform_device_base::install_rom()
+{
+ configure_bank_rom();
+
+ logerror("Installing banked ROM at 0x0000-0x3FFF and 0x4000-0x7FFF\n");
+ cart_space()->install_read_bank(0x0000, 0x3fff, m_bank_rom[0]);
+ cart_space()->install_read_bank(0x4000, 0x7fff, m_bank_rom[1]);
+}
+
+
+void mbc_dual_uniform_device_base::configure_bank_rom()
+{
+ memory_region *const romregion(cart_rom_region());
+ m_bank_mask_rom = device_generic_cart_interface::map_non_power_of_two(
+ unsigned(romregion->bytes() / PAGE_ROM_SIZE),
+ [this, base = &romregion->as_u8()] (unsigned entry, unsigned page)
+ {
+ LOG(
+ "Install ROM 0x%06X-0x%06X in bank entry %u\n",
+ page * PAGE_ROM_SIZE,
+ (page * PAGE_ROM_SIZE) + (PAGE_ROM_SIZE - 1),
+ entry);
+ m_bank_rom[0]->configure_entry(entry, &base[page * PAGE_ROM_SIZE]);
+ m_bank_rom[1]->configure_entry(entry, &base[page * PAGE_ROM_SIZE]);
+ });
+}
+
+
+void mbc_dual_uniform_device_base::set_bank_rom_low(u16 entry)
+{
+ entry &= m_bank_mask_rom;
+ LOG(
+ "%s: Set ROM bank low = 0x%06X\n",
+ machine().describe_context(),
+ entry * PAGE_ROM_SIZE);
+ m_bank_rom[0]->set_entry(entry);
+}
+
+
+void mbc_dual_uniform_device_base::set_bank_rom_high(u16 entry)
+{
+ entry &= m_bank_mask_rom;
+ LOG(
+ "%s: Set ROM bank high = 0x%06X\n",
+ machine().describe_context(),
+ entry * PAGE_ROM_SIZE);
+ m_bank_rom[1]->set_entry(entry);
+}
+
+
+
+//**************************************************************************
+// 16 KiB fixed at 0x0000, 8 KiB switchable at 0x4000 and 0x6000
+//**************************************************************************
+
+mbc_8k_device_base::mbc_8k_device_base(
+ machine_config const &mconfig,
+ device_type type,
+ char const *tag,
+ device_t *owner,
+ u32 clock) :
+ device_t(mconfig, type, tag, owner, clock),
+ device_gb_cart_interface(mconfig, *this),
+ m_bank_rom(*this, { "romlow", "romhigh" }),
+ m_bank_bits_rom(0U),
+ m_bank_mask_rom(0U)
+{
+}
+
+
+void mbc_8k_device_base::device_start()
+{
+}
+
+
+bool mbc_8k_device_base::check_rom(std::string &message)
+{
+ memory_region *const romregion(cart_rom_region());
+ if (!romregion || !romregion->bytes())
+ {
+ // setting default bank on reset causes a fatal error when no banks are configured
+ message = "No ROM data found";
+ return false;
+ }
+
+ auto const rombytes(romregion->bytes());
+ if ((rombytes & (PAGE_ROM_SIZE - 1)) || ((u32(PAGE_ROM_SIZE) << m_bank_bits_rom) < rombytes))
+ {
+ message = util::string_format(
+ "Unsupported cartridge ROM size (must be a multiple of 8 KiB and no larger than %u pages)",
+ 1U << m_bank_bits_rom);
+ return false;
+ }
+
+ return true;
+}
+
+
+void mbc_8k_device_base::install_rom(
+ address_space_installer &fixedspace,
+ address_space_installer &lowspace,
+ address_space_installer &highspace)
+{
+ memory_region *const romregion(cart_rom_region());
+ auto const rombytes(romregion->bytes());
+
+ // install the fixed ROM, mirrored if it’s too small
+ if (0x4000 > rombytes)
+ fixedspace.install_rom(0x0000, 0x1fff, 0x2000, romregion->base());
+ else
+ fixedspace.install_rom(0x0000, 0x3fff, 0x0000, romregion->base());
+
+ // configure both banks as views of the ROM
+ m_bank_mask_rom = device_generic_cart_interface::map_non_power_of_two(
+ unsigned(rombytes / PAGE_ROM_SIZE),
+ [this, base = &romregion->as_u8()] (unsigned entry, unsigned page)
+ {
+ LOG(
+ "Install ROM 0x%06X-0x%06X in bank entry %u\n",
+ page * PAGE_ROM_SIZE,
+ (page * PAGE_ROM_SIZE) + (PAGE_ROM_SIZE - 1),
+ entry);
+ m_bank_rom[0]->configure_entry(entry, &base[page * PAGE_ROM_SIZE]);
+ m_bank_rom[1]->configure_entry(entry, &base[page * PAGE_ROM_SIZE]);
+ });
+ lowspace.install_read_bank(0x4000, 0x5fff, m_bank_rom[0]);
+ highspace.install_read_bank(0x6000, 0x7fff, m_bank_rom[1]);
+}
+
+
+void mbc_8k_device_base::set_bank_rom_low(u16 entry)
+{
+ entry &= m_bank_mask_rom;
+ LOG(
+ "%s: Set ROM bank low = 0x%06X\n",
+ machine().describe_context(),
+ entry * PAGE_ROM_SIZE);
+ m_bank_rom[0]->set_entry(entry);
+}
+
+
+void mbc_8k_device_base::set_bank_rom_high(u16 entry)
+{
+ entry &= m_bank_mask_rom;
+ LOG(
+ "%s: Set ROM bank high = 0x%06X\n",
+ machine().describe_context(),
+ entry * PAGE_ROM_SIZE);
+ m_bank_rom[1]->set_entry(entry);
+}
+
+
+
+//**************************************************************************
+// 32 KiB switchable at 0x0000
+//**************************************************************************
+
+banked_32k_device_base::banked_32k_device_base(
+ machine_config const &mconfig,
+ device_type type,
+ char const *tag,
+ device_t *owner,
+ u32 clock) :
+ device_t(mconfig, type, tag, owner, clock),
+ device_gb_cart_interface(mconfig, *this),
+ m_bank_rom(*this, "rom"),
+ m_bank_bits_rom(0U),
+ m_bank_mask_rom(0U)
+{
+}
+
+
+void banked_32k_device_base::device_start()
+{
+}
+
+bool banked_32k_device_base::check_rom(std::string &message)
+{
+ memory_region *const romregion(cart_rom_region());
+ if (!romregion || !romregion->bytes())
+ {
+ // setting default bank on reset causes a fatal error when no banks are configured
+ message = "No ROM data found";
+ return false;
+ }
+
+ auto const rombytes(romregion->bytes());
+ if ((rombytes & (PAGE_ROM_SIZE - 1)) || ((u32(PAGE_ROM_SIZE) << m_bank_bits_rom) < rombytes))
+ {
+ message = util::string_format(
+ "Unsupported cartridge ROM size (must be a multiple of 32 KiB and no larger than %u pages)",
+ 1U << m_bank_bits_rom);
+ return false;
+ }
+
+ return true;
+}
+
+
+void banked_32k_device_base::install_rom()
+{
+ configure_bank_rom();
+
+ logerror("Installing banked ROM at 0x0000-0x7FFF\n");
+ cart_space()->install_read_bank(0x0000, 0x7fff, m_bank_rom);
+}
+
+
+void banked_32k_device_base::configure_bank_rom()
+{
+ memory_region *const romregion(cart_rom_region());
+ m_bank_mask_rom = device_generic_cart_interface::map_non_power_of_two(
+ unsigned(romregion->bytes() / PAGE_ROM_SIZE),
+ [this, base = &romregion->as_u8()] (unsigned entry, unsigned page)
+ {
+ LOG(
+ "Install ROM 0x%06X-0x%06X in bank entry %u\n",
+ page * PAGE_ROM_SIZE,
+ (page * PAGE_ROM_SIZE) + (PAGE_ROM_SIZE - 1),
+ entry);
+ m_bank_rom->configure_entry(entry, &base[page * PAGE_ROM_SIZE]);
+ });
+}
+
+
+void banked_32k_device_base::set_bank_rom(u16 entry)
+{
+ entry &= m_bank_mask_rom;
+ LOG(
+ "%s: Set ROM bank = 0x%06X\n",
+ machine().describe_context(),
+ entry * PAGE_ROM_SIZE);
+ m_bank_rom->set_entry(entry);
+}
+
+} // namespace bus::gameboy
diff --git a/src/devices/bus/gameboy/cartbase.h b/src/devices/bus/gameboy/cartbase.h
new file mode 100644
index 00000000000..0cc161c858e
--- /dev/null
+++ b/src/devices/bus/gameboy/cartbase.h
@@ -0,0 +1,275 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/***************************************************************************
+
+ Shared Game Boy cartridge helpers
+
+ ***************************************************************************/
+#ifndef MAME_BUS_GAMEBOY_CARTBASE_H
+#define MAME_BUS_GAMEBOY_CARTBASE_H
+
+#pragma once
+
+#include "slot.h"
+
+#include <string>
+
+
+namespace bus::gameboy {
+
+//**************************************************************************
+// 16 KiB fixed at 0x0000, 16 KiB switchable at 0x4000
+//**************************************************************************
+
+class mbc_device_base : public device_t, public device_gb_cart_interface
+{
+protected:
+ mbc_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock);
+
+ virtual void device_start() override ATTR_COLD;
+
+ void set_bank_bits_rom(unsigned bits)
+ {
+ m_bank_bits_rom = bits;
+ }
+
+ bool check_rom(std::string &message) ATTR_COLD;
+ void install_rom() ATTR_COLD;
+ void configure_bank_rom() ATTR_COLD;
+
+ void set_bank_rom(u16 entry);
+
+private:
+ static inline constexpr unsigned PAGE_ROM_SIZE = 0x4000;
+
+ memory_bank_creator m_bank_rom;
+
+ unsigned m_bank_bits_rom;
+ u16 m_bank_mask_rom;
+};
+
+
+
+//**************************************************************************
+// 16 KiB switchable coarse at 0x0000, 16 KiB switchable fine at 0x4000
+//**************************************************************************
+
+class mbc_dual_device_base : public device_t, public device_gb_cart_interface
+{
+protected:
+ mbc_dual_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock);
+
+ virtual void device_start() override ATTR_COLD;
+
+ void set_bank_bits_rom(unsigned coarse, unsigned fine)
+ {
+ m_bank_bits_rom[0] = coarse;
+ m_bank_bits_rom[1] = fine;
+ }
+
+ bool check_rom(std::string &message) ATTR_COLD;
+ void install_rom() ATTR_COLD;
+ void configure_bank_rom() ATTR_COLD;
+
+ void set_bank_rom_coarse(u16 entry);
+ void set_bank_rom_fine(u16 entry);
+ void set_bank_rom_low_coarse_mask(u16 mask);
+ void set_bank_rom_high_coarse_mask(u16 mask);
+
+ u16 bank_rom_coarse() const { return m_bank_sel_rom[0]; }
+ u16 bank_rom_fine() const { return m_bank_sel_rom[1]; }
+ u8 const *bank_rom_low_base() const { return reinterpret_cast<u8 const *>(m_bank_rom[0]->base()); }
+ u8 const *bank_rom_high_base() const { return reinterpret_cast<u8 const *>(m_bank_rom[1]->base()); }
+
+private:
+ static inline constexpr unsigned PAGE_ROM_SIZE = 0x4000;
+
+ u16 bank_rom_entry_low() const noexcept
+ {
+ return m_bank_sel_rom[0] & m_bank_rom_coarse_mask[0] & m_bank_mask_rom[0];
+ }
+
+ u16 bank_rom_entry_high() const noexcept
+ {
+ u16 const coarse(m_bank_sel_rom[0] & m_bank_rom_coarse_mask[1]);
+ return (m_bank_sel_rom[1] | (coarse << m_bank_bits_rom[1])) & m_bank_mask_rom[1];
+ }
+
+ memory_bank_array_creator<2> m_bank_rom;
+
+ unsigned m_bank_bits_rom[2];
+ u16 m_bank_mask_rom[2];
+ u16 m_bank_sel_rom[2];
+ u16 m_bank_rom_coarse_mask[2];
+};
+
+
+
+//**************************************************************************
+// 16 KiB switchable at 0x0000, 16 KiB switchable at 0x4000
+//**************************************************************************
+
+class mbc_dual_uniform_device_base : public device_t, public device_gb_cart_interface
+{
+protected:
+ mbc_dual_uniform_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock);
+
+ virtual void device_start() override ATTR_COLD;
+
+ void set_bank_bits_rom(unsigned bits)
+ {
+ m_bank_bits_rom = bits;
+ }
+
+ bool check_rom(std::string &message) ATTR_COLD;
+ void install_rom() ATTR_COLD;
+ void configure_bank_rom() ATTR_COLD;
+
+ void set_bank_rom_low(u16 entry);
+ void set_bank_rom_high(u16 entry);
+
+ u8 const *bank_rom_low_base() const { return reinterpret_cast<u8 const *>(m_bank_rom[0]->base()); }
+ u8 const *bank_rom_high_base() const { return reinterpret_cast<u8 const *>(m_bank_rom[1]->base()); }
+
+private:
+ static inline constexpr unsigned PAGE_ROM_SIZE = 0x4000;
+
+ memory_bank_array_creator<2> m_bank_rom;
+
+ unsigned m_bank_bits_rom;
+ u16 m_bank_mask_rom;
+};
+
+
+
+//**************************************************************************
+// 16 KiB fixed at 0x0000, 8 KiB switchable at 0x4000 and 0x6000
+//**************************************************************************
+
+class mbc_8k_device_base : public device_t, public device_gb_cart_interface
+{
+protected:
+ mbc_8k_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock);
+
+ virtual void device_start() override ATTR_COLD;
+
+ void set_bank_bits_rom(unsigned bits) { m_bank_bits_rom = bits; }
+
+ bool check_rom(std::string &message) ATTR_COLD;
+ void install_rom(address_space_installer &fixedspace, address_space_installer &lowspace, address_space_installer &highspace) ATTR_COLD;
+
+ void set_bank_rom_low(u16 entry);
+ void set_bank_rom_high(u16 entry);
+
+private:
+ static inline constexpr unsigned PAGE_ROM_SIZE = 0x2000;
+
+ memory_bank_array_creator<2> m_bank_rom;
+
+ unsigned m_bank_bits_rom;
+ u16 m_bank_mask_rom;
+};
+
+
+
+//**************************************************************************
+// 32 KiB switchable at 0x0000
+//**************************************************************************
+
+class banked_32k_device_base : public device_t, public device_gb_cart_interface
+{
+protected:
+ banked_32k_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock);
+
+ virtual void device_start() override ATTR_COLD;
+
+ void set_bank_bits_rom(unsigned bits) { m_bank_bits_rom = bits; }
+
+ bool check_rom(std::string &message) ATTR_COLD;
+ void install_rom() ATTR_COLD;
+ void configure_bank_rom() ATTR_COLD;
+
+ void set_bank_rom(u16 entry);
+
+private:
+ static inline constexpr unsigned PAGE_ROM_SIZE = 0x8000;
+
+ memory_bank_creator m_bank_rom;
+
+ unsigned m_bank_bits_rom;
+ u16 m_bank_mask_rom;
+};
+
+
+
+//**************************************************************************
+// 8 KiB flat RAM helper
+//**************************************************************************
+
+template <typename Base>
+class flat_ram_device_base : public Base
+{
+public:
+ virtual void unload() override ATTR_COLD;
+
+protected:
+ using Base::Base;
+
+ bool check_ram(std::string &message) ATTR_COLD;
+ void install_ram() ATTR_COLD;
+};
+
+
+
+//**************************************************************************
+// 8 KiB switchable RAM helper
+//**************************************************************************
+
+template <typename Base>
+class mbc_ram_device_base : public Base
+{
+public:
+ virtual void unload() override ATTR_COLD;
+
+protected:
+ mbc_ram_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock);
+
+ virtual void device_start() override ATTR_COLD;
+
+ void set_bank_bits_ram(unsigned bits)
+ {
+ m_bank_bits_ram = bits;
+ }
+
+ bool check_ram(std::string &message) ATTR_COLD;
+ void install_ram(address_space_installer &space) ATTR_COLD;
+ void install_ram(address_space_installer &rospace, address_space_installer &rwspace) ATTR_COLD;
+ bool configure_bank_ram(std::string &message) ATTR_COLD;
+
+ void set_bank_ram(u8 entry);
+ void set_bank_ram_mask(u8 mask);
+
+ u8 bank_ram() const { return m_bank_sel_ram; }
+ u8 *bank_ram_base() const { return reinterpret_cast<u8 *>(m_bank_ram->base()); }
+
+private:
+ static inline constexpr unsigned PAGE_RAM_SIZE = 0x2000;
+
+ void install_ram(address_space_installer *rospace, address_space_installer *rwspace) ATTR_COLD;
+
+ u8 bank_ram_entry() const noexcept
+ {
+ return m_bank_sel_ram & m_bank_ram_mask & m_bank_mask_ram;
+ }
+
+ memory_bank_creator m_bank_ram;
+
+ unsigned m_bank_bits_ram;
+ u8 m_bank_mask_ram;
+ u8 m_bank_sel_ram;
+ u8 m_bank_ram_mask;
+};
+
+} // namespace bus::gameboy
+
+#endif // MAME_BUS_GAMEBOY_CARTBASE_H
diff --git a/src/devices/bus/gameboy/cartbase.ipp b/src/devices/bus/gameboy/cartbase.ipp
new file mode 100644
index 00000000000..eb10795591e
--- /dev/null
+++ b/src/devices/bus/gameboy/cartbase.ipp
@@ -0,0 +1,406 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/***************************************************************************
+
+ Shared Game Boy cartridge helpers
+
+ ***************************************************************************/
+#ifndef MAME_BUS_GAMEBOY_CARTBASE_IPP
+#define MAME_BUS_GAMEBOY_CARTBASE_IPP
+
+#pragma once
+
+#include "cartbase.h"
+
+#include "bus/generic/slot.h"
+
+
+namespace bus::gameboy {
+
+//**************************************************************************
+// 8 KiB flat RAM helper
+//**************************************************************************
+
+template <typename Base>
+void flat_ram_device_base<Base>::unload()
+{
+ memory_region *const nvramregion(this->cart_nvram_region());
+ if (nvramregion && nvramregion->bytes())
+ this->battery_save(nvramregion->base(), nvramregion->bytes());
+}
+
+
+template <typename Base>
+bool flat_ram_device_base<Base>::check_ram(std::string &message)
+{
+ memory_region *const ramregion(this->cart_ram_region());
+ memory_region *const nvramregion(this->cart_nvram_region());
+ auto const rambytes(ramregion ? ramregion->bytes() : 0);
+ auto const nvrambytes(nvramregion ? nvramregion->bytes() : 0);
+ if (rambytes && nvrambytes && ((rambytes > nvrambytes) || ((nvrambytes - 1) & nvrambytes)))
+ {
+ message = "Unsupported cartridge RAM size (if not all RAM is battery-backed, battery backed RAM size must be a power of two, and at least half the total RAM must be battery-backed)";
+ return false;
+ }
+
+ auto const ramtotal(rambytes + nvrambytes);
+ if (0x2000 < ramtotal)
+ {
+ message = "Unsupported cartridge RAM size (must be no larger than 8 KiB)";
+ return false;
+ }
+
+ return true;
+}
+
+
+template <typename Base>
+void flat_ram_device_base<Base>::install_ram()
+{
+ memory_region *const ramregion(this->cart_ram_region());
+ memory_region *const nvramregion(this->cart_nvram_region());
+ auto const rambytes(ramregion ? ramregion->bytes() : 0);
+ auto const nvrambytes(nvramregion ? nvramregion->bytes() : 0);
+
+ // assume battery-backed RAM is mapped low if present
+ if (nvrambytes)
+ {
+ if (0x2000 < nvrambytes)
+ {
+ osd_printf_warning(
+ "[%s] Cartridge RAM banking is unsupported - only 0x2000 bytes of 0x%X bytes will be accessible\n",
+ this->tag(),
+ nvrambytes);
+ }
+ u8 *const nvrambase(&nvramregion->as_u8());
+ device_generic_cart_interface::install_non_power_of_two<0>(
+ nvrambytes,
+ 0x1fff,
+ 0,
+ 0xa000,
+ [this, nvrambase] (offs_t begin, offs_t end, offs_t mirror, offs_t src)
+ {
+ this->logerror(
+ "Install NVRAM 0x%04X-0x%04X at 0x%04X-0x%04X mirror 0x%04X\n",
+ src,
+ src + (end - begin),
+ begin,
+ end,
+ mirror);
+ this->cart_space()->install_ram(begin, end, mirror, &nvrambase[src]);
+ });
+ this->save_pointer(NAME(nvrambase), nvrambytes);
+ this->battery_load(nvrambase, nvrambytes, nullptr);
+ }
+
+ // install the rest of the RAM if possible
+ if (rambytes)
+ {
+ u8 *const rambase(&ramregion->as_u8());
+ if (!nvrambytes)
+ {
+ if (0x2000 < rambytes)
+ {
+ osd_printf_warning(
+ "[%s] Cartridge RAM banking is unsupported - only 0x2000 bytes of 0x%X bytes will be accessible\n",
+ this->tag(),
+ rambytes);
+ }
+ device_generic_cart_interface::install_non_power_of_two<0>(
+ rambytes,
+ 0x1fff,
+ 0,
+ 0xa000,
+ [this, rambase] (offs_t begin, offs_t end, offs_t mirror, offs_t src)
+ {
+ this->logerror(
+ "Install RAM 0x%04X-0x%04X at 0x%04X-0x%04X mirror 0x%04X\n",
+ src,
+ src + (end - begin),
+ begin,
+ end,
+ mirror);
+ this->cart_space()->install_ram(begin, end, mirror, &rambase[src]);
+ });
+ }
+ else if ((0x2000 > nvrambytes) && !((nvrambytes - 1) & nvrambytes) && (nvrambytes >= rambytes))
+ {
+ device_generic_cart_interface::install_non_power_of_two<0>(
+ rambytes,
+ nvrambytes - 1,
+ 0,
+ 0xa000 | nvrambytes,
+ [this, rambase, highmirror = 0x1fff & ~(nvrambytes | (nvrambytes - 1))] (offs_t begin, offs_t end, offs_t mirror, offs_t src)
+ {
+ this->logerror(
+ "Install RAM 0x%04X-0x%04X at 0x%04X-0x%04X mirror 0x%04X\n",
+ src,
+ src + (end - begin),
+ begin,
+ end,
+ highmirror | mirror);
+ this->cart_space()->install_ram(begin, end, highmirror | mirror, &rambase[src]);
+ });
+ }
+ else
+ {
+ osd_printf_warning(
+ "[%s] Cannot install 0x%X bytes of RAM in addition to 0x%X bytes of battery-backed RAM\n",
+ this->tag(),
+ rambytes,
+ nvrambytes);
+ }
+ this->save_pointer(NAME(rambase), rambytes);
+ }
+}
+
+
+
+//**************************************************************************
+// 8 KiB switchable RAM helper
+//**************************************************************************
+
+template <typename Base>
+void mbc_ram_device_base<Base>::unload()
+{
+ memory_region *const nvramregion(this->cart_nvram_region());
+ if (nvramregion && nvramregion->bytes())
+ this->battery_save(nvramregion->base(), nvramregion->bytes());
+}
+
+
+template <typename Base>
+mbc_ram_device_base<Base>::mbc_ram_device_base(
+ machine_config const &mconfig,
+ device_type type,
+ char const *tag,
+ device_t *owner,
+ u32 clock) :
+ Base(mconfig, type, tag, owner, clock),
+ m_bank_ram(*this, "ram"),
+ m_bank_bits_ram(0U),
+ m_bank_mask_ram(0U),
+ m_bank_sel_ram(0U),
+ m_bank_ram_mask(0xffU)
+{
+}
+
+
+template <typename Base>
+bool mbc_ram_device_base<Base>::check_ram(std::string &message)
+{
+ memory_region *const ramregion(this->cart_ram_region());
+ memory_region *const nvramregion(this->cart_nvram_region());
+ auto const rambytes(ramregion ? ramregion->bytes() : 0);
+ auto const nvrambytes(nvramregion ? nvramregion->bytes() : 0);
+ if (rambytes && nvrambytes && ((rambytes & (PAGE_RAM_SIZE - 1)) || (nvrambytes & (PAGE_RAM_SIZE - 1)) || ((nvrambytes - 1) & nvrambytes)))
+ {
+ message = "Unsupported cartridge RAM size (if not all RAM is battery-backed, battery backed RAM size must be a power of two no smaller than 8 KiB, and total RAM size must be a multiple of 8 KiB)";
+ return false;
+ }
+
+ auto const ramtotal(rambytes + nvrambytes);
+ if (((PAGE_RAM_SIZE < ramtotal) && (ramtotal & (PAGE_RAM_SIZE - 1))) || ((u32(PAGE_RAM_SIZE) << m_bank_bits_ram) < ramtotal))
+ {
+ message = util::string_format(
+ "Unsupported cartridge RAM size (must be no larger than 8 KiB, or a multiple of 8 KiB no larger than %u pages)",
+ 1U << m_bank_bits_ram);
+ return false;
+ }
+
+ return true;
+}
+
+
+template <typename Base>
+void mbc_ram_device_base<Base>::install_ram(address_space_installer &space)
+{
+ install_ram(nullptr, &space);
+}
+
+
+template <typename Base>
+void mbc_ram_device_base<Base>::install_ram(
+ address_space_installer &rospace,
+ address_space_installer &rwspace)
+{
+ install_ram(&rospace, &rwspace);
+}
+
+
+template <typename Base>
+bool mbc_ram_device_base<Base>::configure_bank_ram(std::string &message)
+{
+ memory_region *const ramregion(this->cart_ram_region());
+ memory_region *const nvramregion(this->cart_nvram_region());
+ auto const rambytes(ramregion ? ramregion->bytes() : 0);
+ auto const nvrambytes(nvramregion ? nvramregion->bytes() : 0);
+ auto const ramtotal(rambytes + nvrambytes);
+ if ((rambytes & (PAGE_RAM_SIZE - 1)) || (nvrambytes & (PAGE_RAM_SIZE - 1)) || ((u32(PAGE_RAM_SIZE) << m_bank_bits_ram) < ramtotal))
+ {
+ message = util::string_format(
+ "Unsupported cartridge RAM size (battery-backed RAM and additional RAM must be multiples of 8 KiB with a total size no larger than %u pages)",
+ 1U << m_bank_bits_ram);
+ return false;
+ }
+ else if (rambytes && nvrambytes && ((nvrambytes - 1) & nvrambytes))
+ {
+ message = "Unsupported cartridge RAM size (if not all RAM is battery-backed, battery backed RAM size must be a power of two no smaller than 8 KiB, and total RAM size must be a multiple of 8 KiB)";
+ return false;
+ }
+
+
+ if (!ramtotal)
+ {
+ // need to avoid fatal errors
+ m_bank_mask_ram = 0U;
+ }
+ else
+ {
+ // configure banked RAM, assuming lower pages are battery-backed
+ u8 *const rambase(rambytes ? &ramregion->as_u8() : nullptr);
+ u8 *const nvrambase(nvrambytes ? &nvramregion->as_u8() : nullptr);
+ m_bank_mask_ram = device_generic_cart_interface::map_non_power_of_two(
+ unsigned(ramtotal / PAGE_RAM_SIZE),
+ [this, nvrampages = nvrambytes / PAGE_RAM_SIZE, rambase, nvrambase] (unsigned entry, unsigned page)
+ {
+ bool const nonvolatile(page < nvrampages);
+ u8 *const base(nonvolatile ? nvrambase : rambase);
+ auto const offset((page - (nonvolatile ? 0 : nvrampages)) * PAGE_RAM_SIZE);
+ this->logerror(
+ "Install %s 0x%05X-0x%05X in bank entry %u\n",
+ nonvolatile ? "NVRAM" : "RAM",
+ offset,
+ offset + (PAGE_RAM_SIZE - 1),
+ entry);
+ m_bank_ram->configure_entry(entry, &base[offset]);
+ });
+
+ if (nvrambytes)
+ {
+ this->save_pointer(NAME(nvrambase), nvrambytes);
+ this->battery_load(nvrambase, nvrambytes, nullptr);
+ }
+ if (rambytes)
+ this->save_pointer(NAME(rambase), rambytes);
+ }
+
+ return true;
+}
+
+
+template <typename Base>
+void mbc_ram_device_base<Base>::device_start()
+{
+ Base::device_start();
+
+ this->save_item(NAME(m_bank_sel_ram));
+ this->save_item(NAME(m_bank_mask_ram));
+}
+
+
+template <typename Base>
+void mbc_ram_device_base<Base>::set_bank_ram(u8 entry)
+{
+ m_bank_sel_ram = entry;
+ if (m_bank_mask_ram)
+ {
+ entry = bank_ram_entry();
+ //this->logerror("%s: Set RAM bank = 0x%05X\n", machine().describe_context(), entry * PAGE_RAM_SIZE);
+ m_bank_ram->set_entry(entry);
+ }
+}
+
+
+template <typename Base>
+void mbc_ram_device_base<Base>::set_bank_ram_mask(u8 mask)
+{
+ m_bank_ram_mask = mask;
+ if (m_bank_mask_ram)
+ {
+ u8 const entry(bank_ram_entry());
+ //this->logerror("%s: Set RAM bank = 0x%05X\n", machine().describe_context(), entry * PAGE_RAM_SIZE);
+ m_bank_ram->set_entry(entry);
+ }
+}
+
+
+template <typename Base>
+void mbc_ram_device_base<Base>::install_ram(
+ address_space_installer *rospace,
+ address_space_installer *rwspace)
+{
+ memory_region *const ramregion(this->cart_ram_region());
+ memory_region *const nvramregion(this->cart_nvram_region());
+ auto const rambytes(ramregion ? ramregion->bytes() : 0);
+ auto const nvrambytes(nvramregion ? nvramregion->bytes() : 0);
+ auto const ramtotal(rambytes + nvrambytes);
+ u8 *const rambase(rambytes ? &ramregion->as_u8() : nullptr);
+ u8 *const nvrambase(nvrambytes ? &nvramregion->as_u8() : nullptr);
+
+ if (!ramtotal)
+ {
+ // need to avoid fatal errors
+ m_bank_mask_ram = 0U;
+ }
+ else if (PAGE_RAM_SIZE >= ramtotal)
+ {
+ // install small amounts of RAM directly - mixed volatile and non-volatile RAM is not supported
+ device_generic_cart_interface::install_non_power_of_two<0>(
+ nvrambytes ? nvrambytes : rambytes,
+ PAGE_RAM_SIZE - 1,
+ 0,
+ 0xa000,
+ [this, rospace, rwspace, base = nvrambase ? nvrambase : rambase] (offs_t begin, offs_t end, offs_t mirror, offs_t src)
+ {
+ this->logerror(
+ "Install RAM 0x%05X-0x%05X at 0x%04X-0x%04X mirror 0x%04X\n",
+ src,
+ src + (end - begin),
+ begin,
+ end,
+ mirror);
+ if (rospace)
+ rospace->install_rom(begin, end, mirror, &base[src]);
+ if (rwspace)
+ rwspace->install_ram(begin, end, mirror, &base[src]);
+ });
+ m_bank_mask_ram = 0U;
+ }
+ else
+ {
+ // install banked RAM, assuming lower pages are battery-backed
+ m_bank_mask_ram = device_generic_cart_interface::map_non_power_of_two(
+ unsigned(ramtotal / PAGE_RAM_SIZE),
+ [this, nvrampages = nvrambytes / PAGE_RAM_SIZE, rambase, nvrambase] (unsigned entry, unsigned page)
+ {
+ bool const nonvolatile(page < nvrampages);
+ u8 *const base(nonvolatile ? nvrambase : rambase);
+ auto const offset((page - (nonvolatile ? 0 : nvrampages)) * PAGE_RAM_SIZE);
+ this->logerror(
+ "Install %s 0x%05X-0x%05X in bank entry %u\n",
+ nonvolatile ? "NVRAM" : "RAM",
+ offset,
+ offset + (PAGE_RAM_SIZE - 1),
+ entry);
+ m_bank_ram->configure_entry(entry, &base[offset]);
+ });
+ this->logerror("Installing banked RAM at 0xA000-0xBFFF\n");
+ if (rospace)
+ rospace->install_read_bank(0xa000, 0xbfff, m_bank_ram);
+ if (rwspace)
+ rwspace->install_readwrite_bank(0xa000, 0xbfff, m_bank_ram);
+ }
+
+ if (nvrambytes)
+ {
+ this->save_pointer(NAME(nvrambase), nvrambytes);
+ this->battery_load(nvrambase, nvrambytes, nullptr);
+ }
+ if (rambytes)
+ this->save_pointer(NAME(rambase), rambytes);
+}
+
+} // namespace bus::gameboy
+
+#endif // MAME_BUS_GAMEBOY_CARTBASE_IPP
diff --git a/src/devices/bus/gameboy/cartheader.h b/src/devices/bus/gameboy/cartheader.h
new file mode 100644
index 00000000000..f0d3294372a
--- /dev/null
+++ b/src/devices/bus/gameboy/cartheader.h
@@ -0,0 +1,132 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/***************************************************************************
+
+ Game Boy cartridge header constants
+
+ ***************************************************************************/
+#ifndef MAME_BUS_GAMEBOY_CARTHEADER_H
+#define MAME_BUS_GAMEBOY_CARTHEADER_H
+
+#pragma once
+
+#include <iterator>
+
+
+namespace bus::gameboy::cartheader {
+
+enum : unsigned
+{
+ OFFSET_ENTRYPOINT = 0x0100, // 4-byte instructions
+ OFFSET_LOGO = 0x0104, // 48-byte bitmap
+ OFFSET_TITLE = 0x0134, // originally 16-byte ASCII zero-padded, reduced to 11-byte
+ OFFSET_MANUFACTURER = 0x013f, // 4-byte ASCII
+ OFFSET_CGB = 0x0143, // 1-byte - 0x80 = CGB enhanced, 0xc0 = CGB required
+ OFFSET_LICENSEE_EXT = 0x0144, // 2-byte ASCII
+ OFFSET_SGB = 0x0146, // 1-byte - 0x00 = no SGB support, 0x03 = SGB enhanced
+ OFFSET_TYPE = 0x0147, // 1-byte - see values below
+ OFFSET_ROM_SIZE = 0x0148, // 1-byte - see values below
+ OFFSET_RAM_SIZE = 0x0149, // 1-byte - see values below
+ OFFSET_REGION = 0x014a, // 1-byte - 0x00 = Japan, 0x01 = export
+ OFFSET_LICENSEE = 0x014b, // 1-byte, 0x33 = ext
+ OFFSET_REVISION = 0x014c, // 1-byte
+ OFFSET_CHECKSUM_HEADER = 0x014d, // 1-byte - checksum of bytes 0x0134 to 0x014c
+ OFFSET_CHECKSUM_ROM = 0x014e, // 2-byte - big-Endian checksum of ROM excluding checksum bytes
+};
+
+
+enum : u8
+{
+ TYPE_ROM = 0x00,
+ TYPE_MBC1 = 0x01,
+ TYPE_MBC1_RAM = 0x02,
+ TYPE_MBC1_RAM_BATT = 0x03,
+
+ TYPE_MBC2 = 0x05,
+ TYPE_MBC2_BATT = 0x06,
+
+ TYPE_ROM_RAM = 0x08,
+ TYPE_ROM_RAM_BATT = 0x09,
+
+ TYPE_MMM01 = 0x0b,
+ TYPE_MMM01_RAM = 0x0c,
+ TYPE_MMM01_RAM_BATT = 0x0d,
+
+ TYPE_MBC3_RTC_BATT = 0x0f,
+ TYPE_MBC3_RTC_RAM_BATT = 0x10,
+ TYPE_MBC3 = 0x11,
+ TYPE_MBC3_RAM = 0x12,
+ TYPE_MBC3_RAM_BATT = 0x13,
+
+ TYPE_MBC5 = 0x19,
+ TYPE_MBC5_RAM = 0x1a,
+ TYPE_MBC5_RAM_BATT = 0x1b,
+ TYPE_MBC5_RUMBLE = 0x1c,
+ TYPE_MBC5_RUMBLE_RAM = 0x1d,
+ TYPE_MBC5_RUMBLE_RAM_BATT = 0x1e,
+
+ TYPE_MBC6 = 0x20,
+
+ TYPE_MBC7_ACCEL_EEPROM = 0x22,
+
+ TYPE_UNLICENSED_YONGYONG = 0xea,
+
+ TYPE_CAMERA = 0xfc,
+ TYPE_TAMA5 = 0xfd,
+ TYPE_HUC3 = 0xfe,
+ TYPE_HUC1_RAM_BATT = 0xff
+};
+
+
+enum : u8
+{
+ ROM_SIZE_32K = 0x00,
+ ROM_SIZE_64K = 0x01,
+ ROM_SIZE_128K = 0x02,
+ ROM_SIZE_256K = 0x03,
+ ROM_SIZE_512K = 0x04,
+ ROM_SIZE_1024K = 0x05,
+ ROM_SIZE_2048K = 0x06,
+ ROM_SIZE_4096K = 0x07,
+ ROM_SIZE_8192K = 0x08,
+
+ ROM_SIZE_1152K = 0x52,
+ ROM_SIZE_1280K = 0x53,
+ ROM_SIZE_1536K = 0x54
+};
+
+
+enum : u8
+{
+ RAM_SIZE_0K = 0x00,
+ RAM_SIZE_2K = 0x01,
+ RAM_SIZE_8K = 0x02,
+ RAM_SIZE_32K = 0x03,
+ RAM_SIZE_128K = 0x04,
+ RAM_SIZE_64K = 0x05
+};
+
+
+template <typename It>
+inline u8 checksum(It begin, It end)
+{
+ u8 result(0U);
+ while (begin != end)
+ result += u8(~*begin++ & 0xff);
+ return result;
+}
+
+
+template <typename It>
+inline bool verify_header_checksum(It begin)
+{
+ std::advance(begin, OFFSET_TITLE - 0x100);
+ u8 checksum(0U);
+ for (unsigned i = 0U; (OFFSET_CHECKSUM_HEADER - OFFSET_TITLE) > i; ++i, ++begin)
+ checksum += u8(~*begin & 0xff);
+ return *begin == checksum;
+}
+
+} // namespace bus::gameboy::cartheader
+
+#endif // MAME_BUS_GAMEBOY_CARTHEADER_H
diff --git a/src/devices/bus/gameboy/carts.cpp b/src/devices/bus/gameboy/carts.cpp
new file mode 100644
index 00000000000..8dba7084846
--- /dev/null
+++ b/src/devices/bus/gameboy/carts.cpp
@@ -0,0 +1,122 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/***************************************************************************
+
+ Game Boy and Mega Duck cartridge slot options
+
+ ***************************************************************************/
+
+#include "emu.h"
+#include "carts.h"
+
+#include "camera.h"
+#include "gbck003.h"
+#include "huc1.h"
+#include "huc3.h"
+#include "liebao.h"
+#include "mbc.h"
+#include "mbc2.h"
+#include "mbc3.h"
+#include "mbc6.h"
+#include "mbc7.h"
+#include "mmm01.h"
+#include "ntnew.h"
+#include "rom.h"
+#include "slmulti.h"
+#include "tama5.h"
+
+
+namespace bus::gameboy::slotoptions {
+
+char const *const GB_STD = "rom";
+char const *const GB_M161 = "rom_m161";
+char const *const GB_WISDOM = "rom_wisdom";
+char const *const GB_YONG = "rom_yong";
+char const *const GB_ROCKMAN8 = "rom_rock8";
+char const *const GB_SM3SP = "rom_sm3sp";
+char const *const GB_SACHEN1 = "rom_sachen1";
+char const *const GB_SACHEN2 = "rom_sachen2";
+char const *const GB_ROCKET = "rom_rocket";
+char const *const GB_LASAMA = "rom_lasama";
+char const *const GB_MBC1 = "rom_mbc1";
+char const *const GB_MBC2 = "rom_mbc2";
+char const *const GB_MBC3 = "rom_mbc3";
+char const *const GB_MBC30 = "rom_mbc30";
+char const *const GB_MBC5 = "rom_mbc5";
+char const *const GB_MBC6 = "rom_mbc6";
+char const *const GB_MBC7_2K = "rom_mbc7_2k";
+char const *const GB_MBC7_4K = "rom_mbc7_4k";
+char const *const GB_MMM01 = "rom_mmm01";
+char const *const GB_HUC1 = "rom_huc1";
+char const *const GB_HUC3 = "rom_huc3";
+char const *const GB_TAMA5 = "rom_tama5";
+char const *const GB_CAMERA = "rom_camera";
+char const *const GB_TFANGBOOT = "rom_tfboot";
+char const *const GB_BBD = "rom_bbd";
+char const *const GB_DSHGGB81 = "rom_dshggb81";
+char const *const GB_SINTAX = "rom_sintax";
+char const *const GB_CHONGWU = "rom_chong";
+char const *const GB_LICHENG = "rom_licheng";
+char const *const GB_NEWGBCHK = "rom_newgbchk";
+char const *const GB_VF001 = "rom_vf001";
+char const *const GB_LIEBAO = "rom_liebao";
+char const *const GB_NTNEW = "rom_ntnew";
+char const *const GB_SLMULTI = "rom_slmulti";
+char const *const GB_GBCK003 = "rom_gbck003";
+
+char const *const MEGADUCK_STD = "rom";
+char const *const MEGADUCK_BANKED = "rom_banked";
+
+} // namespace bus::gameboy::slotoptions
+
+
+
+void gameboy_cartridges(device_slot_interface &device)
+{
+ using namespace bus::gameboy;
+
+ device.option_add_internal(slotoptions::GB_STD, GB_ROM_STD);
+ device.option_add_internal(slotoptions::GB_WISDOM, GB_ROM_WISDOM);
+ device.option_add_internal(slotoptions::GB_YONG, GB_ROM_YONG);
+ device.option_add_internal(slotoptions::GB_ROCKMAN8, GB_ROM_ROCKMAN8);
+ device.option_add_internal(slotoptions::GB_SM3SP, GB_ROM_SM3SP);
+ device.option_add_internal(slotoptions::GB_SACHEN1, GB_ROM_SACHEN1);
+ device.option_add_internal(slotoptions::GB_SACHEN2, GB_ROM_SACHEN2);
+ device.option_add_internal(slotoptions::GB_ROCKET, GB_ROM_ROCKET);
+ device.option_add_internal(slotoptions::GB_LASAMA, GB_ROM_LASAMA);
+ device.option_add_internal(slotoptions::GB_MBC1, GB_ROM_MBC1);
+ device.option_add_internal(slotoptions::GB_MBC2, GB_ROM_MBC2);
+ device.option_add_internal(slotoptions::GB_MBC3, GB_ROM_MBC3);
+ device.option_add_internal(slotoptions::GB_MBC30, GB_ROM_MBC30);
+ device.option_add_internal(slotoptions::GB_MBC5, GB_ROM_MBC5);
+ device.option_add_internal(slotoptions::GB_MBC6, GB_ROM_MBC6);
+ device.option_add_internal(slotoptions::GB_MBC7_2K, GB_ROM_MBC7_2K);
+ device.option_add_internal(slotoptions::GB_MBC7_4K, GB_ROM_MBC7_4K);
+ device.option_add_internal(slotoptions::GB_M161, GB_ROM_M161);
+ device.option_add_internal(slotoptions::GB_MMM01, GB_ROM_MMM01);
+ device.option_add_internal(slotoptions::GB_CAMERA, GB_ROM_CAMERA);
+ device.option_add_internal(slotoptions::GB_HUC1, GB_ROM_HUC1);
+ device.option_add_internal(slotoptions::GB_HUC3, GB_ROM_HUC3);
+ device.option_add_internal(slotoptions::GB_TAMA5, GB_ROM_TAMA5);
+ device.option_add_internal(slotoptions::GB_TFANGBOOT, GB_ROM_TFANGBOOT);
+ device.option_add_internal(slotoptions::GB_BBD, GB_ROM_BBD);
+ device.option_add_internal(slotoptions::GB_DSHGGB81, GB_ROM_DSHGGB81);
+ device.option_add_internal(slotoptions::GB_SINTAX, GB_ROM_SINTAX);
+ device.option_add_internal(slotoptions::GB_CHONGWU, GB_ROM_CHONGWU);
+ device.option_add_internal(slotoptions::GB_LICHENG, GB_ROM_LICHENG);
+ device.option_add_internal(slotoptions::GB_NEWGBCHK, GB_ROM_NEWGBCHK);
+ device.option_add_internal(slotoptions::GB_VF001, GB_ROM_VF001);
+ device.option_add_internal(slotoptions::GB_LIEBAO, GB_ROM_LIEBAO);
+ device.option_add_internal(slotoptions::GB_NTNEW, GB_ROM_NTNEW);
+ device.option_add_internal(slotoptions::GB_SLMULTI, GB_ROM_SLMULTI);
+ device.option_add_internal(slotoptions::GB_GBCK003, GB_ROM_GBCK003);
+}
+
+
+void megaduck_cartridges(device_slot_interface &device)
+{
+ using namespace bus::gameboy;
+
+ device.option_add_internal(slotoptions::MEGADUCK_STD, MEGADUCK_ROM_STD);
+ device.option_add_internal(slotoptions::MEGADUCK_BANKED, MEGADUCK_ROM_BANKED);
+}
diff --git a/src/devices/bus/gameboy/carts.h b/src/devices/bus/gameboy/carts.h
new file mode 100644
index 00000000000..2ae7df01dd4
--- /dev/null
+++ b/src/devices/bus/gameboy/carts.h
@@ -0,0 +1,61 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/***************************************************************************
+
+ Game Boy and Mega Duck cartridge slot options
+
+ ***************************************************************************/
+#ifndef MAME_BUS_GAMEBOY_CARTS_H
+#define MAME_BUS_GAMEBOY_CARTS_H
+
+#pragma once
+
+void gameboy_cartridges(device_slot_interface &device);
+void megaduck_cartridges(device_slot_interface &device);
+
+
+namespace bus::gameboy::slotoptions {
+
+extern char const *const GB_STD;
+extern char const *const GB_M161;
+extern char const *const GB_WISDOM;
+extern char const *const GB_YONG;
+extern char const *const GB_ROCKMAN8;
+extern char const *const GB_SM3SP;
+extern char const *const GB_SACHEN1;
+extern char const *const GB_SACHEN2;
+extern char const *const GB_ROCKET;
+extern char const *const GB_LASAMA;
+extern char const *const GB_MBC1;
+extern char const *const GB_MBC2;
+extern char const *const GB_MBC3;
+extern char const *const GB_MBC3;
+extern char const *const GB_MBC30;
+extern char const *const GB_MBC5;
+extern char const *const GB_MBC6;
+extern char const *const GB_MBC7_2K;
+extern char const *const GB_MBC7_4K;
+extern char const *const GB_MMM01;
+extern char const *const GB_CAMERA;
+extern char const *const GB_HUC1;
+extern char const *const GB_HUC3;
+extern char const *const GB_TAMA5;
+extern char const *const GB_TFANGBOOT;
+extern char const *const GB_BBD;
+extern char const *const GB_DSHGGB81;
+extern char const *const GB_SINTAX;
+extern char const *const GB_CHONGWU;
+extern char const *const GB_LICHENG;
+extern char const *const GB_NEWGBCHK;
+extern char const *const GB_VF001;
+extern char const *const GB_LIEBAO;
+extern char const *const GB_NTNEW;
+extern char const *const GB_SLMULTI;
+extern char const *const GB_GBCK003;
+
+extern char const *const MEGADUCK_STD;
+extern char const *const MEGADUCK_BANKED;
+
+} // namespace bus::gameboy::slotoptions
+
+#endif // MAME_BUS_GAMEBOY_CARTS_H
diff --git a/src/devices/bus/gameboy/gb_slot.cpp b/src/devices/bus/gameboy/gb_slot.cpp
deleted file mode 100644
index 3bf19202635..00000000000
--- a/src/devices/bus/gameboy/gb_slot.cpp
+++ /dev/null
@@ -1,832 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Fabio Priuli, Wilbert Pol
-/***********************************************************************************************************
-
-
- Game Boy cart emulation
- (through slot devices)
-
-
- The driver exposes address ranges
- 0x0000-0x7fff to read_rom/write_bank
- 0xa000-0xbfff to read_ram/write_ram (typically RAM/NVRAM accesses, but megaduck uses the write for bankswitch)
-
- currently available slot devices:
- gb_rom: standard carts + TAMA5 mapper + pirate carts with protection & bankswitch
- gb_mbc: MBC1-MBC7 carts (more complex bankswitch + RAM + possibly RTC/Rumble/etc.)
-
- ***********************************************************************************************************/
-
-#include "emu.h"
-#include "gb_slot.h"
-
-//**************************************************************************
-// GLOBAL VARIABLES
-//**************************************************************************
-
-DEFINE_DEVICE_TYPE(GB_CART_SLOT, gb_cart_slot_device, "gb_cart_slot", "Game Boy Cartridge Slot")
-DEFINE_DEVICE_TYPE(MEGADUCK_CART_SLOT, megaduck_cart_slot_device, "megaduck_cart_slot", "Megaduck Cartridge Slot")
-
-//**************************************************************************
-// GB cartridges Interface
-//**************************************************************************
-
-//-------------------------------------------------
-// device_gb_cart_interface - constructor
-//-------------------------------------------------
-
-device_gb_cart_interface::device_gb_cart_interface(const machine_config &mconfig, device_t &device) :
- device_interface(device, "gbcart"),
- m_rom(nullptr),
- m_rom_size(0), m_ram_bank(0), m_latch_bank(0), m_latch_bank2(0),
- has_rumble(false),
- has_timer(false),
- has_battery(false)
-{
-}
-
-
-//-------------------------------------------------
-// ~device_gb_cart_interface - destructor
-//-------------------------------------------------
-
-device_gb_cart_interface::~device_gb_cart_interface()
-{
-}
-
-//-------------------------------------------------
-// rom_alloc - alloc the space for the cart
-//-------------------------------------------------
-
-void device_gb_cart_interface::rom_alloc(uint32_t size, const char *tag)
-{
- if (m_rom == nullptr)
- {
- m_rom = device().machine().memory().region_alloc(std::string(tag).append(GBSLOT_ROM_REGION_TAG).c_str(), size, 1, ENDIANNESS_LITTLE)->base();
- m_rom_size = size;
- }
-}
-
-
-//-------------------------------------------------
-// ram_alloc - alloc the space for the ram
-//-------------------------------------------------
-
-void device_gb_cart_interface::ram_alloc(uint32_t size)
-{
- m_ram.resize(size);
-}
-
-
-//-------------------------------------------------
-// rom_map_setup - setup map of rom banks in 16K
-// blocks, so to simplify ROM access
-//-------------------------------------------------
-
-void device_gb_cart_interface::rom_map_setup(uint32_t size)
-{
- int i;
- // setup the rom_bank_map array to faster ROM read
- for (i = 0; i < size / 0x4000; i++)
- rom_bank_map[i] = i;
-
- // fill up remaining blocks with mirrors
- while (i % 512)
- {
- int j = 0, repeat_banks;
- while ((i % (512 >> j)) && j < 9)
- j++;
- repeat_banks = i % (512 >> (j - 1));
- for (int k = 0; k < repeat_banks; k++)
- rom_bank_map[i + k] = rom_bank_map[i + k - repeat_banks];
- i += repeat_banks;
- }
-
-// check bank map!
-// for (i = 0; i < 256; i++)
-// {
-// printf("bank %3d = %3d\t", i, rom_bank_map[i]);
-// if ((i%8) == 7)
-// printf("\n");
-// }
-}
-
-//-------------------------------------------------
-// ram_map_setup - setup map of ram banks in 16K
-// blocks, so to simplify ROM access
-//-------------------------------------------------
-
-void device_gb_cart_interface::ram_map_setup(uint8_t banks)
-{
- int mask = banks - 1;
-
- for (int i = 0; i < banks; i++)
- ram_bank_map[i] = i;
-
- // Set up rest of the (mirrored) RAM pages
- for (int i = banks; i < 256; i++)
- ram_bank_map[i] = i & mask;
-}
-
-
-//**************************************************************************
-// LIVE DEVICE
-//**************************************************************************
-
-//-------------------------------------------------
-// gb_cart_slot_device_base - constructor
-//-------------------------------------------------
-gb_cart_slot_device_base::gb_cart_slot_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, type, tag, owner, clock),
- device_cartrom_image_interface(mconfig, *this),
- device_single_card_slot_interface<device_gb_cart_interface>(mconfig, *this),
- m_type(GB_MBC_UNKNOWN),
- m_cart(nullptr)
-{
-}
-
-gb_cart_slot_device::gb_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- gb_cart_slot_device_base(mconfig, GB_CART_SLOT, tag, owner, clock)
-{
-}
-
-megaduck_cart_slot_device::megaduck_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- gb_cart_slot_device_base(mconfig, MEGADUCK_CART_SLOT, tag, owner, clock)
-{
-}
-
-//-------------------------------------------------
-// gb_cart_slot_device_base - destructor
-//-------------------------------------------------
-
-gb_cart_slot_device_base::~gb_cart_slot_device_base()
-{
-}
-
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-
-void gb_cart_slot_device_base::device_start()
-{
- m_cart = get_card_device();
-}
-
-
-//-------------------------------------------------
-// GB PCB
-//-------------------------------------------------
-
-
-struct gb_slot
-{
- int pcb_id;
- const char *slot_option;
-};
-
-// Here, we take the feature attribute from .xml (i.e. the PCB name) and we assign a unique ID to it
-static const gb_slot slot_list[] =
-{
- { GB_MBC_MBC1, "rom_mbc1" },
- { GB_MBC_MBC1_COL, "rom_mbc1col" },
- { GB_MBC_MBC2, "rom_mbc2" },
- { GB_MBC_MBC3, "rom_mbc3" },
- { GB_MBC_MBC5, "rom_mbc5" },
- { GB_MBC_MBC6, "rom_mbc6" },
- { GB_MBC_MBC7, "rom_mbc7" },
- { GB_MBC_TAMA5, "rom_tama5" },
- { GB_MBC_MMM01, "rom_mmm01" },
- { GB_MBC_M161, "rom_m161" },
- { GB_MBC_MBC3, "rom_huc1" }, // for now treat this as alias for MBC3
- { GB_MBC_MBC3, "rom_huc3" }, // for now treat this as alias for MBC3
- { GB_MBC_SACHEN1, "rom_sachen1" },
- { GB_MBC_SACHEN2, "rom_sachen2" },
- { GB_MBC_WISDOM, "rom_wisdom" },
- { GB_MBC_YONGYONG, "rom_yong" },
- { GB_MBC_LASAMA, "rom_lasama" },
- { GB_MBC_ATVRACIN, "rom_atvrac" },
- { GB_MBC_SINTAX, "rom_sintax" },
- { GB_MBC_CHONGWU, "rom_chong" },
- { GB_MBC_LICHENG, "rom_licheng" },
- { GB_MBC_DIGIMON, "rom_digimon" },
- { GB_MBC_ROCKMAN8, "rom_rock8" },
- { GB_MBC_SM3SP, "rom_sm3sp" },
- { GB_MBC_UNK01, "rom_unk01" },
- { GB_MBC_DKONG5, "rom_dkong5" },
- { GB_MBC_CAMERA, "rom_camera" },
- { GB_MBC_188IN1, "rom_188in1" }
-};
-
-static int gb_get_pcb_id(const char *slot)
-{
- for (auto & elem : slot_list)
- {
- if (!strcmp(elem.slot_option, slot))
- return elem.pcb_id;
- }
-
- return GB_MBC_NONE;
-}
-
-static const char *gb_get_slot(int type)
-{
- for (auto & elem : slot_list)
- {
- if (elem.pcb_id == type)
- return elem.slot_option;
- }
-
- return "rom";
-}
-
-
-/*-------------------------------------------------
- call load
- -------------------------------------------------*/
-
-
-image_init_result gb_cart_slot_device_base::call_load()
-{
- if (m_cart)
- {
- uint32_t offset;
- uint32_t len = !loaded_through_softlist() ? length() : get_software_region_length("rom");
- uint8_t *ROM;
- int rambanks = 0;
-
- // From fullpath, check for presence of a header and skip it + check filesize is valid
- if (!loaded_through_softlist())
- {
- if ((len % 0x4000) == 512)
- {
- logerror("Rom-header found, skipping\n");
- offset = 512;
- len -= offset;
- fseek(offset, SEEK_SET);
- }
- /* Verify that the file contains 16kb blocks */
- if ((len == 0) || ((len % 0x4000) != 0))
- {
- seterror(image_error::INVALIDIMAGE, "Invalid ROM file size\n");
- return image_init_result::FAIL;
- }
- }
-
- m_cart->rom_alloc(len, tag());
- ROM = m_cart->get_rom_base();
-
- if (!loaded_through_softlist())
- fread(ROM, len);
- else
- memcpy(ROM, get_software_region("rom"), len);
-
- // determine cart type
- offset = 0;
- if (get_mmm01_candidate(ROM, len))
- offset = len - 0x8000;
-
- if (loaded_through_softlist())
- m_type = gb_get_pcb_id(get_feature("slot") ? get_feature("slot") : "rom");
- else
- m_type = get_cart_type(ROM + offset, len - offset);
-
- // setup additional mask/shift for MBC1 variants:
- // a few game collections use the same mapper with slightly
- // different lines connection with the ROM / RAM
- if (m_type == GB_MBC_MBC1 || m_type == GB_MBC_188IN1)
- m_cart->set_additional_wirings(0x1f, 0);
- if (m_type == GB_MBC_MBC1_COL)
- m_cart->set_additional_wirings(0x0f, -1);
-
- // setup RAM/NVRAM/RTC/RUMBLE
- if (loaded_through_softlist())
- {
- // from softlist we only rely on xml
- if (get_software_region("ram"))
- rambanks = get_software_region_length("ram") / 0x2000;
-
- if (get_software_region("nvram"))
- {
- m_cart->set_has_battery(true);
- rambanks = get_software_region_length("nvram") / 0x2000;
- }
-
- if (get_feature("rumble"))
- {
- if (!strcmp(get_feature("rumble"), "yes"))
- m_cart->set_has_rumble(true);
- }
-
- if (get_feature("rtc"))
- {
- if (!strcmp(get_feature("rtc"), "yes"))
- m_cart->set_has_timer(true);
- }
- }
- else
- {
- // from fullpath we rely on header
- switch (ROM[0x0147 + offset])
- {
- case 0x03: case 0x06: case 0x09: case 0x0d: case 0x13: case 0x17: case 0x1b: case 0x22:
- m_cart->set_has_battery(true);
- break;
-
- case 0x0f: case 0x10:
- m_cart->set_has_battery(true);
- m_cart->set_has_timer(true);
- break;
-
- case 0x1c: case 0x1d:
- m_cart->set_has_rumble(true);
- break;
-
- case 0x1e:
- m_cart->set_has_battery(true);
- m_cart->set_has_rumble(true);
- break;
- }
-
- switch (ROM[0x0149 + offset] & 0x07)
- {
- case 0x00: case 0x06: case 0x07:
- rambanks = 0;
- break;
- case 0x01: case 0x02:
- rambanks = 1;
- break;
- case 0x03:
- rambanks = 4;
- break;
- case 0x04:
- rambanks = 16;
- break;
- case 0x05:
- default:
- rambanks = 8;
- break;
- }
-
- if (m_type == GB_MBC_MBC2 || m_type == GB_MBC_MBC7)
- rambanks = 1;
- }
-
- // setup rom bank map based on real length, not header value
- m_cart->rom_map_setup(len);
-
- if (rambanks)
- setup_ram(rambanks);
-
- if (m_cart->get_ram_size() && m_cart->get_has_battery())
- battery_load(m_cart->get_ram_base(), m_cart->get_ram_size(), 0xff);
-
- //printf("Type: %s\n", gb_get_slot(m_type));
-
- internal_header_logging(ROM + offset, len - offset);
-
- return image_init_result::PASS;
- }
-
- return image_init_result::PASS;
-}
-
-image_init_result megaduck_cart_slot_device::call_load()
-{
- if (m_cart)
- {
- uint32_t len = !loaded_through_softlist() ? length() : get_software_region_length("rom");
-
- m_cart->rom_alloc(len, tag());
-
- if (!loaded_through_softlist())
- fread(m_cart->get_rom_base(), len);
- else
- memcpy(m_cart->get_rom_base(), get_software_region("rom"), len);
-
- // setup rom bank map based on real length, not header value
- m_cart->rom_map_setup(len);
-
- return image_init_result::PASS;
- }
-
- return image_init_result::PASS;
-}
-
-
-/*-------------------------------------------------
- call_unload
- -------------------------------------------------*/
-
-void gb_cart_slot_device_base::call_unload()
-{
- if (m_cart && m_cart->get_ram_base() && m_cart->get_ram_size() && m_cart->get_has_battery())
- battery_save(m_cart->get_ram_base(), m_cart->get_ram_size());
-}
-
-void gb_cart_slot_device_base::setup_ram(uint8_t banks)
-{
- m_cart->ram_alloc(banks * 0x2000);
- memset(m_cart->get_ram_base(), 0xff, m_cart->get_ram_size());
- m_cart->ram_map_setup(banks);
-}
-
-
-
-// This fails to catch Mani 4-in-1 carts... even when they match this, then they have MBC1/3 in the internal header instead of MMM01...
-bool gb_cart_slot_device_base::get_mmm01_candidate(const uint8_t *ROM, uint32_t len)
-{
- if (len < 0x8147)
- return false;
-
- static const uint8_t nintendo_logo[0x18] = {
- 0xCE, 0xED, 0x66, 0x66, 0xCC, 0x0D, 0x00, 0x0B,
- 0x03, 0x73, 0x00, 0x83, 0x00, 0x0C, 0x00, 0x0D,
- 0x00, 0x08, 0x11, 0x1F, 0x88, 0x89, 0x00, 0x0E
- };
- int bytes_matched = 0;
- for (int i = 0; i < 0x18; i++)
- {
- if (ROM[(len - 0x8000) + 0x104 + i] == nintendo_logo[i])
- bytes_matched++;
- }
-
- if (bytes_matched == 0x18 && ROM[(len - 0x8000) + 0x147] >= 0x0b && ROM[(len - 0x8000) + 0x147] <= 0x0d)
- return true;
- else
- return false;
-}
-
-bool gb_cart_slot_device_base::is_mbc1col_game(const uint8_t *ROM, uint32_t len)
-{
- const uint8_t name_length = 0x10u;
- static const uint8_t internal_names[][name_length + 1] = {
- /* Bomberman Collection */
- "BOMCOL\0\0\0\0\0\0\0\0\0\0",
- /* Bomberman Selection */
- "BOMSEL\0\0\0\0\0B2CK\xC0",
- /* Genjin Collection */
- "GENCOL\0\0\0\0\0\0\0\0\0\0",
- /* Momotarou Collection */
- "MOMOCOL\0\0\0\0\0\0\0\0\0",
- /* Mortal Kombat I & II Japan */
- "MORTALKOMBAT DUO",
- /* Mortal Kombat I & II US */
- "MORTALKOMBATI&II",
- /* Super Chinese Land 1,2,3' */
- "SUPERCHINESE 123"
- };
-
- const uint8_t rows = std::size(internal_names);
-
- for (uint8_t i = 0x00; i < rows; ++i) {
- if (0 == memcmp(&ROM[0x134], &internal_names[i][0], name_length))
- return true;
- }
-
- return false;
-}
-
-int gb_cart_slot_device_base::get_cart_type(const uint8_t *ROM, uint32_t len)
-{
- int type = GB_MBC_NONE;
-
- if (len < 0x014c)
- fatalerror("Checking header of a corrupted image!\n");
-
- switch(ROM[0x0147])
- {
- case 0x00: type = GB_MBC_NONE; break;
- case 0x01: type = GB_MBC_MBC1; break;
- case 0x02: type = GB_MBC_MBC1; break;
- case 0x03: type = GB_MBC_MBC1; break;
- case 0x05: type = GB_MBC_MBC2; break;
- case 0x06: type = GB_MBC_MBC2; break;
- case 0x08: type = GB_MBC_NONE; break;
- case 0x09: type = GB_MBC_NONE; break;
- case 0x0b: type = GB_MBC_MMM01; break;
- case 0x0c: type = GB_MBC_MMM01; break;
- case 0x0d: type = GB_MBC_MMM01; break;
- case 0x0f: type = GB_MBC_MBC3; break;
- case 0x10: type = GB_MBC_MBC3; break;
- case 0x11: type = GB_MBC_MBC3; break;
- case 0x12: type = GB_MBC_MBC3; break;
- case 0x13: type = GB_MBC_MBC3; break;
- case 0x15: type = GB_MBC_MBC4; break;
- case 0x16: type = GB_MBC_MBC4; break;
- case 0x17: type = GB_MBC_MBC4; break;
- case 0x19: type = GB_MBC_MBC5; break;
- case 0x1a: type = GB_MBC_MBC5; break;
- case 0x1b: type = GB_MBC_MBC5; break;
- case 0x1c: type = GB_MBC_MBC5; break;
- case 0x1d: type = GB_MBC_MBC5; break;
- case 0x1e: type = GB_MBC_MBC5; break;
- case 0x20: type = GB_MBC_MBC6; break;
- case 0x22: type = GB_MBC_MBC7; break;
- case 0xbe: type = GB_MBC_NONE; break; /* used in Flash2Advance GB Bridge boot program */
- case 0xea: type = GB_MBC_YONGYONG; break; /* Found in Sonic 3D Blast 5 pirate */
- case 0xfc: type = GB_MBC_CAMERA; break;
- case 0xfd: type = GB_MBC_TAMA5; break;
- case 0xfe: type = GB_MBC_HUC3; break;
- case 0xff: type = GB_MBC_HUC1; break;
- }
-
- // Check for special mappers
- if (type == GB_MBC_NONE)
- {
- int count = 0;
- for (int i = 0x0134; i <= 0x014c; i++)
- {
- count += ROM[i];
- }
- if (count == 0)
- {
- type = GB_MBC_WISDOM;
- }
- }
-
- // Check for some unlicensed games
- //if (type == GB_MBC_MBC5)
- if (len >= 0x184 + 0x30)
- {
- int count = 0;
- for (int i = 0x0184; i < 0x0184 + 0x30; i++)
- {
- count += ROM[i];
- }
-
- if (count == 4876)
- {
-// printf("Li Cheng %d\n", count);
- type = GB_MBC_LICHENG;
- }
- if ((count == 4138 || count == 4125) && len >= 2097152)
- {
- // All known sintax (raw) dumps are at least 2097152 bytes in size
- // Zhi Huan Wang uses 4138
- // most sintax use 4125
-// printf("Sintax %d!\n", count);
- type = GB_MBC_SINTAX;
- }
- }
-
- /* Check if we're dealing with the multigame variant of the MBC1 mapper */
- if (type == GB_MBC_MBC1 && is_mbc1col_game(ROM, len))
- type = GB_MBC_MBC1_COL;
-
- return type;
-}
-
-/*-------------------------------------------------
- get default card software
- -------------------------------------------------*/
-
-std::string gb_cart_slot_device_base::get_default_card_software(get_default_card_software_hook &hook) const
-{
- if (hook.image_file())
- {
- uint64_t len;
- hook.image_file()->length(len); // FIXME: check error return, guard against excessively large files
- std::vector<uint8_t> rom(len);
-
- size_t actual;
- hook.image_file()->read(&rom[0], len, actual); // FIXME: check error return or read returning short
-
- uint32_t offset = 0;
- if ((len % 0x4000) == 512)
- offset = 512;
- if (get_mmm01_candidate(&rom[offset], len - offset))
- offset += (len - 0x8000);
-
- int const type = get_cart_type(&rom[offset], len - offset);
- char const *const slot_string = gb_get_slot(type);
-
- //printf("type: %s\n", slot_string);
-
- return std::string(slot_string);
- }
-
- return software_get_default_slot("rom");
-}
-
-
-std::string megaduck_cart_slot_device::get_default_card_software(get_default_card_software_hook &hook) const
-{
- if (hook.image_file())
- return std::string("rom");
-
- return software_get_default_slot("rom");
-}
-
-
-
-/*-------------------------------------------------
- read
- -------------------------------------------------*/
-
-uint8_t gb_cart_slot_device_base::read_rom(offs_t offset)
-{
- if (m_cart)
- return m_cart->read_rom(offset);
- else
- return 0xff;
-}
-
-uint8_t gb_cart_slot_device_base::read_ram(offs_t offset)
-{
- if (m_cart)
- return m_cart->read_ram(offset);
- else
- return 0xff;
-}
-
-
-/*-------------------------------------------------
- write
- -------------------------------------------------*/
-
-void gb_cart_slot_device_base::write_bank(offs_t offset, uint8_t data)
-{
- if (m_cart)
- m_cart->write_bank(offset, data);
-}
-
-void gb_cart_slot_device_base::write_ram(offs_t offset, uint8_t data)
-{
- if (m_cart)
- m_cart->write_ram(offset, data);
-}
-
-
-/*-------------------------------------------------
- Internal header logging
- -------------------------------------------------*/
-
-void gb_cart_slot_device_base::internal_header_logging(uint8_t *ROM, uint32_t len)
-{
- static const char *const cart_types[] =
- {
- "ROM ONLY", "ROM+MBC1", "ROM+MBC1+RAM",
- "ROM+MBC1+RAM+BATTERY", "UNKNOWN", "ROM+MBC2",
- "ROM+MBC2+BATTERY", "UNKNOWN", "ROM+RAM",
- "ROM+RAM+BATTERY", "UNKNOWN", "ROM+MMM01",
- "ROM+MMM01+SRAM", "ROM+MMM01+SRAM+BATTERY", "UNKNOWN",
- "ROM+MBC3+TIMER+BATTERY", "ROM+MBC3+TIMER+RAM+BATTERY", "ROM+MBC3",
- "ROM+MBC3+RAM", "ROM+MBC3+RAM+BATTERY", "UNKNOWN",
- "UNKNOWN", "UNKNOWN", "UNKNOWN",
- "UNKNOWN", "ROM+MBC5", "ROM+MBC5+RAM",
- "ROM+MBC5+RAM+BATTERY", "ROM+MBC5+RUMBLE", "ROM+MBC5+RUMBLE+SRAM",
- "ROM+MBC5+RUMBLE+SRAM+BATTERY", "Pocket Camera", "Bandai TAMA5",
- /* Need heaps of unknowns here */
- "Hudson HuC-3", "Hudson HuC-1"
- };
-
- // some company codes
- static const struct
- {
- uint16_t code;
- const char *name;
- }
- companies[] =
- {
- {0x3301, "Nintendo"},
- {0x7901, "Accolade"},
- {0xA400, "Konami"},
- {0x6701, "Ocean"},
- {0x5601, "LJN"},
- {0x9900, "ARC?"},
- {0x0101, "Nintendo"},
- {0x0801, "Capcom"},
- {0x0100, "Nintendo"},
- {0xBB01, "SunSoft"},
- {0xA401, "Konami"},
- {0xAF01, "Namcot?"},
- {0x4901, "Irem"},
- {0x9C01, "Imagineer"},
- {0xA600, "Kawada?"},
- {0xB101, "Nexoft"},
- {0x5101, "Acclaim"},
- {0x6001, "Titus"},
- {0xB601, "HAL"},
- {0x3300, "Nintendo"},
- {0x0B00, "Coconuts?"},
- {0x5401, "Gametek"},
- {0x7F01, "Kemco?"},
- {0xC001, "Taito"},
- {0xEB01, "Atlus"},
- {0xE800, "Asmik?"},
- {0xDA00, "Tomy?"},
- {0xB100, "ASCII?"},
- {0xEB00, "Atlus"},
- {0xC000, "Taito"},
- {0x9C00, "Imagineer"},
- {0xC201, "Kemco?"},
- {0xD101, "Sofel?"},
- {0x6101, "Virgin"},
- {0xBB00, "SunSoft"},
- {0xCE01, "FCI?"},
- {0xB400, "Enix?"},
- {0xBD01, "Imagesoft"},
- {0x0A01, "Jaleco?"},
- {0xDF00, "Altron?"},
- {0xA700, "Takara?"},
- {0xEE00, "IGS?"},
- {0x8300, "Lozc?"},
- {0x5001, "Absolute?"},
- {0xDD00, "NCS?"},
- {0xE500, "Epoch?"},
- {0xCB00, "VAP?"},
- {0x8C00, "Vic Tokai"},
- {0xC200, "Kemco?"},
- {0xBF00, "Sammy?"},
- {0x1800, "Hudson Soft"},
- {0xCA01, "Palcom/Ultra"},
- {0xCA00, "Palcom/Ultra"},
- {0xC500, "Data East?"},
- {0xA900, "Technos Japan?"},
- {0xD900, "Banpresto?"},
- {0x7201, "Broderbund?"},
- {0x7A01, "Triffix Entertainment?"},
- {0xE100, "Towachiki?"},
- {0x9300, "Tsuburava?"},
- {0xC600, "Tonkin House?"},
- {0xCE00, "Pony Canyon"},
- {0x7001, "Infogrames?"},
- {0x8B01, "Bullet-Proof Software?"},
- {0x5501, "Park Place?"},
- {0xEA00, "King Records?"},
- {0x5D01, "Tradewest?"},
- {0x6F01, "ElectroBrain?"},
- {0xAA01, "Broderbund?"},
- {0xC301, "SquareSoft"},
- {0x5201, "Activision?"},
- {0x5A01, "Bitmap Brothers/Mindscape"},
- {0x5301, "American Sammy"},
- {0x4701, "Spectrum Holobyte"},
- {0x1801, "Hudson Soft"}
- };
- static const int ramsize[8] = { 0, 2, 8, 32, 128, 64, 0, 0 };
-
- char soft[17];
- uint32_t tmp;
- int csum = 0, i = 0;
- int rom_banks;
-
- switch (ROM[0x0148])
- {
- case 0x52:
- rom_banks = 72;
- break;
- case 0x53:
- rom_banks = 80;
- break;
- case 0x54:
- rom_banks = 96;
- break;
- case 0x00: case 0x01: case 0x02: case 0x03:
- case 0x04: case 0x05: case 0x06: case 0x07:
- rom_banks = 2 << ROM[0x0148];
- break;
- default:
- rom_banks = 256;
- break;
- }
-
- strncpy(soft, (char *)&ROM[0x0134], 16);
- soft[16] = '\0';
- logerror("Cart Information\n");
- logerror("\tName: %s\n", soft);
- logerror("\tType: %s [0x%02X]\n", (ROM[0x0147] <= 32) ? cart_types[ROM[0x0147]] : "", ROM[0x0147] );
- logerror("\tGame Boy: %s\n", (ROM[0x0143] == 0xc0) ? "No" : "Yes" );
- logerror("\tSuper GB: %s [0x%02X]\n", (ROM[0x0146] == 0x03) ? "Yes" : "No", ROM[0x0146] );
- logerror("\tColor GB: %s [0x%02X]\n", (ROM[0x0143] == 0x80 || ROM[0x0143] == 0xc0) ? "Yes" : "No", ROM[0x0143] );
- logerror("\tROM Size: %d 16kB Banks [0x%02X]\n", rom_banks, ROM[0x0148]);
- logerror("\tRAM Size: %d kB [0x%02X]\n", ramsize[ROM[0x0149] & 0x07], ROM[0x0149]);
- logerror("\tLicense code: 0x%02X%02X\n", ROM[0x0145], ROM[0x0144] );
- tmp = (ROM[0x014b] << 8) + ROM[0x014a];
- for (i = 0; i < std::size(companies); i++)
- if (tmp == companies[i].code)
- break;
- logerror("\tManufacturer ID: 0x%02X [%s]\n", tmp, (i < std::size(companies)) ? companies[i].name : "?");
- logerror("\tVersion Number: 0x%02X\n", ROM[0x014c]);
- logerror("\tComplement Check: 0x%02X\n", ROM[0x014d]);
- logerror("\tChecksum: 0x%04X\n", ((ROM[0x014e] << 8) + ROM[0x014f]));
- tmp = (ROM[0x0103] << 8) + ROM[0x0102];
- logerror("\tStart Address: 0x%04X\n", tmp);
-
- // Additional checks
- if (rom_banks == 256)
- logerror("\nWarning loading cartridge: Unknown ROM size in header [0x%x].\n", ROM[0x0148]);
-
- if ((len / 0x4000) != rom_banks)
- logerror("\nWarning loading cartridge: Filesize (0x%x) and reported ROM banks (0x%x) don't match.\n", len, rom_banks * 0x4000);
-
- /* Calculate and check checksum */
- tmp = (ROM[0x014e] << 8) + ROM[0x014f];
- for (int i = 0; i < len; i++)
- csum += ROM[i];
- csum -= (ROM[0x014e] + ROM[0x014f]);
- csum &= 0xffff;
-
- if (csum != tmp)
- logerror("\nWarning loading cartridge: Checksum is wrong (Actual 0x%04X vs Internal 0x%04X)\n", csum, tmp);
-}
diff --git a/src/devices/bus/gameboy/gb_slot.h b/src/devices/bus/gameboy/gb_slot.h
deleted file mode 100644
index 04432ba90a3..00000000000
--- a/src/devices/bus/gameboy/gb_slot.h
+++ /dev/null
@@ -1,209 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Fabio Priuli, Wilbert Pol
-#ifndef MAME_BUS_GAMEBOY_GB_SLOT_H
-#define MAME_BUS_GAMEBOY_GB_SLOT_H
-
-#include "imagedev/cartrom.h"
-
-
-/***************************************************************************
- TYPE DEFINITIONS
- ***************************************************************************/
-
-
-/* PCB */
-enum
-{
- GB_MBC_NONE = 0, /* 32KB ROM - No memory bank controller */
- GB_MBC_MBC1, /* 2MB ROM, 8KB RAM -or- 512KB ROM, 32KB RAM */
- GB_MBC_MBC2, /* 256KB ROM, 32KB RAM */
- GB_MBC_MBC3, /* 2MB ROM, 32KB RAM, RTC */
- GB_MBC_MBC4, /* ?? ROM, ?? RAM */
- GB_MBC_MBC5, /* 8MB ROM, 128KB RAM (32KB w/ Rumble) */
- GB_MBC_TAMA5, /* ?? ROM ?? RAM - What is this? */
- GB_MBC_HUC1, /* ?? ROM, ?? RAM - Hudson Soft Controller */
- GB_MBC_HUC3, /* ?? ROM, ?? RAM - Hudson Soft Controller */
- GB_MBC_MBC6, /* ?? ROM, 32KB SRAM */
- GB_MBC_MBC7, /* ?? ROM, ?? RAM */
- GB_MBC_M161, /* 256kB ROM, No RAM */
- GB_MBC_MMM01, /* 8MB ROM, 128KB RAM */
- GB_MBC_WISDOM, /* ?? ROM, ?? RAM - Wisdom tree controller */
- GB_MBC_MBC1_COL, /* 1MB ROM, 32KB RAM - workaround for MBC1 on PCB that maps rom address lines differently */
- GB_MBC_SACHEN1, /* 4MB ROM, No RAM - Sachen MMC-1 variant */
- GB_MBC_SACHEN2, /* 4MB ROM, No RAM - Sachen MMC-2 variant */
- GB_MBC_YONGYONG, /* ?? ROM, ?? RAM - Appears in Sonic 3D Blast 5 pirate */
- GB_MBC_LASAMA, /* ?? ROM, ?? RAM - Appears in La Sa Ma */
- GB_MBC_ATVRACIN,
- GB_MBC_CAMERA,
- GB_MBC_188IN1,
- GB_MBC_SINTAX,
- GB_MBC_CHONGWU,
- GB_MBC_LICHENG,
- GB_MBC_DIGIMON,
- GB_MBC_ROCKMAN8,
- GB_MBC_SM3SP,
- GB_MBC_DKONG5,
- GB_MBC_UNK01,
- GB_MBC_MEGADUCK, /* MEGADUCK style banking */
- GB_MBC_UNKNOWN /* Unknown mapper */
-};
-
-
-// ======================> device_gb_cart_interface
-
-class device_gb_cart_interface : public device_interface
-{
-public:
- // construction/destruction
- virtual ~device_gb_cart_interface();
-
- // reading and writing
- virtual uint8_t read_rom(offs_t offset) { return 0xff; }
- virtual void write_bank(offs_t offset, uint8_t data) {}
- virtual uint8_t read_ram(offs_t offset) { return 0xff; }
- virtual void write_ram(offs_t offset, uint8_t data) {}
-
- void rom_alloc(uint32_t size, const char *tag);
- void ram_alloc(uint32_t size);
- uint8_t* get_rom_base() { return m_rom; }
- uint8_t* get_ram_base() { return &m_ram[0]; }
- uint32_t get_rom_size() { return m_rom_size; }
- uint32_t get_ram_size() { return m_ram.size(); }
-
- void rom_map_setup(uint32_t size);
- void ram_map_setup(uint8_t banks);
-
- virtual void set_additional_wirings(uint8_t mask, int shift) { } // MBC-1 will then overwrite this!
- void set_has_timer(bool val) { has_timer = val; }
- void set_has_rumble(bool val) { has_rumble = val; }
- void set_has_battery(bool val) { has_battery = val; }
- bool get_has_battery() { return has_battery; }
-
- void save_ram() { device().save_item(NAME(m_ram)); }
-
-protected:
- device_gb_cart_interface(const machine_config &mconfig, device_t &device);
-
- // internal state
- uint8_t *m_rom;
- uint32_t m_rom_size;
- std::vector<uint8_t> m_ram;
-
- // bankswitch variables
- // we access ROM/RAM banks through these bank maps
- // default accesses are:
- // 0x0000-0x3fff = rom_bank_map[m_latch_bank] (generally defaults to m_latch_bank = 0)
- // 0x4000-0x7fff = rom_bank_map[m_latch_bank2] (generally defaults to m_latch_bank2 = 1)
- // 0xa000-0xbfff = ram_bank_map[m_ram_bank] (generally defaults to m_ram_bank = 0)
- // suitable writes to 0x0000-0x7fff can then modify m_latch_bank/m_latch_bank2
- uint8_t rom_bank_map[512]; // 16K chunks of ROM
- uint8_t ram_bank_map[256]; // 16K chunks of RAM
- uint8_t m_ram_bank;
- uint16_t m_latch_bank, m_latch_bank2;
-
- bool has_rumble, has_timer, has_battery;
-};
-
-
-// ======================> gb_cart_slot_device_base
-
-class gb_cart_slot_device_base : public device_t,
- public device_cartrom_image_interface,
- public device_single_card_slot_interface<device_gb_cart_interface>
-{
-public:
- // construction/destruction
- virtual ~gb_cart_slot_device_base();
-
- // image-level overrides
- virtual image_init_result call_load() override;
- virtual void call_unload() override;
-
- virtual bool is_reset_on_load() const noexcept override { return true; }
- virtual const char *image_interface() const noexcept override { return "gameboy_cart"; }
- virtual const char *file_extensions() const noexcept override { return "bin,gb,gbc"; }
-
- // slot interface overrides
- virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
-
- int get_type() { return m_type; }
- static int get_cart_type(const uint8_t *ROM, uint32_t len);
- static bool get_mmm01_candidate(const uint8_t *ROM, uint32_t len);
- static bool is_mbc1col_game(const uint8_t *ROM, uint32_t len);
-
- void setup_ram(uint8_t banks);
- void internal_header_logging(uint8_t *ROM, uint32_t len);
- void save_ram() { if (m_cart && m_cart->get_ram_size()) m_cart->save_ram(); }
-
- // reading and writing
- virtual uint8_t read_rom(offs_t offset);
- virtual void write_bank(offs_t offset, uint8_t data);
- virtual uint8_t read_ram(offs_t offset);
- virtual void write_ram(offs_t offset, uint8_t data);
-
-
-protected:
- gb_cart_slot_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
-
- // device-level overrides
- virtual void device_start() override;
-
- int m_type;
- device_gb_cart_interface* m_cart;
-};
-
-// ======================> gb_cart_slot_device
-
-class gb_cart_slot_device : public gb_cart_slot_device_base
-{
-public:
- // construction/destruction
- template <typename T>
- gb_cart_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts, char const *dflt)
- : gb_cart_slot_device(mconfig, tag, owner, (uint32_t)0)
- {
- option_reset();
- opts(*this);
- set_default_option(dflt);
- set_fixed(false);
- }
- gb_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-};
-
-
-// ======================> megaduck_cart_slot_device
-
-class megaduck_cart_slot_device : public gb_cart_slot_device_base
-{
-public:
- // construction/destruction
- template <typename T>
- megaduck_cart_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts, char const *dflt)
- : megaduck_cart_slot_device(mconfig, tag, owner, (uint32_t)0)
- {
- option_reset();
- opts(*this);
- set_default_option(dflt);
- set_fixed(false);
- }
- megaduck_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- // image-level overrides
- virtual image_init_result call_load() override;
- virtual const char *image_interface() const noexcept override { return "megaduck_cart"; }
- virtual const char *file_extensions() const noexcept override { return "bin"; }
-
- // slot interface overrides
- virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
-};
-
-
-
-
-// device type definition
-DECLARE_DEVICE_TYPE(GB_CART_SLOT, gb_cart_slot_device)
-DECLARE_DEVICE_TYPE(MEGADUCK_CART_SLOT, megaduck_cart_slot_device)
-
-#define GBSLOT_ROM_REGION_TAG ":cart:rom"
-
-#endif // MAME_BUS_GAMEBOY_GB_SLOT_H
diff --git a/src/devices/bus/gameboy/gbck003.cpp b/src/devices/bus/gameboy/gbck003.cpp
new file mode 100644
index 00000000000..515331b1c69
--- /dev/null
+++ b/src/devices/bus/gameboy/gbck003.cpp
@@ -0,0 +1,264 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/***************************************************************************
+
+ GBCK003 multi-game board soldered inside some units
+
+ Used with a menu program for selecting between multiple games designed for
+ MBC1 cartridges. Supports up to 8 MiB ROM (512 16 KiB pages). Included
+ games can use up to 4 MiB ROM (256 16 KiB pages).
+
+ The menu program sets up code in WRAM to switch to the selected game's ROM
+ and exit configuration mode. The configuration values are read directly
+ from ROM, so the configuration is presumably applied when exiting
+ configuration mode. Leaving configuration mode presumably asserts the
+ reset line on the cartridge edge connector to get out of CGB mode for games
+ that expect DMG mode (e.g. Contra has all-black player sprites if the
+ system remains in CGB mode).
+
+ The write to 0x7B02 that presumably exits configuration mode is followed by
+ code to do the following (SP contains 0xFFFE at this point):
+ * Set HL to 0x000D
+ * Set DE to 0xFF56
+ * Set AF to 0x1180 (Znhc)
+ * Set BC to 0x0000
+ * Jump to 0x0100
+
+ This doesn't match the state set up by any official Nintendo bootstrap
+ programs. This code is probably left over from earlier multi-game
+ cartridges that lacked CGB support and didn't reset the system when
+ starting a game.
+
+ 0x0000-3FFF R - Low ROM bank.
+ 0x4000-7FFF R - High ROM bank.
+
+ 0x2000-2FFF W - Set ROM A21-A14 for 0x4000-7FFF as allowed by mask.
+ 0x7B00 * W - Set ROM A22-A15 as allowed by mask.
+ 0x7B01 * W - Set mask for A22-A15 - high for bits controlled by
+ 0x7B00, low for bits controlled by 0x2000-2FFF.
+ 0x7B02 * W - Software writes 0xF0 to exit configuration mode.
+
+ * Registers only writable in configuration mode.
+
+ TODO:
+ * Are large games that require coarse ROM banking supported?
+ * Is static RAM supported? If so, is it banked?
+ * What actual ranges are the configuration registers accessible in?
+ * This isn't really a cartridge - does it belong elsewhere?
+
+ ***************************************************************************/
+
+#include "emu.h"
+#include "gbck003.h"
+
+#include "cartbase.ipp"
+
+#include <string>
+
+//#define VERBOSE 1
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+
+namespace bus::gameboy {
+
+namespace {
+
+class gbck003_device : public flat_ram_device_base<mbc_dual_uniform_device_base>
+{
+public:
+ gbck003_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+ virtual std::error_condition load(std::string &message) override ATTR_COLD;
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+private:
+ void bank_switch_inner(u8 data);
+ void bank_switch_outer(u8 data);
+ void bank_set_mux(u8 data);
+ void exit_config_mode(u8 data);
+
+ TIMER_CALLBACK_MEMBER(do_reset);
+
+ u16 bank_rom_entry_low() const noexcept
+ {
+ // TODO: is this affected by the multiplexer?
+ return u16(m_bank_setting[0]) << 1;
+ }
+
+ u16 bank_rom_entry_high() const noexcept
+ {
+ return (u16(m_bank_setting[0] & m_bank_mux_rom) << 1) | (m_bank_setting[1] & ~(u16(m_bank_mux_rom) << 1));
+ }
+
+ u8 m_bank_setting[2];
+ u8 m_bank_mux_rom;
+ u8 m_config_mode;
+};
+
+
+gbck003_device::gbck003_device(
+ machine_config const &mconfig,
+ char const *tag,
+ device_t *owner,
+ u32 clock) :
+ flat_ram_device_base<mbc_dual_uniform_device_base>(mconfig, GB_ROM_GBCK003, tag, owner, clock),
+ m_bank_setting{ 0U, 0U },
+ m_bank_mux_rom(0U),
+ m_config_mode(0U)
+{
+}
+
+
+std::error_condition gbck003_device::load(std::string &message)
+{
+ // set up ROM/RAM
+ set_bank_bits_rom(9);
+ if (!check_rom(message))
+ return image_error::BADSOFTWARE;
+ install_rom();
+ install_ram();
+
+ // install bank switch handlers
+ cart_space()->install_write_handler(
+ 0x2000, 0x3fff,
+ emu::rw_delegate(*this, FUNC(gbck003_device::bank_switch_inner)));
+ cart_space()->install_write_handler(
+ 0x7b00, 0x7b00,
+ emu::rw_delegate(*this, FUNC(gbck003_device::bank_switch_outer)));
+ cart_space()->install_write_handler(
+ 0x7b01, 0x7b01,
+ emu::rw_delegate(*this, FUNC(gbck003_device::bank_set_mux)));
+ cart_space()->install_write_handler(
+ 0x7b02, 0x7b02,
+ emu::rw_delegate(*this, FUNC(gbck003_device::exit_config_mode)));
+
+ // set initial power-on state
+ set_bank_rom_low(0);
+ set_bank_rom_high(1);
+
+ // all good
+ return std::error_condition();
+}
+
+
+void gbck003_device::device_start()
+{
+ flat_ram_device_base<mbc_dual_uniform_device_base>::device_start();
+
+ // this stuff must survive reset for getting out of CGB mode
+ m_bank_setting[0] = 0U;
+ m_bank_mux_rom = 0xff;
+ m_config_mode = 1U;
+
+ save_item(NAME(m_bank_setting));
+ save_item(NAME(m_bank_mux_rom));
+ save_item(NAME(m_config_mode));
+}
+
+
+void gbck003_device::device_reset()
+{
+ flat_ram_device_base<mbc_dual_uniform_device_base>::device_reset();
+
+ // TODO: proper reset state
+ m_bank_setting[1] = 1U;
+
+ set_bank_rom_high(bank_rom_entry_high());
+}
+
+
+void gbck003_device::bank_switch_inner(u8 data)
+{
+ data &= 0x1f;
+ m_bank_setting[1] = data ? data : 1;
+ set_bank_rom_high(bank_rom_entry_high());
+}
+
+
+void gbck003_device::bank_switch_outer(u8 data)
+{
+ if (m_config_mode)
+ {
+ LOG(
+ "%s: Set base page = 0x%03X (0x%06X)\n",
+ machine().describe_context(),
+ u16(data) << 1,
+ u32(data) << 15);
+ m_bank_setting[0] = data;
+ set_bank_rom_low(bank_rom_entry_low());
+ set_bank_rom_high(bank_rom_entry_high());
+ }
+ else
+ {
+ logerror(
+ "%s: Write 0x7B00 = 0x%02X after disabling configuration mode\n",
+ machine().describe_context(),
+ data);
+ }
+}
+
+
+void gbck003_device::bank_set_mux(u8 data)
+{
+ if (m_config_mode)
+ {
+ LOG(
+ "%s: Set bank multiplexer = 0x%03X\n",
+ machine().describe_context(),
+ u16(data) << 1);
+ m_bank_mux_rom = data;
+ set_bank_rom_high(bank_rom_entry_high());
+ }
+ else
+ {
+ logerror(
+ "%s: Write 0x7B01 = 0x%02X after disabling configuration mode\n",
+ machine().describe_context(),
+ data);
+ }
+}
+
+
+void gbck003_device::exit_config_mode(u8 data)
+{
+ if (m_config_mode)
+ {
+ if (0xf0 == data)
+ {
+ LOG("%s: Configuration mode disabled, resetting system\n", machine().describe_context());
+ m_config_mode = 0U;
+ machine().scheduler().synchronize(timer_expired_delegate(FUNC(gbck003_device::do_reset), this));
+ }
+ else
+ {
+ logerror(
+ "%s: Unknown write 0x7B02 = 0x%02X in configuration mode\n",
+ machine().describe_context(),
+ data);
+ }
+ }
+ else
+ {
+ logerror(
+ "%s: Write 0x7B02 = 0x%02X after disabling configuration mode\n",
+ machine().describe_context(),
+ data);
+ }
+}
+
+
+TIMER_CALLBACK_MEMBER(gbck003_device::do_reset)
+{
+ machine().root_device().reset(); // TODO: expose reset line on cartridge interface
+}
+
+} // anonymous namespace
+
+} // namespace bus::gameboy
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(GB_ROM_GBCK003, device_gb_cart_interface, bus::gameboy::gbck003_device, "gb_rom_gbck003", "Game Boy GBCK003 Multi-Game Board")
diff --git a/src/devices/bus/gameboy/gbck003.h b/src/devices/bus/gameboy/gbck003.h
new file mode 100644
index 00000000000..04aa19f2c44
--- /dev/null
+++ b/src/devices/bus/gameboy/gbck003.h
@@ -0,0 +1,18 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/***************************************************************************
+
+ GBCK003 multi-game board soldered inside some units
+
+ ***************************************************************************/
+#ifndef MAME_BUS_GAMEBOY_GBCK003_H
+#define MAME_BUS_GAMEBOY_GBCK003_H
+
+#pragma once
+
+#include "slot.h"
+
+
+DECLARE_DEVICE_TYPE(GB_ROM_GBCK003, device_gb_cart_interface)
+
+#endif // MAME_BUS_GAMEBOY_GBCK003_H
diff --git a/src/devices/bus/gameboy/gbslot.cpp b/src/devices/bus/gameboy/gbslot.cpp
new file mode 100644
index 00000000000..0f183b66cb1
--- /dev/null
+++ b/src/devices/bus/gameboy/gbslot.cpp
@@ -0,0 +1,1360 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/***************************************************************************
+
+ Game Boy cartridge slot
+
+ ***************************************************************************/
+
+#include "emu.h"
+#include "gbslot.h"
+
+#include "cartheader.h"
+#include "carts.h"
+#include "gbxfile.h"
+#include "mmm01.h"
+
+#include "bus/generic/slot.h"
+#include "cpu/lr35902/lr35902d.h"
+
+#include "disasmintf.h"
+
+#include <algorithm>
+#include <cstring>
+#include <iterator>
+#include <memory>
+#include <optional>
+#include <sstream>
+#include <string_view>
+#include <tuple>
+#include <utility>
+#include <vector>
+
+//#define VERBOSE 1
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+
+namespace bus::gameboy {
+
+namespace {
+
+class dasm_helper : public util::disasm_interface::data_buffer
+{
+public:
+ dasm_helper(u8 const *data, offs_t base_pc) : m_data(data), m_base_pc(base_pc)
+ { }
+
+ virtual u8 r8(offs_t pc) const override
+ { return m_data[pc - m_base_pc]; }
+
+ virtual u16 r16(offs_t pc) const override
+ { return r8(pc) | (u16(r8(pc + 1)) << 8); }
+
+ virtual u32 r32(offs_t pc) const override
+ { return r16(pc) | (u32(r16(pc + 2)) << 16); }
+
+ virtual u64 r64(offs_t pc) const override
+ { return r32(pc) | (u64(r32(pc + 4)) << 32); }
+
+private:
+ u8 const *const m_data;
+ offs_t const m_base_pc;
+};
+
+
+std::string disassemble_entry_point(u8 const *header)
+{
+ dasm_helper helper(header, 0x0100);
+ lr35902_disassembler dasm;
+ std::ostringstream str;
+ auto const result = dasm.disassemble(str, 0x0100, helper, helper);
+ str << " (";
+ bool first = true;
+ for (unsigned i = 0; (result & util::disasm_interface::LENGTHMASK) > i; ++i)
+ {
+ util::stream_format(str, first ? "%02X" : " %02X", header[i]);
+ first = false;
+ }
+ str << ')';
+ return std::move(str).str();
+}
+
+
+std::string cart_title_text(u8 const *header)
+{
+ std::string_view title(
+ reinterpret_cast<char const *>(&header[cartheader::OFFSET_TITLE - 0x100]),
+ cartheader::OFFSET_LICENSEE_EXT - cartheader::OFFSET_TITLE);
+
+ // best effort to strip off repurposed fields
+ if (!title[cartheader::OFFSET_MANUFACTURER - cartheader::OFFSET_TITLE - 1])
+ title.remove_suffix(cartheader::OFFSET_LICENSEE_EXT - cartheader::OFFSET_MANUFACTURER);
+ if (BIT(title.back(), 7))
+ title.remove_suffix(1);
+
+ // strip NUL padding, short-circuit empty titles
+ auto const last = title.find_last_not_of('\0');
+ if (std::string_view::npos == last)
+ return "\"\"";
+ title.remove_suffix(title.length() - last - 1);
+
+ // replace non-ASCII characters with octal escapes
+ std::ostringstream str;
+ str.setf(std::ios_base::oct, std::ios_base::basefield);
+ str.fill('0');
+ str << '"';
+ while (!title.empty())
+ {
+ auto const invalid = std::find_if(
+ title.begin(),
+ title.end(),
+ [] (char ch) { return (' ' > ch) || ('~' < ch); });
+ auto const len = std::distance(title.begin(), invalid);
+ if (len)
+ {
+ str << title.substr(0, len);
+ title.remove_prefix(len);
+ }
+ else
+ {
+ str << '\\';
+ str.width(3);
+ str << unsigned(u8(title.front()));
+ title.remove_prefix(1);
+ }
+ }
+ str << '"';
+ return std::move(str).str();
+}
+
+
+char const *cart_cgb_support_description(u8 const flags)
+{
+ if (!BIT(flags, 7))
+ return "unsupported";
+ else if (BIT(flags, 2, 2))
+ return "PGB mode";
+ else if (BIT(flags, 6))
+ return "required";
+ else
+ return "enhanced";
+}
+
+
+char const *cart_sgb_support_description(u8 const *header)
+{
+ if (0x33 != header[cartheader::OFFSET_LICENSEE - 0x100])
+ return "unaware";
+ else if (0x03 != header[cartheader::OFFSET_SGB - 0x100])
+ return "unsupported";
+ else
+ return "enhanced";
+}
+
+
+char const *cart_type_description(u8 type)
+{
+ switch (type)
+ {
+ case cartheader::TYPE_ROM:
+ return "flat ROM";
+ case cartheader::TYPE_MBC1:
+ return "Nintendo MBC1";
+ case cartheader::TYPE_MBC1_RAM:
+ return "Nintendo MBC1 with RAM";
+ case cartheader::TYPE_MBC1_RAM_BATT:
+ return "Nintendo MBC1 with battery-backed RAM";
+ case cartheader::TYPE_MBC2:
+ return "Nintendo MBC2";
+ case cartheader::TYPE_MBC2_BATT:
+ return "Nintendo MBC2 with backup battery";
+ case cartheader::TYPE_ROM_RAM:
+ return "flat ROM with RAM";
+ case cartheader::TYPE_ROM_RAM_BATT:
+ return "flat ROM with battery-backed RAM";
+ case cartheader::TYPE_MMM01:
+ return "Nintendo MMM01";
+ case cartheader::TYPE_MMM01_RAM:
+ return "Nintendo MMM01 with RAM";
+ case cartheader::TYPE_MMM01_RAM_BATT:
+ return "Nintendo MMM01 with battery-backed RAM";
+ case cartheader::TYPE_MBC3_RTC_BATT:
+ return "Nintendo MBC3 with backup battery and real-time clock crystal";
+ case cartheader::TYPE_MBC3_RTC_RAM_BATT:
+ return "Nintendo MBC3 with battery-backed RAM and real-time clock crystal";
+ case cartheader::TYPE_MBC3:
+ return "Nintendo MBC3";
+ case cartheader::TYPE_MBC3_RAM:
+ return "Nintendo MBC3 with RAM";
+ case cartheader::TYPE_MBC3_RAM_BATT:
+ return "Nintendo MBC3 with battery-backed RAM";
+ case cartheader::TYPE_MBC5:
+ return "Nintendo MBC5";
+ case cartheader::TYPE_MBC5_RAM:
+ return "Nintendo MBC5 with RAM";
+ case cartheader::TYPE_MBC5_RAM_BATT:
+ return "Nintendo MBC5 with battery-backed RAM";
+ case cartheader::TYPE_MBC5_RUMBLE:
+ return "Nintendo MBC5 with vibration motor";
+ case cartheader::TYPE_MBC5_RUMBLE_RAM:
+ return "Nintendo MBC5 with RAM and vibration motor";
+ case cartheader::TYPE_MBC5_RUMBLE_RAM_BATT:
+ return "Nintendo MBC5 with battery-backed RAM and vibration motor";
+ case cartheader::TYPE_MBC6:
+ return "Nintendo MBC6 with Flash memory and battery-backed RAM";
+ case cartheader::TYPE_MBC7_ACCEL_EEPROM:
+ return "Nintendo MBC7 with EEPROM and two-axis accelerometer";
+ case cartheader::TYPE_UNLICENSED_YONGYONG:
+ return "Yong Yong pirate";
+ case cartheader::TYPE_CAMERA:
+ return "Nintendo Game Boy Camera with battery-backed RAM";
+ case cartheader::TYPE_TAMA5:
+ return "Bandai TAMA5 with battery-backed TAMA6 and real-time clock";
+ case cartheader::TYPE_HUC3:
+ return "Hudson Soft HuC-3 with battery-baked RAM";
+ case cartheader::TYPE_HUC1_RAM_BATT:
+ return "Hudson Soft HuC-1 with battery-baked RAM";
+ default:
+ return "unknown";
+ }
+}
+
+
+std::string cart_rom_size_description(u8 size, memory_region *romregion)
+{
+ auto const actual = romregion ? romregion->bytes() : 0U;
+ switch (size)
+ {
+ case cartheader::ROM_SIZE_32K:
+ case cartheader::ROM_SIZE_64K:
+ case cartheader::ROM_SIZE_128K:
+ case cartheader::ROM_SIZE_256K:
+ case cartheader::ROM_SIZE_512K:
+ return util::string_format(
+ "%u KiB actual %u%s",
+ 32U << (size - cartheader::ROM_SIZE_32K),
+ actual,
+ ((u32(0x8000) << (size - cartheader::ROM_SIZE_32K)) != actual) ? " MISMATCH!" : "");
+ case cartheader::ROM_SIZE_1024K:
+ case cartheader::ROM_SIZE_2048K:
+ case cartheader::ROM_SIZE_4096K:
+ case cartheader::ROM_SIZE_8192K:
+ return util::string_format(
+ "%u MiB actual %u%s",
+ 1U << (size - cartheader::ROM_SIZE_1024K),
+ actual,
+ ((u32(0x8000) << (size - cartheader::ROM_SIZE_32K)) != actual) ? " MISMATCH!" : "");
+ case cartheader::ROM_SIZE_1152K:
+ case cartheader::ROM_SIZE_1280K:
+ case cartheader::ROM_SIZE_1536K:
+ return util::string_format(
+ "%u KiB actual %u%s",
+ 0x400U | (0x80U << (size - cartheader::ROM_SIZE_1152K)),
+ actual,
+ ((u32(0x10'0000) | (u32(0x2'0000) << (size - cartheader::ROM_SIZE_1152K))) != actual) ? " MISMATCH!" : "");
+ default:
+ return util::string_format("unknown actual %u", actual);
+ }
+}
+
+
+std::string cart_ram_size_description(u8 size)
+{
+ switch (size)
+ {
+ case cartheader::RAM_SIZE_0K:
+ return "none";
+ case cartheader::RAM_SIZE_2K:
+ case cartheader::RAM_SIZE_8K:
+ case cartheader::RAM_SIZE_32K:
+ case cartheader::RAM_SIZE_128K:
+ return util::string_format("%u KiB", 2U << ((size - cartheader::RAM_SIZE_2K) << 1));
+ case cartheader::RAM_SIZE_64K:
+ return "64 KiB";
+ default:
+ return "unknown";
+ }
+}
+
+
+char const *cart_region_description(u8 region)
+{
+ switch (region)
+ {
+ case 0: return "Japan";
+ case 1: return "export";
+ default: return "unknown";
+ }
+}
+
+
+std::string cart_licensee_description(u8 const *header)
+{
+ // TODO: fill in and correct lists, distinguish duplicates
+ static constexpr std::pair<u8, char const *> BASE[] = {
+ { 0x01, "Nintendo" },
+ { 0x08, "Capcom" }, { 0x09, "Hot-B" }, { 0x0a, "Jaleco" }, { 0x0b, "Coconuts Japan" },
+ { 0x0c, "Elite Systems" },
+ { 0x13, "Electronic Arts" },
+ { 0x18, "Hudson Soft" }, { 0x19, "ITC Entertainment" }, { 0x1a, "Yanoman" },
+ { 0x1d, "Japan Clary" }, { 0x1f, "Virgin" },
+ { 0x24, "PCM Complete" }, { 0x25, "San-X" },
+ { 0x28, "KEMCO" }, { 0x29, "Seta" },
+ { 0x30, "Infogrames" }, { 0x31, "Nintendo" }, { 0x32, "Bandai" },
+ { 0x34, "Konami" }, { 0x35, "HectorSoft" },
+ { 0x38, "Capcom" }, { 0x39, "Banpresto" },
+ { 0x3e, "Gremlin" },
+ { 0x41, "Ubi Soft" }, { 0x42, "Atlus" },
+ { 0x44, "Malibu" }, { 0x46, "Angel" }, { 0x47, "Spectrum Holobyte" },
+ { 0x49, "Irem" }, { 0x4a, "Virgin" },
+ { 0x4d, "Malibu" }, { 0x4f, "U.S. Gold" },
+ { 0x50, "Absolute" }, { 0x51, "Acclaim" }, { 0x52, "Activision" }, { 0x53, "American Sammy" },
+ { 0x54, "GameTek" }, { 0x55, "Park Place Productions" }, { 0x56, "LJN Entertainment" }, { 0x57, "Matchbox" },
+ { 0x59, "Milton Bradley" }, { 0x5a, "Mindscape" }, { 0x5b, "Romstar" },
+ { 0x5c, "Naxat Soft" }, { 0x5d, "Tradewest" },
+ { 0x60, "Titus" }, { 0x61, "Virgin" },
+ { 0x67, "Ocean" },
+ { 0x69, "Electronic Arts" },
+ { 0x6e, "Elite Systems" }, { 0x6f, "Electro Brain Corp." },
+ { 0x70, "Infogrames" }, { 0x71, "Interplay" }, { 0x72, "Broderbund" }, { 0x73, "Sculptured Software" },
+ { 0x75, "SCi Games" },
+ { 0x78, "THQ" }, { 0x79, "Accolade" }, { 0x7a, "Triffix Entertainment" },
+ { 0x7c, "Microprose" }, { 0x7f, "Kemco" },
+ { 0x80, "Misawa Entertainment" }, { 0x83, "LOZC" },
+ { 0x86, "Tokuma Shoten Intermedia " },
+ { 0x8b, "Bullet-Proof Software" },
+ { 0x8c, "Vic Tokai" }, { 0x8e, "Ape" }, { 0x8f, "I'Max Corp." },
+ { 0x91, "Chunsoft Co." }, { 0x92, "Video System" }, { 0x93, "Tsuburaya Productions Co." },
+ { 0x95, "Varie Corporation" }, { 0x97, "Kaneko" },
+ { 0x99, "Arc" }, { 0x9a, "Nihon Bussan Co." }, { 0x9b, "Tecmo" },
+ { 0x9c, "Imagineer" }, { 0x9d, "Banpresto" }, { 0x9f, "Nova" },
+ { 0xa1, "Hori Electric Co." }, { 0xa2, "Bandai" },
+ { 0xa4, "Konami" }, { 0xa6, "Kawada Co." }, { 0xa7, "Takara" },
+ { 0xa9, "Technos Japan" }, { 0xaa, "Broderbund" },
+ { 0xac, "Toei Animation" }, { 0xad, "Toho Co." }, { 0xaf, "Namco" },
+ { 0xb0, "Acclaim" }, { 0xb1, "ASCII Corporation" }, { 0xb2, "Bandai" },
+ { 0xb4, "Enix" }, { 0xb6, "HAL Laboratory" }, { 0xb7, "SNK" },
+ { 0xb9, "Pony Canyon" }, { 0xba, "Culture Brain" }, { 0xbb, "Sunsoft" },
+ { 0xbd, "Sony Imagesoft" }, { 0xbf, "Sammy" },
+ { 0xc0, "Taito" }, { 0xc2, "Kemco" }, { 0xc3, "Square Soft" },
+ { 0xc4, "Tokuma Shoten Intermedia" }, { 0xc5, "Data East" }, { 0xc6, "Tonkinhouse" },
+ { 0xc8, "Koei" }, { 0xca, "Ultra" }, { 0xcb, "Vap" },
+ { 0xcc, "Use Corporation" }, { 0xcd, "Meldac" }, { 0xce, "Pony Canyon" }, { 0xcf, "Angel" },
+ { 0xd0, "Taito" }, { 0xd1, "Sofel" }, { 0xd2, "quest" }, { 0xd3, "Sigma Enterprises" },
+ { 0xd4, "ASK Kodansha Co." }, { 0xd6, "Naxat Soft" }, { 0xd7, "Copya System" },
+ { 0xd9, "Banpresto" }, { 0xda, "Tomy" }, { 0xdb, "LJN Entertainment" },
+ { 0xdd, "NCS Corporation" }, { 0xde, "Human" }, { 0xdf, "Altron Corporation" },
+ { 0xe0, "Jaleco" }, { 0xe1, "Towa Chiki" }, { 0xe2, "Yutaka" }, { 0xe3, "Varie Corporation" },
+ { 0xe5, "Epoch Co." }, { 0xe7, "Athena" },
+ { 0xe8, "Asmik Ace Entertainment" }, { 0xe9, "Natsume" }, { 0xea, "King Records Co." }, { 0xeb, "Atlus" },
+ { 0xec, "Epic/Sony Records" }, { 0xee, "IGS Co." },
+ { 0xf0, "A Wave" }, { 0xf3, "Extreme Entertainment Group" },
+ { 0xff, "LJN Entertainment" } };
+ static constexpr std::pair<u16, char const *> EXTENDED[] = {
+ { 0x3031, "Nintendo R&D1" },
+ { 0x3038, "Capcom" },
+ { 0x3133, "Electronic Arts" },
+ { 0x3138, "Hudson Soft" },
+ { 0x3139, "b-ai" },
+ { 0x3230, "KSS" },
+ { 0x3232, "pow" },
+ { 0x3234, "PCM Complete" },
+ { 0x3235, "San-X" },
+ { 0x3238, "Kemco Japan" },
+ { 0x3239, "Seta" },
+ { 0x3330, "Viacom" },
+ { 0x3331, "Nintendo" },
+ { 0x3332, "Bandai" },
+ { 0x3333, "Ocean/Acclaim" },
+ { 0x3334, "Konami" },
+ { 0x3335, "HectorSoft" },
+ { 0x3337, "Taito" },
+ { 0x3338, "Hudson" },
+ { 0x3339, "Banpresto" },
+ { 0x3431, "Ubi Soft" },
+ { 0x3432, "Atlus" },
+ { 0x3434, "Malibu" },
+ { 0x3436, "Angel" },
+ { 0x3437, "Bullet-Proof Software" },
+ { 0x3439, "Irem" },
+ { 0x3530, "Absolute" },
+ { 0x3531, "Acclaim" },
+ { 0x3532, "Activision" },
+ { 0x3533, "American Sammy" },
+ { 0x3534, "Konami" },
+ { 0x3535, "Hi Tech Entertainment" },
+ { 0x3536, "LJN Entertainment" },
+ { 0x3537, "Matchbox" },
+ { 0x3538, "Mattel" },
+ { 0x3539, "Milton Bradley" },
+ { 0x3630, "Titus" },
+ { 0x3631, "Virgin" },
+ { 0x3634, "LucasArts" },
+ { 0x3637, "Ocean" },
+ { 0x3639, "Electronic Arts" },
+ { 0x3730, "Infogrames" },
+ { 0x3731, "Interplay" },
+ { 0x3732, "Broderbund" },
+ { 0x3733, "Sculptured Software" },
+ { 0x3735, "SCi Games" },
+ { 0x3738, "THQ" },
+ { 0x3739, "Accolade" },
+ { 0x3830, "Misawa Entertainment" },
+ { 0x3833, "LOZC" },
+ { 0x3836, "Tokuma Shoten Intermedia" },
+ { 0x3837, "Tsukuda Original" },
+ { 0x3931, "Chunsoft Co." },
+ { 0x3932, "Video System" },
+ { 0x3933, "Ocean/Acclaim" },
+ { 0x3935, "Varie Corporation" },
+ { 0x3936, "Yonezawa/s'pal" },
+ { 0x3937, "Kaneko" },
+ { 0x3939, "Pack-In-Video Co." },
+ { 0x4134, "Konami (Yu-Gi-Oh!)" } };
+
+ // 0x33 means two bytes of the title have been repurposed
+ u8 const licensee = header[cartheader::OFFSET_LICENSEE - 0x100];
+ if (0x33 == licensee)
+ {
+ u16 const ext = (u16(header[cartheader::OFFSET_LICENSEE_EXT - 0x100]) << 8) | header[cartheader::OFFSET_LICENSEE_EXT + 1 - 0x100];
+ auto const found = std::lower_bound(
+ std::begin(EXTENDED),
+ std::end(EXTENDED),
+ ext,
+ [] (auto const &x, auto const &y) { return x.first < y; });
+ if ((std::end(EXTENDED) != found) && (found->first == ext))
+ return util::string_format("0x%02X (%s)", ext, found->second);
+ else
+ return util::string_format("0x%04X (unknown)", ext);
+ }
+ else
+ {
+ auto const found = std::lower_bound(
+ std::begin(BASE),
+ std::end(BASE),
+ licensee,
+ [] (auto const &x, auto const &y) { return x.first < y; });
+ if ((std::end(BASE) != found) && (found->first == licensee))
+ return util::string_format("0x%02X (%s)", licensee, found->second);
+ else
+ return util::string_format("0x%02X (unknown)", licensee);
+ }
+}
+
+
+u32 get_mmm01_initial_low_page(u64 length)
+{
+ // this is inefficient but it works, offloading the logic to a common helper
+ std::vector<unsigned> pages;
+ auto const mask = device_generic_cart_interface::map_non_power_of_two(
+ unsigned(length / 0x4000),
+ [&pages] (unsigned entry, unsigned page) { pages.emplace_back(page); });
+ return u32(pages[0x01fe & mask] * u32(0x4000));
+}
+
+
+bool is_wisdom_tree(std::string_view tag, util::random_read &file, u64 length, u64 offset, u8 const *header)
+{
+ // all Wisdom Tree games declare 32 KiB ROM
+ if (cartheader::ROM_SIZE_32K != header[cartheader::OFFSET_ROM_SIZE - 0x100])
+ return false;
+
+ // no Wisdom Tree game declares cartridge RAM
+ if (cartheader::RAM_SIZE_0K != header[cartheader::OFFSET_RAM_SIZE - 0x100])
+ return false;
+
+ // 8 MiB maximum supported program ROM
+ if ((u32(0x8000) << 8) < length)
+ return false;
+
+ // only makes sense with more than 32 KiB program ROM
+ if (0x8000 >= length)
+ return false;
+
+ // must be multiple of 32 KiB program ROM page size
+ if (length & 0x7fff)
+ return false;
+
+ // assume Wisdom Tree
+ osd_printf_verbose(
+ "[%s] Assuming 0x%06X-byte cartridge declaring 32 KiB ROM and no RAM uses Wisdom Tree banking\n",
+ tag,
+ length);
+ return true;
+}
+
+
+bool is_mbc30(std::string_view tag, util::random_read &file, u64 length, u64 offset, u8 const *header)
+{
+ // MBC30 supposedly has an additional ROM bank output
+ if ((u32(0x4000) << 7) < length)
+ {
+ osd_printf_verbose(
+ "[%s] Assuming 0x%06X-byte cartridge declaring MBC3 controller uses MBC30\n",
+ tag,
+ length);
+ return true;
+ }
+
+ // MBC30 has three RAM bank outputs, supporting up to 64 KiB static RAM
+ if (cartheader::RAM_SIZE_64K == header[cartheader::OFFSET_RAM_SIZE - 0x100])
+ {
+ osd_printf_verbose(
+ "[%s] Assuming cartridge declaring MBC3 controller with 64 KiB RAM uses MBC30\n",
+ tag);
+ return true;
+ }
+
+ // MBC3 should be fine
+ return false;
+}
+
+
+bool is_m161(std::string_view tag, util::random_read &file, u64 length, u64 offset, u8 const *header)
+{
+ // supports eight 32 KiB banks at most, doesn't make sense without at least two banks
+ if (((u32(0x8000) << 3) < length) || (0x8000 >= length) || (length & 0x7fff))
+ return false;
+
+ // doesn't support banked RAM
+ u8 const ramsize(header[cartheader::OFFSET_RAM_SIZE - 0x100]);
+ switch (ramsize)
+ {
+ case cartheader::RAM_SIZE_0K:
+ case cartheader::RAM_SIZE_2K:
+ case cartheader::RAM_SIZE_8K:
+ break;
+ default:
+ return false;
+ }
+
+ // check header checksum for the first page
+ if (!cartheader::verify_header_checksum(header))
+ return false;
+
+ // there's one known cartridge using this scheme
+ static constexpr u8 KNOWN_COLLECTIONS[][0x10] = {
+ { 'T', 'E', 'T', 'R', 'I', 'S', ' ', 'S', 'E', 'T', 0, 0, 0, 0, 0, 0 } };
+ auto const known(
+ std::find_if(
+ std::begin(KNOWN_COLLECTIONS),
+ std::end(KNOWN_COLLECTIONS),
+ [header] (auto const &name)
+ {
+ return std::equal(std::begin(name), std::end(name), &header[cartheader::OFFSET_TITLE - 0x100]);
+ }));
+ if (std::end(KNOWN_COLLECTIONS) != known)
+ {
+ osd_printf_verbose("[%s] Detected known M161 game title\n", tag);
+ return true;
+ }
+
+ // look for a valid header in the second page
+ u8 header2[0x50];
+ auto const [err, actual] = read_at(file, offset + 0x8000 + 0x0100, header2, sizeof(header2));
+ if (err || (sizeof(header2) != actual) || !cartheader::verify_header_checksum(header2))
+ return false;
+
+ // make sure it fits with the cartridge RAM size declaration
+ switch (header2[cartheader::OFFSET_TYPE - 0x100])
+ {
+ case cartheader::TYPE_ROM:
+ osd_printf_verbose("[%s] Detected valid plain ROM game header at 0x8000, assuming M161 cartridge\n", tag);
+ return true;
+ case cartheader::TYPE_ROM_RAM:
+ case cartheader::TYPE_ROM_RAM_BATT:
+ switch (header[cartheader::OFFSET_RAM_SIZE - 0x100])
+ {
+ case cartheader::RAM_SIZE_2K:
+ if (cartheader::RAM_SIZE_0K != ramsize)
+ {
+ osd_printf_verbose(
+ "[%s] Detected valid plain ROM + 2 KiB RAM game header at 0x8000, assuming M161 cartridge\n",
+ tag);
+ return true;
+ }
+ return false;
+ case cartheader::RAM_SIZE_8K:
+ if (cartheader::RAM_SIZE_8K == ramsize)
+ {
+ osd_printf_verbose(
+ "[%s] Detected valid plain ROM + 8 KiB RAM game header at 0x8000, assuming M161 cartridge\n",
+ tag);
+ return true;
+ }
+ return false;
+ }
+ return false;
+ default:
+ return false;
+ }
+}
+
+
+char const *guess_mbc7_type(std::string_view tag, util::random_read &file, u64 length, u64 offset, u8 const *header)
+{
+ // there are only two games using MBC7 - by coincidence, the larger program requires the larger EEPROM
+ if (0x100000 < length)
+ {
+ osd_printf_verbose("[%s] Assuming 0x%06X-byte MBC7 program expects 4 Kibit 93LC66 EEPROM\n", tag, length);
+ return slotoptions::GB_MBC7_4K;
+ }
+ else
+ {
+ osd_printf_verbose("[%s] Assuming 0x%06X-byte MBC7 program expects 2 Kibit 93LC56 EEPROM\n", tag, length);
+ return slotoptions::GB_MBC7_2K;
+ }
+}
+
+
+bool read_gbx_footer_trailer(util::random_read &file, u64 length, gbxfile::trailer &trailer)
+{
+ if (sizeof(trailer) >= length)
+ return false;
+
+ auto const [err, actual] = read_at(file, length - sizeof(trailer), &trailer, sizeof(trailer));
+ if (err || (sizeof(trailer) != actual))
+ return false;
+
+ trailer.swap();
+ return (gbxfile::MAGIC_GBX == trailer.magic) && (length >= trailer.size);
+}
+
+
+std::optional<char const *> probe_gbx_footer(std::string_view tag, util::random_read &file, u64 &length, u64 &offset)
+{
+ // first try to read the trailer and look for a recognised version
+ gbxfile::trailer trailer;
+ if (!read_gbx_footer_trailer(file, length, trailer))
+ return std::nullopt;
+ else if ((1 != trailer.ver_maj) || ((sizeof(trailer) + sizeof(gbxfile::leader_1_0)) > trailer.size))
+ return std::nullopt;
+
+ // need to read the footer leader
+ std::error_condition err;
+ size_t actual;
+ gbxfile::leader_1_0 leader;
+ std::tie(err, actual) = read_at(file, length - trailer.size, &leader, sizeof(leader));
+ if (err || (sizeof(leader) != actual))
+ {
+ osd_printf_warning(
+ "[%s] Error reading GBX trailer leader - assuming file is not GBX format\n",
+ tag);
+ return std::nullopt;
+ }
+ leader.swap();
+
+ // if the ROM would overlap the footer, assume it isn't GBX format
+ if ((length - trailer.size) < leader.rom_bytes)
+ return std::nullopt;
+
+ // if we got this far, trust the program ROM size declared in the footer
+ osd_printf_verbose(
+ "[%s] Found GBX footer version %u.%u declaring 0x%06X-byte ROM\n",
+ tag,
+ trailer.ver_maj,
+ trailer.ver_min,
+ leader.rom_bytes);
+ length = leader.rom_bytes;
+ offset = 0;
+
+ // map known GBX cartridge types to slot options
+ char const *result = nullptr;
+ switch (leader.cart_type)
+ {
+ case gbxfile::TYPE_PLAIN:
+ result = slotoptions::GB_STD;
+ break;
+ case gbxfile::TYPE_M161:
+ result = slotoptions::GB_M161;
+ break;
+ case gbxfile::TYPE_TAMA5:
+ result = slotoptions::GB_TAMA5;
+ break;
+ case gbxfile::TYPE_WISDOM:
+ result = slotoptions::GB_WISDOM;
+ break;
+ case gbxfile::TYPE_SACHEN1:
+ result = slotoptions::GB_SACHEN1;
+ break;
+ case gbxfile::TYPE_SACHEN2:
+ result = slotoptions::GB_SACHEN2;
+ break;
+ case gbxfile::TYPE_ROCKET:
+ result = slotoptions::GB_ROCKET;
+ break;
+ case gbxfile::TYPE_MBC1:
+ case gbxfile::TYPE_MBC1_COLL:
+ result = slotoptions::GB_MBC1;
+ break;
+ case gbxfile::TYPE_MBC2:
+ result = slotoptions::GB_MBC2;
+ break;
+ case gbxfile::TYPE_MBC3:
+ if (((u32(0x4000) << 7) < leader.rom_bytes) || ((u32(0x2000) << 2) < leader.ram_bytes))
+ result = slotoptions::GB_MBC30;
+ else
+ result = slotoptions::GB_MBC3;
+ break;
+ case gbxfile::TYPE_MBC5:
+ result = slotoptions::GB_MBC5;
+ break;
+ case gbxfile::TYPE_MBC6:
+ result = slotoptions::GB_MBC6;
+ break;
+ case gbxfile::TYPE_MBC7:
+ {
+ // need to probe for EEPROM size
+ // TODO: does the GBX footer declare the EEPROM size as cartridge RAM size?
+ u8 header[0x50];
+ std::tie(err, actual) = read_at(file, offset + 0x100, header, sizeof(header));
+ if (!err && (sizeof(header) == actual))
+ {
+ result = guess_mbc7_type(tag, file, length, offset, header);
+ }
+ else
+ {
+ osd_printf_warning(
+ "[%s] Error reading cartridge header - defaulting to 93LC66 EEPROM for MBC7\n",
+ tag);
+ result = slotoptions::GB_MBC7_4K;
+ }
+ }
+ break;
+ case gbxfile::TYPE_MMM01:
+ result = slotoptions::GB_MMM01;
+ break;
+ case gbxfile::TYPE_CAMERA:
+ result = slotoptions::GB_CAMERA;
+ break;
+ case gbxfile::TYPE_HUC1:
+ result = slotoptions::GB_HUC1;
+ break;
+ case gbxfile::TYPE_HUC3:
+ result = slotoptions::GB_HUC3;
+ break;
+ case gbxfile::TYPE_TFANGBOOT:
+ result = slotoptions::GB_TFANGBOOT;
+ break;
+ case gbxfile::TYPE_BBD:
+ result = slotoptions::GB_BBD;
+ break;
+ case gbxfile::TYPE_DSHGGB81:
+ result = slotoptions::GB_DSHGGB81;
+ break;
+ case gbxfile::TYPE_SINTAX:
+ result = slotoptions::GB_SINTAX;
+ break;
+ case gbxfile::TYPE_LICHENG:
+ result = slotoptions::GB_LICHENG;
+ break;
+ case gbxfile::TYPE_NEWGBCHK:
+ result = slotoptions::GB_NEWGBCHK;
+ break;
+ case gbxfile::TYPE_VF001:
+ result = slotoptions::GB_VF001;
+ break;
+ case gbxfile::TYPE_LIEBAO:
+ result = slotoptions::GB_LIEBAO;
+ break;
+ case gbxfile::TYPE_NTNEW:
+ result = slotoptions::GB_NTNEW;
+ break;
+ case gbxfile::TYPE_SLMULTI:
+ result = slotoptions::GB_SLMULTI;
+ break;
+ }
+ if (result)
+ {
+ osd_printf_verbose(
+ "[%s] GBX cartridge type 0x%08X mapped to slot option '%s'\n",
+ tag,
+ leader.cart_type,
+ result);
+ }
+ else
+ {
+ osd_printf_verbose(
+ "[%s] Unknown GBX cartridge type 0x%08X\n",
+ tag,
+ leader.cart_type);
+ }
+ return result;
+}
+
+
+char const *guess_image_format(std::string_view tag, util::random_read &file, u64 &length, u64 &offset)
+{
+ // probe for GBX format - this can set the length and offset while still failing to select a slot option
+ std::optional<char const *> const gbxoption = probe_gbx_footer(tag, file, length, offset);
+ if (gbxoption)
+ return *gbxoption;
+
+ // some ROM images apparently have a 512-byte header
+ if ((0x4000 < length) && ((length & 0x3fff) == 0x0200))
+ {
+ osd_printf_verbose("[%s] Assuming 0x%06X-byte cartridge file contains 0x0200-byte header\n", tag, length);
+ length -= 0x2000;
+ offset = 0x0200;
+ return nullptr;
+ }
+
+ // assume it's a common .gb plain ROM image file
+ osd_printf_verbose("[%s] Assuming 0x%06X-byte cartridge file is a plain ROM image\n", tag, length);
+ offset = 0;
+ return nullptr;
+}
+
+
+bool detect_mmm01(std::string_view tag, util::random_read &file, u64 length, u64 offset, u8 const *header)
+{
+ // MMM01 cartridges must be a multiple of 16 KiB no larger than 8 MiB
+ if ((length & 0x3fff) || ((u32(0x4000) << 9) < length))
+ return false;
+
+ // now check for a valid cartridge header
+ u32 const lastpage(get_mmm01_initial_low_page(length));
+ u8 backheader[0x50];
+ auto const [err, actual] = read_at(file, lastpage + 0x100, backheader, sizeof(backheader));
+ if (err || (sizeof(backheader) != actual))
+ {
+ osd_printf_warning(
+ "[%s] Error reading last page of program ROM - assuming cartridge does not use MMM01 controller\n",
+ tag);
+ return false;
+ }
+ if (!cartheader::verify_header_checksum(backheader))
+ return false;
+
+
+ // well-behaved game that declares MMM01 here
+ u8 const backtype(backheader[cartheader::OFFSET_TYPE - 0x100]);
+ switch (backtype)
+ {
+ case cartheader::TYPE_MMM01:
+ case cartheader::TYPE_MMM01_RAM:
+ case cartheader::TYPE_MMM01_RAM_BATT:
+ osd_printf_verbose(
+ "[%s] Found MMM01 header at 0x%06X, assuming cartridge uses MMM01 header\n",
+ tag,
+ lastpage);
+ return true;
+ case cartheader::TYPE_MBC3:
+ {
+ static constexpr u8 KNOWN_COLLECTIONS[][0x10] = {
+ { 'B', 'O', 'U', 'K', 'E', 'N', 'J', 'I', 'M', 'A', '2', ' ', 'S', 'E', 'T', 0 },
+ { 'B', 'U', 'B', 'B', 'L', 'E', 'B', 'O', 'B', 'B', 'L', 'E', ' ', 'S', 'E', 'T' },
+ { 'G', 'A', 'N', 'B', 'A', 'R', 'U', 'G', 'A', ' ', 'S', 'E', 'T', 0, 0, 0 },
+ { 'R', 'T', 'Y', 'P', 'E', ' ', '2', ' ', 'S', 'E', 'T', 0, 0, 0, 0, 0 } };
+ auto const known(
+ std::find_if(
+ std::begin(KNOWN_COLLECTIONS),
+ std::end(KNOWN_COLLECTIONS),
+ [&backheader] (auto const &name)
+ {
+ return std::equal(std::begin(name), std::end(name), &backheader[cartheader::OFFSET_TITLE - 0x100]);
+ }));
+ if (std::end(KNOWN_COLLECTIONS) != known)
+ {
+ osd_printf_verbose("[%s] Detected known MMM01 game title\n", tag);
+ return true;
+ }
+ }
+ break;
+ }
+
+ // not a recognised MMM01 game
+ return false;
+}
+
+
+char const *guess_cart_type(std::string_view tag, util::random_read &file, u64 length, u64 offset, u8 const *header)
+{
+ u8 const carttype = header[cartheader::OFFSET_TYPE - 0x0100];
+ switch (carttype)
+ {
+ case cartheader::TYPE_ROM:
+ if (is_wisdom_tree(tag, file, length, offset, header))
+ return slotoptions::GB_WISDOM;
+ return slotoptions::GB_STD;
+ case cartheader::TYPE_MBC1:
+ case cartheader::TYPE_MBC1_RAM:
+ case cartheader::TYPE_MBC1_RAM_BATT:
+ return slotoptions::GB_MBC1;
+ // 0x04
+ case cartheader::TYPE_MBC2:
+ case cartheader::TYPE_MBC2_BATT:
+ return slotoptions::GB_MBC2;
+ case cartheader::TYPE_ROM_RAM:
+ case cartheader::TYPE_ROM_RAM_BATT:
+ return slotoptions::GB_STD;
+ // 0x09
+ // 0x0a
+ case cartheader::TYPE_MMM01:
+ case cartheader::TYPE_MMM01_RAM:
+ case cartheader::TYPE_MMM01_RAM_BATT:
+ return slotoptions::GB_MMM01;
+ // 0x0e
+ case cartheader::TYPE_MBC3_RTC_BATT:
+ if (is_mbc30(tag, file, length, offset, header))
+ return slotoptions::GB_MBC30;
+ return slotoptions::GB_MBC3;
+ case cartheader::TYPE_MBC3_RTC_RAM_BATT:
+ if (is_m161(tag, file, length, offset, header))
+ return slotoptions::GB_M161;
+ else if (is_mbc30(tag, file, length, offset, header))
+ return slotoptions::GB_MBC30;
+ return slotoptions::GB_MBC3;
+ case cartheader::TYPE_MBC3:
+ case cartheader::TYPE_MBC3_RAM:
+ case cartheader::TYPE_MBC3_RAM_BATT:
+ if (is_mbc30(tag, file, length, offset, header))
+ return slotoptions::GB_MBC30;
+ return slotoptions::GB_MBC3;
+ // 0x14
+ case cartheader::TYPE_MBC5:
+ case cartheader::TYPE_MBC5_RAM:
+ case cartheader::TYPE_MBC5_RAM_BATT:
+ case cartheader::TYPE_MBC5_RUMBLE:
+ case cartheader::TYPE_MBC5_RUMBLE_RAM:
+ case cartheader::TYPE_MBC5_RUMBLE_RAM_BATT:
+ return slotoptions::GB_MBC5;
+ // 0x1f
+ case cartheader::TYPE_MBC6:
+ return slotoptions::GB_MBC6;
+ // 0x21
+ case cartheader::TYPE_MBC7_ACCEL_EEPROM:
+ return guess_mbc7_type(tag, file, length, offset, header);
+
+ case cartheader::TYPE_UNLICENSED_YONGYONG:
+ return slotoptions::GB_YONG;
+
+ case cartheader::TYPE_CAMERA:
+ return slotoptions::GB_CAMERA;
+ case cartheader::TYPE_TAMA5:
+ return slotoptions::GB_TAMA5;
+ case cartheader::TYPE_HUC3:
+ return slotoptions::GB_HUC3;
+ case cartheader::TYPE_HUC1_RAM_BATT:
+ return slotoptions::GB_HUC1;
+ }
+
+ if (0x8000 >= length)
+ {
+ osd_printf_warning(
+ "[%s] Unknown cartridge type 0x%02X - defaulting to flat ROM for 0x%04X-byte cartridge\n",
+ tag,
+ carttype,
+ length);
+ return slotoptions::GB_STD;
+ }
+ else if ((u32(0x4000) << 7) >= length)
+ {
+ osd_printf_warning(
+ "[%s] Unknown cartridge type 0x%02X - defaulting to MBC1 for 0x%06X-byte cartridge\n",
+ tag,
+ carttype,
+ length);
+ return slotoptions::GB_MBC1;
+ }
+ else
+ {
+ osd_printf_warning(
+ "[%s] Unknown cartridge type 0x%02X - defaulting to MBC5 for 0x%06X-byte cartridge\n",
+ tag,
+ carttype,
+ length);
+ return slotoptions::GB_MBC5;
+ }
+}
+
+} // anonymous namespace
+
+} // namespace bus::gameboy
+
+
+
+//**************************************************************************
+// gb_cart_slot_device
+//**************************************************************************
+
+gb_cart_slot_device::gb_cart_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) :
+ gb_cart_slot_device_base(mconfig, GB_CART_SLOT, tag, owner, clock)
+{
+}
+
+
+std::string gb_cart_slot_device::get_default_card_software(get_default_card_software_hook &hook) const
+{
+ using namespace bus::gameboy;
+
+ if (hook.image_file())
+ {
+ u64 len;
+ if (hook.image_file()->length(len))
+ {
+ // if we can't get the file, use MBC1 - it's a common mapper and also works with flat ROMs
+ osd_printf_warning("[%s] Error getting cartridge ROM length - defaulting to MBC1\n", tag());
+ return slotoptions::GB_MBC1;
+ }
+
+ u64 offset;
+ char const *const guess(guess_image_format(tag(), *hook.image_file(), len, offset));
+ if (guess)
+ return guess;
+
+ u8 header[0x50];
+ auto const [err, actual] = read_at(*hook.image_file(), offset + 0x0100, header, sizeof(header));
+ if (err || (sizeof(header) != actual))
+ {
+ // reading header failed - guess based on size
+ if (0x8000 >= len)
+ {
+ osd_printf_warning(
+ "[%s] Error reading cartridge header - defaulting to flat ROM for 0x%04X-byte cartridge\n",
+ tag(),
+ len);
+ return slotoptions::GB_STD;
+ }
+ else if ((u32(0x4000) << 7) >= len)
+ {
+ osd_printf_warning(
+ "[%s] Error reading cartridge header - defaulting to MBC1 for 0x%06X-byte cartridge\n",
+ tag(),
+ len);
+ return slotoptions::GB_MBC1;
+ }
+ else
+ {
+ osd_printf_warning(
+ "[%s] Error reading cartridge header - defaulting to MBC5 for 0x%06X-byte cartridge\n",
+ tag(),
+ len);
+ return slotoptions::GB_MBC5;
+ }
+ }
+
+ // MMM01 controller doesn't initially map the first page
+ if (detect_mmm01(tag(), *hook.image_file(), len, offset, header))
+ return slotoptions::GB_MMM01;
+ else
+ return guess_cart_type(tag(), *hook.image_file(), len, offset, header);
+ }
+
+ // this will return the explicit setting for a software list item
+ return software_get_default_slot(slotoptions::GB_STD);
+}
+
+
+void gb_cart_slot_device::device_reset_after_children()
+{
+ using namespace bus::gameboy;
+
+ gb_cart_slot_device_base::device_reset_after_children();
+
+ // read the header as seen by the system on reset
+ u8 header[0x50];
+ {
+ auto const suppressor = machine().disable_side_effects();
+ for (unsigned i = 0; std::size(header) > i; ++i)
+ header[i] = cart_space().read_byte(0x100 + i);
+ }
+
+ // get some fields that are used multiple times
+ u8 const cgb = header[cartheader::OFFSET_CGB - 0x100];
+ u8 const type = header[cartheader::OFFSET_TYPE - 0x100];
+ u8 const romsize = header[cartheader::OFFSET_ROM_SIZE - 0x100];
+ u8 const ramsize = header[cartheader::OFFSET_RAM_SIZE - 0x100];
+ u8 const region = header[cartheader::OFFSET_REGION - 0x100];
+ u8 const headerchecksum = header[cartheader::OFFSET_CHECKSUM_HEADER - 0x100];
+ u16 const romchecksum = (u16(header[cartheader::OFFSET_CHECKSUM_ROM - 0x100]) << 8) | header[cartheader::OFFSET_CHECKSUM_ROM + 1 - 0x100];
+
+ // calculate checksums
+ u8 const headercalc = cartheader::checksum(
+ &header[cartheader::OFFSET_TITLE - 0x100],
+ &header[cartheader::OFFSET_CHECKSUM_HEADER - 0x100]);
+ u16 romcalc = 0U - (romchecksum >> 8) - (romchecksum & 0x00ff);
+ memory_region *const romregion = memregion("rom");
+ if (romregion)
+ {
+ u8 const *const data = &romregion->as_u8();
+ romcalc = std::accumulate(&data[0], &data[romregion->bytes()], romcalc);
+ }
+
+ // log parsed header for informational purposes
+ logerror(
+ "Cartridge header information:\n"
+ " * Entry point: %s\n"
+ " * Title: %s\n"
+ " * Game Boy Color: %s\n"
+ " * Super Game Boy: 0x%02X (%s)\n"
+ " * Type: 0x%02X (%s)\n"
+ " * ROM size: 0x%02X (%s)\n"
+ " * RAM size: 0x%02X (%s)\n"
+ " * Region: 0x%02X (%s)\n"
+ " * Licensee: %s\n"
+ " * Revision: 0x%02X\n"
+ " * Header checksum: 0x%02X (calculated 0x%02X%s)\n"
+ " * ROM checksum: 0x%04X (calculated 0x%04X%s)\n",
+ disassemble_entry_point(header),
+ cart_title_text(header),
+ cart_cgb_support_description(cgb),
+ header[cartheader::OFFSET_SGB - 0x100],
+ cart_sgb_support_description(header),
+ type,
+ cart_type_description(type),
+ romsize,
+ cart_rom_size_description(romsize, romregion),
+ ramsize,
+ cart_ram_size_description(ramsize),
+ region,
+ cart_region_description(region),
+ cart_licensee_description(header),
+ header[cartheader::OFFSET_REVISION - 0x100],
+ headerchecksum,
+ headercalc,
+ (headerchecksum != headercalc) ? " MISMATCH!" : "",
+ romchecksum,
+ romcalc,
+ (romchecksum != romcalc) ? " MISMATCH!" : "");
+}
+
+
+std::pair<std::error_condition, std::string> gb_cart_slot_device::load_image_file(util::random_read &file)
+{
+ using namespace bus::gameboy;
+
+ bool proberam = true;
+ auto len = length();
+ u64 offset;
+
+ // probe for GBX format
+ memory_region *gbxregion = nullptr;
+ gbxfile::trailer gbxtrailer;
+ if (read_gbx_footer_trailer(file, len, gbxtrailer))
+ {
+ // try reading the GBX footer into temporary space before more checks
+ std::unique_ptr<u8 []> const footer(new (std::nothrow) u8 [gbxtrailer.size]);
+ if (!footer)
+ return std::make_pair(std::errc::not_enough_memory, "Error allocating memory to read GBX file footer");
+ auto const [err, actual] = read_at(file, len - gbxtrailer.size, footer.get(), gbxtrailer.size);
+ if (err || (gbxtrailer.size != actual))
+ return std::make_pair(err ? err : std::errc::io_error, "Error reading GBX file footer");
+ if (1 != gbxtrailer.ver_maj)
+ {
+ // some unsupported GBX version - assume footer immediately follows ROM
+ osd_printf_verbose(
+ "[%s] Found found unsupported GBX file footer version %u.%u (%u bytes)\n",
+ tag(),
+ gbxtrailer.ver_maj,
+ gbxtrailer.ver_min,
+ gbxtrailer.size);
+ LOG("Allocating %u byte GBX file footer region\n", gbxtrailer.size);
+ gbxregion = machine().memory().region_alloc(subtag("gbx"), gbxtrailer.size, 1, ENDIANNESS_BIG);
+ std::memcpy(gbxregion->base(), footer.get(), gbxtrailer.size);
+ offset = 0;
+ len -= gbxtrailer.size;
+ }
+ else if ((sizeof(gbxfile::leader_1_0) + sizeof(gbxtrailer)) > gbxtrailer.size)
+ {
+ osd_printf_verbose(
+ "[%s] %u-byte GBX footer is too small to contain %u-byte leader and %u-byte trailer, assuming file is not GBX format\n",
+ tag(),
+ gbxtrailer.size,
+ sizeof(gbxfile::leader_1_0),
+ sizeof(gbxtrailer));
+ }
+ else
+ {
+ // ensure ROM doesn't overlap leader
+ gbxfile::leader_1_0 leader;
+ std::memcpy(&leader, footer.get(), sizeof(leader));
+ leader.swap();
+ if ((len - gbxtrailer.size) < leader.rom_bytes)
+ {
+ osd_printf_verbose(
+ "[%s] GBX footer specifies 0x%06X-byte ROM which exceeds 0x%06X-byte content, assuming file is not GBX format\n",
+ tag(),
+ leader.rom_bytes,
+ len - gbxtrailer.size);
+ }
+ else
+ {
+ // looks like supported GBX format
+ osd_printf_verbose(
+ "[%s] Found GBX file footer version %u.%u (%u bytes):\n"
+ " * %u bytes ROM\n"
+ " * %u bytes RAM\n"
+ "%s"
+ "%s"
+ "%s",
+ tag(),
+ gbxtrailer.ver_maj,
+ gbxtrailer.ver_min,
+ gbxtrailer.size,
+ leader.rom_bytes,
+ leader.ram_bytes,
+ leader.batt ? " * backup battery\n" : "",
+ leader.rumble ? " * vibration motor\n" : "",
+ leader.rtc ? " * real-time clock oscillator\n" : "");
+ proberam = false;
+ offset = 0;
+ len = leader.rom_bytes;
+
+ // copy the footer in case the cart needs it
+ LOG("Allocating %u byte GBX file footer region\n", gbxtrailer.size);
+ gbxregion = machine().memory().region_alloc(subtag("gbx"), gbxtrailer.size, 1, ENDIANNESS_BIG);
+ std::memcpy(gbxregion->base(), footer.get(), gbxtrailer.size);
+
+ // allocate RAM if appropriate
+ if (leader.ram_bytes)
+ {
+ LOG(
+ "Allocating %u byte cartridge %sRAM region\n",
+ leader.ram_bytes,
+ leader.batt ? "non-volatile " : "");
+ machine().memory().region_alloc(subtag(leader.batt ? "nvram" : "ram"), leader.ram_bytes, 1, ENDIANNESS_LITTLE);
+ }
+ }
+ }
+ }
+
+ // if it doesn't appear to be GBX format, check for apparent 512-byte header
+ if (!gbxregion)
+ {
+ if ((0x4000 < len) && ((len & 0x3fff) == 0x0200))
+ {
+ osd_printf_verbose("[%s] Assuming 0x%06X-byte cartridge file contains 0x0200-byte header\n", tag(), len);
+ len -= 0x2000;
+ offset = 0x0200;
+ }
+ else
+ {
+ offset = 0;
+ }
+ }
+
+ // load program ROM
+ if (len)
+ {
+ LOG("Allocating %u byte cartridge ROM region\n", len);
+ memory_region *const romregion = machine().memory().region_alloc(subtag("rom"), len, 1, ENDIANNESS_LITTLE);
+ auto const [err, actual] = read_at(file, offset, romregion->base(), len);
+ if (err || (len != actual))
+ return std::make_pair(err ? err : std::errc::io_error, "Error reading ROM data from cartridge file");
+
+ // allocate cartridge RAM based on header if necessary
+ if (proberam)
+ {
+ u8 const *const rombase = &romregion->as_u8();
+ u32 basepage = 0;
+ if (get_card_device()->device().type() == GB_ROM_MMM01)
+ basepage = get_mmm01_initial_low_page(len);
+ if ((basepage + cartheader::OFFSET_CHECKSUM_ROM) <= len)
+ allocate_cart_ram(&rombase[basepage]);
+ }
+ }
+
+ return std::make_pair(std::error_condition(), std::string());
+}
+
+
+void gb_cart_slot_device::allocate_cart_ram(u8 const *basepage)
+{
+ using namespace bus::gameboy;
+
+ if (cartheader::verify_header_checksum(&basepage[0x100]))
+ {
+ osd_printf_verbose("[%s] Detecting cartridge RAM size/type from header\n", tag());
+ bool nonvolatile;
+ u8 const carttype = basepage[cartheader::OFFSET_TYPE];
+ switch (carttype)
+ {
+ case cartheader::TYPE_MBC1_RAM_BATT:
+ case cartheader::TYPE_MBC2_BATT:
+ case cartheader::TYPE_ROM_RAM_BATT:
+ case cartheader::TYPE_MMM01_RAM_BATT:
+ case cartheader::TYPE_MBC3_RTC_BATT:
+ case cartheader::TYPE_MBC3_RTC_RAM_BATT:
+ case cartheader::TYPE_MBC3_RAM_BATT:
+ case cartheader::TYPE_MBC5_RAM_BATT:
+ case cartheader::TYPE_MBC5_RUMBLE_RAM_BATT:
+ case cartheader::TYPE_CAMERA:
+ case cartheader::TYPE_TAMA5:
+ case cartheader::TYPE_HUC3:
+ case cartheader::TYPE_HUC1_RAM_BATT:
+ osd_printf_verbose(
+ "[%s] Cartridge type 0x%02X assumed to preserve cartridge RAM contents\n",
+ tag(),
+ carttype);
+ nonvolatile = true;
+ break;
+ default:
+ nonvolatile = false;
+ }
+
+ u32 rambytes;
+ if ((cartheader::TYPE_MBC2 == carttype) || (cartheader::TYPE_MBC2_BATT == carttype))
+ {
+ osd_printf_verbose(
+ "[%s] Cartridge type 0x%02X has internal 512 nybble static RAM\n",
+ tag(),
+ carttype);
+ rambytes = 512;
+ }
+ else
+ {
+ u8 const ramsize = basepage[cartheader::OFFSET_RAM_SIZE];
+ switch (ramsize)
+ {
+ default:
+ osd_printf_warning("[%s] Cartridge declares unknown RAM size 0x%02X\n", tag(), ramsize);
+ [[fallthrough]];
+ case cartheader::RAM_SIZE_0K:
+ rambytes = 0;
+ break;
+ case cartheader::RAM_SIZE_2K:
+ rambytes = 2 * 1024;
+ break;
+ case cartheader::RAM_SIZE_8K:
+ rambytes = 8 * 1024;
+ break;
+ case cartheader::RAM_SIZE_32K:
+ rambytes = 32 * 1024;
+ break;
+ case cartheader::RAM_SIZE_128K:
+ rambytes = 128 * 1024;
+ break;
+ case cartheader::RAM_SIZE_64K:
+ rambytes = 64 * 1024;
+ break;
+ }
+ if (rambytes)
+ {
+ osd_printf_verbose(
+ "[%s] Cartridge declares RAM size 0x%02X corresponding to %u bytes\n",
+ tag(),
+ ramsize,
+ rambytes);
+ }
+ }
+
+ if (rambytes)
+ {
+ LOG(
+ "Allocating %u byte cartridge %sRAM region\n",
+ rambytes,
+ nonvolatile ? "non-volatile " : "");
+ machine().memory().region_alloc(subtag(nonvolatile ? "nvram" : "ram"), rambytes, 1, ENDIANNESS_LITTLE);
+ }
+ }
+}
+
+
+
+//**************************************************************************
+// Device type definitions
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(GB_CART_SLOT, gb_cart_slot_device, "gb_cart_slot", "Game Boy Cartridge Slot")
diff --git a/src/devices/bus/gameboy/gbslot.h b/src/devices/bus/gameboy/gbslot.h
new file mode 100644
index 00000000000..f235da46428
--- /dev/null
+++ b/src/devices/bus/gameboy/gbslot.h
@@ -0,0 +1,87 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/***************************************************************************
+
+ Game Boy cartridge slot
+
+ Cartridge edge connector (0.05" pitch single-sided):
+ Pin Name Description
+ 1 VCC +5 V DC power
+ 2 PHI CPU clock output
+ 3 /WR write strobe
+ 4 /RD read strobe
+ 5 /CS RAM chip select (active for address 0xa000-0xdfff)
+ 6 A0 address bit 0 (least significant)
+ 7 A1 address bit 1
+ 8 A2 address bit 2
+ 9 A3 address bit 3
+ 10 A4 address bit 4
+ 11 A5 address bit 5
+ 12 A6 address bit 6
+ 13 A7 address bit 7
+ 14 A8 address bit 8
+ 15 A9 address bit 9
+ 16 A10 address bit 10
+ 17 A11 address bit 11
+ 18 A12 address bit 12
+ 19 A13 address bit 13
+ 20 A14 address bit 14
+ 21 A15 address bit 15 (most significant)
+ 22 D0 data bit 0 (least significant)
+ 23 D1 data bit 1
+ 24 D2 data bit 2
+ 25 D3 data bit 3
+ 26 D4 data bit 4
+ 27 D5 data bit 5
+ 28 D6 data bit 6
+ 29 D7 data bit 7 (most significant)
+ 30 /RST system reset
+ 31 AUDIOIN connected to SoC VIN pin (only used by some music players)
+ 32 GND Ground
+
+ ***************************************************************************/
+#ifndef MAME_BUS_GAMEBOY_GBSLOT_H
+#define MAME_BUS_GAMEBOY_GBSLOT_H
+
+#pragma once
+
+#include "slot.h"
+
+#include <string>
+
+
+class gb_cart_slot_device : public gb_cart_slot_device_base
+{
+public:
+ template <typename T>
+ gb_cart_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts, char const *dflt) :
+ gb_cart_slot_device(mconfig, tag, owner, 0U)
+ {
+ option_reset();
+ opts(*this);
+ set_default_option(dflt);
+ set_fixed(false);
+ }
+ gb_cart_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+ // device_image_interface implementation
+ virtual const char *image_interface() const noexcept override { return "gameboy_cart"; }
+ virtual const char *file_extensions() const noexcept override { return "bin,gb,gbc,gbx"; }
+
+ // device_slot_interface implementation
+ virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override ATTR_COLD;
+
+protected:
+ // device_t implementation
+ virtual void device_reset_after_children() override ATTR_COLD;
+
+ // gb_cart_slot_device_base implementation
+ virtual std::pair<std::error_condition, std::string> load_image_file(util::random_read &file) override ATTR_COLD;
+
+ void allocate_cart_ram(u8 const *basepage) ATTR_COLD;
+};
+
+
+DECLARE_DEVICE_TYPE(GB_CART_SLOT, gb_cart_slot_device)
+
+#endif // MAME_BUS_GAMEBOY_GBSLOT_H
diff --git a/src/devices/bus/gameboy/gbxfile.cpp b/src/devices/bus/gameboy/gbxfile.cpp
new file mode 100644
index 00000000000..9058697b709
--- /dev/null
+++ b/src/devices/bus/gameboy/gbxfile.cpp
@@ -0,0 +1,59 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/***************************************************************************
+
+ GBX file format helpers
+
+ ***************************************************************************/
+
+#include "emu.h"
+#include "gbxfile.h"
+
+#include <cstring>
+
+
+namespace bus::gameboy::gbxfile {
+
+bool get_data(
+ memory_region *region,
+ leader_1_0 &leader,
+ u8 const *&extra,
+ u32 &extralen)
+{
+ // no region, no dice
+ if (!region)
+ return false;
+
+ // needs to contain enough data for the trailer at the very least
+ auto const bytes(region->bytes());
+ if (bytes < sizeof(trailer))
+ return false;
+
+ // check for supported format
+ u8 *const base(&region->as_u8());
+ trailer t;
+ std::memcpy(&t, &base[bytes - sizeof(t)], sizeof(t));
+ t.swap();
+ if ((MAGIC_GBX != t.magic) || (1 != t.ver_maj))
+ return false;
+
+ // check that the footer fits and the leader doesn't overlap the trailer
+ if ((bytes < t.size) || ((sizeof(leader) + sizeof(t)) > t.size))
+ return false;
+
+ // get leader in host byte order
+ std::memcpy(&leader, &base[bytes - t.size], sizeof(leader));
+ leader.swap();
+
+ // get pointer to extra data if there's any
+ extralen = t.size - sizeof(leader) - sizeof(t);
+ if (extralen)
+ extra = &base[bytes - t.size + sizeof(leader)];
+ else
+ extra = nullptr;
+
+ // all good
+ return true;
+}
+
+} // namespace bus::gameboy::gbxfile
diff --git a/src/devices/bus/gameboy/gbxfile.h b/src/devices/bus/gameboy/gbxfile.h
new file mode 100644
index 00000000000..0a30a7b25ac
--- /dev/null
+++ b/src/devices/bus/gameboy/gbxfile.h
@@ -0,0 +1,130 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/***************************************************************************
+
+ GBX file format helpers
+
+ GBX files start with the program ROM contents, and end with a footer.
+ Multi-byte values in the footer are stored in big-Endian order. Fields are
+ arranged for natural alignment. Version 1.0 seems to be the only
+ widespread version.
+
+ The footer ends with a 16-byte trailer:
+ * Offset from end of file to start of footer (4 bytes).
+ * Major version of footer format (4 bytes).
+ * Minor version of footer format (4 bytes).
+ * Magic number 0x47425821 or FourCC 'GBX!' (4 bytes).
+
+ The footer starts with a leader. Version 1.0 uses a 16-byte leader:
+ * A FourCC indicating the cartridge type (4 bytes).
+ * Flag indicating whether cartridge RAM contents is preserved (1 byte).
+ * Flag indicating whether a vibration motor is present (1 byte).
+ * Flag indicating whether a real-time clock oscillator is present (1 byte).
+ * Always seems to be zero - possibly unused padding (1 byte).
+ * Program ROM size in bytes (4 bytes).
+ * Cartridge RAM size in bytes (4 bytes).
+
+ There is additional data between the leader and trailer that can hold
+ additional wiring or configuration details for the cartridge if necessary.
+ In general, it's 32 bytes long, and unused portions are filled with 0x00.
+ It seems to be entirely unused for most cartridge types.
+
+ Vast Fame VF001 (FourCC 'VF01') additional data:
+ * Command preload value (1 byte).
+
+ Kong Feng DSH-GGB81 (FourCC 'GB81') additional data:
+ * Cartridge/PCB type (1 byte):
+ - 0x00: DSH-GGB81
+ - 0x01: BC-R1616T3P
+
+ The list of cartridge type FourCC values here is incomplete.
+
+ ***************************************************************************/
+#ifndef MAME_BUS_GAMEBOY_GBXFILE_H
+#define MAME_BUS_GAMEBOY_GBXFILE_H
+
+#pragma once
+
+
+namespace bus::gameboy::gbxfile {
+
+enum : u32
+{
+ MAGIC_GBX = 0x47425821 // 'GBX!'
+};
+
+enum : u32
+{
+ TYPE_BBD = 0x42424400, // 'BBD\0'
+ TYPE_CAMERA = 0x43414d52, // 'CAMR'
+ TYPE_DSHGGB81 = 0x47423831, // 'GB81'
+ TYPE_HUC1 = 0x48554331, // 'HUC1'
+ TYPE_HUC3 = 0x48554333, // 'HUC3'
+ TYPE_SLMULTI = 0x4c424d43, // 'LBMC'
+ TYPE_LICHENG = 0x4c494348, // 'LICH'
+ TYPE_LIEBAO = 0x4c494241, // 'LIBA'
+ TYPE_M161 = 0x4d313631, // 'M161'
+ TYPE_MBC1_COLL = 0x4d42314d, // 'MB1M'
+ TYPE_MBC1 = 0x4d424331, // 'MBC1'
+ TYPE_MBC2 = 0x4d424332, // 'MBC2'
+ TYPE_MBC3 = 0x4d424333, // 'MBC3'
+ TYPE_MBC5 = 0x4d424335, // 'MBC5'
+ TYPE_MBC6 = 0x4d424336, // 'MBC6'
+ TYPE_MBC7 = 0x4d424337, // 'MBC7'
+ TYPE_MMM01 = 0x4d4d4d31, // 'MMM1'
+ TYPE_NEWGBCHK = 0x4e47484b, // 'NGHK'
+ TYPE_NTNEW = 0x4e544e00, // 'NTN\0'
+ TYPE_TFANGBOOT = 0x504b4a44, // 'PKJD'
+ TYPE_ROCKET = 0x524f434b, // 'ROCK'
+ TYPE_PLAIN = 0x524f4d00, // 'ROM\0'
+ TYPE_SACHEN1 = 0x53414d31, // 'SAM1'
+ TYPE_SACHEN2 = 0x53414d32, // 'SAM2'
+ TYPE_SINTAX = 0x534e5458, // 'SNTX'
+ TYPE_TAMA5 = 0x54414d35, // 'TAM5'
+ TYPE_VF001 = 0x56463031, // 'VF01'
+ TYPE_WISDOM = 0x57495344 // 'WISD'
+};
+
+struct leader_1_0
+{
+ u32 cart_type;
+ u8 batt;
+ u8 rumble;
+ u8 rtc;
+ u8 unknown; // maybe padding?
+ u32 rom_bytes;
+ u32 ram_bytes;
+
+ void swap()
+ {
+ cart_type = big_endianize_int32(cart_type);
+ rom_bytes = big_endianize_int32(rom_bytes);
+ ram_bytes = big_endianize_int32(ram_bytes);
+ }
+};
+
+struct trailer
+{
+ u32 size;
+ u32 ver_maj;
+ u32 ver_min;
+ u32 magic;
+
+ void swap()
+ {
+ size = big_endianize_int32(size);
+ ver_maj = big_endianize_int32(ver_maj);
+ ver_min = big_endianize_int32(ver_min);
+ magic = big_endianize_int32(magic);
+ }
+};
+
+bool get_data(
+ memory_region *region,
+ leader_1_0 &leader,
+ u8 const *&extra,
+ u32 &extralen);
+
+} // namespace bus::gameboy::gbxfile
+
+#endif // MAME_BUS_GAMEBOY_GBXFILE_H
diff --git a/src/devices/bus/gameboy/huc1.cpp b/src/devices/bus/gameboy/huc1.cpp
new file mode 100644
index 00000000000..71c937cef95
--- /dev/null
+++ b/src/devices/bus/gameboy/huc1.cpp
@@ -0,0 +1,192 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/***************************************************************************
+
+ Hudson Soft HuC1 Memory Controller
+
+ Provides ROM and RAM banking and infrared I/O. Supports up to 1 MiB ROM
+ (64 16 KiB pages) and up to 32 KiB static RAM (4 8 KiB pages). If RAM bank
+ lines are used for coarse ROM banking, up to 4 MiB ROM (256 16 KiB pages)
+ can be supported.
+
+ The HuC1 controller appears to only respond to A15-A13 and D6-D0, i.e.
+ addresses are effectively masked with 0xE000 and data is effectively masked
+ with 0x3F.
+
+ The HuC1 controller doesn't support disabling cartridge RAM without
+ selecting infrared I/O. However, some games still write 0x00 or 0x0A to
+ the infrared/RAM select register as if it behaved like the Nintendo MBC
+ series RAM enable register. Some games write to the 0x6000-0x7FFF range,
+ but this has no detectable effect.
+
+ 0x0000-3FFF R - Fixed ROM bank, always first page of ROM.
+ 0x4000-7FFF R - Selectable ROM bank, page 0-255 of ROM.
+ 0xA000-BFFF RW - Static RAM or infrared I/O.
+
+ 0x0000-1FFF W - Select infrared (0x0E) or RAM (not 0x0E) at 0xA000.
+ 0x2000-3FFF W - Select ROM page mapped at 0x4000.
+ 0x4000-5FFF W - Select RAM page mapped at 0xA000.
+
+ TODO:
+ * If you try to use the infrared link feature in gbkiss, it says to press
+ the B button to stop communication, but it doesn't respond to any inputs.
+ Is this normal?
+ * What is the default state for banking and infrared select on reset?
+ * Does ROM bank 0 map to bank 1 like MBC1?
+ * How many RAM page lines are there? No games use more than 2.
+ * Do any bits of the infrared I/O registers have any significance besides
+ the least significant bit?
+ * Do any values besides 0x0E have special significance for infrared/RAM
+ select?
+
+ ***************************************************************************/
+
+#include "emu.h"
+#include "huc1.h"
+
+#include "cartbase.ipp"
+
+#include <string>
+
+//#define VERBOSE 1
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+
+namespace bus::gameboy {
+
+namespace {
+
+class huc1_device : public mbc_ram_device_base<mbc_dual_device_base>
+{
+public:
+ static constexpr feature_type unemulated_features() { return feature::COMMS; }
+
+ huc1_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+ virtual std::error_condition load(std::string &message) override ATTR_COLD;
+
+protected:
+ virtual void device_reset() override ATTR_COLD;
+
+private:
+ void infrared_select(u8 data);
+ void bank_switch_fine(u8 data);
+ void bank_switch_coarse(u8 data);
+ u8 read_ir(address_space &space);
+ void write_ir(u8 data);
+
+ memory_view m_view_ir;
+};
+
+
+huc1_device::huc1_device(
+ machine_config const &mconfig,
+ char const *tag,
+ device_t *owner,
+ u32 clock) :
+ mbc_ram_device_base<mbc_dual_device_base>(mconfig, GB_ROM_HUC1, tag, owner, clock),
+ m_view_ir(*this, "ir")
+{
+}
+
+
+std::error_condition huc1_device::load(std::string &message)
+{
+ // check for valid ROM/RAM regions
+ set_bank_bits_rom(2, 6);
+ set_bank_bits_ram(2);
+ if (!check_rom(message) || !check_ram(message))
+ return image_error::BADSOFTWARE;
+
+ // if that checked out, install memory
+ install_rom();
+ install_ram(*cart_space());
+
+ // install memory controller handlers
+ cart_space()->install_write_handler(
+ 0x0000, 0x1fff,
+ emu::rw_delegate(*this, FUNC(huc1_device::infrared_select)));
+ cart_space()->install_write_handler(
+ 0x2000, 0x3fff,
+ emu::rw_delegate(*this, FUNC(huc1_device::bank_switch_fine)));
+ cart_space()->install_write_handler(
+ 0x4000, 0x5fff,
+ emu::rw_delegate(*this, FUNC(huc1_device::bank_switch_coarse)));
+
+ // install infrared handlers
+ cart_space()->install_view(0xa000, 0xbfff, m_view_ir);
+ m_view_ir[0].install_read_handler(
+ 0xa000, 0xbfff,
+ emu::rw_delegate(*this, FUNC(huc1_device::read_ir)));
+ m_view_ir[0].install_write_handler(
+ 0xa000, 0xbfff,
+ emu::rw_delegate(*this, FUNC(huc1_device::write_ir)));
+
+ // all good
+ return std::error_condition();
+}
+
+
+void huc1_device::device_reset()
+{
+ mbc_ram_device_base<mbc_dual_device_base>::device_reset();
+
+ // TODO: what's the proper reset state?
+ m_view_ir.disable();
+
+ set_bank_rom_fine(0);
+ set_bank_rom_coarse(0);
+ set_bank_ram(0);
+}
+
+
+void huc1_device::infrared_select(u8 data)
+{
+ if (0x0e == (data & 0x0e))
+ {
+ LOG("%s: Infrared I/O selected\n", machine().describe_context());
+ m_view_ir.select(0);
+ }
+ else
+ {
+ LOG("%s: Cartridge RAM selected\n", machine().describe_context());
+ m_view_ir.disable();
+ }
+}
+
+
+void huc1_device::bank_switch_fine(u8 data)
+{
+ // TODO: does zero map to bank 1 like MBC1?
+ set_bank_rom_fine(data & 0x3f);
+}
+
+
+void huc1_device::bank_switch_coarse(u8 data)
+{
+ // TODO: how many output lines are physically present?
+ set_bank_rom_coarse(data & 0x03);
+ set_bank_ram(data & 0x03);
+}
+
+
+u8 huc1_device::read_ir(address_space &space)
+{
+ LOG("%s: Infrared read\n");
+ return (space.unmap() & 0xc0) | 0x00; // least significant bit clear - dark
+}
+
+
+void huc1_device::write_ir(u8 data)
+{
+ // bit zero high to turn on the IR LED, or low to turn it off
+ LOG("%s: Infrared write 0x%02X\n", machine().describe_context(), data);
+}
+
+} // anonymous namespace
+
+} // namespace bus::gameboy
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(GB_ROM_HUC1, device_gb_cart_interface, bus::gameboy::huc1_device, "gb_rom_huc1", "Game Boy Hudson Soft HuC1 Cartridge")
diff --git a/src/devices/bus/gameboy/huc1.h b/src/devices/bus/gameboy/huc1.h
new file mode 100644
index 00000000000..b1037eadb04
--- /dev/null
+++ b/src/devices/bus/gameboy/huc1.h
@@ -0,0 +1,18 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/***************************************************************************
+
+ Hudson Soft HuC-1 Memory Controller
+
+ ***************************************************************************/
+#ifndef MAME_BUS_GAMEBOY_HUC1_H
+#define MAME_BUS_GAMEBOY_HUC1_H
+
+#pragma once
+
+#include "slot.h"
+
+
+DECLARE_DEVICE_TYPE(GB_ROM_HUC1, device_gb_cart_interface)
+
+#endif // MAME_BUS_GAMEBOY_HUC1_H
diff --git a/src/devices/bus/gameboy/huc3.cpp b/src/devices/bus/gameboy/huc3.cpp
new file mode 100644
index 00000000000..c9b13943225
--- /dev/null
+++ b/src/devices/bus/gameboy/huc3.cpp
@@ -0,0 +1,698 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/***************************************************************************
+
+ Hudson Soft HuC-3 Memory Controller
+
+ Provides ROM and RAM banking, infrared I/O, a real-time clock and a melody
+ generator.
+
+ The HuC-3 controller appears to only respond to A15-A13 and D6-D0, i.e.
+ addresses are effectively masked with 0xE000 and data is effectively masked
+ with 0x7F.
+
+ Major components in the cartridge include:
+ * U1 program ROM
+ * U2 HuC-3 controller
+ * U3 LH52256CT-10LL 32K*8 static RAM
+ * U4 MM1026A or MM1134A system reset/backup power switch
+ * U5 TC74LVX04FT hex inverter
+ * D1 infrared LED
+ * Q1 infrared phototransistor
+ * X1 real-time clock crystal
+ * BATT CR2025 coin cell (user-replaceable)
+
+ HuC-3 48-pin QFP known connectons:
+ 1 13 D1 25 37
+ 2 Audio out 14 D0 26 38 XTAL out
+ 3 Audio out 15 27 39 XTAL in
+ 4 Audio out 16 28 40 GND
+ 5 17 29 41 GND
+ 6 18 A15 30 42 GND
+ 7 GND 19 GND 31 GND 43
+ 8 D6 20 32 44
+ 9 D5 21 33 45 /WR
+ 10 D4 22 34 46 /RD
+ 11 D3 23 A13 35 GND 47
+ 12 D2 24 IR out 36 GND 48
+
+ 0x0000-3FFF R - Fixed ROM bank, always first page of ROM.
+ 0x4000-7FFF R - Selectable ROM bank, page 0-255 of ROM.
+ 0xA000-BFFF RW - Static RAM or I/O.
+
+ 0x0000-1FFF W - Select RAM or I/O at 0xA000.
+ 0x2000-3FFF W - Select ROM page mapped at 0x4000.
+ 0x4000-5FFF W - Select RAM page mapped at 0xA000.
+
+ Only the four least significant bits of the RAM or I/O selection value are
+ significant. The ten unused values will map nothing into 0xA000-0xBFFF.
+ Used values:
+ 0x0 - RAM (read-only)
+ 0xA - RAM (read/write)
+ 0xB - Write command/data
+ 0xC - Read command/data
+ 0xD - Clear least significant bit to execute command
+ 0xE - Infrared I/O
+
+ The HuC-3 chip likely contains a 4-bit microcontroller that implements the
+ real-time clock and melody generator functionality. The game communicates
+ with the microcontroller via I/O 0xB, 0xC and 0xD.
+
+ Conceptually, the value written to 0xB contains two values: a 3-bit command
+ in bits 6-4, and a 4-bit value in bits 3-0. Reading 0x0C gives the same
+ command in bits 6-4 and a response value in bits 3-0. Writing to 0xB or
+ reading from 0xC has no immediate side effects.
+
+ Bit 0 for 0xD reads high when the microcontroller is ready to accept a
+ command. Writing with bit 0 clear causes the microcontroller to execute
+ the command previously written to 0xB. The microcontroller will set bit 0
+ when it has completed the command and is ready to execute another command.
+
+ Five of the eight possible commands are used by the games:
+ 0x1 - Read register and increment address (value put in bits 3-0 of 0xC).
+ 0x3 - Write register and increment address (value from bits 3-0 of 0xB).
+ 0x4 - Set register address low nybble.
+ 0x5 - Set register address high nybble.
+ 0x6 - Execute extended command (selector from bits 3-0 of 0xB).
+
+ The games use four of the sixteen possible extended commands:
+ 0x0 - Atomically read real-time clock to registers 0x00-0x06.
+ 0x1 - Atomically write real-time clock from registers 0x00-0x06.
+ Also updates event time in registers 0x58-0x5D.
+ 0x2 - Some kind of handshake/status request - sets result to 0x1.
+ 0xe - Sent twice to trigger melody generator.
+
+ Registers are likely a window into the microcontroller's memory. Known
+ registers:
+ 0x00-02 - Minute counter read/write (least significant nybble low)
+ 0x03-05 - Day counter read/write (least significant nybble low)
+ 0x10-12 - Minute counter (least significant nybble low)
+ 0x13-15 - Day counter (least significant nybble low)
+ 0x26 - Bits 1-0 select melody
+ 0x27 - Enable (0x1) or disable (not 0x1) melody
+ 0x58-5A - Event time minutes (least significant nybble low)
+ 0x5B-5D - Event time days (least significant nybble low)
+
+ TODO:
+ * Simulate more microcontroller functionality as it's discovered.
+ * Simulate melody generator?
+ * What is the default state for banking and infrared select on reset?
+ * Does ROM bank 0 map to bank 1 like MBC1?
+ * How many RAM page lines are there? No games use more than 2.
+
+ ***************************************************************************/
+
+#include "emu.h"
+#include "huc3.h"
+
+#include "cartbase.ipp"
+#include "gbxfile.h"
+
+#include "dirtc.h"
+
+#include <algorithm>
+#include <cassert>
+#include <iterator>
+#include <limits>
+#include <string>
+#include <tuple>
+#include <type_traits>
+
+//#define VERBOSE 1
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+
+namespace bus::gameboy {
+
+namespace {
+
+class huc3_device :
+ public mbc_ram_device_base<mbc_dual_device_base>,
+ public device_rtc_interface,
+ public device_nvram_interface
+{
+public:
+ static constexpr feature_type unemulated_features() { return feature::SOUND | feature::COMMS; }
+
+ huc3_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+ virtual std::error_condition load(std::string &message) override ATTR_COLD;
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ virtual void rtc_clock_updated(int year, int month, int day, int day_of_week, int hour, int minute, int second) override ATTR_COLD;
+
+ virtual void nvram_default() override ATTR_COLD;
+ virtual bool nvram_read(util::read_stream &file) override ATTR_COLD;
+ virtual bool nvram_write(util::write_stream &file) override ATTR_COLD;
+ virtual bool nvram_can_write() const override ATTR_COLD;
+
+private:
+ void io_select(u8 data);
+ void bank_switch_fine(u8 data);
+ void bank_switch_coarse(u8 data);
+ void write_command(u8 data);
+ u8 read_command(address_space &space);
+ u8 read_status(address_space &space);
+ void write_control(u8 data);
+ u8 read_ir(address_space &space);
+ void write_ir(u8 data);
+
+ TIMER_CALLBACK_MEMBER(rtc_advance_seconds);
+
+ void execute_instruction()
+ {
+ switch (m_ctrl_data & 0x0f)
+ {
+ case 0x0:
+ LOG("Instruction 0x0 - atomic RTC read\n");
+ std::copy_n(&m_registers[0x10], 7, &m_registers[0x00]);
+ break;
+ case 0x1:
+ {
+ LOG("Instruction 0x2 - atomic RTC write\n");
+
+ s16 const newminutes(read_12bit(0x00));
+ s16 const newdays(read_12bit(0x03));
+ s16 const oldminutes(read_12bit(0x10));
+ s16 const olddays(read_12bit(0x13));
+ s16 const eventminutes(read_12bit(0x58));
+ s16 const eventdays(read_12bit(0x5b));
+
+ s16 minutesdelta(newminutes - oldminutes);
+ s16 daysdelta(newdays - olddays);
+ while ((60 * 24) <= (eventminutes + minutesdelta))
+ {
+ minutesdelta -= 60 * 24;
+ ++daysdelta;
+ }
+ while (0 > (eventminutes + minutesdelta))
+ {
+ minutesdelta += 60 * 24;
+ --daysdelta;
+ }
+
+ assert(0 <= (eventminutes + minutesdelta));
+ assert((60 * 24) > (eventminutes + minutesdelta));
+ std::copy_n(&m_registers[0x00], 7, &m_registers[0x10]);
+ write_12bit(0x58, s16(eventminutes + minutesdelta));
+ write_12bit(0x5b, s16(eventdays + daysdelta));
+ }
+ break;
+ case 0x2:
+ logerror("Instruction 0x2 - setting data to 0x1\n");
+ m_ctrl_data = 0x01U;
+ break;
+ case 0xe:
+ logerror("Instruction 0xE - play melody\n");
+ break;
+ default:
+ logerror(
+ "%s: Unknown instruction 0x%X\n",
+ machine().describe_context(),
+ m_ctrl_data);
+ }
+ }
+
+ u16 read_12bit(u8 offset) const
+ {
+ return
+ (u16(m_registers[(offset + 0) & 0xff] & 0x0f) << 0) |
+ (u16(m_registers[(offset + 1) & 0xff] & 0x0f) << 4) |
+ (u16(m_registers[(offset + 2) & 0xff] & 0x0f) << 8);
+ }
+
+ void write_12bit(u8 offset, u16 data)
+ {
+ m_registers[(offset + 0) & 0xff] = (data >> 0) & 0x0f;
+ m_registers[(offset + 1) & 0xff] = (data >> 4) & 0x0f;
+ m_registers[(offset + 2) & 0xff] = (data >> 8) & 0x0f;
+ }
+
+ memory_view m_view_io;
+ emu_timer *m_timer_rtc;
+ s64 m_machine_seconds;
+ bool m_has_battery;
+
+ u8 m_seconds;
+ u8 m_ctrl_cmd;
+ u8 m_ctrl_data;
+ u8 m_ctrl_addr;
+ u8 m_registers[0x100];
+};
+
+
+huc3_device::huc3_device(
+ machine_config const &mconfig,
+ char const *tag,
+ device_t *owner,
+ u32 clock) :
+ mbc_ram_device_base<mbc_dual_device_base>(mconfig, GB_ROM_HUC3, tag, owner, clock),
+ device_rtc_interface(mconfig, *this),
+ device_nvram_interface(mconfig, *this),
+ m_view_io(*this, "io"),
+ m_timer_rtc(nullptr),
+ m_machine_seconds(0),
+ m_has_battery(false),
+ m_seconds(0U),
+ m_ctrl_cmd(0U),
+ m_ctrl_data(0U),
+ m_ctrl_addr(0U)
+{
+}
+
+
+std::error_condition huc3_device::load(std::string &message)
+{
+ // check for backup battery
+ if (loaded_through_softlist())
+ {
+ // if there's an NVRAM region, there must be a backup battery
+ if (cart_nvram_region())
+ {
+ logerror("Found 'nvram' region, backup battery must be present\n");
+ m_has_battery = true;
+ }
+ else
+ {
+ logerror("No 'nvram' region found, assuming no backup battery present\n");
+ m_has_battery = true;
+ }
+ }
+ else
+ {
+ gbxfile::leader_1_0 leader;
+ u8 const *extra;
+ u32 extralen;
+ if (gbxfile::get_data(gbx_footer_region(), leader, extra, extralen))
+ {
+ m_has_battery = bool(leader.batt);
+ logerror(
+ "GBX format image specifies %sbackup battery present\n",
+ m_has_battery ? "" : "no ");
+ }
+ else
+ {
+ // just assume the coin cell is present - every known game has it
+ logerror("Assuming backup battery present\n");
+ m_has_battery = true;
+ }
+ }
+
+ // check for valid ROM/RAM regions
+ set_bank_bits_rom(2, 7);
+ set_bank_bits_ram(2);
+ if (!check_rom(message) || !check_ram(message))
+ return image_error::BADSOFTWARE;
+
+ // if that checked out, install memory
+ cart_space()->install_view(0xa000, 0xbfff, m_view_io);
+ install_rom();
+ install_ram(m_view_io[0], m_view_io[1]);
+
+ // install memory controller handlers
+ cart_space()->install_write_handler(
+ 0x0000, 0x1fff,
+ emu::rw_delegate(*this, FUNC(huc3_device::io_select)));
+ cart_space()->install_write_handler(
+ 0x2000, 0x3fff,
+ emu::rw_delegate(*this, FUNC(huc3_device::bank_switch_fine)));
+ cart_space()->install_write_handler(
+ 0x4000, 0x5fff,
+ emu::rw_delegate(*this, FUNC(huc3_device::bank_switch_coarse)));
+
+ // install I/O handlers
+ m_view_io[2].install_write_handler(
+ 0xa000, 0xbfff,
+ emu::rw_delegate(*this, FUNC(huc3_device::write_command)));
+ m_view_io[3].install_read_handler(
+ 0xa000, 0xbfff,
+ emu::rw_delegate(*this, FUNC(huc3_device::read_command)));
+ m_view_io[4].install_read_handler(
+ 0xa000, 0xbfff,
+ emu::rw_delegate(*this, FUNC(huc3_device::read_status)));
+ m_view_io[4].install_write_handler(
+ 0xa000, 0xbfff,
+ emu::rw_delegate(*this, FUNC(huc3_device::write_control)));
+ m_view_io[5].install_read_handler(
+ 0xa000, 0xbfff,
+ emu::rw_delegate(*this, FUNC(huc3_device::read_ir)));
+ m_view_io[5].install_write_handler(
+ 0xa000, 0xbfff,
+ emu::rw_delegate(*this, FUNC(huc3_device::write_ir)));
+
+ // all good
+ return std::error_condition();
+}
+
+
+void huc3_device::device_start()
+{
+ mbc_ram_device_base<mbc_dual_device_base>::device_start();
+
+ m_seconds = 0U;
+ std::fill(std::begin(m_registers), std::end(m_registers), 0U);
+
+ m_timer_rtc = timer_alloc(FUNC(huc3_device::rtc_advance_seconds), this);
+
+ save_item(NAME(m_seconds));
+ save_item(NAME(m_ctrl_cmd));
+ save_item(NAME(m_ctrl_data));
+ save_item(NAME(m_ctrl_addr));
+ save_item(NAME(m_registers));
+
+ m_timer_rtc->adjust(attotime(1, 0), 0, attotime(1, 0));
+}
+
+
+void huc3_device::device_reset()
+{
+ mbc_ram_device_base<mbc_dual_device_base>::device_reset();
+
+ // TODO: what's the proper reset state?
+ m_view_io.disable();
+
+ set_bank_rom_fine(0);
+ set_bank_rom_coarse(0);
+ set_bank_ram(0);
+
+ m_ctrl_cmd = 0U;
+ m_ctrl_data = 0U;
+ m_ctrl_addr = 0U;
+}
+
+
+void huc3_device::rtc_clock_updated(
+ int year,
+ int month,
+ int day,
+ int day_of_week,
+ int hour,
+ int minute,
+ int second)
+{
+ if (!m_has_battery)
+ {
+ logerror("No battery present, not updating for elapsed time\n");
+ }
+ else if (std::numeric_limits<s64>::min() == m_machine_seconds)
+ {
+ logerror("Failed to load machine time from previous session, not updating for elapsed time\n");
+ }
+ else
+ {
+ // do a simple seconds elapsed since last run calculation
+ system_time current;
+ machine().current_datetime(current);
+ s64 delta(std::make_signed_t<decltype(current.time)>(current.time) - m_machine_seconds);
+ logerror("Previous session time, %d current time %d, delta %d\n", current.time, m_machine_seconds, delta);
+ if (0 > delta)
+ {
+ // This happens if the user runs the emulation faster
+ // than real time, exits, and then starts again without
+ // waiting for the difference between emulated and real
+ // time to elapse.
+ logerror("Previous session ended in the future, not updating for elapsed time\n");
+ }
+ else
+ {
+ // combine the counter nybbles for convenience
+ u16 minutes(read_12bit(0x10));
+ u16 days(read_12bit(0x13));
+ logerror(
+ "Time before applying delta %u %02u:%02u:%02u\n",
+ days,
+ minutes / 60,
+ minutes % 60,
+ m_seconds);
+
+ // deal with seconds
+ unsigned s(delta % 60);
+ delta /= 60;
+ if (64 <= m_seconds)
+ {
+ m_seconds = 0U;
+ --s;
+ ++delta;
+ }
+ if (60 <= (m_seconds + s))
+ ++delta;
+ m_seconds = (m_seconds + s) % 60;
+
+ // update the minute counter value
+ unsigned m(delta % (60 * 24));
+ delta /= 60 * 24;
+ if ((60 * 24) <= minutes)
+ {
+ minutes = 0U;
+ --m;
+ ++delta;
+ }
+ if ((60 * 24) <= (minutes + m))
+ ++delta;
+ minutes = (minutes + m) % (60 * 24);
+
+ // no special handling for day counter
+ days += delta;
+
+ // write the counter nybbles back to registers
+ write_12bit(0x10, minutes);
+ write_12bit(0x13, days);
+ logerror(
+ "Time after applying delta %u %02u:%02u:%02u\n",
+ days,
+ minutes / 60,
+ minutes % 60,
+ m_seconds);
+ }
+ }
+}
+
+
+void huc3_device::nvram_default()
+{
+ // TODO: proper cold RTC state
+ m_machine_seconds = std::numeric_limits<s64>::min();
+ m_seconds = 0U;
+ std::fill(std::begin(m_registers), std::end(m_registers), 0U);
+}
+
+
+bool huc3_device::nvram_read(util::read_stream &file)
+{
+ if (m_has_battery)
+ {
+ std::error_condition err;
+ std::size_t actual;
+
+ // read previous machine time (seconds since epoch)
+ u64 machinesecs;
+ std::tie(err, actual) = read(file, &machinesecs, sizeof(machinesecs));
+ if (err || (sizeof(machinesecs) != actual))
+ return false;
+ m_machine_seconds = big_endianize_int64(machinesecs);
+
+ // read seconds counter and register contents
+ std::tie(err, actual) = read(file, &m_seconds, sizeof(m_seconds));
+ if (err || (sizeof(m_seconds) != actual))
+ return false;
+ std::tie(err, actual) = read(file, &m_registers[0], sizeof(m_registers));
+ if (err || (sizeof(m_registers) != actual))
+ return false;
+ }
+ else
+ {
+ logerror("No battery present, not loading real-time clock register contents\n");
+ }
+ return true;
+}
+
+
+bool huc3_device::nvram_write(util::write_stream &file)
+{
+ // save current machine time as seconds since epoch, seconds counter, and register contents
+ system_time current;
+ machine().current_datetime(current);
+ u64 const machinesecs(big_endianize_int64(s64(std::make_signed_t<decltype(current.time)>(current.time))));
+ std::error_condition err;
+ std::size_t written;
+ std::tie(err, written) = write(file, &machinesecs, sizeof(machinesecs));
+ if (err)
+ return false;
+ std::tie(err, written) = write(file, &m_seconds, sizeof(m_seconds));
+ if (err)
+ return false;
+ std::tie(err, written) = write(file, &m_registers[0], sizeof(m_registers));
+ if (err)
+ return false;
+ return true;
+}
+
+
+bool huc3_device::nvram_can_write() const
+{
+ return m_has_battery;
+}
+
+
+void huc3_device::io_select(u8 data)
+{
+ switch (data & 0x0f)
+ {
+ case 0x00:
+ LOG("%s: Select RAM (read-only)\n", machine().describe_context());
+ m_view_io.select(0);
+ break;
+ case 0x0a:
+ LOG("%s: Select RAM (read/write)\n", machine().describe_context());
+ m_view_io.select(1);
+ break;
+ case 0x0b:
+ LOG("%s: Select control data write\n", machine().describe_context());
+ m_view_io.select(2);
+ break;
+ case 0x0c:
+ LOG("%s: Select control data read\n", machine().describe_context());
+ m_view_io.select(3);
+ break;
+ case 0x0d:
+ LOG("%s: Select control command/status\n", machine().describe_context());
+ m_view_io.select(4);
+ break;
+ case 0x0e:
+ LOG("%s: Select infrared I/O\n", machine().describe_context());
+ m_view_io.select(5);
+ break;
+ default:
+ LOG("%s: Select unused I/O 0x%X\n", machine().describe_context(), data & 0x0f);
+ m_view_io.disable();
+ }
+}
+
+
+void huc3_device::bank_switch_fine(u8 data)
+{
+ // TODO: does zero map to bank 1 like MBC1?
+ set_bank_rom_fine(data & 0x7f);
+}
+
+
+void huc3_device::bank_switch_coarse(u8 data)
+{
+ // TODO: how many output lines are physically present?
+ set_bank_rom_coarse(data & 0x03);
+ set_bank_ram(data & 0x03);
+}
+
+
+void huc3_device::write_command(u8 data)
+{
+ m_ctrl_cmd = BIT(data, 4, 3);
+ m_ctrl_data = BIT(data, 0, 4);
+ LOG(
+ "%s: Write command = 0x%X data = 0x%X\n",
+ machine().describe_context(),
+ m_ctrl_cmd,
+ m_ctrl_data);
+}
+
+
+u8 huc3_device::read_command(address_space &space)
+{
+ LOG(
+ "%s: Read command = 0x%X data = 0x%X\n",
+ machine().describe_context(),
+ m_ctrl_cmd,
+ m_ctrl_data);
+ return (space.unmap() & 0x80) | (m_ctrl_cmd << 4) | m_ctrl_data;
+}
+
+
+u8 huc3_device::read_status(address_space &space)
+{
+ LOG("%s: Read status\n", machine().describe_context());
+ return (space.unmap() & 0x80) | 0x7f; // least significant bit set when ready to receive a command
+}
+
+
+void huc3_device::write_control(u8 data)
+{
+ // TODO: Is there more to this?
+ LOG("%s: Write control = 0x%02X\n", machine().describe_context(), data);
+ if (!BIT(data, 0))
+ {
+ switch (m_ctrl_cmd)
+ {
+ case 0x1:
+ LOG("Command 0x1 - read register 0x%02X\n", m_ctrl_addr);
+ m_ctrl_data = m_registers[m_ctrl_addr++] & 0x0f;
+ break;
+ case 0x3:
+ LOG("Command 0x3 - write register 0x%02X = 0x%X\n", m_ctrl_addr, m_ctrl_data);
+ m_registers[m_ctrl_addr++] = m_ctrl_data & 0x0f;
+ break;
+ case 0x4:
+ m_ctrl_addr = (m_ctrl_addr & 0xf0) | (m_ctrl_data & 0x0f);
+ LOG("Command 0x4 - set register address = 0x%02X\n", m_ctrl_addr);
+ break;
+ case 0x5:
+ m_ctrl_addr = (m_ctrl_addr & 0x0f) | (m_ctrl_data << 4);
+ LOG("Command 0x5 - set register address = 0x%02X\n", m_ctrl_addr);
+ break;
+ case 0x6:
+ LOG("Command 0x6 - execute instruction 0x%X\n", m_ctrl_data);
+ execute_instruction();
+ break;
+ default:
+ logerror(
+ "%s: Unknown command 0x%X data = 0x%X\n",
+ machine().describe_context(),
+ m_ctrl_cmd,
+ m_ctrl_data);
+ }
+ }
+}
+
+
+u8 huc3_device::read_ir(address_space &space)
+{
+ LOG("%s: Infrared read\n", machine().describe_context());
+ return (space.unmap() & 0xc0) | 0x00; // least significant bit clear - dark
+}
+
+
+void huc3_device::write_ir(u8 data)
+{
+ // bit zero high to turn on the IR LED, or low to turn it off
+ LOG("%s: Infrared write 0x%02X\n", machine().describe_context(), data);
+}
+
+
+TIMER_CALLBACK_MEMBER(huc3_device::rtc_advance_seconds)
+{
+ if ((60 - 1) > m_seconds)
+ {
+ ++m_seconds;
+ return;
+ }
+
+ m_seconds = 0U;
+ u16 const minutes(read_12bit(0x10));
+ if (((60 * 24) - 1) > minutes)
+ {
+ write_12bit(0x10, minutes + 1);
+ return;
+ }
+
+ write_12bit(0x10, 0);
+ write_12bit(0x13, read_12bit(0x13) + 1);
+}
+
+} // anonymous namespace
+
+} // namespace bus::gameboy
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(GB_ROM_HUC3, device_gb_cart_interface, bus::gameboy::huc3_device, "gb_rom_huc3", "Game Boy Hudson Soft HuC-3 Cartridge")
diff --git a/src/devices/bus/gameboy/huc3.h b/src/devices/bus/gameboy/huc3.h
new file mode 100644
index 00000000000..13f73056b5c
--- /dev/null
+++ b/src/devices/bus/gameboy/huc3.h
@@ -0,0 +1,18 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/***************************************************************************
+
+ Hudson Soft HuC-3 Memory Controller
+
+ ***************************************************************************/
+#ifndef MAME_BUS_GAMEBOY_HUC3_H
+#define MAME_BUS_GAMEBOY_HUC3_H
+
+#pragma once
+
+#include "slot.h"
+
+
+DECLARE_DEVICE_TYPE(GB_ROM_HUC3, device_gb_cart_interface)
+
+#endif // MAME_BUS_GAMEBOY_HUC3_H
diff --git a/src/devices/bus/gameboy/liebao.cpp b/src/devices/bus/gameboy/liebao.cpp
new file mode 100644
index 00000000000..7916f5fc5d0
--- /dev/null
+++ b/src/devices/bus/gameboy/liebao.cpp
@@ -0,0 +1,159 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/***************************************************************************
+
+ Memory controller used by Liebao Technology
+
+ Supports switching 8 KiB pages at 0x4000 and 0x6000 independently. Only
+ even pages can be mapped at 0x4000, and only odd pages can be mapped at
+ 0x6000. Everything here is guesswork based on the behaviour of a single
+ game.
+
+ ***************************************************************************/
+
+#include "emu.h"
+#include "liebao.h"
+
+#include "cartbase.ipp"
+
+//#define VERBOSE 1
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+
+namespace bus::gameboy {
+
+namespace {
+
+class liebao_device : public mbc_ram_device_base<mbc_8k_device_base>
+{
+public:
+ liebao_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+ virtual std::error_condition load(std::string &message) override ATTR_COLD;
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+private:
+ void enable_ram(offs_t offset, u8 data);
+ void bank_switch_rom(offs_t offset, u8 data);
+ void bank_switch_ram(u8 data);
+ void bank_switch_rom_high(offs_t offset, u8 data);
+
+ memory_view m_view_ram;
+
+ u8 m_bank_high_set;
+};
+
+
+liebao_device::liebao_device(
+ machine_config const &mconfig,
+ char const *tag,
+ device_t *owner,
+ u32 clock) :
+ mbc_ram_device_base<mbc_8k_device_base>(mconfig, GB_ROM_LIEBAO, tag, owner, clock),
+ m_view_ram(*this, "ram"),
+ m_bank_high_set(0U)
+{
+}
+
+
+std::error_condition liebao_device::load(std::string &message)
+{
+ // set up ROM and RAM
+ set_bank_bits_rom(9);
+ set_bank_bits_ram(4);
+ if (!check_rom(message) || !check_ram(message))
+ return image_error::BADSOFTWARE;
+ cart_space()->install_view(0xa000, 0xbfff, m_view_ram);
+ install_rom(*cart_space(), *cart_space(), *cart_space());
+ install_ram(m_view_ram[0]);
+
+ // install handlers
+ cart_space()->install_write_handler(
+ 0x0000, 0x1fff,
+ emu::rw_delegate(*this, FUNC(liebao_device::enable_ram)));
+ cart_space()->install_write_handler(
+ 0x2000, 0x2fff,
+ emu::rw_delegate(*this, FUNC(liebao_device::bank_switch_rom)));
+ cart_space()->install_write_handler(
+ 0x4000, 0x5fff,
+ emu::rw_delegate(*this, FUNC(liebao_device::bank_switch_ram)));
+ cart_space()->install_write_handler(
+ 0x7000, 0x7fff,
+ emu::rw_delegate(*this, FUNC(liebao_device::bank_switch_rom_high)));
+
+ // all good
+ return std::error_condition();
+}
+
+
+void liebao_device::device_start()
+{
+ mbc_ram_device_base<mbc_8k_device_base>::device_start();
+
+ save_item(NAME(m_bank_high_set));
+}
+
+
+void liebao_device::device_reset()
+{
+ mbc_ram_device_base<mbc_8k_device_base>::device_reset();
+
+ m_view_ram.disable();
+ m_bank_high_set = 0U;
+
+ set_bank_rom_low(2);
+ set_bank_rom_high(3);
+ set_bank_ram(0);
+}
+
+
+void liebao_device::enable_ram(offs_t offset, u8 data)
+{
+ // TODO: how many bits are checked?
+ bool const enable(0x0a == (data & 0x0f));
+ LOG(
+ "%s: Cartridge RAM %s\n",
+ machine().describe_context(),
+ enable ? "enabled" : "disabled");
+ if (enable)
+ m_view_ram.select(0);
+ else
+ m_view_ram.disable();
+}
+
+
+void liebao_device::bank_switch_rom(offs_t offset, u8 data)
+{
+ set_bank_rom_low(u16(data) << 1);
+ if (m_bank_high_set || ((offset & 0x00ff) == 0x00d2))
+ m_bank_high_set = 0U;
+ else
+ set_bank_rom_high((u16(data) << 1) | 0x01);
+}
+
+
+void liebao_device::bank_switch_ram(u8 data)
+{
+ set_bank_ram(data & 0x0f);
+}
+
+
+void liebao_device::bank_switch_rom_high(offs_t offset, u8 data)
+{
+ if ((offset & 0x00ff) == 0x00d2)
+ {
+ m_bank_high_set = 1U;
+ set_bank_rom_high((u16(data) << 1) | 0x01);
+ }
+}
+
+} // anonymous namespace
+
+} // namespace bus::gameboy
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(GB_ROM_LIEBAO, device_gb_cart_interface, bus::gameboy::liebao_device, "gb_rom_liebao", "Game Boy Liebao Technology Cartridge")
diff --git a/src/devices/bus/gameboy/liebao.h b/src/devices/bus/gameboy/liebao.h
new file mode 100644
index 00000000000..ba1c67f25a4
--- /dev/null
+++ b/src/devices/bus/gameboy/liebao.h
@@ -0,0 +1,18 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/***************************************************************************
+
+ Memory controller used by Liebao Technology
+
+ ***************************************************************************/
+#ifndef MAME_BUS_GAMEBOY_LIEBAO_H
+#define MAME_BUS_GAMEBOY_LIEBAO_H
+
+#pragma once
+
+#include "slot.h"
+
+
+DECLARE_DEVICE_TYPE(GB_ROM_LIEBAO, device_gb_cart_interface)
+
+#endif // MAME_BUS_GAMEBOY_LIEBAO_H
diff --git a/src/devices/bus/gameboy/mbc.cpp b/src/devices/bus/gameboy/mbc.cpp
index bb052f9be57..2db965839ad 100644
--- a/src/devices/bus/gameboy/mbc.cpp
+++ b/src/devices/bus/gameboy/mbc.cpp
@@ -1,11 +1,55 @@
// license:BSD-3-Clause
-// copyright-holders:Fabio Priuli, Wilbert Pol
+// copyright-holders:Vas Crabb, Wilbert Pol
/***********************************************************************************************************
Game Boy carts with MBC (Memory Bank Controller)
- TODO: RTC runs too fast while in-game, in MBC-3 games... find the problem!
+ MBC1 Mapper
+ ===========
+
+ The MBC1 mapper has two modes: 2MB ROM/8KB RAM or 512KB ROM/32KB RAM.
+ Initially, the mapper operates in 2MB ROM/8KB RAM mode.
+
+ 0000-1FFF - Writing to this area enables (value 0x0A) or disables (not 0x0A) the
+ SRAM.
+ 2000-3FFF - Writing a value 0bXXXBBBBB into the 2000-3FFF memory area selects the
+ lower 5 bits of the ROM bank to select for the 4000-7FFF memory area.
+ If a value of 0bXXX00000 is written then this will automatically be
+ changed to 0bXXX00001 by the mbc chip. Initial value 00.
+ 4000-5FFF - Writing a value 0bXXXXXXBB into the 4000-5FFF memory area either selects
+ the RAM bank to use or bits 6 and 7 for the ROM bank to use for the 4000-7FFF
+ memory area. This behaviour depends on the memory mode chosen.
+ These address lines are fixed in mode 1 and switch depending on A14 in mode 0.
+ In mode 0 these will drive 0 when RB 00 is accessed (A14 low) or the value set
+ in 4000-5FFF when RB <> 00 is accessed (A14 high).
+ Switching between modes does not clear this register. Initial value 00.
+ 6000-7FFF - Writing a value 0bXXXXXXXB into the 6000-7FFF memory area switches the mode.
+ B=0 - 2MB ROM/8KB RAM mode
+ B=1 - 512KB ROM/32KB RAM mode
+
+ Regular ROM aliasing rules apply.
+
+
+ MBC5 Mapper
+ ===========
+
+ 0000-1FFF - Writing to this area enables (0x0A) or disables (not 0x0A) the SRAM area.
+ 2000-2FFF - Writing to this area updates bits 7-0 of the ROM bank number to
+ appear at 4000-7FFF.
+ 3000-3FFF - Writing to this area updates bit 8 of the ROM bank number to appear
+ at 4000-7FFF.
+ 4000-5FFF - Writing to this area select the RAM bank number to use. If the
+ cartridge includes a Rumble Pack then bit 3 is used to control
+ rumble motor (0 - disable motor, 1 - enable motor).
+
+
+ TODO:
+ * MBC5 logo spoofing class implements several strategies. It's likely not all carts using it use all
+ the strategies. Strategies implemented by each cartridge should be identified.
+ * HK0701 and HK0819 seem to differ in that HK0819 fully decodes ROM addresses while HK0701 mirrors - we
+ should probably emulated the difference at some point.
+ * BC-R1616T3P is a variant of DSHGGB-81 with the same ROM scrambling but without logo spoofing.
***********************************************************************************************************/
@@ -13,1429 +57,1510 @@
#include "emu.h"
#include "mbc.h"
+#include "cartbase.ipp"
+#include "cartheader.h"
+#include "gbxfile.h"
-//-------------------------------------------------
-// gb_rom_mbc*_device - constructor
-//-------------------------------------------------
-
-DEFINE_DEVICE_TYPE(GB_ROM_MBC1, gb_rom_mbc1_device, "gb_rom_mbc1", "GB MBC1 Carts")
-DEFINE_DEVICE_TYPE(GB_ROM_MBC2, gb_rom_mbc2_device, "gb_rom_mbc2", "GB MBC2 Carts")
-DEFINE_DEVICE_TYPE(GB_ROM_MBC3, gb_rom_mbc3_device, "gb_rom_mbc3", "GB MBC3 Carts")
-DEFINE_DEVICE_TYPE(GB_ROM_MBC5, gb_rom_mbc5_device, "gb_rom_mbc5", "GB MBC5 Carts")
-DEFINE_DEVICE_TYPE(GB_ROM_MBC6, gb_rom_mbc6_device, "gb_rom_mbc6", "GB MBC6 Carts")
-DEFINE_DEVICE_TYPE(GB_ROM_MBC7, gb_rom_mbc7_device, "gb_rom_mbc7", "GB MBC7 Carts")
-DEFINE_DEVICE_TYPE(GB_ROM_M161, gb_rom_m161_device, "gb_rom_m161", "GB M161 Carts")
-DEFINE_DEVICE_TYPE(GB_ROM_MMM01, gb_rom_mmm01_device, "gb_rom_mmm01", "GB MMM01 Carts")
-DEFINE_DEVICE_TYPE(GB_ROM_SACHEN1, gb_rom_sachen_mmc1_device, "gb_rom_sachen1", "GB Sachen MMC1 Carts")
-DEFINE_DEVICE_TYPE(GB_ROM_SACHEN2, gb_rom_sachen_mmc2_device, "gb_rom_sachen2", "GB Sachen MMC2 Carts")
-DEFINE_DEVICE_TYPE(GB_ROM_188IN1, gb_rom_188in1_device, "gb_rom_188in1", "GB 188in1")
-DEFINE_DEVICE_TYPE(GB_ROM_SINTAX, gb_rom_sintax_device, "gb_rom_sintax", "GB MBC5 Sintax Carts")
-DEFINE_DEVICE_TYPE(GB_ROM_CHONGWU, gb_rom_chongwu_device, "gb_rom_chongwu", "GB Chong Wu Xiao Jing Ling")
-DEFINE_DEVICE_TYPE(GB_ROM_LICHENG, gb_rom_licheng_device, "gb_rom_licheng", "GB MBC5 Li Cheng Carts")
-DEFINE_DEVICE_TYPE(GB_ROM_DIGIMON, gb_rom_digimon_device, "gb_rom_digimon", "GB Digimon")
-DEFINE_DEVICE_TYPE(GB_ROM_ROCKMAN8, gb_rom_rockman8_device, "gb_rom_rockman8", "GB MBC1 Rockman 8")
-DEFINE_DEVICE_TYPE(GB_ROM_SM3SP, gb_rom_sm3sp_device, "gb_sm3sp", "GB MBC1 Super Mario 3 Special")
-DEFINE_DEVICE_TYPE(GB_ROM_CAMERA, gb_rom_camera_device, "gb_rom_camera", "GB Camera")
-
-
-gb_rom_mbc_device::gb_rom_mbc_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, type, tag, owner, clock)
- , device_gb_cart_interface(mconfig, *this)
- , m_ram_enable(0)
-{
-}
-
-gb_rom_mbc1_device::gb_rom_mbc1_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
- : gb_rom_mbc_device(mconfig, type, tag, owner, clock)
- , m_mode(MODE_16M_64k)
- , m_mask(0x1f)
- , m_shift(0)
-{
-}
-
-gb_rom_mbc1_device::gb_rom_mbc1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : gb_rom_mbc1_device(mconfig, GB_ROM_MBC1, tag, owner, clock)
-{
-}
-
-gb_rom_mbc2_device::gb_rom_mbc2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : gb_rom_mbc_device(mconfig, GB_ROM_MBC2, tag, owner, clock)
-{
-}
+#include "bus/generic/slot.h"
-gb_rom_mbc3_device::gb_rom_mbc3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : gb_rom_mbc_device(mconfig, GB_ROM_MBC3, tag, owner, clock)
- , m_rtc_ready(0)
-{
-}
+#include "corestr.h"
-gb_rom_mbc5_device::gb_rom_mbc5_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
- : gb_rom_mbc_device(mconfig, type, tag, owner, clock)
- , m_rumble(*this, "Rumble")
-{
-}
+#include <algorithm>
+#include <iterator>
+#include <limits>
+#include <locale>
+#include <sstream>
+#include <type_traits>
-gb_rom_mbc5_device::gb_rom_mbc5_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : gb_rom_mbc5_device(mconfig, GB_ROM_MBC5, tag, owner, clock)
-{
-}
+//#define VERBOSE 1
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
-gb_rom_mbc6_device::gb_rom_mbc6_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : gb_rom_mbc_device(mconfig, GB_ROM_MBC6, tag, owner, clock), m_latch1(0), m_latch2(0), m_bank_4000(0), m_bank_6000(0)
-{
-}
-gb_rom_mbc7_device::gb_rom_mbc7_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : gb_rom_mbc_device(mconfig, GB_ROM_MBC7, tag, owner, clock)
-{
-}
+namespace bus::gameboy {
-gb_rom_m161_device::gb_rom_m161_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : gb_rom_mbc_device(mconfig, GB_ROM_M161, tag, owner, clock), m_base_bank(0), m_load_disable(0)
-{
-}
+namespace {
-gb_rom_mmm01_device::gb_rom_mmm01_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : gb_rom_mbc_device(mconfig, GB_ROM_MMM01, tag, owner, clock), m_romb(0), m_romb_nwe(0), m_ramb(0), m_ramb_nwe(0), m_mode(0), m_mode_nwe(0), m_map(0), m_mux(0)
-{
-}
+//**************************************************************************
+// MBC1/MBC3/MBC5 banked RAM support helper class
+//**************************************************************************
-gb_rom_sachen_mmc1_device::gb_rom_sachen_mmc1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : gb_rom_sachen_mmc1_device(mconfig, GB_ROM_SACHEN1, tag, owner, clock)
+class rom_mbc_device_base : public mbc_ram_device_base<mbc_dual_device_base>
{
-}
-
-gb_rom_sachen_mmc1_device::gb_rom_sachen_mmc1_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
- : gb_rom_mbc_device(mconfig, type, tag, owner, clock), m_base_bank(0), m_mask(0), m_mode(0), m_unlock_cnt(0)
-{
-}
-
-gb_rom_sachen_mmc2_device::gb_rom_sachen_mmc2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : gb_rom_sachen_mmc1_device(mconfig, GB_ROM_SACHEN2, tag, owner, clock)
-{
-}
+protected:
+ rom_mbc_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock) :
+ mbc_ram_device_base<mbc_dual_device_base>(mconfig, type, tag, owner, clock),
+ m_view_ram(*this, "ram"),
+ m_bank_lines{ 0U, 0U }
+ {
+ }
-gb_rom_188in1_device::gb_rom_188in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : gb_rom_mbc1_device(mconfig, GB_ROM_188IN1, tag, owner, clock), m_game_base(0)
-{
-}
+ std::error_condition install_memory(std::string &message, unsigned highbits, unsigned lowbits) ATTR_COLD
+ {
+ // see if the cartridge shouldn't use all the low bank bits
+ char const *const lowbitsfeature(get_feature("banklowbits"));
+ if (lowbitsfeature)
+ {
+ std::istringstream s;
+ s.imbue(std::locale::classic());
+ s.str(lowbitsfeature);
+ int b(-1);
+ if (!(s >> b) || (0 > b) || (lowbits < b))
+ {
+ message = util::string_format(
+ "Invalid 'banklowbits' value (must be a number from 0 to %u)\n",
+ lowbits);
+ return image_error::BADSOFTWARE;
+ }
+ lowbits = b;
+ }
-gb_rom_sintax_device::gb_rom_sintax_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : gb_rom_mbc_device(mconfig, GB_ROM_SINTAX, tag, owner, clock), m_bank_mask(0), m_bank(0), m_reg(0), m_currentxor(0), m_xor2(0), m_xor3(0), m_xor4(0), m_xor5(0), m_sintax_mode(0)
-{
-}
+ // check for valid ROM/RAM regions
+ set_bank_bits_rom(highbits, lowbits);
+ set_bank_bits_ram(highbits);
+ if (!check_rom(message) || !check_ram(message))
+ return image_error::BADSOFTWARE;
+
+ // everything checked out - install memory and return success
+ m_bank_lines[0] = util::make_bitmask<u16>(lowbits);
+ m_bank_lines[1] = util::make_bitmask<u16>(highbits);
+ cart_space()->install_view(0xa000, 0xbfff, m_view_ram);
+ install_rom();
+ install_ram(m_view_ram[0]);
+ return std::error_condition();
+ }
-gb_rom_chongwu_device::gb_rom_chongwu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : gb_rom_mbc5_device(mconfig, GB_ROM_CHONGWU, tag, owner, clock), m_protection_checked(0)
-{
-}
+ void set_bank_rom_fine(u16 entry)
+ {
+ mbc_ram_device_base<mbc_dual_device_base>::set_bank_rom_fine(entry & m_bank_lines[0]);
+ }
-gb_rom_licheng_device::gb_rom_licheng_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : gb_rom_mbc5_device(mconfig, GB_ROM_LICHENG, tag, owner, clock)
-{
-}
+ void set_ram_enable(bool enable)
+ {
+ LOG(
+ "%s: Cartridge RAM %s\n",
+ machine().describe_context(),
+ enable ? "enabled" : "disabled");
+ if (enable)
+ m_view_ram.select(0);
+ else
+ m_view_ram.disable();
+ }
-gb_rom_digimon_device::gb_rom_digimon_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : gb_rom_mbc5_device(mconfig, GB_ROM_DIGIMON, tag, owner, clock)
-{
-}
+ void bank_switch_coarse(u8 data)
+ {
+ set_bank_rom_coarse(data & m_bank_lines[1]);
+ set_bank_ram(data & m_bank_lines[1]);
+ }
-gb_rom_rockman8_device::gb_rom_rockman8_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : gb_rom_mbc_device(mconfig, GB_ROM_ROCKMAN8, tag, owner, clock), m_bank_mask(0), m_bank(0), m_reg(0)
-{
-}
+private:
+ memory_view m_view_ram;
-gb_rom_sm3sp_device::gb_rom_sm3sp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : gb_rom_mbc_device(mconfig, GB_ROM_SM3SP, tag, owner, clock), m_bank_mask(0), m_bank(0), m_reg(0), m_mode(0)
-{
-}
+ u16 m_bank_lines[2];
+};
-gb_rom_camera_device::gb_rom_camera_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : gb_rom_mbc_device(mconfig, GB_ROM_CAMERA, tag, owner, clock)
-{
-}
-//-------------------------------------------------
-// shared_start
-//-------------------------------------------------
+//**************************************************************************
+// MBC5 and clones (max 128 MiB ROM, max 128 KiB SRAM)
+//**************************************************************************
-void gb_rom_mbc_device::shared_start()
+class mbc5_device_base : public rom_mbc_device_base
{
- save_item(NAME(m_latch_bank));
- save_item(NAME(m_latch_bank2));
- save_item(NAME(m_ram_bank));
- save_item(NAME(m_ram_enable));
-}
+public:
+ virtual std::error_condition load(std::string &message) override ATTR_COLD
+ {
+ // set up ROM and RAM
+ std::error_condition err = install_memory(message);
+ if (err)
+ return err;
+
+ // install handlers
+ cart_space()->install_write_handler(
+ 0x0000, 0x1fff,
+ emu::rw_delegate(*this, FUNC(mbc5_device_base::enable_ram)));
+ cart_space()->install_write_handler(
+ 0x2000, 0x2fff,
+ emu::rw_delegate(*this, FUNC(mbc5_device_base::bank_switch_fine_low)));
+ cart_space()->install_write_handler(
+ 0x3000, 0x3fff,
+ emu::rw_delegate(*this, FUNC(mbc5_device_base::bank_switch_fine_high)));
+ cart_space()->install_write_handler(
+ 0x4000, 0x5fff,
+ emu::rw_delegate(*this, FUNC(mbc5_device_base::bank_switch_coarse)));
+
+ // all good
+ return std::error_condition();
+ }
-//-------------------------------------------------
-// shared_reset
-//-------------------------------------------------
+protected:
+ mbc5_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock) :
+ rom_mbc_device_base(mconfig, type, tag, owner, clock)
+ {
+ }
-void gb_rom_mbc_device::shared_reset()
-{
- m_latch_bank = 0;
- m_latch_bank2 = 1;
- m_ram_bank = 0;
- m_ram_enable = 0;
-}
+ virtual void device_reset() override ATTR_COLD
+ {
+ rom_mbc_device_base::device_reset();
-//-------------------------------------------------
-// mapper specific start/reset
-//-------------------------------------------------
+ set_bank_rom_coarse(0);
+ set_bank_rom_fine(0);
+ set_ram_enable(false);
+ set_bank_ram(0);
+ }
-void gb_rom_mbc3_device::device_start()
-{
- shared_start();
- save_item(NAME(m_rtc_regs));
- save_item(NAME(m_rtc_ready));
-}
+ std::error_condition install_memory(std::string &message) ATTR_COLD
+ {
+ return rom_mbc_device_base::install_memory(message, 4, 9);
+ }
-void gb_rom_mbc3_device::device_reset()
-{
- shared_reset();
- memset(m_rtc_regs, 0, sizeof(m_rtc_regs));
- m_rtc_ready = 0;
-}
+ void enable_ram(u8 data)
+ {
+ set_ram_enable(0x0a == data);
+ }
-void gb_rom_mbc6_device::device_start()
-{
- save_item(NAME(m_bank_4000));
- save_item(NAME(m_bank_6000));
- save_item(NAME(m_latch1));
- save_item(NAME(m_latch2));
- save_item(NAME(m_latch_bank));
- save_item(NAME(m_latch_bank2));
- save_item(NAME(m_ram_bank));
- save_item(NAME(m_ram_enable));
-}
-
-void gb_rom_mbc6_device::device_reset()
-{
- m_bank_4000 = 2; // correct default?
- m_bank_6000 = 3; // correct default?
- m_latch1 = 0; // correct default?
- m_latch2 = 0; // correct default?
-
- m_latch_bank = 2; // correct default?
- m_latch_bank2 = 3; // correct default?
- m_ram_bank = 0;
- m_ram_enable = 0;
-}
-
-void gb_rom_m161_device::device_start()
-{
- shared_start();
- save_item(NAME(m_base_bank));
- save_item(NAME(m_load_disable));
-}
+ void bank_switch_fine_low(u8 data)
+ {
+ set_bank_rom_fine((bank_rom_fine() & 0x0100) | u16(data));
+ }
-void gb_rom_m161_device::device_reset()
-{
- shared_reset();
- m_base_bank = 0;
- m_load_disable = 0;
-}
+ void bank_switch_fine_high(u8 data)
+ {
+ set_bank_rom_fine((bank_rom_fine() & 0x00ff) | (u16(data & 0x01) << 8));
+ }
+};
-void gb_rom_mmm01_device::device_start()
-{
- shared_start();
- save_item(NAME(m_romb));
- save_item(NAME(m_romb_nwe));
- save_item(NAME(m_ramb));
- save_item(NAME(m_ramb_nwe));
- save_item(NAME(m_mode));
- save_item(NAME(m_mode_nwe));
- save_item(NAME(m_map));
- save_item(NAME(m_mux));
-}
-
-void gb_rom_mmm01_device::device_reset()
-{
- m_romb = 0x000;
- m_romb_nwe = 0x00;
- m_ramb = 0x00;
- m_ramb_nwe = 0x00;
- m_mode = 0x00;
- m_map = 0x00;
- m_mux = 0x00;
-}
-
-void gb_rom_sachen_mmc1_device::device_start()
-{
- shared_start();
- save_item(NAME(m_base_bank));
- save_item(NAME(m_mask));
- save_item(NAME(m_mode));
- save_item(NAME(m_unlock_cnt));
-}
-
-void gb_rom_sachen_mmc1_device::device_reset()
-{
- shared_reset();
- m_base_bank = 0x00;
- m_mask = 0x00;
- m_mode = MODE_LOCKED;
- m_unlock_cnt = 0x00;
-}
-
-void gb_rom_sachen_mmc2_device::device_start()
-{
- shared_start();
- save_item(NAME(m_base_bank));
- save_item(NAME(m_mask));
- save_item(NAME(m_mode));
- save_item(NAME(m_unlock_cnt));
-}
-
-void gb_rom_sachen_mmc2_device::device_reset()
-{
- shared_reset();
- m_base_bank = 0x00;
- m_mask = 0x00;
- m_mode = MODE_LOCKED_DMG;
- m_unlock_cnt = 0x00;
-}
-
-void gb_rom_sintax_device::device_start()
-{
- shared_start();
- save_item(NAME(m_sintax_mode));
- save_item(NAME(m_currentxor));
- save_item(NAME(m_xor2));
- save_item(NAME(m_xor3));
- save_item(NAME(m_xor4));
- save_item(NAME(m_xor5));
-}
-
-void gb_rom_sintax_device::device_reset()
-{
- shared_reset();
- m_sintax_mode = 0;
- m_currentxor = 0;
- m_xor2 = 0;
- m_xor3 = 0;
- m_xor4 = 0;
- m_xor5 = 0;
-}
-
-void gb_rom_chongwu_device::device_start()
-{
- shared_start();
- save_item(NAME(m_protection_checked));
-}
-void gb_rom_chongwu_device::device_reset()
-{
- shared_reset();
- m_protection_checked = 0;
-}
-void gb_rom_camera_device::device_start()
-{
- shared_start();
- save_item(NAME(m_camera_regs));
-}
+//**************************************************************************
+// MBC5-like pirate cartridges with logo spoofing
+//**************************************************************************
-void gb_rom_camera_device::device_reset()
+class mbc5_logo_spoof_device_base : public mbc5_device_base
{
- shared_reset();
- memset(m_camera_regs, 0, sizeof(m_camera_regs));
-}
-
-
-/*-------------------------------------------------
- mapper specific handlers
- -------------------------------------------------*/
+public:
+ virtual std::error_condition load(std::string &message) override ATTR_COLD
+ {
+ // install regular MBC5 handlers
+ std::error_condition const result(mbc5_device_base::load(message));
+ if (result)
+ return result;
+
+ // intercept ROM reads for logo spoofing
+ cart_space()->install_read_handler(
+ 0x0000, 0x7fff,
+ emu::rw_delegate(*this, FUNC(mbc5_logo_spoof_device_base::read_rom)));
+
+ // all good
+ return std::error_condition();
+ }
-uint8_t gb_rom_mbc_device::read_rom(offs_t offset)
-{
- return m_rom[rom_bank_map[m_latch_bank] + offset];
-}
+protected:
+ mbc5_logo_spoof_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock) :
+ mbc5_device_base(mconfig, type, tag, owner, clock),
+ m_ram_tap(),
+ m_notif_cart_space(),
+ m_counter(0U),
+ m_spoof_logo(0U),
+ m_installing_tap(false)
+ {
+ }
-uint8_t gb_rom_mbc_device::read_ram(offs_t offset)
-{
- if (!m_ram.empty())
- return m_ram[ram_bank_map[m_ram_bank] * 0x2000 + offset];
- else
- return 0xff;
-}
+ virtual void device_start() override ATTR_COLD
+ {
+ mbc5_device_base::device_start();
-void gb_rom_mbc_device::write_ram(offs_t offset, uint8_t data)
-{
- if (!m_ram.empty())
- m_ram[ram_bank_map[m_ram_bank] * 0x2000 + offset] = data;
-}
+ save_item(NAME(m_counter));
+ save_item(NAME(m_spoof_logo));
+ }
+ virtual void device_reset() override ATTR_COLD
+ {
+ mbc5_device_base::device_reset();
-// MBC1
+ m_counter = 0U;
+ m_spoof_logo = 0U;
-uint8_t gb_rom_mbc1_device::read_rom(offs_t offset)
-{
- if (offset & 0x4000) /* RB1 */
- return m_rom[rom_bank_map[(m_ram_bank << (5 + m_shift)) | m_latch_bank2] * 0x4000 + (offset & 0x3fff)];
- else
- { /* RB0 */
- int bank = (m_mode == MODE_4M_256k) ? (m_ram_bank << (5 + m_shift)) : 0;
- return m_rom[rom_bank_map[bank] * 0x4000 + (offset & 0x3fff)];
+ install_ram_tap();
+ add_ram_notifier();
}
-}
-void gb_rom_mbc1_device::write_bank(offs_t offset, uint8_t data)
-{
- // the mapper only uses inputs A15..A13
- switch (offset & 0xe000)
+ virtual void device_post_load() override ATTR_COLD
{
- case 0x0000: // RAM Enable Register
- m_ram_enable = ((data & 0x0f) == 0x0a) ? 1 : 0;
- break;
- case 0x2000: // ROM Bank Register
- data &= 0x1f;
- m_latch_bank2 = data ? data : 1;
- m_latch_bank2 &= m_mask;
- break;
- case 0x4000: // RAM Bank Register
- m_ram_bank = data & 0x3;
- break;
- case 0x6000: // MBC1 Mode Register
- m_mode = (data & 0x1) ? MODE_4M_256k : MODE_16M_64k;
- break;
- }
-}
+ mbc5_device_base::device_post_load();
-uint8_t gb_rom_mbc1_device::read_ram(offs_t offset)
-{
- if (!m_ram.empty() && m_ram_enable)
- {
- int bank = (m_mode == MODE_4M_256k) ? m_ram_bank : 0;
- return m_ram[ram_bank_map[bank] * 0x2000 + offset];
+ install_ram_tap();
+ if (!m_spoof_logo)
+ add_ram_notifier();
}
- else
- return 0xff;
-}
-void gb_rom_mbc1_device::write_ram(offs_t offset, uint8_t data)
-{
- if (!m_ram.empty() && m_ram_enable)
+ u8 read_rom(offs_t offset)
{
- int bank = (m_mode == MODE_4M_256k) ? m_ram_bank : 0;
- m_ram[ram_bank_map[bank] * 0x2000 + offset] = data;
+ offset = rom_access(offset);
+ return (BIT(offset, 14) ? bank_rom_high_base() : bank_rom_low_base())[offset & 0x3fff];
}
-}
+ offs_t rom_access(offs_t offset)
+ {
+ if (!machine().side_effects_disabled() && (3U > m_spoof_logo))
+ {
+ // These cartridges work by counting low-to-high transitions on A15.
+ // CPU keeps A15 high while reading internal bootstrap ROM.
+ // Doing this on ROM reads is a good enough approximation for it to work.
+ if (0x30 != m_counter)
+ {
+ ++m_counter;
+ }
+ else
+ {
+ switch (m_spoof_logo)
+ {
+ case 0U:
+ m_counter = 1U;
+ [[fallthrough]];
+ case 1U:
+ ++m_spoof_logo;
+ m_notif_cart_space.reset();
+ m_ram_tap.remove();
+ LOG(
+ "%s: Spoof logo step %u\n",
+ machine().describe_context(),
+ m_spoof_logo);
+ }
+ }
-// MBC2
-
-uint8_t gb_rom_mbc2_device::read_rom(offs_t offset)
-{
- if (offset & 0x4000) /* RB1 */
- return m_rom[rom_bank_map[m_latch_bank2] * 0x4000 + (offset & 0x3fff)];
- else /* RB0 */
- return m_rom[rom_bank_map[m_latch_bank] * 0x4000 + (offset & 0x3fff)];
-}
+ // accessing entry point disables logo spoofing logic
+ if (0x0100 == offset)
+ m_spoof_logo = 3U;
+ }
-void gb_rom_mbc2_device::write_bank(offs_t offset, uint8_t data)
-{
- // the mapper only has data lines D3..D0
- data &= 0x0f;
+ // A7 is held high to show pirate logo
+ if (m_spoof_logo && ((2U != m_spoof_logo) || (cartheader::OFFSET_LOGO > offset) || (cartheader::OFFSET_TITLE <= offset)))
+ return offset;
+ else
+ return offset | 0x0080;
+ }
- // the mapper only uses inputs A15..A14, A8 for register accesses
- switch (offset & 0xc100)
+private:
+ void install_ram_tap()
{
- case 0x0000: // RAM Enable Register
- m_ram_enable = (data == 0x0a) ? 1 : 0;
- break;
- case 0x0100: // ROM Bank Register
- m_latch_bank2 = (data == 0x00) ? 0x01 : data;
- break;
+ if (!m_installing_tap)
+ {
+ m_installing_tap = true;
+ m_ram_tap.remove();
+ if (!m_spoof_logo)
+ {
+ m_ram_tap = cart_space()->install_write_tap(
+ 0xc000, 0xdfff,
+ "ram_tap_w",
+ [this] (offs_t offset, u8 &data, u8 mem_mask)
+ {
+ assert(!m_spoof_logo);
+
+ if (!machine().side_effects_disabled())
+ {
+ m_counter = 0U;
+ ++m_spoof_logo;
+ LOG(
+ "%s: Spoof logo step %u\n",
+ machine().describe_context(),
+ m_spoof_logo);
+ m_notif_cart_space.reset();
+ m_ram_tap.remove();
+ }
+ },
+ &m_ram_tap);
+ }
+ else
+ {
+ m_notif_cart_space.reset();
+ }
+ m_installing_tap = false;
+ }
}
-}
-uint8_t gb_rom_mbc2_device::read_ram(offs_t offset)
-{
- if (!m_ram.empty() && m_ram_enable)
- return m_ram[ram_bank_map[m_ram_bank] * 0x2000 + (offset & 0x01ff)] | 0xf0;
- else
- return 0xff;
-}
-
-void gb_rom_mbc2_device::write_ram(offs_t offset, uint8_t data)
-{
- if (!m_ram.empty() && m_ram_enable)
- m_ram[ram_bank_map[m_ram_bank] * 0x2000 + (offset & 0x01ff)] = data & 0x0f;
-}
+ void add_ram_notifier()
+ {
+ m_notif_cart_space = cart_space()->add_change_notifier(
+ [this] (read_or_write mode)
+ {
+ if (u32(mode) & u32(read_or_write::WRITE))
+ install_ram_tap();
+ });
+ }
+ memory_passthrough_handler m_ram_tap;
+ util::notifier_subscription m_notif_cart_space;
-// MBC3
+ u8 m_counter;
+ u8 m_spoof_logo;
+ bool m_installing_tap;
+};
-void gb_rom_mbc3_device::update_rtc()
-{
- system_time curtime;
- machine().current_datetime(curtime);
- m_rtc_regs[0] = curtime.local_time.second;
- m_rtc_regs[1] = curtime.local_time.minute;
- m_rtc_regs[2] = curtime.local_time.hour;
- m_rtc_regs[3] = curtime.local_time.day & 0xff;
- m_rtc_regs[4] = (m_rtc_regs[4] & 0xf0) | (curtime.local_time.day >> 8);
-}
-uint8_t gb_rom_mbc3_device::read_rom(offs_t offset)
-{
- if (offset < 0x4000)
- return m_rom[rom_bank_map[m_latch_bank] * 0x4000 + (offset & 0x3fff)];
- else
- return m_rom[rom_bank_map[m_latch_bank2] * 0x4000 + (offset & 0x3fff)];
-}
+//**************************************************************************
+// MBC5-like pirate cartridges with scrambled bank numbers and data
+//**************************************************************************
-void gb_rom_mbc3_device::write_bank(offs_t offset, uint8_t data)
+class mbc5_scrambled_device_base : public mbc5_logo_spoof_device_base
{
- if (offset < 0x2000)
- m_ram_enable = ((data & 0x0f) == 0x0a) ? 1 : 0;
- else if (offset < 0x4000)
+ virtual std::error_condition load(std::string &message) override ATTR_COLD
{
- // 7bits
- data &= 0x7f;
- /* Selecting bank 0 == selecting bank 1 */
- if (data == 0)
- data = 1;
-
- m_latch_bank2 = data;
+ // install regular MBC5 handlers
+ std::error_condition const result(mbc5_logo_spoof_device_base::load(message));
+ if (result)
+ return result;
+
+ // bank numbers and ROM contents are scrambled for protection
+ cart_space()->install_read_handler(
+ 0x0000, 0x3fff,
+ emu::rw_delegate(*this, FUNC(mbc5_scrambled_device_base::read_rom_low)));
+ cart_space()->install_read_handler(
+ 0x4000, 0x7fff,
+ emu::rw_delegate(*this, FUNC(mbc5_scrambled_device_base::read_rom_high)));
+ cart_space()->install_write_handler(
+ 0x2000, 0x2000, 0x0000, 0x0f00, 0x0000,
+ emu::rw_delegate(*this, FUNC(mbc5_scrambled_device_base::bank_switch_fine_low_scrambled)));
+ cart_space()->install_write_handler(
+ 0x2001, 0x2001, 0x0000, 0x0f00, 0x0000,
+ emu::rw_delegate(*this, FUNC(mbc5_scrambled_device_base::set_data_scramble)));
+ cart_space()->install_write_handler(
+ 0x2080, 0x2080, 0x0000, 0x0f00, 0x0000,
+ emu::rw_delegate(*this, FUNC(mbc5_scrambled_device_base::set_bank_scramble)));
+
+ // all good
+ return std::error_condition();
}
- else if (offset < 0x6000)
+
+protected:
+ using unscramble_function = u8 (*)(u8);
+
+ mbc5_scrambled_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock) :
+ mbc5_logo_spoof_device_base(mconfig, type, tag, owner, clock),
+ m_unscramble_data(nullptr),
+ m_unscramble_bank(nullptr),
+ m_scramble_mode{ 0U, 0U }
{
- m_ram_bank = data;
}
- else if (has_timer)
+
+ virtual void device_start() override ATTR_COLD
{
- if (m_rtc_ready == 1 && data == 0)
- m_rtc_ready = 0;
- if (m_rtc_ready == 0 && data == 1)
- {
- m_rtc_ready = 1;
- update_rtc();
- }
+ mbc5_logo_spoof_device_base::device_start();
+
+ save_item(NAME(m_scramble_mode));
}
-}
-uint8_t gb_rom_mbc3_device::read_ram(offs_t offset)
-{
- if (m_ram_bank < 4 && m_ram_enable)
+ virtual void device_reset() override ATTR_COLD
{
- // RAM
- if (!m_ram.empty())
- return m_ram[ram_bank_map[m_ram_bank] * 0x2000 + (offset & 0x1fff)];
+ mbc5_logo_spoof_device_base::device_reset();
+
+ m_unscramble_data = unscramble_data(0U);
+ m_unscramble_bank = unscramble_bank(0U);
+ m_scramble_mode[0] = 0U;
+ m_scramble_mode[1] = 0U;
}
- if (m_ram_bank >= 0x8 && m_ram_bank <= 0xc)
+
+ virtual void device_post_load() override ATTR_COLD
{
- // RTC registers
- if (has_timer)
- return m_rtc_regs[m_ram_bank - 8];
+ mbc5_logo_spoof_device_base::device_post_load();
+
+ m_unscramble_data = unscramble_data(m_scramble_mode[0]);
+ m_unscramble_bank = unscramble_bank(m_scramble_mode[1]);
}
- return 0xff;
-}
-void gb_rom_mbc3_device::write_ram(offs_t offset, uint8_t data)
-{
- if (m_ram_bank < 4 && m_ram_enable)
+ virtual unscramble_function unscramble_data(u8 data) = 0;
+ virtual unscramble_function unscramble_bank(u8 data) = 0;
+
+ template <unsigned... B>
+ static u8 unscramble(u8 data)
{
- // RAM
- if (!m_ram.empty())
- m_ram[ram_bank_map[m_ram_bank] * 0x2000 + (offset & 0x1fff)] = data;
+ return bitswap<8>(data, B...);
}
- if (m_ram_bank >= 0x8 && m_ram_bank <= 0xc && m_ram_enable)
+
+private:
+ u8 read_rom_low(offs_t offset)
{
- // RTC registers are writeable too
- if (has_timer)
- m_rtc_regs[m_ram_bank - 8] = data;
+ offset = rom_access(offset);
+ return bank_rom_low_base()[offset];
}
-}
-
-// MBC5
-uint8_t gb_rom_mbc5_device::read_rom(offs_t offset)
-{
- if (offset < 0x4000)
- return m_rom[rom_bank_map[m_latch_bank] * 0x4000 + (offset & 0x3fff)];
- else
- return m_rom[rom_bank_map[m_latch_bank2] * 0x4000 + (offset & 0x3fff)];
-}
+ u8 read_rom_high(offs_t offset)
+ {
+ offset = rom_access(0x4000 | offset) & 0x3fff;
+ return m_unscramble_data(bank_rom_high_base()[offset]);
+ }
-void gb_rom_mbc5_device::write_bank(offs_t offset, uint8_t data)
-{
- if (offset < 0x2000)
- m_ram_enable = ((data & 0x0f) == 0x0a) ? 1 : 0;
- else if (offset < 0x3000)
+ void bank_switch_fine_low_scrambled(u8 data)
{
- // MBC5 has a 9 bit bank select
- // Writing into 2000-2fff sets the lower 8 bits
- m_latch_bank2 = (m_latch_bank2 & 0x100) | data;
+ set_bank_rom_fine((bank_rom_fine() & 0x0100) | u16(m_unscramble_bank(data)));
}
- else if (offset < 0x4000)
+
+ void set_data_scramble(u8 data)
{
- // MBC5 has a 9 bit bank select
- // Writing into 3000-3fff sets the 9th bit
- m_latch_bank2 = (m_latch_bank2 & 0xff) | ((data & 0x01) << 8);
+ LOG(
+ "%s: Set ROM data scrambling mode 0x%02X\n",
+ machine().describe_context(),
+ data);
+ if (data != m_scramble_mode[0])
+ {
+ m_unscramble_data = unscramble_data(data);
+ m_scramble_mode[0] = data;
+ }
+
+ // TODO: does this actually trigger a bank switch?
+ set_bank_rom_fine((bank_rom_fine() & 0x0100) | u16(data));
}
- else if (offset < 0x6000)
+
+ void set_bank_scramble(u8 data)
{
- data &= 0x0f;
- if (has_rumble)
+ LOG(
+ "%s: Set ROM bank number scrambling mode 0x%02X\n",
+ machine().describe_context(),
+ data);
+ if (data != m_scramble_mode[1])
{
- m_rumble = BIT(data, 3);
- data &= 0x7;
+ m_unscramble_bank = unscramble_bank(data);
+ m_scramble_mode[1] = data;
}
- m_ram_bank = data;
+
+ // TODO: does this actually trigger a bank switch?
+ set_bank_rom_fine((bank_rom_fine() & 0x0100) | u16(data));
}
-}
-uint8_t gb_rom_mbc5_device::read_ram(offs_t offset)
-{
- if (!m_ram.empty() && m_ram_enable)
- return m_ram[ram_bank_map[m_ram_bank] * 0x2000 + (offset & 0x1fff)];
- else
- return 0xff;
-}
+ unscramble_function m_unscramble_data;
+ unscramble_function m_unscramble_bank;
-void gb_rom_mbc5_device::write_ram(offs_t offset, uint8_t data)
-{
- if (!m_ram.empty() && m_ram_enable)
- m_ram[ram_bank_map[m_ram_bank] * 0x2000 + (offset & 0x1fff)] = data;
-}
+ u8 m_scramble_mode[2];
+};
-// MBC6
-uint8_t gb_rom_mbc6_device::read_rom(offs_t offset)
-{
- if (offset < 0x4000)
- return m_rom[rom_bank_map[m_latch_bank] * 0x4000 + (offset & 0x3fff)];
- else if (offset < 0x6000)
- return m_rom[rom_bank_map[m_bank_4000 >> 1] * 0x4000 + (m_bank_4000 & 0x01) * 0x2000 + (offset & 0x1fff)];
- else
- return m_rom[rom_bank_map[m_bank_6000 >> 1] * 0x4000 + (m_bank_6000 & 0x01) * 0x2000 + (offset & 0x1fff)];
-}
-
-void gb_rom_mbc6_device::write_bank(offs_t offset, uint8_t data)
+
+//**************************************************************************
+// MBC1 (max 2 MiB ROM, max 32 KiB SRAM)
+//**************************************************************************
+
+class mbc1_device : public rom_mbc_device_base
{
- if (offset < 0x2000)
+public:
+ mbc1_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) :
+ rom_mbc_device_base(mconfig, GB_ROM_MBC1, tag, owner, clock)
{
- logerror( "%s write to mbc6 ram enable area: %04X <- 0x%02X\n", machine().describe_context(), offset, data );
}
- else if (offset < 0x3000)
+
+ virtual std::error_condition load(std::string &message) override ATTR_COLD
{
- if (!(offset & 0x0800))
- m_latch1 = data;
- else if (data == 0x00)
- m_bank_4000 = m_latch1;
+ // probe for "collection" cartridges wired for 4-bit fine bank number
+ unsigned banklowbits(5U);
+ if (is_collection())
+ banklowbits = 4U;
+
+ // set up ROM and RAM
+ std::error_condition err = install_memory(message, 2, banklowbits);
+ if (err)
+ return err;
+
+ // install handlers
+ cart_space()->install_write_handler(
+ 0x0000, 0x1fff,
+ emu::rw_delegate(*this, FUNC(mbc1_device::enable_ram)));
+ cart_space()->install_write_handler(
+ 0x2000, 0x3fff,
+ emu::rw_delegate(*this, FUNC(mbc1_device::bank_switch_fine)));
+ cart_space()->install_write_handler(
+ 0x4000, 0x5fff,
+ emu::rw_delegate(*this, FUNC(mbc1_device::bank_switch_coarse)));
+ cart_space()->install_write_handler(
+ 0x6000, 0x7fff,
+ emu::rw_delegate(*this, FUNC(mbc1_device::bank_low_mask)));
+
+ // all good
+ return std::error_condition();
}
- else if (offset < 0x4000)
+
+protected:
+ virtual void device_reset() override ATTR_COLD
{
- if (!(offset & 0x0800))
- m_latch2 = data;
- else if (data == 0x00)
- m_bank_6000 = m_latch2;
+ rom_mbc_device_base::device_reset();
+
+ set_bank_rom_coarse(0);
+ set_bank_rom_fine(1);
+ set_bank_rom_low_coarse_mask(0x00);
+ set_ram_enable(false);
+ set_bank_ram(0);
+ set_bank_ram_mask(0x00);
}
-}
-
-uint8_t gb_rom_mbc6_device::read_ram(offs_t offset)
-{
- if (!m_ram.empty())
- return m_ram[ram_bank_map[m_ram_bank] * 0x2000 + (offset & 0x1fff)];
- else
- return 0xff;
-}
-
-void gb_rom_mbc6_device::write_ram(offs_t offset, uint8_t data)
-{
- if (!m_ram.empty())
- m_ram[ram_bank_map[m_ram_bank] * 0x2000 + (offset & 0x1fff)] = data;
-}
-
-// MBC7
-uint8_t gb_rom_mbc7_device::read_rom(offs_t offset)
-{
- if (offset < 0x4000)
- return m_rom[rom_bank_map[m_latch_bank] * 0x4000 + (offset & 0x3fff)];
- else
- return m_rom[rom_bank_map[m_latch_bank2] * 0x4000 + (offset & 0x3fff)];
-}
+private:
+ void enable_ram(u8 data)
+ {
+ set_ram_enable(0x0a == (data & 0x0f));
+ }
-void gb_rom_mbc7_device::write_bank(offs_t offset, uint8_t data)
-{
- if (offset < 0x2000)
+ void bank_switch_fine(u8 data)
{
- // FIXME: Add RAM enable support
- logerror("%s Write to ram enable register 0x%04X <- 0x%02X\n", machine().describe_context(), offset, data);
+ data &= 0x1f;
+ set_bank_rom_fine(data ? data : 1);
}
- else if (offset < 0x3000)
+
+ void bank_low_mask(u8 data)
{
- logerror( "%s write to mbc7 rom select register: 0x%04X <- 0x%02X\n", machine().describe_context(), 0x2000 + offset, data );
- /* Bit 12 must be set for writing to the mbc register */
- if (offset & 0x0100)
- m_latch_bank2 = data;
+ u8 const mask(data ? 0x03 : 0x00);
+ LOG(
+ "%s: RAM/low ROM bank switching %s\n",
+ machine().describe_context(),
+ mask ? "enabled" : "disabled");
+ set_bank_rom_low_coarse_mask(mask);
+ set_bank_ram_mask(mask);
}
- else
+
+ bool is_collection() ATTR_COLD
{
- logerror( "%s write to mbc7 rom area: 0x%04X <- 0x%02X\n", machine().describe_context(), 0x3000 + offset, data );
- /* Bit 12 must be set for writing to the mbc register */
- if (offset & 0x0100)
+ // addressing must be explicitly specified in software lists
+ if (loaded_through_softlist())
+ return false;
+
+ // need ROM to probe
+ memory_region *const romregion(cart_rom_region());
+ if (!romregion)
+ return false;
+
+ // doesn't make sense without more than 256 KiB, and can address up to 1 MiB in 16 KiB pages
+ auto const rombytes(romregion->bytes());
+ if (((u32(0x4000) << 6) < rombytes) || ((u32(0x4000) << 4) >= rombytes) || (rombytes & 0x3fff))
+ return false;
+
+ // reject if the header checksum for the first page fails
+ u8 const *const rombase(romregion->base());
+ if (!cartheader::verify_header_checksum(rombase + 0x100))
+ return false;
+
+ // check title in first page header against list of known collections
+ static constexpr u8 KNOWN_COLLECTIONS[][0x10] = {
+ { 'B', 'O', 'M', 'C', 'O', 'L', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 'B', 'O', 'M', 'S', 'E', 'L', 0, 0, 0, 0, 0, 'B', '2', 'C', 'K', 0xc0 },
+ { 'G', 'E', 'N', 'C', 'O', 'L', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 'M', 'O', 'M', 'O', 'C', 'O', 'L', 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ { 'M', 'O', 'R', 'T', 'A', 'L', 'K', 'O', 'M', 'B', 'A', 'T', ' ', 'D', 'U', 'O' },
+ { 'M', 'O', 'R', 'T', 'A', 'L', 'K', 'O', 'M', 'B', 'A', 'T', 'I', '&', 'I', 'I' },
+ { 'S', 'U', 'P', 'E', 'R', 'C', 'H', 'I', 'N', 'E', 'S', 'E', ' ', '1', '2', '3' } };
+ auto const known(
+ std::find_if(
+ std::begin(KNOWN_COLLECTIONS),
+ std::end(KNOWN_COLLECTIONS),
+ [rombase] (auto const &name)
+ {
+ return std::equal(std::begin(name), std::end(name), &rombase[cartheader::OFFSET_TITLE]);
+ }));
+ if (std::end(KNOWN_COLLECTIONS) != known)
{
- switch (offset & 0x7000)
- {
- case 0x3000: /* 0x3000-0x3fff */
- case 0x4000: /* 0x4000-0x4fff */
- case 0x5000: /* 0x5000-0x5fff */
- case 0x6000: /* 0x6000-0x6fff */
- case 0x7000: /* 0x7000-0x7fff */
- break;
- }
+ logerror("Detected known multi-game collection with 4-bit fine bank addressing\n");
+ return true;
}
- }
-}
-uint8_t gb_rom_mbc7_device::read_ram(offs_t offset)
-{
- if (!m_ram.empty())
- return m_ram[ram_bank_map[m_ram_bank] * 0x2000 + (offset & 0x1fff)];
- else
- return 0xff;
-}
-
-void gb_rom_mbc7_device::write_ram(offs_t offset, uint8_t data)
-{
- if (!m_ram.empty())
- m_ram[ram_bank_map[m_ram_bank] * 0x2000 + (offset & 0x1fff)] = data;
-}
-
-
-// M161
-
-uint8_t gb_rom_m161_device::read_rom(offs_t offset)
-{
- return m_rom[rom_bank_map[m_base_bank] * 0x4000 + (offset & 0x7fff)];
-}
+ // reject if the header checksum for the second coarse page fails
+ if (!cartheader::verify_header_checksum(rombase + (u32(0x4000) << 4) + 0x100))
+ return false;
-void gb_rom_m161_device::write_bank(offs_t offset, uint8_t data)
-{
- // the mapper (74HC161A) only has data lines D2..D0
- data &= 0x07;
+ // assume it's a collection if the type indicates an MBC1 cartridge
+ switch (rombase[(u32(0x4000) << 4) + cartheader::OFFSET_TYPE])
+ {
+ case cartheader::TYPE_MBC1:
+ case cartheader::TYPE_MBC1_RAM:
+ case cartheader::TYPE_MBC1_RAM_BATT:
+ logerror("Detected MBC1 header in page 0x10, using 4-bit fine bank addressing\n");
+ return true;
+ }
- // A15 is connected to #LOAD and overwritten by QD (m_load_disable)
- switch (offset & 0x8000)
- {
- case 0x0000: // Base Bank Register
- if (!m_load_disable)
- m_base_bank = data << 1;
- m_load_disable = 0x01;
- break;
- default:
- break;
+ // assume anything else uses a different (presumably more conventional) scheme
+ return false;
}
-}
-
-
-// MMM01
-
-uint8_t gb_rom_mmm01_device::read_rom(offs_t offset)
-{
- uint16_t romb = m_romb & ~(0x1e0 | m_romb_nwe);
- uint16_t romb_base = m_romb & (0x1e0 | m_romb_nwe);
- uint8_t ramb_masked = ((offset & 0x4000) | m_mode ? m_ramb : m_ramb & ~0x03);
-
- // zero-adjust RA18..RA14
- romb = (romb ? romb : 0x01);
- // if unmapped, force
- romb = (m_map ? romb : 0x01);
-
- // RB 0 logic
- if (!(offset & 0x4000))
- romb = 0x00;
-
- // combine with base
- romb |= romb_base;
+};
- // multiplex with AA14..AA13
- if (m_mux)
- romb = (romb & ~0x60) | ((ramb_masked & 0x03) << 5);
- // if unmapped, force
- if (!m_map)
- romb |= 0x1fe;
- return m_rom[rom_bank_map[romb] * 0x4000 + (offset & 0x3fff)];
-}
+//**************************************************************************
+// MBC5 (max 128 MiB ROM, max 128 KiB SRAM)
+//**************************************************************************
-void gb_rom_mmm01_device::write_bank(offs_t offset, uint8_t data)
+class mbc5_device : public mbc5_device_base
{
- // the mapper only has data lines D6..D0
- data &= 0x7f;
+public:
+ mbc5_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) :
+ mbc5_device_base(mconfig, GB_ROM_MBC5, tag, owner, clock),
+ m_rumble(*this, "rumble"),
+ m_has_rumble(false)
+ {
+ }
- // the mapper only uses inputs A15..A13
- switch (offset & 0xe000)
+ virtual std::error_condition load(std::string &message) override ATTR_COLD
{
- case 0x0000: // Map Latch, AA #WE, RAM Enable
- if (!m_map) {
- m_ramb_nwe = (data & (0x30)) >> 4;
- m_map = (data & 0x40);
+ // check whether rumble motor is present
+ char const *const rumblefeature(get_feature("rumble"));
+ if (rumblefeature)
+ {
+ // explicitly specified in software list
+ if (util::streqlower(rumblefeature, "yes") || util::streqlower(rumblefeature, "true"))
+ {
+ logerror("Rumble motor present\n");
+ m_has_rumble = true;
}
- m_ram_enable = ((data & 0x0f) == 0x0a) ? 1 : 0;
- break;
- case 0x2000: // RA20..RA19 RA18..RA14
- if (!m_map)
- m_romb = (m_romb & ~0x60) | (data & 0x60);
-
- m_romb = (m_romb & (~0x1f | m_romb_nwe)) | (data & (0x1f & ~m_romb_nwe));
- break;
- case 0x4000: // Mode #WE, RA22..RA21, AA16..AA15, AA14..AA13
- if (!m_map) {
- m_mode_nwe = data & 0x40;
- m_romb = (m_romb & ~0x180) | ((data & 0x30) << 3);
- m_ramb = (m_ramb & ~0x0c) | (data & 0x0c);
+ else if (util::streqlower(rumblefeature, "no") || util::streqlower(rumblefeature, "false"))
+ {
+ logerror("No rumble motor present\n");
+ m_has_rumble = false;
}
-
- m_ramb = (m_ramb & (~0x03 | m_ramb_nwe)) | (data & (0x03 & ~m_ramb_nwe));
- break;
- case 0x6000: // Mux, RA18..RA15 #WE/Mask, ???, MBC1 Mode
- if (!m_map) {
- m_mux = data & 0x40;
- // m_romb_nwe is aligned to RA14, hence >> 1 instead of >> 2
- m_romb_nwe = (data & 0x3c) >> 1;
+ else
+ {
+ message = "Invalid 'rumble' feature value (must be yes or no)";
+ return image_error::BADSOFTWARE;
}
+ }
+ else if (loaded_through_softlist())
+ {
+ logerror("No 'rumble' feature found, assuming no rumble motor present\n");
+ m_has_rumble = false;
+ }
+ else
+ {
+ gbxfile::leader_1_0 leader;
+ u8 const *extra;
+ u32 extralen;
+ if (gbxfile::get_data(gbx_footer_region(), leader, extra, extralen))
+ {
+ m_has_rumble = bool(leader.rumble);
+ logerror("GBX format image specifies %srumble motor present\n", m_has_rumble ? "" : "no ");
+ }
+ else
+ {
+ // try probing the header
+ memory_region *const romregion(cart_rom_region());
+ if (romregion && (romregion->bytes() > cartheader::OFFSET_TYPE))
+ {
+ u8 const carttype((&romregion->as_u8())[cartheader::OFFSET_TYPE]);
+ switch (carttype)
+ {
+ case cartheader::TYPE_MBC5_RUMBLE:
+ case cartheader::TYPE_MBC5_RUMBLE_RAM:
+ case cartheader::TYPE_MBC5_RUMBLE_RAM_BATT:
+ m_has_rumble = true;
+ break;
+ case cartheader::TYPE_MBC5:
+ case cartheader::TYPE_MBC5_RAM:
+ case cartheader::TYPE_MBC5_RAM_BATT:
+ m_has_rumble = false;
+ break;
+ default:
+ osd_printf_warning(
+ "[%s] Unrecognized cartridge type 0x%02X in header, assuming no rumble motor present\n",
+ tag(),
+ carttype);
+ m_has_rumble = false;
+ }
+ logerror(
+ "Cartridge type 0x%02X in header, %srumble motor present\n",
+ carttype,
+ m_has_rumble ? "" : "no ");
+ }
+ }
+ }
- if (!m_mode_nwe)
- m_mode = data & 0x01;
- break;
- default:
- break;
- }
-}
-
-uint8_t gb_rom_mmm01_device::read_ram(offs_t offset)
-{
- uint8_t ramb_masked = ((offset & 0x4000) | m_mode ? m_ramb : m_ramb & ~0x03);
- uint8_t ramb = ramb_masked;
+ // install base MBC5 handlers
+ std::error_condition const result(mbc5_device_base::load(message));
+ if (result)
+ return result;
- // multiplex with RA20..RA19
- if (m_mux)
- ramb = (ramb & ~0x03) | ((m_romb & 0x60) >> 5);
+ // install rumble-aware handler if appropriate
+ if (m_has_rumble)
+ {
+ cart_space()->install_write_handler(
+ 0x4000, 0x5fff,
+ emu::rw_delegate(*this, FUNC(mbc5_device::bank_switch_coarse)));
+ }
- if (!m_ram.empty() && m_ram_enable)
- {
- return m_ram[ram_bank_map[ramb] * 0x2000 + (offset & 0x1fff)];
+ // all good
+ return std::error_condition();
}
- else
- return 0xff;
-}
-void gb_rom_mmm01_device::write_ram(offs_t offset, uint8_t data)
-{
- uint8_t ramb_masked = ((offset & 0x4000) | m_mode ? m_ramb : m_ramb & ~0x03);
- uint8_t ramb = ramb_masked;
-
- // multiplex with RA20..RA19
- if (m_mux)
- ramb = (ramb & ~0x03) | ((m_romb & 0x60) >> 5);
-
- if (!m_ram.empty() && m_ram_enable)
+protected:
+ virtual void device_start() override ATTR_COLD
{
- m_ram[ram_bank_map[ramb] * 0x2000 + (offset & 0x1fff)] = data;
- }
-}
+ mbc5_device_base::device_start();
-// Sachen MMC1
+ m_rumble.resolve();
+ }
-uint8_t gb_rom_sachen_mmc1_device::read_rom(offs_t offset)
-{
- uint16_t off_edit = offset;
-
- /* Wait for 0x31 transitions of A15 (hi -> lo), i.e. ROM accesses; A15 = HI while in bootstrap */
- /* This is 0x31 transitions, because we increment counter _after_ checking it */
- if (m_unlock_cnt == 0x30)
- m_mode = MODE_UNLOCKED;
- else
- m_unlock_cnt++;
-
- /* Logo Switch */
- if (m_mode == MODE_LOCKED)
- off_edit |= 0x80;
-
- /* Header Un-Scramble */
- if ((off_edit & 0xff00) == 0x0100) {
- off_edit &= 0xffac;
- off_edit |= ((offset >> 6) & 0x01) << 0;
- off_edit |= ((offset >> 4) & 0x01) << 1;
- off_edit |= ((offset >> 1) & 0x01) << 4;
- off_edit |= ((offset >> 0) & 0x01) << 6;
- }
- //logerror("read from %04X (%04X)\n", offset, off_edit);
-
- if (offset & 0x4000) /* RB1 */
- return m_rom[rom_bank_map[(m_base_bank & m_mask) | (m_latch_bank2 & ~m_mask)] * 0x4000 + (offset & 0x3fff)];
- else /* RB0 */
- return m_rom[rom_bank_map[(m_base_bank & m_mask) | (m_latch_bank & ~m_mask)] * 0x4000 + (off_edit & 0x3fff)];
-}
-
-void gb_rom_sachen_mmc1_device::write_bank(offs_t offset, uint8_t data)
-{
- /* Only A15..A6, A4, A1..A0 are connected */
- /* We only decode upper three bits */
- switch ((offset & 0xffd3) & 0xe000)
+ virtual void device_reset() override ATTR_COLD
{
- case 0x0000: /* Base ROM Bank Register */
+ mbc5_device_base::device_reset();
- if ((m_latch_bank2 & 0x30) == 0x30)
- m_base_bank = data;
- //logerror("write to base bank %X - %X\n", data, (m_base_bank & m_mask) | (m_latch_bank2 & ~m_mask));
- break;
-
- case 0x2000: /* ROM Bank Register */
-
- m_latch_bank2 = data ? data : 0x01;
- //logerror("write to latch %X - %X\n", data, (m_base_bank & m_mask) | (m_latch_bank2 & ~m_mask));
- break;
+ if (m_has_rumble)
+ m_rumble = 0;
+ }
- case 0x4000: /* ROM Bank Mask Register */
+private:
+ void bank_switch_coarse(u8 data)
+ {
+ assert(m_has_rumble);
+ mbc5_device_base::bank_switch_coarse(data);
+ m_rumble = BIT(data, 3);
+ }
- if ((m_latch_bank2 & 0x30) == 0x30)
- m_mask = data;
- //logerror("write to mask %X - %X\n", data, (m_base_bank & m_mask) | (m_latch_bank2 & ~m_mask));
- break;
+ output_finder<> m_rumble;
+ bool m_has_rumble;
+};
- case 0x6000:
- /* nothing happens when writing to 0x6000-0x7fff, as verified by Tauwasser */
- break;
- default:
+//**************************************************************************
+// MBC5 variant used by BBD games
+//**************************************************************************
- //logerror("write to unknown/unmapped area %04X <= %02X\n", offset, data);
- /* did not extensively test other unlikely ranges */
- break;
+class bbd_device : public mbc5_scrambled_device_base
+{
+public:
+ bbd_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) :
+ mbc5_scrambled_device_base(mconfig, GB_ROM_BBD, tag, owner, clock)
+ {
}
-}
-// Sachen MMC2
+protected:
+ virtual unscramble_function unscramble_data(u8 data) override
+ {
+ switch (data & 0x07)
+ {
+ case 0x0: // no scrambling
+ return &bbd_device::unscramble<7, 6, 5, 4, 3, 2, 1, 0>;
+ case 0x4: // Garou
+ return &bbd_device::unscramble<7, 6, 2, 4, 3, 1, 5, 0>;
+ case 0x5: // Harry Potter
+ return &bbd_device::unscramble<7, 6, 5, 1, 3, 2, 4, 0>;
+ case 0x7: // Digimon Adventure
+ return &bbd_device::unscramble<7, 6, 2, 4, 3, 5, 1, 0>;
+ }
-uint8_t gb_rom_sachen_mmc2_device::read_rom(offs_t offset)
-{
- uint16_t off_edit = offset;
+ logerror(
+ "%s: Unsupported ROM data scrambling mode 0x%02X\n",
+ machine().describe_context(),
+ data);
+ return &bbd_device::unscramble<7, 6, 5, 4, 3, 2, 1, 0>;
+ }
- /* Wait for 0x30 transitions of A15 (lo -> hi), i.e. ROM accesses; A15 = HI while in bootstrap */
- /* This is 0x30 transitions, because we increment counter _after_ checking it, but A15 lo -> hi*/
- /* transition means first read (hi -> lo transition) must not count */
+ virtual unscramble_function unscramble_bank(u8 data) override
+ {
+ switch (data & 0x07)
+ {
+ case 0x0: // no scrambling
+ return &bbd_device::unscramble<7, 6, 5, 4, 3, 2, 1, 0>;
+ case 0x3: // Digimon Adventure, Garou - two most significant bits unconfirmed
+ return &bbd_device::unscramble<7, 6, 5, 1, 0, 2, 4, 3>;
+ case 0x5: // Harry Potter - two most significant bits unconfirmed
+ return &bbd_device::unscramble<7, 6, 5, 0, 4, 3, 2, 1>;
+ }
- if (m_unlock_cnt == 0x30 && m_mode == MODE_LOCKED_DMG) {
- m_mode = MODE_LOCKED_CGB;
- m_unlock_cnt = 0x00;
- } else if (m_unlock_cnt == 0x30 && m_mode == MODE_LOCKED_CGB) {
- m_mode = MODE_UNLOCKED;
+ logerror(
+ "%s: Unsupported ROM bank number scrambling mode 0x%02X\n",
+ machine().describe_context(),
+ data);
+ return &bbd_device::unscramble<7, 6, 5, 4, 3, 2, 1, 0>;
}
+};
- if (m_unlock_cnt != 0x30)
- m_unlock_cnt++;
- /* Logo Switch */
- if (m_mode == MODE_LOCKED_CGB)
- off_edit |= 0x80;
- /* Header Un-Scramble */
- if ((off_edit & 0xff00) == 0x0100) {
- off_edit &= 0xffac;
- off_edit |= ((offset >> 6) & 0x01) << 0;
- off_edit |= ((offset >> 4) & 0x01) << 1;
- off_edit |= ((offset >> 1) & 0x01) << 4;
- off_edit |= ((offset >> 0) & 0x01) << 6;
- }
- //logerror("read from %04X (%04X) cnt: %02X\n", offset, off_edit, m_unlock_cnt);
+//**************************************************************************
+// MBC5 variant with DSHGGB-81 PCB
+//**************************************************************************
- if (offset & 0x4000) /* RB1 */
- return m_rom[rom_bank_map[(m_base_bank & m_mask) | (m_latch_bank2 & ~m_mask)] * 0x4000 + (offset & 0x3fff)];
- else /* RB0 */
- return m_rom[rom_bank_map[(m_base_bank & m_mask) | (m_latch_bank & ~m_mask)] * 0x4000 + (off_edit & 0x3fff)];
-}
-
-uint8_t gb_rom_sachen_mmc2_device::read_ram(offs_t offset)
+class dshggb81_device : public mbc5_scrambled_device_base
{
- if (m_mode == MODE_LOCKED_DMG) {
- m_unlock_cnt = 0x00;
- m_mode = MODE_LOCKED_CGB;
+public:
+ dshggb81_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) :
+ mbc5_scrambled_device_base(mconfig, GB_ROM_DSHGGB81, tag, owner, clock)
+ {
}
- return 0xff;
-
-}
-void gb_rom_sachen_mmc2_device::write_ram(offs_t offset, uint8_t data)
-{
- if (m_mode == MODE_LOCKED_DMG) {
- m_unlock_cnt = 0x00;
- m_mode = MODE_LOCKED_CGB;
+protected:
+ virtual unscramble_function unscramble_data(u8 data) override
+ {
+ switch (data & 0x07)
+ {
+ default: // just to shut up dumb compilers
+ case 0x0: return &dshggb81_device::unscramble<7, 6, 5, 4, 3, 2, 1, 0>;
+ case 0x1: return &dshggb81_device::unscramble<7, 5, 6, 4, 3, 1, 2, 0>;
+ case 0x2: return &dshggb81_device::unscramble<7, 1, 2, 4, 3, 5, 6, 0>;
+ case 0x3: return &dshggb81_device::unscramble<7, 6, 2, 4, 3, 1, 5, 0>;
+ case 0x4: return &dshggb81_device::unscramble<7, 6, 1, 4, 3, 2, 5, 0>;
+ case 0x5: return &dshggb81_device::unscramble<7, 1, 5, 4, 3, 6, 2, 0>;
+ case 0x6: return &dshggb81_device::unscramble<7, 5, 2, 4, 3, 6, 1, 0>;
+ case 0x7: return &dshggb81_device::unscramble<7, 1, 6, 4, 3, 5, 2, 0>;
+ }
}
-}
+ virtual unscramble_function unscramble_bank(u8 data) override
+ {
+ switch (data & 0x07)
+ {
+ case 0x0: // no scrambling
+ return &dshggb81_device::unscramble<7, 6, 5, 4, 3, 2, 1, 0>;
+ }
+
+ logerror(
+ "%s: Unsupported ROM bank number scrambling mode 0x%02X\n",
+ machine().describe_context(),
+ data);
+ return &dshggb81_device::unscramble<7, 6, 5, 4, 3, 2, 1, 0>;
+ }
+};
-// 188 in 1 pirate (only preliminary)
-uint8_t gb_rom_188in1_device::read_rom(offs_t offset)
-{
- if (offset < 0x4000)
- return m_rom[m_game_base + rom_bank_map[m_latch_bank] * 0x4000 + (offset & 0x3fff)];
- else
- return m_rom[m_game_base + rom_bank_map[m_latch_bank2] * 0x4000 + (offset & 0x3fff)];
-}
+//**************************************************************************
+// MBC5 variant used by Sintax games
+//**************************************************************************
-void gb_rom_188in1_device::write_bank(offs_t offset, uint8_t data)
+class sintax_device : public mbc5_logo_spoof_device_base
{
- if (offset == 0x7b00)
+public:
+ sintax_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) :
+ mbc5_logo_spoof_device_base(mconfig, GB_ROM_SINTAX, tag, owner, clock),
+ m_scramble_mode(0U),
+ m_xor_index(0U)
{
- if (data < 0x80)
- logerror("write to 0x%X data 0x%X\n", offset, data);
- else
- {
- data -= 0x80;
- m_game_base = 0x400000 + (data * 0x8000);
- //logerror("offset 0x%X\n", m_game_base);
- }
}
- else if (offset == 0x7b01 || offset == 0x7b02)
+
+ virtual std::error_condition load(std::string &message) override ATTR_COLD
{
- // what do these writes do?
- printf("write to 0x%X data 0x%X\n", offset, data);
+ // install regular MBC5 handlers
+ std::error_condition const result(mbc5_logo_spoof_device_base::load(message));
+ if (result)
+ return result;
+
+ // bank numbers and ROM contents are scrambled for protection
+ cart_space()->install_read_handler(
+ 0x0000, 0x3fff,
+ emu::rw_delegate(*this, FUNC(sintax_device::read_rom_low)));
+ cart_space()->install_read_handler(
+ 0x4000, 0x7fff,
+ emu::rw_delegate(*this, FUNC(sintax_device::read_rom_high)));
+ cart_space()->install_write_handler(
+ 0x2000, 0x2fff,
+ emu::rw_delegate(*this, FUNC(sintax_device::bank_switch_fine_low_scrambled)));
+ cart_space()->install_write_handler(
+ 0x5000, 0x5fff,
+ emu::rw_delegate(*this, FUNC(sintax_device::set_scramble_mode)));
+ cart_space()->install_write_handler(
+ 0x7000, 0x70ff, 0x0000, 0x0f00, 0x0000,
+ emu::rw_delegate(*this, FUNC(sintax_device::set_xor)));
+
+ // all good
+ return std::error_condition();
}
- else
- gb_rom_mbc1_device::write_bank(offset, data);
-}
+protected:
+ virtual void device_start() override ATTR_COLD
+ {
+ mbc5_logo_spoof_device_base::device_start();
-// MBC5 variant used by Li Cheng / Niutoude games
-
-void gb_rom_licheng_device::write_bank(offs_t offset, uint8_t data)
-{
- if (offset > 0x2100 && offset < 0x3000)
- return;
+ save_item(NAME(m_scramble_mode));
+ save_item(NAME(m_xor_index));
+ save_item(NAME(m_xor_table));
+ }
- gb_rom_mbc5_device::write_bank(offset, data);
-}
+ virtual void device_reset() override ATTR_COLD
+ {
+ mbc5_logo_spoof_device_base::device_reset();
-// MBC5 variant used by Chong Wu Xiao Jing Ling (this appears to be a re-release of a Li Cheng / Niutoude game,
-// given that it contains the Niutoude logo, with most protection checks patched out)
+ m_scramble_mode = 0U;
+ m_xor_index = 0U;
+ std::fill(std::begin(m_xor_table), std::end(m_xor_table), 0U);
+ }
-uint8_t gb_rom_chongwu_device::read_rom(offs_t offset)
-{
- // protection check at the first read here...
- if (offset == 0x41c3 && !m_protection_checked)
+private:
+ u8 read_rom_low(offs_t offset)
{
- m_protection_checked = 1;
- return 0x5d;
+ offset = rom_access(offset);
+ return bank_rom_low_base()[offset];
}
- if (offset < 0x4000)
- return m_rom[rom_bank_map[m_latch_bank] * 0x4000 + (offset & 0x3fff)];
- else
- return m_rom[rom_bank_map[m_latch_bank2] * 0x4000 + (offset & 0x3fff)];
-}
-
-// MBC5 variant used by Sintax games
+ u8 read_rom_high(offs_t offset)
+ {
+ offset = rom_access(0x4000 | offset) & 0x3fff;
+ return bank_rom_high_base()[offset] ^ m_xor_table[m_xor_index];
+ }
-void gb_rom_sintax_device::set_xor_for_bank(uint8_t bank)
-{
- switch (bank & 0x0f)
+ void bank_switch_fine_low_scrambled(u8 data)
{
- case 0x00: case 0x04: case 0x08: case 0x0c:
- m_currentxor = m_xor2;
+ m_xor_index = data & 0x03;
+
+ switch (m_scramble_mode & 0x0f)
+ {
+ case 0x00: // Lion King, Golden Sun
+ data = bitswap<8>(data, 7, 0, 5, 6, 3, 4, 1, 2);
break;
- case 0x01: case 0x05: case 0x09: case 0x0d:
- m_currentxor = m_xor3;
+ case 0x01: // Langrisser
+ data = bitswap<8>(data, 0, 1, 6, 7, 4, 5, 2, 3);
break;
- case 0x02: case 0x06: case 0x0a: case 0x0e:
- m_currentxor = m_xor4;
+ case 0x05: // Maple Story, Pokemon Platinum
+ data = bitswap<8>(data, 7, 6, 1, 0, 3, 2, 5, 4); // needs verification
break;
- case 0x03: case 0x07: case 0x0b: case 0x0f:
- m_currentxor = m_xor5;
+ case 0x07: // Bynasty Warriors 5
+ data = bitswap<8>(data, 2, 0, 3, 1, 5, 4, 7, 6); // 5 and 7 unconfirmed
break;
- }
-}
+ case 0x09:
+ data = bitswap<8>(data, 4, 5, 2, 3, 0, 1, 6, 7);
+ break;
+ case 0x0b: // Shaolin Legend
+ data = bitswap<8>(data, 2, 3, 0, 1, 6, 7, 4, 5); // 5 and 6 unconfirmed
+ break;
+ case 0x0d: // older games
+ data = bitswap<8>(data, 1, 0, 7, 6, 5, 4, 3, 2);
+ break;
+ case 0x0f: // no scrambling
+ break;
+ default:
+ logerror(
+ "%s: Unsupported ROM bank number scrambling mode 0x%X\n",
+ machine().describe_context(),
+ m_scramble_mode & 0x0f);
+ }
-uint8_t gb_rom_sintax_device::read_rom(offs_t offset)
-{
- if (offset < 0x4000)
- return m_rom[rom_bank_map[m_latch_bank] * 0x4000 + (offset & 0x3fff)];
- else
- return m_rom[rom_bank_map[m_latch_bank2] * 0x4000 + (offset & 0x3fff)] ^ m_currentxor;
-}
+ set_bank_rom_fine((bank_rom_fine() & 0x0100) | u16(data));
+ }
-void gb_rom_sintax_device::write_bank(offs_t offset, uint8_t data)
-{
- if (offset < 0x2000)
- m_ram_enable = ((data & 0x0f) == 0x0a) ? 1 : 0;
- else if (offset < 0x3000)
+ void set_scramble_mode(u8 data)
{
- set_xor_for_bank(data);
-
- switch (m_sintax_mode & 0x0f)
+ if (!m_scramble_mode)
{
- case 0x0d:
- data = bitswap<8>(data, 1,0,7,6,5,4,3,2);
- break;
- case 0x09:
- //data = bitswap<8>(data, 3,2,5,4,0,1,6,7); // Monkey..no
- data = bitswap<8>(data, 4,5,2,3,0,1,6,7);
- break;
- case 0x00: // 0x10=lion 0x00 hmmmmm // 1 and 0 unconfirmed
- data = bitswap<8>(data, 7,0,5,6,3,4,1,2);
- break;
- case 0x01:
- data = bitswap<8>(data, 0,1,6,7,4,5,2,3);
- break;
- case 0x05:
- data = bitswap<8>(data, 7,6,1,0,3,2,5,4); // Not 100% on this one
- break;
- case 0x07:
- data = bitswap<8>(data, 2,0,3,1,5,4,7,6); // 5 and 7 unconfirmed
- break;
- case 0x0b:
- data = bitswap<8>(data, 2,3,0,1,6,7,4,5); // 5 and 6 unconfirmed
- break;
+ LOG(
+ "%s: Set scramble mode = 0x%02X\n",
+ machine().describe_context(),
+ data);
+ m_scramble_mode = data;
+ bank_switch_fine_low_scrambled(0x01);
}
- m_latch_bank2 = (m_latch_bank2 & 0x100) | data;
- }
- else if (offset < 0x4000)
- {
- m_latch_bank2 = (m_latch_bank2 & 0xff) | ((data & 0x01) << 8);
- }
- else if (offset < 0x5000)
- {
- data &= 0x0f;
- m_ram_bank = data;
- }
- else if (offset < 0x6000)
- {
- if (!m_sintax_mode)
+ else
{
- m_sintax_mode = data;
- write_bank(0x2000, 1); //force a fake bank switch
+ LOG(
+ "%s: Ignoring scramble mode = 0x%02X when already set to 0x%02X\n",
+ machine().describe_context(),
+ data,
+ m_scramble_mode);
}
-// printf("sintax mode %x\n", m_sintax_mode & 0xf);
}
- else if (offset >= 0x7000)
+
+ void set_xor(offs_t offset, u8 data)
{
- switch ((offset & 0x00f0) >> 4)
+ u8 const index(offset >> 4);
+ if ((2 <= index) && (6 > index))
{
- case 2:
- m_xor2 = data;
- break;
- case 3:
- m_xor3 = data;
- break;
- case 4:
- m_xor4 = data;
- break;
- case 5:
- m_xor5 = data;
- break;
+ LOG(
+ "%s: Set XOR entry %u = 0x%02X\n",
+ machine().describe_context(),
+ index - 2,
+ data);
+ m_xor_table[index - 2] = data;
}
-
- if (m_currentxor == 0)
- set_xor_for_bank(4);
}
-}
-
-uint8_t gb_rom_sintax_device::read_ram(offs_t offset)
-{
- if (!m_ram.empty() && m_ram_enable)
- return m_ram[ram_bank_map[m_ram_bank] * 0x2000 + (offset & 0x1fff)];
- else
- return 0xff;
-}
-
-void gb_rom_sintax_device::write_ram(offs_t offset, uint8_t data)
-{
- if (!m_ram.empty() && m_ram_enable)
- m_ram[ram_bank_map[m_ram_bank] * 0x2000 + (offset & 0x1fff)] = data;
-}
-
-/*
-
- Further MBC5 variants to emulate:
-
- Digimon 2 & Digimon 4 (Yong Yong)
-
- Digimon 2 writes at $2000 to select latch2 (data must be divided by 2, and 0 becomes 1),
- then writes to $2400 a series of values that the patched version does not write...
- Digimon 4 seems to share part of the $2000 behavior, but does not write to $2400...
+ u8 m_scramble_mode;
+ u8 m_xor_index;
+ u8 m_xor_table[4];
+};
- */
-// MBC5 variant used by Digimon 2 (and maybe 4?)
-uint8_t gb_rom_digimon_device::read_rom(offs_t offset)
-{
- if (offset < 0x4000)
- return m_rom[rom_bank_map[m_latch_bank] * 0x4000 + (offset & 0x3fff)];
- else
- return m_rom[rom_bank_map[m_latch_bank2] * 0x4000 + (offset & 0x3fff)];
-}
+//**************************************************************************
+// MBC5 variant used by Chǒngwù Xiǎo Jīnglíng - Jié Jīn Tǎ Zhī Wáng
+//**************************************************************************
-void gb_rom_digimon_device::write_bank(offs_t offset, uint8_t data)
+class chongwu_device : public mbc5_logo_spoof_device_base
{
- if (offset < 0x2000)
- m_ram_enable = ((data & 0x0f) == 0x0a) ? 1 : 0;
- else if (offset == 0x2000)
+public:
+ chongwu_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) :
+ mbc5_logo_spoof_device_base(mconfig, GB_ROM_CHONGWU, tag, owner, clock),
+ m_protection_checked(0U),
+ m_installing_tap(false)
{
-// printf("written $02 %X at %X\n", data, offset);
- if (!data)
- data++;
- m_latch_bank2 = data/2;
}
- else if (offset < 0x3000)
+
+protected:
+ virtual void device_start() override ATTR_COLD
{
-// printf("written $03 %X at %X\n", data, offset);
+ mbc5_logo_spoof_device_base::device_start();
+
+ save_item(NAME(m_protection_checked));
}
- else if (offset < 0x4000)
+
+ virtual void device_reset() override ATTR_COLD
{
-// printf("written $04 %X at %X\n", data, offset);
+ mbc5_logo_spoof_device_base::device_reset();
+
+ m_protection_checked = 0U;
+
+ install_protection_tap();
+ m_notif_cart_space = cart_space()->add_change_notifier(
+ [this] (read_or_write mode)
+ {
+ if (u32(mode) & u32(read_or_write::READ))
+ install_protection_tap();
+ });
}
- else if (offset < 0x6000)
+
+private:
+ void install_protection_tap()
{
-// printf("written $05-$06 %X at %X\n", data, offset);
- data &= 0x0f;
- m_ram_bank = data;
+ if (!m_installing_tap)
+ {
+ m_installing_tap = true;
+ m_protection_tap.remove();
+ if (!m_protection_checked)
+ {
+ m_protection_tap = cart_space()->install_read_tap(
+ 0x41c3, 0x41c3,
+ "protection_tap_r",
+ [this] (offs_t offset, u8 &data, u8 mem_mask)
+ {
+ assert(!m_protection_checked);
+
+ m_protection_checked = 1U;
+ m_notif_cart_space.reset();
+ m_protection_tap.remove();
+
+ data = 0x5d;
+ },
+ &m_protection_tap);
+ }
+ else
+ {
+ m_notif_cart_space.reset();
+ }
+ m_installing_tap = false;
+ }
}
-// else
-// printf("written $07 %X at %X\n", data, offset);
-}
-uint8_t gb_rom_digimon_device::read_ram(offs_t offset)
-{
- if (!m_ram.empty() && m_ram_enable)
- return m_ram[ram_bank_map[m_ram_bank] * 0x2000 + (offset & 0x1fff)];
- else
- return 0xff;
-}
+ memory_passthrough_handler m_protection_tap;
+ util::notifier_subscription m_notif_cart_space;
-void gb_rom_digimon_device::write_ram(offs_t offset, uint8_t data)
-{
- if (!m_ram.empty() && m_ram_enable)
- m_ram[ram_bank_map[m_ram_bank] * 0x2000 + (offset & 0x1fff)] = data;
-}
+ u8 m_protection_checked;
+ bool m_installing_tap;
+};
-// MBC1 variant used by Yong Yong for Rockman 8
-uint8_t gb_rom_rockman8_device::read_rom(offs_t offset)
-{
- if (offset < 0x4000)
- return m_rom[m_latch_bank * 0x4000 + (offset & 0x3fff)];
- else
- return m_rom[m_latch_bank2 * 0x4000 + (offset & 0x3fff)];
-}
+//**************************************************************************
+// MBC5 variant used by Li Cheng/Niutoude games
+//**************************************************************************
-void gb_rom_rockman8_device::write_bank(offs_t offset, uint8_t data)
+class licheng_device : public mbc5_logo_spoof_device_base
{
- if (offset < 0x2000)
- return;
- else if (offset < 0x4000)
+public:
+ licheng_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) :
+ mbc5_logo_spoof_device_base(mconfig, GB_ROM_LICHENG, tag, owner, clock)
{
- // 5bits only
- data &= 0x1f;
- if (data == 0)
- data = 1;
- if (data > 0xf)
- data -= 8;
+ }
- m_latch_bank2 = data;
+ virtual std::error_condition load(std::string &message) override ATTR_COLD
+ {
+ // install regular MBC5 handlers
+ std::error_condition const result(mbc5_logo_spoof_device_base::load(message));
+ if (result)
+ return result;
+
+ // protection against using a standard MBC5 - actual ignored range uncertain
+ // 0x2100 must not be ignored for Cannon Fodder sound
+ // 0x2180 must be ignored for FF DX3
+ cart_space()->unmap_write(0x2101, 0x2fff);
+
+ // all good
+ return std::error_condition();
}
-}
+};
-uint8_t gb_rom_rockman8_device::read_ram(offs_t offset)
-{
- if (!m_ram.empty())
- return m_ram[offset];
- else
- return 0xff;
-}
-void gb_rom_rockman8_device::write_ram(offs_t offset, uint8_t data)
-{
- if (!m_ram.empty())
- m_ram[offset] = data;
-}
-
-// MBC1 variant used by Yong Yong for Super Mario 3 Special
-
-// Mario special seems to be 512k image (mirrored up to 1m or 2m [redump needed to establish this])
-// it consists of 13 unique 16k chunks layed out as follows
-// unique chunk --> bank in bin
-// 1st to 7th --> 0x00 to 0x06
-// 8th --> 0x08
-// 9th --> 0x0b
-// 10th --> 0x0c
-// 11th --> 0x0d
-// 12th --> 0x0f
-// 13th --> 0x13
-
-// writing data to 0x2000-0x2fff switches bank according to the table below
-// (the value values corresponding to table[0x0f] is not confirmed, choices
-// 0,1,2,3,8,c,f freeze the game, while 4,5,6,7,b,d,0x13 work with glitches)
-static uint8_t smb3_table1[0x20] =
-{
- 0x00,0x04,0x01,0x05, 0x02,0x06,0x03,0x05, 0x08,0x0c,0x03,0x0d, 0x03,0x0b,0x0b,0x08 /* original doc here put 0x0f (i.e. 11th unique bank) */,
- 0x05,0x06,0x0b,0x0d, 0x08,0x06,0x13,0x0b, 0x08,0x05,0x05,0x08, 0x0b,0x0d,0x06,0x05
-};
-// according to old doc from Brian Provinciano, writing bit5 in 0x5000-0x5fff should
-// change the bank layout, in the sense that writing to bankswitch acts like if
-// the original rom has a different layout (as if unique chunks were under permutations
-// (24), (365) and (8a9) with 0,1,7,b,c fixed) and the same table above is used
-// however, no such a write ever happen (only bit4 is written, but changing mode with
-// bit4 breaks the gfx...)
+//**************************************************************************
+// New Game Boy Color cartridges with HK0701 and HK0819 boards
+//**************************************************************************
-uint8_t gb_rom_sm3sp_device::read_rom(offs_t offset)
+class ngbchk_device : public rom_mbc_device_base
{
- if (offset < 0x4000)
- return m_rom[rom_bank_map[0] * 0x4000 + (offset & 0x3fff)];
- else
- return m_rom[m_latch_bank2 * 0x4000 + (offset & 0x3fff)];
-}
+public:
+ ngbchk_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) :
+ rom_mbc_device_base(mconfig, GB_ROM_NEWGBCHK, tag, owner, clock),
+ m_view_prot(*this, "protection")
+ {
+ }
-void gb_rom_sm3sp_device::write_bank(offs_t offset, uint8_t data)
-{
-// printf("write 0x%x at %x\n", data, offset);
- if (offset < 0x2000)
- return;
- else if (offset < 0x3000)
- {
- // Table 1 confirmed...
- // 0->0, 4->2, 6->3
- // 1e -> 6 (level 1 bg gfx)
- // 19 -> 5 (level 2 bg gfx)
- // 1b -> 8 (level 3 bg gfx)
- // 1d -> D (level 4 bg gfx)
- // 1c -> B (bonus house bg gfx)
- // 1 (9 maybe, or 3)? f (5 maybe)? 2->1?
- // 16 -> 4-8? b?
-
- // 5bits only
- data &= 0x1f;
+ virtual std::error_condition load(std::string &message) override ATTR_COLD
+ {
+ // TODO: ROM addresses seem to be fully decoded with HK0819 (rather than mirroring)
+
+ // set up ROM and RAM
+ // TODO: how many RAM bank outputs are actually present?
+ std::error_condition err = install_memory(message, 2, 7);
+ if (err)
+ return err;
+
+ // install handlers
+ cart_space()->install_write_handler(
+ 0x0000, 0x1fff,
+ emu::rw_delegate(*this, FUNC(ngbchk_device::enable_ram)));
+ cart_space()->install_write_handler(
+ 0x2000, 0x3fff,
+ emu::rw_delegate(*this, FUNC(ngbchk_device::bank_switch_fine)));
+ cart_space()->install_write_handler(
+ 0x4000, 0x5fff,
+ emu::rw_delegate(*this, FUNC(ngbchk_device::bank_switch_coarse)));
+
+ // install protection over the top of high ROM bank
+ cart_space()->install_view(
+ 0x4000, 0x7fff,
+ m_view_prot);
+ m_view_prot[0].install_read_handler(
+ 0x4000, 0x4fff, 0x0ff0, 0x0000, 0x0000,
+ emu::rw_delegate(*this, FUNC(ngbchk_device::protection)));
+ m_view_prot[0].unmap_read(0x5000, 0x7fff);
+
+ // all good
+ return std::error_condition();
+ }
- m_latch_bank2 = smb3_table1[data];
- if (m_mode)
- {
- switch (m_latch_bank2)
- {
- case 0x02: m_latch_bank2 = 4; break;
- case 0x03: m_latch_bank2 = 6; break;
- case 0x04: m_latch_bank2 = 2; break;
- case 0x05: m_latch_bank2 = 3; break;
- case 0x06: m_latch_bank2 = 5; break;
- case 0x0b: m_latch_bank2 = 0xd; break;
- case 0x0c: m_latch_bank2 = 0xb; break;
- case 0x0d: m_latch_bank2 = 0xc; break;
-
- case 0x00:
- case 0x01:
- case 0x08:
- case 0x0f:
- case 0x13:
- default:
- break;
- }
- }
+protected:
+ virtual void device_reset() override ATTR_COLD
+ {
+ rom_mbc_device_base::device_reset();
+
+ // TODO: proper reset state
+ set_bank_rom_coarse(0);
+ set_bank_rom_fine(0);
+ set_ram_enable(false);
+
+ m_view_prot.disable();
}
- else if (offset < 0x5000)
+
+private:
+ void enable_ram(u8 data)
{
-// printf("write $5 %X at %X\n", data, offset);
- //maybe rumble??
+ // TODO: how many bits are checked?
+ set_ram_enable(0x0a == data);
}
- else if (offset < 0x6000)
+
+ void bank_switch_fine(u8 data)
{
-// printf("write mode %x\n", data);
- m_mode = BIT(data, 5);
-// write_bank(0x2000, 1);
+ set_bank_rom_fine(data & 0x7f);
+ LOG(
+ "%s: Protection read %s\n",
+ machine().describe_context(),
+ BIT(data, 7) ? "enabled" : "disabled");
+ if (BIT(data, 7))
+ m_view_prot.select(0);
+ else
+ m_view_prot.disable();
}
-}
-uint8_t gb_rom_sm3sp_device::read_ram(offs_t offset)
-{
- if (!m_ram.empty())
- return m_ram[offset];
- else
- return 0xff;
-}
+ u8 protection(offs_t offset)
+ {
+ offset >>= 4;
+ switch (offset & 0x007)
+ {
+ default: // just to shut up dumb compilers
+ case 0x000:
+ return offset;
+ case 0x001:
+ return offset ^ 0xaa;
+ case 0x002:
+ return offset ^ 0x55;
+ case 0x003:
+ return (offset >> 1) | (offset << 7);
+ case 0x004:
+ return (offset << 1) | (offset >> 7);
+ case 0x05:
+ return bitswap<8>(offset, 0, 1, 2, 3, 4, 5, 6, 7);
+ case 0x06:
+ return
+ (bitswap<4>(offset | (offset >> 1), 6, 4, 2, 0) << 4) |
+ bitswap<4>(offset & (offset >> 1), 6, 4, 2, 0);
+ case 0x07:
+ return
+ (bitswap<4>(offset ^ (~offset >> 1), 6, 4, 2, 0) << 4) |
+ bitswap<4>(offset ^ (offset >> 1), 6, 4, 2, 0);
+ }
+ }
-void gb_rom_sm3sp_device::write_ram(offs_t offset, uint8_t data)
-{
- if (!m_ram.empty())
- m_ram[offset] = data;
-}
+ memory_view m_view_prot;
+};
-void gb_rom_camera_device::update_camera()
-{
- m_camera_regs[0] &= ~0x1;
-}
-uint8_t gb_rom_camera_device::read_rom(offs_t offset)
-{
- if (offset < 0x4000)
- return m_rom[rom_bank_map[m_latch_bank] * 0x4000 + (offset & 0x3fff)];
- else
- return m_rom[rom_bank_map[m_latch_bank2] * 0x4000 + (offset & 0x3fff)];
-}
-void gb_rom_camera_device::write_bank(offs_t offset, uint8_t data)
-{
- if (offset < 0x2000)
- m_ram_enable = ((data & 0x0f) == 0x0a) ? 1 : 0;
- else if (offset < 0x4000)
+//**************************************************************************
+// Fast Fame VF001 MBC5 variant with protection
+//**************************************************************************
+
+class vf001_device : public mbc5_logo_spoof_device_base
+{
+public:
+ vf001_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) :
+ mbc5_logo_spoof_device_base(mconfig, GB_ROM_VF001, tag, owner, clock),
+ m_bank_rom_upper(*this, "upper"),
+ m_bank_mask_rom_upper(0U),
+ m_command_preload(0U),
+ m_prot_cmd_enable(0U),
+ m_prot_cmd_data(0U),
+ m_readback_address(0U),
+ m_readback_bank(0U),
+ m_readback_length(0U),
+ m_readback_data{ 0U, 0U, 0U, 0U },
+ m_readback_count(0U),
+ m_split_address(0U),
+ m_split_enable(0U)
{
- // 7bits
- data &= 0x7f;
- /* Selecting bank 0 == selecting bank 1 */
- if (data == 0)
- data = 1;
+ }
+
+ virtual std::error_condition load(std::string &message) override ATTR_COLD
+ {
+ // get the command preload value
+ // TODO: add a way to specify this in software lists
+ gbxfile::leader_1_0 leader;
+ u8 const *extra;
+ u32 extralen;
+ if (gbxfile::get_data(gbx_footer_region(), leader, extra, extralen))
+ {
+ if (1 <= extralen)
+ {
+ m_command_preload = extra[0];
+ logerror(
+ "GBX format image specifies command preload value 0x%02X\n",
+ m_command_preload);
+ }
+ }
- m_latch_bank2 = data;
+ // install regular MBC5 handlers
+ std::error_condition const result(mbc5_logo_spoof_device_base::load(message));
+ if (result)
+ return result;
+
+ // set up an additional bank for the upper part of the low bank when split
+ memory_region *const romregion(cart_rom_region());
+ m_bank_mask_rom_upper = device_generic_cart_interface::map_non_power_of_two(
+ unsigned(romregion->bytes() / 0x4000),
+ [this, base = &romregion->as_u8()] (unsigned entry, unsigned page)
+ {
+ LOG(
+ "Install ROM 0x%06X-0x%06X in upper bank entry %u\n",
+ page * 0x4000,
+ (page * 0x4000) + 0x3fff,
+ entry);
+ m_bank_rom_upper->configure_entry(entry, &base[page * 0x4000]);
+ });
+ m_bank_rom_upper->set_entry(0);
+
+ // install handlers with protection emulation
+ cart_space()->install_read_handler(
+ 0x0000, 0x7fff,
+ emu::rw_delegate(*this, FUNC(vf001_device::read_rom)));
+ cart_space()->install_write_handler(
+ 0x6000, 0x700f, 0x100f, 0x0000, 0x0000,
+ emu::rw_delegate(*this, FUNC(vf001_device::prot_cmd)));
+
+ // all good
+ return std::error_condition();
}
- else if (offset < 0x6000)
+
+protected:
+ virtual void device_start() override ATTR_COLD
{
- m_ram_bank = data & 0x1f;
+ mbc5_logo_spoof_device_base::device_start();
+
+ m_prot_cmd_data = 0U;
+ m_readback_address = 0U;
+ m_readback_bank = 0U;
+ std::fill(std::begin(m_readback_data), std::end(m_readback_data), 0U);
+ m_split_address = 0U;
+
+ save_item(NAME(m_prot_cmd_enable));
+ save_item(NAME(m_prot_cmd_data));
+ save_item(NAME(m_readback_address));
+ save_item(NAME(m_readback_bank));
+ save_item(NAME(m_readback_length));
+ save_item(NAME(m_readback_data));
+ save_item(NAME(m_readback_count));
+ save_item(NAME(m_split_address));
+ save_item(NAME(m_split_enable));
}
-}
-uint8_t gb_rom_camera_device::read_ram(offs_t offset)
-{
- if ((m_ram_bank & 0x10) != 0)
- return (offset == 0) ? (m_camera_regs[0] & 0x7) : 0;
- if (!m_ram.empty() && (m_camera_regs[0] & 0x1) == 0)
+ virtual void device_reset() override ATTR_COLD
{
- /* Use first saved image as the snapshot. Top and bottom of snapshot are not saved. */
- if (m_ram_bank == 0 && offset >= 0x100 && offset < 0xf00)
- return m_ram[0x1f00 + offset];
- return m_ram[ram_bank_map[m_ram_bank] * 0x2000 + (offset & 0x1fff)];
+ mbc5_logo_spoof_device_base::device_reset();
+
+ m_prot_cmd_enable = 0U;
+ m_readback_length = 0U;
+ m_readback_count = 0U;
+ m_split_enable = 0U;
}
- return 0;
-}
-void gb_rom_camera_device::write_ram(offs_t offset, uint8_t data)
-{
- if ((m_ram_bank & 0x10) != 0)
+private:
+ u8 read_rom(offs_t offset)
{
- if (offset == 0)
+ u8 const data(mbc5_logo_spoof_device_base::read_rom(offset));
+
+ if (!m_readback_count && m_readback_length && !machine().side_effects_disabled())
{
- m_camera_regs[0] = data & 0x7;
- if (data & 0x1) update_camera();
+ if ((offset == m_readback_address) && ((BIT(offset, 14) ? bank_rom_fine() : 0) == m_readback_bank))
+ {
+ LOG(
+ "%s: Readback triggered by read from ROM bank 0x%02X address 0x%04X, length = %u\n",
+ machine().describe_context(),
+ m_readback_bank,
+ m_readback_address,
+ m_readback_length);
+ m_readback_count = m_readback_length;
+ }
}
- else if (offset < 54)
+
+ if (m_readback_count)
{
- m_camera_regs[offset] = data;
+ u8 const index(m_readback_length - m_readback_count);
+ if (!machine().side_effects_disabled())
+ --m_readback_count;
+ LOG(
+ "%s: Readback %u = 0x%02X\n",
+ machine().describe_context(),
+ index,
+ m_readback_data[index]);
+ return m_readback_data[index];
}
+
+ bool const split_upper(m_split_enable && (m_split_address <= offset) && (0x4000 > offset));
+ return !split_upper ? data : reinterpret_cast<u8 const *>(m_bank_rom_upper->base())[offset];
}
- else if (m_ram_enable && (m_camera_regs[0] & 0x1) == 0)
+
+ void prot_cmd(offs_t offset, u8 data)
{
- // RAM
- if (!m_ram.empty())
- m_ram[ram_bank_map[m_ram_bank] * 0x2000 + (offset & 0x1fff)] = data;
+ if ((0x1000 == offset) && (0x96 == data))
+ {
+ m_prot_cmd_enable = 1U;
+ m_prot_cmd_data = m_command_preload;
+ LOG(
+ "%s: Enabled protection commands, initial data = 0x%02X\n",
+ machine().describe_context(),
+ m_prot_cmd_data);
+ }
+ else if ((0x100f == offset) && (0x96 == data))
+ {
+ LOG("%s: Disabled protection commands\n", machine().describe_context());
+ m_prot_cmd_enable = 0U;
+ }
+ else if (m_prot_cmd_enable)
+ {
+ if (((0x0001 <= offset) && (0x1000 > offset)) || (0x100b <= offset))
+ {
+ logerror(
+ "%s: Unknown protection command address 0x%04X = 0x%02X\n",
+ machine().describe_context(),
+ offset,
+ data);
+ return;
+ }
+
+ // previous data is rotated right and combined with new data
+ m_prot_cmd_data = ((m_prot_cmd_data >> 1) | (m_prot_cmd_data << 7)) ^ data;
+
+ switch (offset)
+ {
+ case 0x0000:
+ m_bank_rom_upper->set_entry(m_prot_cmd_data & m_bank_mask_rom_upper);
+ LOG(
+ "%s: Bank split upper bank = 0x%02X\n",
+ machine().describe_context(),
+ m_prot_cmd_data);
+ break;
+ case 0x1000:
+ if (BIT(m_prot_cmd_data, 2))
+ {
+ m_readback_length = (m_prot_cmd_data & 0x03) + 1;
+ LOG(
+ "%s: Readback length = %u\n",
+ machine().describe_context(),
+ m_readback_length);
+ }
+ break;
+ case 0x1001:
+ case 0x1002:
+ m_readback_address &= BIT(offset, 0) ? 0xff00 : 0x00ff;
+ m_readback_address |= u16(m_prot_cmd_data) << (BIT(offset, 0) ? 0 : 8);
+ LOG(
+ "%s: Readback address = 0x%04X\n",
+ machine().describe_context(),
+ m_readback_address);
+ break;
+ case 0x1003:
+ m_readback_bank = m_prot_cmd_data;
+ LOG(
+ "%s: Readback bank = 0x%02X\n",
+ machine().describe_context(),
+ m_readback_bank);
+ break;
+ case 0x1004:
+ case 0x1005:
+ case 0x1006:
+ case 0x1007:
+ m_readback_data[offset & 0x0003] = m_prot_cmd_data;
+ LOG(
+ "%s: Readback data %u = 0x%02X\n",
+ machine().describe_context(),
+ offset & 0x0003,
+ m_prot_cmd_data);
+ break;
+ case 0x1008:
+ m_split_enable = (0x0f == (m_prot_cmd_data & 0x0f)) ? 1U : 0U;
+ LOG(
+ "%s: Bank split %s\n",
+ machine().describe_context(),
+ m_split_enable ? "enabled" : "disabled");
+ break;
+ case 0x1009:
+ case 0x100a:
+ m_split_address &= BIT(offset, 0) ? 0xff00 : 0x00ff;
+ m_split_address |= u16(m_prot_cmd_data) << (BIT(offset, 0) ? 0 : 8);
+ LOG(
+ "%s: Bank split address = 0x%04X\n",
+ machine().describe_context(),
+ m_split_address);
+ break;
+ }
+ }
}
-}
+
+ memory_bank_creator m_bank_rom_upper;
+ u8 m_bank_mask_rom_upper;
+ u8 m_command_preload;
+
+ u8 m_prot_cmd_enable;
+ u8 m_prot_cmd_data;
+
+ u16 m_readback_address;
+ u8 m_readback_bank;
+ u8 m_readback_length;
+ u8 m_readback_data[4];
+ u8 m_readback_count;
+
+ u16 m_split_address;
+ u8 m_split_enable;
+};
+
+} // anonymous namespace
+
+} // namespace bus::gameboy
+
+
+// device type definition
+DEFINE_DEVICE_TYPE_PRIVATE(GB_ROM_MBC1, device_gb_cart_interface, bus::gameboy::mbc1_device, "gb_rom_mbc1", "Game Boy MBC1 Cartridge")
+DEFINE_DEVICE_TYPE_PRIVATE(GB_ROM_MBC5, device_gb_cart_interface, bus::gameboy::mbc5_device, "gb_rom_mbc5", "Game Boy MBC5 Cartridge")
+DEFINE_DEVICE_TYPE_PRIVATE(GB_ROM_BBD, device_gb_cart_interface, bus::gameboy::bbd_device, "gb_rom_bbd", "Game Boy BBD Cartridge")
+DEFINE_DEVICE_TYPE_PRIVATE(GB_ROM_DSHGGB81, device_gb_cart_interface, bus::gameboy::dshggb81_device, "gb_rom_dshggb81", "Game Boy DSHGGB-81 Cartridge")
+DEFINE_DEVICE_TYPE_PRIVATE(GB_ROM_SINTAX, device_gb_cart_interface, bus::gameboy::sintax_device, "gb_rom_sintax", "Game Boy Sintax MBC5 Cartridge")
+DEFINE_DEVICE_TYPE_PRIVATE(GB_ROM_CHONGWU, device_gb_cart_interface, bus::gameboy::chongwu_device, "gb_rom_chongwu", "Game Boy Chongwu Xiao Jingling Pokemon Pikecho Cartridge")
+DEFINE_DEVICE_TYPE_PRIVATE(GB_ROM_LICHENG, device_gb_cart_interface, bus::gameboy::licheng_device, "gb_rom_licheng", "Game Boy Li Cheng MBC5 Cartridge")
+DEFINE_DEVICE_TYPE_PRIVATE(GB_ROM_NEWGBCHK, device_gb_cart_interface, bus::gameboy::ngbchk_device, "gb_rom_ngbchk", "Game Boy HK0701/HK0819 Cartridge")
+DEFINE_DEVICE_TYPE_PRIVATE(GB_ROM_VF001, device_gb_cart_interface, bus::gameboy::vf001_device, "gb_rom_vf001", "Game Boy Vast Fame VF001 Cartridge")
diff --git a/src/devices/bus/gameboy/mbc.h b/src/devices/bus/gameboy/mbc.h
index 52e5e56b583..0da79f570d1 100644
--- a/src/devices/bus/gameboy/mbc.h
+++ b/src/devices/bus/gameboy/mbc.h
@@ -1,452 +1,21 @@
// license:BSD-3-Clause
-// copyright-holders:Fabio Priuli, Wilbert Pol
+// copyright-holders:Vas Crabb, Wilbert Pol
#ifndef MAME_BUS_GAMEBOY_MBC_H
#define MAME_BUS_GAMEBOY_MBC_H
-#include "gb_slot.h"
+#pragma once
+#include "slot.h"
-// ======================> gb_rom_mbc_device
-class gb_rom_mbc_device : public device_t,
- public device_gb_cart_interface
-{
-public:
- // reading and writing
- virtual uint8_t read_rom(offs_t offset) override;
- virtual uint8_t read_ram(offs_t offset) override;
- virtual void write_ram(offs_t offset, uint8_t data) override;
-
-protected:
- // construction/destruction
- gb_rom_mbc_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
-
- // device-level overrides
- virtual void device_start() override { shared_start(); }
- virtual void device_reset() override { shared_reset(); }
-
- void shared_start();
- void shared_reset();
-
- uint8_t m_ram_enable;
-};
-
-// ======================> gb_rom_mbc1_device
-
-class gb_rom_mbc1_device : public gb_rom_mbc_device
-{
-public:
-
- // construction/destruction
- gb_rom_mbc1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual uint8_t read_rom(offs_t offset) override;
- virtual void write_bank(offs_t offset, uint8_t data) override;
- virtual uint8_t read_ram(offs_t offset) override;
- virtual void write_ram(offs_t offset, uint8_t data) override;
-
-protected:
- enum {
- MODE_16M_64k = 0, /// 16Mbit ROM, 64kBit RAM
- MODE_4M_256k = 1 /// 4Mbit ROM, 256kBit RAM
- };
-
- gb_rom_mbc1_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
-
- // device-level overrides
- virtual void device_start() override { shared_start(); save_item(NAME(m_mode)); }
- virtual void device_reset() override { shared_reset(); m_mode = MODE_16M_64k; }
- virtual void set_additional_wirings(uint8_t mask, int shift) override { m_mask = mask; m_shift = shift; } // these get set at cart loading
-
- uint8_t m_mode, m_mask;
- int m_shift;
-};
-
-// ======================> gb_rom_mbc2_device
-
-class gb_rom_mbc2_device : public gb_rom_mbc_device
-{
-public:
- // construction/destruction
- gb_rom_mbc2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual uint8_t read_rom(offs_t offset) override;
- virtual void write_bank(offs_t offset, uint8_t data) override;
- virtual uint8_t read_ram(offs_t offset) override;
- virtual void write_ram(offs_t offset, uint8_t data) override;
-
-protected:
- // device-level overrides
- virtual void device_start() override { shared_start(); }
- virtual void device_reset() override { shared_reset(); }
-};
-
-// ======================> gb_rom_mbc3_device
-
-class gb_rom_mbc3_device : public gb_rom_mbc_device
-{
-public:
- // construction/destruction
- gb_rom_mbc3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual uint8_t read_rom(offs_t offset) override;
- virtual void write_bank(offs_t offset, uint8_t data) override;
- virtual uint8_t read_ram(offs_t offset) override;
- virtual void write_ram(offs_t offset, uint8_t data) override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
-
-private:
- void update_rtc();
- uint8_t m_rtc_regs[5];
- int m_rtc_ready;
-};
-
-// ======================> gb_rom_mbc5_device
-
-class gb_rom_mbc5_device : public gb_rom_mbc_device
-{
-public:
- // construction/destruction
- gb_rom_mbc5_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual uint8_t read_rom(offs_t offset) override;
- virtual void write_bank(offs_t offset, uint8_t data) override;
- virtual uint8_t read_ram(offs_t offset) override;
- virtual void write_ram(offs_t offset, uint8_t data) override;
-
-protected:
- gb_rom_mbc5_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
-
- // device-level overrides
- virtual void device_start() override { shared_start(); m_rumble.resolve(); }
- virtual void device_reset() override { shared_reset(); }
-
- output_finder<> m_rumble;
-};
-
-// ======================> gb_rom_mbc6_device
-
-class gb_rom_mbc6_device : public gb_rom_mbc_device
-{
-public:
- // construction/destruction
- gb_rom_mbc6_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual uint8_t read_rom(offs_t offset) override;
- virtual void write_bank(offs_t offset, uint8_t data) override;
- virtual uint8_t read_ram(offs_t offset) override;
- virtual void write_ram(offs_t offset, uint8_t data) override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
-
- uint16_t m_latch1, m_latch2;
- uint8_t m_bank_4000, m_bank_6000;
-};
-
-// ======================> gb_rom_mbc7_device
-
-class gb_rom_mbc7_device : public gb_rom_mbc_device
-{
-public:
- // construction/destruction
- gb_rom_mbc7_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual uint8_t read_rom(offs_t offset) override;
- virtual void write_bank(offs_t offset, uint8_t data) override;
- virtual uint8_t read_ram(offs_t offset) override;
- virtual void write_ram(offs_t offset, uint8_t data) override;
-
-protected:
- // device-level overrides
- virtual void device_start() override { shared_start(); }
- virtual void device_reset() override { shared_reset(); }
-};
-
-// ======================> gb_rom_m161_device
-
-class gb_rom_m161_device : public gb_rom_mbc_device
-{
-public:
- // construction/destruction
- gb_rom_m161_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual uint8_t read_rom(offs_t offset) override;
- virtual void write_bank(offs_t offset, uint8_t data) override;
- virtual uint8_t read_ram(offs_t offset) override { return 0xff; }
- virtual void write_ram(offs_t offset, uint8_t data) override { }
-
-protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
-
- uint8_t m_base_bank;
- uint8_t m_load_disable;
-};
-
-// ======================> gb_rom_mmm01_device
-class gb_rom_mmm01_device : public gb_rom_mbc_device
-{
-public:
- // construction/destruction
- gb_rom_mmm01_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- // reading and writing
- virtual uint8_t read_rom(offs_t offset) override;
- virtual void write_bank(offs_t offset, uint8_t data) override;
- virtual uint8_t read_ram(offs_t offset) override;
- virtual void write_ram(offs_t offset, uint8_t data) override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
-
- uint16_t m_romb;
- uint8_t m_romb_nwe;
- uint8_t m_ramb;
- uint8_t m_ramb_nwe;
- uint8_t m_mode;
- uint8_t m_mode_nwe;
- uint8_t m_map;
- uint8_t m_mux;
-};
-
-// ======================> gb_rom_sachen_mmc1_device
-
-class gb_rom_sachen_mmc1_device : public gb_rom_mbc_device
-{
-public:
- // construction/destruction
- gb_rom_sachen_mmc1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual uint8_t read_rom(offs_t offset) override;
- virtual void write_bank(offs_t offset, uint8_t data) override;
- virtual uint8_t read_ram(offs_t offset) override { return 0xff; }
- virtual void write_ram(offs_t offset, uint8_t data) override { }
-
-protected:
- enum {
- MODE_LOCKED,
- MODE_UNLOCKED
- };
-
- gb_rom_sachen_mmc1_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
-
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
-
- uint8_t m_base_bank, m_mask, m_mode, m_unlock_cnt;
-};
-
-// ======================> gb_rom_sachen_mmc2_device
-
-class gb_rom_sachen_mmc2_device : public gb_rom_sachen_mmc1_device
-{
-public:
- // construction/destruction
- gb_rom_sachen_mmc2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual uint8_t read_rom(offs_t offset) override;
- virtual uint8_t read_ram(offs_t offset) override;
- virtual void write_ram(offs_t offset, uint8_t data) override;
-
-protected:
- enum {
- MODE_LOCKED_DMG,
- MODE_LOCKED_CGB,
- MODE_UNLOCKED
- };
-
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
-};
-
-// ======================> gb_rom_188in1_device
-class gb_rom_188in1_device : public gb_rom_mbc1_device
-{
-public:
- // construction/destruction
- gb_rom_188in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- // reading and writing
- virtual uint8_t read_rom(offs_t offset) override;
- virtual void write_bank(offs_t offset, uint8_t data) override;
-
-protected:
- // device-level overrides
- virtual void device_start() override { shared_start(); save_item(NAME(m_game_base)); }
- virtual void device_reset() override { shared_reset(); m_game_base = 0; }
-
-private:
- uint32_t m_game_base;
-};
-
-// ======================> gb_rom_sintax_device
-class gb_rom_sintax_device : public gb_rom_mbc_device
-{
-public:
- // construction/destruction
- gb_rom_sintax_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- // reading and writing
- virtual uint8_t read_rom(offs_t offset) override;
- virtual void write_bank(offs_t offset, uint8_t data) override;
- virtual uint8_t read_ram(offs_t offset) override;
- virtual void write_ram(offs_t offset, uint8_t data) override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- void set_xor_for_bank(uint8_t bank);
-
- uint8_t m_bank_mask, m_bank, m_reg;
-
- uint8_t m_currentxor, m_xor2, m_xor3, m_xor4, m_xor5, m_sintax_mode;
-};
-
-// ======================> gb_rom_chongwu_device
-
-class gb_rom_chongwu_device : public gb_rom_mbc5_device
-{
-public:
- // construction/destruction
- gb_rom_chongwu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual uint8_t read_rom(offs_t offset) override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
-
- uint8_t m_protection_checked;
-};
-
-// ======================> gb_rom_licheng_device
-
-class gb_rom_licheng_device : public gb_rom_mbc5_device
-{
-public:
- // construction/destruction
- gb_rom_licheng_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void write_bank(offs_t offset, uint8_t data) override;
-};
-
-// ======================> gb_rom_digimon_device
-
-class gb_rom_digimon_device : public gb_rom_mbc5_device
-{
-public:
- // construction/destruction
- gb_rom_digimon_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual uint8_t read_rom(offs_t offset) override;
- virtual void write_bank(offs_t offset, uint8_t data) override;
- virtual uint8_t read_ram(offs_t offset) override;
-
-protected:
- // device-level overrides
- virtual void device_start() override { shared_start(); }
- virtual void device_reset() override { shared_reset(); }
- virtual void write_ram(offs_t offset, uint8_t data) override;
-};
-
-// ======================> gb_rom_rockman8_device
-class gb_rom_rockman8_device : public gb_rom_mbc_device
-{
-public:
- // construction/destruction
- gb_rom_rockman8_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- // reading and writing
- virtual uint8_t read_rom(offs_t offset) override;
- virtual void write_bank(offs_t offset, uint8_t data) override;
- virtual uint8_t read_ram(offs_t offset) override;
- virtual void write_ram(offs_t offset, uint8_t data) override;
-
-protected:
- // device-level overrides
- virtual void device_start() override { shared_start(); }
- virtual void device_reset() override { shared_reset(); }
-
- uint8_t m_bank_mask, m_bank, m_reg;
-};
-
-// ======================> gb_rom_sm3sp_device
-class gb_rom_sm3sp_device : public gb_rom_mbc_device
-{
-public:
- // construction/destruction
- gb_rom_sm3sp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- // reading and writing
- virtual uint8_t read_rom(offs_t offset) override;
- virtual void write_bank(offs_t offset, uint8_t data) override;
- virtual uint8_t read_ram(offs_t offset) override;
- virtual void write_ram(offs_t offset, uint8_t data) override;
-
-protected:
- // device-level overrides
- virtual void device_start() override { shared_start(); }
- virtual void device_reset() override { shared_reset(); }
-
- uint8_t m_bank_mask, m_bank, m_reg, m_mode;
-};
-
-// ======================> gb_rom_camera_device
-class gb_rom_camera_device : public gb_rom_mbc_device
-{
-public:
- // construction/destruction
- gb_rom_camera_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual uint8_t read_rom(offs_t offset) override;
- virtual void write_bank(offs_t offset, uint8_t data) override;
- virtual uint8_t read_ram(offs_t offset) override;
- virtual void write_ram(offs_t offset, uint8_t data) override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
-
-private:
- void update_camera();
- uint8_t m_camera_regs[54];
-};
-
-
-
-// device type definition
-DECLARE_DEVICE_TYPE(GB_ROM_MBC1, gb_rom_mbc1_device)
-DECLARE_DEVICE_TYPE(GB_ROM_MBC2, gb_rom_mbc2_device)
-DECLARE_DEVICE_TYPE(GB_ROM_MBC3, gb_rom_mbc3_device)
-DECLARE_DEVICE_TYPE(GB_ROM_MBC5, gb_rom_mbc5_device)
-DECLARE_DEVICE_TYPE(GB_ROM_MBC6, gb_rom_mbc6_device)
-DECLARE_DEVICE_TYPE(GB_ROM_MBC7, gb_rom_mbc7_device)
-DECLARE_DEVICE_TYPE(GB_ROM_M161, gb_rom_m161_device)
-DECLARE_DEVICE_TYPE(GB_ROM_MMM01, gb_rom_mmm01_device)
-DECLARE_DEVICE_TYPE(GB_ROM_SACHEN1, gb_rom_sachen_mmc1_device)
-DECLARE_DEVICE_TYPE(GB_ROM_SACHEN2, gb_rom_sachen_mmc2_device)
-DECLARE_DEVICE_TYPE(GB_ROM_188IN1, gb_rom_188in1_device)
-DECLARE_DEVICE_TYPE(GB_ROM_SINTAX, gb_rom_sintax_device)
-DECLARE_DEVICE_TYPE(GB_ROM_CHONGWU, gb_rom_chongwu_device)
-DECLARE_DEVICE_TYPE(GB_ROM_LICHENG, gb_rom_licheng_device)
-DECLARE_DEVICE_TYPE(GB_ROM_DIGIMON, gb_rom_digimon_device)
-DECLARE_DEVICE_TYPE(GB_ROM_ROCKMAN8, gb_rom_rockman8_device)
-DECLARE_DEVICE_TYPE(GB_ROM_SM3SP, gb_rom_sm3sp_device)
-DECLARE_DEVICE_TYPE(GB_ROM_CAMERA, gb_rom_camera_device)
+DECLARE_DEVICE_TYPE(GB_ROM_MBC1, device_gb_cart_interface)
+DECLARE_DEVICE_TYPE(GB_ROM_MBC5, device_gb_cart_interface)
+DECLARE_DEVICE_TYPE(GB_ROM_BBD, device_gb_cart_interface)
+DECLARE_DEVICE_TYPE(GB_ROM_DSHGGB81, device_gb_cart_interface)
+DECLARE_DEVICE_TYPE(GB_ROM_SINTAX, device_gb_cart_interface)
+DECLARE_DEVICE_TYPE(GB_ROM_CHONGWU, device_gb_cart_interface)
+DECLARE_DEVICE_TYPE(GB_ROM_LICHENG, device_gb_cart_interface)
+DECLARE_DEVICE_TYPE(GB_ROM_NEWGBCHK, device_gb_cart_interface)
+DECLARE_DEVICE_TYPE(GB_ROM_VF001, device_gb_cart_interface)
#endif // MAME_BUS_GAMEBOY_MBC_H
diff --git a/src/devices/bus/gameboy/mbc2.cpp b/src/devices/bus/gameboy/mbc2.cpp
new file mode 100644
index 00000000000..8b108501cfb
--- /dev/null
+++ b/src/devices/bus/gameboy/mbc2.cpp
@@ -0,0 +1,225 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/***************************************************************************
+
+ Nintendo Game Boy Memory Bank Controller 2
+
+ Low-cost controller for games with modest ROM requirements and save file
+ support. Supports up to 256 KiB ROM (16 16 KiB pages), and has 512 nybbles
+ of internal static RAM.
+
+ Only A15-A14, A8-A0, D3-D0, and the read/write/RAM select lines are
+ connected to the MBC2 chip, i.e. addresses are effectively masked with
+ 0xC01F and data is effectively masked with 0x0F.
+
+ 0x0000-3FFF R - Fixed ROM bank, always first page of ROM.
+ 0x4000-7FFF R - Selectable ROM bank, page 1-15 of ROM.
+ 0xA000-A1FF RW - Internal static RAM on low nybble if enabled.
+ Mirrored up to 0xBFFF.
+
+ 0b0011xxx0xxxx W - Static RAM enable - write 0x0A on low nybble to enable,
+ any other value to disable.
+ 0b0011xxx1xxxx W - Select ROM page mapped at 0x4000. Only low nybble is
+ significant. Writing 0 selects page 1.
+
+ ***************************************************************************/
+
+#include "emu.h"
+#include "mbc2.h"
+
+#include "cartbase.h"
+#include "cartheader.h"
+
+#include <string>
+
+//#define VERBOSE 1
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+
+namespace bus::gameboy {
+
+namespace {
+
+class mbc2_device : public mbc_device_base
+{
+public:
+ mbc2_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+ virtual std::error_condition load(std::string &message) override ATTR_COLD;
+ virtual void unload() override ATTR_COLD;
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+private:
+ static inline constexpr unsigned RAM_SIZE = 512;
+
+ u8 ram_mbc_read(address_space &space, offs_t offset);
+ void ram_mbc_write(offs_t offset, u8 data);
+ void ram_mbc_enable(u8 data);
+ void bank_rom_switch(u8 data);
+
+ std::unique_ptr<u8 []> m_ram_mbc;
+ u8 m_ram_mbc_enable;
+ bool m_battery_present;
+};
+
+
+mbc2_device::mbc2_device(
+ machine_config const &mconfig,
+ char const *tag,
+ device_t *owner,
+ u32 clock) :
+ mbc_device_base(mconfig, GB_ROM_MBC2, tag, owner, clock),
+ m_ram_mbc_enable(0U),
+ m_battery_present(false)
+{
+}
+
+
+std::error_condition mbc2_device::load(std::string &message)
+{
+ // first check ROM
+ set_bank_bits_rom(4);
+ if (!check_rom(message))
+ return image_error::BADSOFTWARE;
+
+ // decide whether to enable battery backup
+ memory_region *const nvramregion(cart_nvram_region());
+ if (nvramregion)
+ {
+ if (nvramregion->bytes() != RAM_SIZE)
+ {
+ message = "Unsupported cartridge NVRAM size (only MBC2 internal 512 nybble RAM is supported)";
+ return std::error_condition();
+ }
+ m_battery_present = true;
+ logerror("Found 'nvram' region, battery backup enabled\n");
+ }
+ else if (loaded_through_softlist())
+ {
+ logerror("No 'nvram' region found, battery backup disabled\n");
+ m_battery_present = false;
+ }
+ else
+ {
+ // guess based on header
+ u8 const carttype((&cart_rom_region()->as_u8())[cartheader::OFFSET_TYPE]);
+ switch (carttype)
+ {
+ case cartheader::TYPE_MBC2:
+ m_battery_present = false;
+ break;
+ case cartheader::TYPE_MBC2_BATT:
+ m_battery_present = true;
+ break;
+ default:
+ osd_printf_warning(
+ "[%s] Unrecognized cartridge type 0x%02X in header, assuming no battery present\n",
+ tag(),
+ carttype);
+ m_battery_present = false;
+ }
+ osd_printf_verbose(
+ "[%s] Cartridge type 0x%02X in header, battery backup %s\n",
+ tag(),
+ carttype,
+ m_battery_present ? "enabled" : "disabled");
+ }
+
+ // install ROM, RAM and handlers
+ install_rom();
+ cart_space()->install_read_handler(
+ 0xa000, 0xa1ff, 0x0000, 0x1e00, 0x0000,
+ emu::rw_delegate(*this, FUNC(mbc2_device::ram_mbc_read)));
+ cart_space()->install_write_handler(
+ 0xa000, 0xa1ff, 0x0000, 0x1e00, 0x0000,
+ emu::rw_delegate(*this, FUNC(mbc2_device::ram_mbc_write)));
+ cart_space()->install_write_handler(
+ 0x0000, 0x00ff, 0x0000, 0x3e00, 0x0000,
+ emu::rw_delegate(*this, FUNC(mbc2_device::ram_mbc_enable)));
+ cart_space()->install_write_handler(
+ 0x0100, 0x01ff, 0x0000, 0x3e00, 0x0000,
+ emu::rw_delegate(*this, FUNC(mbc2_device::bank_rom_switch)));
+
+ // load battery backup if appropriate
+ if (nvramregion)
+ battery_load(m_ram_mbc.get(), RAM_SIZE, nvramregion->base());
+ else if (m_battery_present)
+ battery_load(m_ram_mbc.get(), RAM_SIZE, 0x0f);
+ for (unsigned i = 0U; RAM_SIZE > i; ++i)
+ m_ram_mbc[i] &= 0x0f;
+
+ // all good
+ return std::error_condition();
+}
+
+
+void mbc2_device::unload()
+{
+ if (m_battery_present)
+ battery_save(m_ram_mbc.get(), RAM_SIZE);
+}
+
+
+void mbc2_device::device_start()
+{
+ mbc_device_base::device_start();
+
+ m_ram_mbc = std::make_unique<u8 []>(RAM_SIZE);
+
+ save_pointer(NAME(m_ram_mbc), RAM_SIZE);
+ save_item(NAME(m_ram_mbc_enable));
+}
+
+
+void mbc2_device::device_reset()
+{
+ mbc_device_base::device_reset();
+
+ m_ram_mbc_enable = 0U;
+
+ set_bank_rom(1);
+}
+
+
+u8 mbc2_device::ram_mbc_read(address_space &space, offs_t offset)
+{
+ if (m_ram_mbc_enable)
+ return (m_ram_mbc[offset] & 0x0f) | (space.unmap() & 0xf0);
+ else
+ return space.unmap();
+}
+
+
+void mbc2_device::ram_mbc_write(offs_t offset, u8 data)
+{
+ if (m_ram_mbc_enable)
+ m_ram_mbc[offset] = data & 0x0f;
+}
+
+
+void mbc2_device::ram_mbc_enable(u8 data)
+{
+ m_ram_mbc_enable = (0x0a == (data & 0x0f)) ? 1U : 0U;
+ LOG(
+ "%s: Internal MBC2 RAM %s\n",
+ machine().describe_context(),
+ m_ram_mbc_enable ? "enabled" : "disabled");
+}
+
+
+void mbc2_device::bank_rom_switch(u8 data)
+{
+ data &= 0x0f;
+ set_bank_rom(data ? data : 1);
+}
+
+} // anonymous namespace
+
+} // namespace bus::gameboy
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(GB_ROM_MBC2, device_gb_cart_interface, bus::gameboy::mbc2_device, "gb_rom_mbc2", "Game Boy MBC2 Cartridge")
diff --git a/src/devices/bus/gameboy/mbc2.h b/src/devices/bus/gameboy/mbc2.h
new file mode 100644
index 00000000000..823347720a6
--- /dev/null
+++ b/src/devices/bus/gameboy/mbc2.h
@@ -0,0 +1,18 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/***************************************************************************
+
+ Nintendo Game Boy Memory Bank Controller 2
+
+ ***************************************************************************/
+#ifndef MAME_BUS_GAMEBOY_MBC2_H
+#define MAME_BUS_GAMEBOY_MBC2_H
+
+#pragma once
+
+#include "slot.h"
+
+
+DECLARE_DEVICE_TYPE(GB_ROM_MBC2, device_gb_cart_interface)
+
+#endif // MAME_BUS_GAMEBOY_MBC2_H
diff --git a/src/devices/bus/gameboy/mbc3.cpp b/src/devices/bus/gameboy/mbc3.cpp
new file mode 100644
index 00000000000..c850ba2e8c9
--- /dev/null
+++ b/src/devices/bus/gameboy/mbc3.cpp
@@ -0,0 +1,854 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/***************************************************************************
+
+ Nintendo Game Boy Memory Bank Controller 3
+
+ Includes a real-time clock in addition to the memory controller features.
+ The real-time clock can be used with or without a backup battery. Without
+ a backup battery, it just keeps time while the game is running. Several
+ games also used this memory controller without a real-time clock crystal.
+
+ The MBC3 supports up to 2 MiB ROM (128 16 KiB pages) and 32 KiB static RAM
+ (4 8 KiB pages). The MBC30 supports up to 4 MiB ROM (256 16 KiB pages) and
+ 64 KiB static RAM (8 8 KiB pages). If RAM bank lines are used for coarse
+ ROM banking, up to 8 MiB ROM (512 16 KiB pages) can be supported by the
+ MBC3, and up to 32 MiB ROM (2048 16 KiB pages) can be supported by the
+ MBC30.
+
+ The MBC30 was only used for a single game. In practice, 128K*8 static RAM
+ chips were used, but only half the space is accessible as the MBC30 chip
+ only has three RAM bank output lines.
+
+ 0x0000-3FFF R - Fixed ROM bank, always first page of ROM.
+ 0x4000-7FFF R - Selectable ROM bank, page 0-127 (MBC) or 0-255 (MBC30) of
+ ROM.
+ 0xA000-BFFF RW - Static RAM or real-time clock registers.
+
+ 0x0000-1FFF W - I/O enable - write 0x0A on low nybble to enable static RAM
+ or real-time clock registers, any other value to disable.
+ 0x2000-3FFF W - Select ROM page mapped at 0x4000. Bit 7 is ignored by
+ MBC3; all bits are significant for MBC30 Writing 0 selects
+ page 1.
+ 0x4000-5FFF W - Select RAM page or real-time clock register mapped at
+ 0xA000 (if enabled). If bit 3 is clear, static RAM is
+ selected; if bit 3 is set, real-time clock registers are
+ selected. Bits 2-0 select the RAM page or register.
+ 0x6000-7FFF W - Write 0x00 followed by 0x01 to latch real-time clock
+ registers.
+
+ Real-time clock registers:
+ 0x0 - Seconds.
+ 0x1 - Minutes.
+ 0x2 - Hours.
+ 0x3 - Bits 7-0 of days.
+ 0x4 - X------- Day counter overflow (set on carry out of bit 8, cleared
+ manually).
+ -X------ Set to halt real-time clock.
+ -------X Bit 8 of days.
+
+ Telefang bootlegs have three additional registers:
+ 0x5 - Low value.
+ 0x6 - High value.
+ 0x7 - Command:
+ 0x11 Decrement low value.
+ 0x12 Decrement high value.
+ 0x41 Add high value to low value.
+ 0x42 Add low value to high value.
+ 0x51 Increment low value.
+ 0x52 Increment high value.
+
+ TODO:
+ * How are the static RAM bank outputs set when real-time clock registers
+ are selected?
+ * What happens if invalid real-time clock registers 5-7 are selected?
+ * How do invalid seconds, minutes and hours values roll over?
+ * Does MBC30 really have eight ROM bank outputs? The one game using it
+ only uses seven.
+ * Does the bootleg Keitai Denjuu Telefang controller actually include a
+ real-time clock? No oscillator crystal is present.
+
+ ***************************************************************************/
+
+#include "emu.h"
+#include "mbc3.h"
+
+#include "cartbase.ipp"
+#include "cartheader.h"
+#include "gbxfile.h"
+
+#include "dirtc.h"
+
+#include "corestr.h"
+
+#include <string>
+#include <tuple>
+
+//#define VERBOSE 1
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+
+namespace bus::gameboy {
+
+namespace {
+
+//**************************************************************************
+// Class declarations
+//**************************************************************************
+
+class mbc3_device_base : public mbc_ram_device_base<mbc_dual_device_base>, public device_rtc_interface, public device_nvram_interface
+{
+protected:
+ mbc3_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock);
+
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ virtual void rtc_clock_updated(int year, int month, int day, int day_of_week, int hour, int minute, int second) override ATTR_COLD;
+
+ virtual void nvram_default() override ATTR_COLD;
+ virtual bool nvram_read(util::read_stream &file) override ATTR_COLD;
+ virtual bool nvram_write(util::write_stream &file) override ATTR_COLD;
+ virtual bool nvram_can_write() const override ATTR_COLD;
+
+ std::error_condition install_memory(std::string &message, unsigned highbits, unsigned lowbits) ATTR_COLD;
+
+protected:
+ u8 const rtc_select() const { return BIT(m_rtc_select, 3); }
+ u8 const rtc_register() const { return m_rtc_select & 0x07; }
+
+ virtual u8 read_rtc(address_space &space);
+ virtual void write_rtc(u8 data);
+
+private:
+ static inline constexpr u8 RTC_MASK[]{ 0x3f, 0x3f, 0x1f, 0xff, 0xc1 };
+ static inline constexpr u8 RTC_ROLLOVER[]{ 0x3c, 0x3c, 0x18, 0x00, 0x00 };
+
+ TIMER_CALLBACK_MEMBER(rtc_advance_seconds);
+
+ void enable_ram_rtc(u8 data);
+ void bank_switch_fine(u8 data);
+ void select_ram_rtc(u8 data);
+ void latch_rtc(u8 data);
+
+ u8 rtc_increment(unsigned index)
+ {
+ m_rtc_regs[0][index] = (m_rtc_regs[0][index] + 1) & RTC_MASK[index];
+ if (RTC_ROLLOVER[index] == (m_rtc_regs[0][index] & RTC_ROLLOVER[index]))
+ m_rtc_regs[0][index] = 0U;
+ return m_rtc_regs[0][index];
+ }
+
+ memory_view m_view_ram;
+
+ emu_timer *m_timer_rtc;
+ s64 m_machine_seconds;
+ bool m_has_rtc_xtal;
+ bool m_has_battery;
+
+ u8 m_rtc_regs[2][5];
+ u8 m_rtc_enable;
+ u8 m_rtc_select;
+ u8 m_rtc_latch;
+};
+
+
+class mbc3_device : public mbc3_device_base
+{
+public:
+ mbc3_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+ virtual std::error_condition load(std::string &message) override ATTR_COLD;
+};
+
+
+class mbc30_device : public mbc3_device_base
+{
+public:
+ mbc30_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+ virtual std::error_condition load(std::string &message) override ATTR_COLD;
+};
+
+
+class tfboot_device : public mbc3_device_base
+{
+public:
+ tfboot_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+ virtual std::error_condition load(std::string &message) override ATTR_COLD;
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ virtual u8 read_rtc(address_space &space) override;
+ virtual void write_rtc(u8 data) override;
+
+private:
+ u8 m_protection[2];
+};
+
+
+
+//**************************************************************************
+// mbc3_device_base
+//**************************************************************************
+
+mbc3_device_base::mbc3_device_base(
+ machine_config const &mconfig,
+ device_type type,
+ char const *tag,
+ device_t *owner,
+ u32 clock) :
+ mbc_ram_device_base<mbc_dual_device_base>(mconfig, type, tag, owner, clock),
+ device_rtc_interface(mconfig, *this),
+ device_nvram_interface(mconfig, *this),
+ m_view_ram(*this, "ram"),
+ m_timer_rtc(nullptr),
+ m_machine_seconds(0),
+ m_has_rtc_xtal(false),
+ m_has_battery(false),
+ m_rtc_enable(0U),
+ m_rtc_select(0U),
+ m_rtc_latch(0U)
+{
+}
+
+
+std::error_condition mbc3_device_base::install_memory(
+ std::string &message,
+ unsigned highbits,
+ unsigned lowbits)
+{
+ // check for RTC oscillator and backup battery
+ if (loaded_through_softlist())
+ {
+ // there's a feature tag indicating presence or absence of RTC crystal
+ char const *const rtcfeature(get_feature("rtc"));
+ if (rtcfeature)
+ {
+ // explicitly specified in software list
+ if (util::streqlower(rtcfeature, "yes") || util::streqlower(rtcfeature, "true"))
+ {
+ logerror("Real-time clock crystal present\n");
+ m_has_rtc_xtal = true;
+ }
+ else if (util::streqlower(rtcfeature, "no") || util::streqlower(rtcfeature, "false"))
+ {
+ logerror("No real-time clock crystal present\n");
+ m_has_rtc_xtal = false;
+ }
+ else
+ {
+ message = "Invalid 'rtc' feature value (must be yes or no)";
+ return image_error::BADSOFTWARE;
+ }
+ }
+ else
+ {
+ logerror("No 'rtc' feature found, assuming no real-time clock crystal present\n");
+ m_has_rtc_xtal = false;
+ }
+
+ // if there's an NVRAM region, there must be a backup battery
+ if (cart_nvram_region())
+ {
+ logerror("Found 'nvram' region, backup battery must be present\n");
+ m_has_battery = true;
+ }
+ else
+ {
+ logerror("No 'nvram' region found, assuming no backup battery present\n");
+ m_has_battery = true;
+ }
+ }
+ else
+ {
+ gbxfile::leader_1_0 leader;
+ u8 const *extra;
+ u32 extralen;
+ if (gbxfile::get_data(gbx_footer_region(), leader, extra, extralen))
+ {
+ m_has_rtc_xtal = bool(leader.rtc);
+ m_has_battery = bool(leader.batt);
+ logerror(
+ "GBX format image specifies %sreal-time clock crystal present, %sbackup battery present\n",
+ m_has_rtc_xtal ? "" : "no ",
+ m_has_battery ? "" : "no ");
+ }
+ else
+ {
+ // try probing the header
+ memory_region *const romregion(cart_rom_region());
+ if (romregion && (romregion->bytes() > cartheader::OFFSET_TYPE))
+ {
+ u8 const carttype((&romregion->as_u8())[cartheader::OFFSET_TYPE]);
+ switch (carttype)
+ {
+ case cartheader::TYPE_MBC3_RTC_BATT:
+ case cartheader::TYPE_MBC3_RTC_RAM_BATT:
+ m_has_rtc_xtal = true;
+ m_has_battery = true;
+ break;
+ case cartheader::TYPE_MBC3:
+ m_has_rtc_xtal = false;
+ m_has_battery = false;
+ break;
+ case cartheader::TYPE_MBC3_RAM:
+ case cartheader::TYPE_MBC3_RAM_BATT:
+ m_has_rtc_xtal = false;
+ m_has_battery = true;
+ break;
+ default:
+ osd_printf_warning(
+ "[%s] Unrecognized cartridge type 0x%02X in header, assuming no real-time clock crystal or backup battery present\n",
+ tag(),
+ carttype);
+ m_has_rtc_xtal = false;
+ m_has_battery = false;
+ }
+ logerror(
+ "Cartridge type 0x%02X in header, %sreal-time clock crystal present, %sbackup battery present\n",
+ carttype,
+ m_has_rtc_xtal ? "" : "no ",
+ m_has_battery ? "" : "no ");
+ }
+ }
+ }
+
+ // check for valid ROM/RAM regions
+ set_bank_bits_rom(highbits, lowbits);
+ set_bank_bits_ram(highbits);
+ if (!check_rom(message) || !check_ram(message))
+ return image_error::BADSOFTWARE;
+
+ // set up ROM and RAM
+ cart_space()->install_view(0xa000, 0xbfff, m_view_ram);
+ install_rom();
+ install_ram(m_view_ram[0]);
+
+ // install bank switching handlers
+ cart_space()->install_write_handler(
+ 0x0000, 0x1fff,
+ emu::rw_delegate(*this, FUNC(mbc3_device_base::enable_ram_rtc)));
+ cart_space()->install_write_handler(
+ 0x2000, 0x3fff,
+ emu::rw_delegate(*this, FUNC(mbc3_device_base::bank_switch_fine)));
+ cart_space()->install_write_handler(
+ 0x4000, 0x5fff,
+ emu::rw_delegate(*this, FUNC(mbc3_device_base::select_ram_rtc)));
+ cart_space()->install_write_handler(
+ 0x6000, 0x7fff,
+ emu::rw_delegate(*this, FUNC(mbc3_device_base::latch_rtc)));
+
+ // install real-time clock handlers
+ m_view_ram[1].install_read_handler(
+ 0xa000, 0xbfff,
+ emu::rw_delegate(*this, FUNC(mbc3_device_base::read_rtc)));
+ m_view_ram[1].install_write_handler(
+ 0xa000, 0xbfff,
+ emu::rw_delegate(*this, FUNC(mbc3_device_base::write_rtc)));
+
+ // if real-time clock crystal is present, start it ticking
+ if (m_has_rtc_xtal)
+ {
+ logerror("Real-time clock crystal present, starting timer\n");
+ m_timer_rtc->adjust(attotime(1, 0), 0, attotime(1, 0));
+ }
+
+ // all good
+ return std::error_condition();
+}
+
+
+void mbc3_device_base::device_start()
+{
+ mbc_ram_device_base<mbc_dual_device_base>::device_start();
+
+ m_timer_rtc = timer_alloc(FUNC(mbc3_device_base::rtc_advance_seconds), this);
+
+ save_item(NAME(m_rtc_regs));
+ save_item(NAME(m_rtc_enable));
+ save_item(NAME(m_rtc_select));
+ save_item(NAME(m_rtc_latch));
+}
+
+
+void mbc3_device_base::device_reset()
+{
+ mbc_ram_device_base<mbc_dual_device_base>::device_reset();
+
+ m_rtc_enable = 0U;
+ m_rtc_select = 0U;
+ m_rtc_latch = 0U;
+
+ set_bank_rom_coarse(0);
+ set_bank_rom_fine(1);
+ set_bank_ram(0);
+ m_view_ram.disable();
+}
+
+
+void mbc3_device_base::rtc_clock_updated(
+ int year,
+ int month,
+ int day,
+ int day_of_week,
+ int hour,
+ int minute,
+ int second)
+{
+ if (!m_has_rtc_xtal && !m_has_battery)
+ {
+ logerror("No real-time clock crystal or no battery present, not updating for elapsed time\n");
+ }
+ else if (std::numeric_limits<s64>::min() == m_machine_seconds)
+ {
+ logerror("Failed to load machine time from previous session, not updating for elapsed time\n");
+ }
+ else if (BIT(m_rtc_regs[0][4], 6))
+ {
+ logerror("Real-time clock halted, not updating for elapsed time\n");
+ }
+ else
+ {
+ // do a simple seconds elapsed since last run calculation
+ system_time current;
+ machine().current_datetime(current);
+ s64 delta(std::make_signed_t<decltype(current.time)>(current.time) - m_machine_seconds);
+ logerror("Previous session time, %d current time %d, delta %d\n", current.time, m_machine_seconds, delta);
+ if (0 > delta)
+ {
+ // This happens if the user runs the emulation faster
+ // than real time, exits, and then starts again without
+ // waiting for the difference between emulated and real
+ // time to elapse.
+ logerror("Previous session ended in the future, not updating for elapsed time\n");
+ }
+ else
+ {
+ logerror(
+ "Time before applying delta %u %02u:%02u:%02u%s\n",
+ (u16(BIT(m_rtc_regs[0][4], 0)) << 8) | m_rtc_regs[0][3],
+ m_rtc_regs[0][2],
+ m_rtc_regs[0][1],
+ m_rtc_regs[0][0],
+ BIT(m_rtc_regs[0][4], 7) ? " (overflow)" : "");
+
+ // annoyingly, we can get two rollovers if we started with an invalid value
+ unsigned seconds(delta % 60);
+ delta /= 60;
+ if (60 <= m_rtc_regs[0][0])
+ {
+ m_rtc_regs[0][0] = 0U;
+ --seconds;
+ ++delta;
+ }
+ if (60 <= (m_rtc_regs[0][0] + seconds))
+ ++delta;
+ m_rtc_regs[0][0] = (m_rtc_regs[0][0] + seconds) % 60;
+
+ // minutes is the same
+ unsigned minutes(delta % 60);
+ delta /= 60;
+ if (60 <= m_rtc_regs[0][1])
+ {
+ m_rtc_regs[0][1] = 0U;
+ --minutes;
+ ++delta;
+ }
+ if (60 <= (m_rtc_regs[0][1] + minutes))
+ ++delta;
+ m_rtc_regs[0][1] = (m_rtc_regs[0][1] + minutes) % 60;
+
+ // hours just has a different rollover point
+ unsigned hours(delta % 24);
+ delta /= 24;
+ if (24 <= m_rtc_regs[0][2])
+ {
+ m_rtc_regs[0][2] = 0U;
+ --hours;
+ ++delta;
+ }
+ if (24 <= (m_rtc_regs[0][2] + hours))
+ ++delta;
+ m_rtc_regs[0][2] = (m_rtc_regs[0][2] + hours) % 24;
+
+ // days has simple binary rollover
+ unsigned days(delta % 256);
+ if (256 <= (m_rtc_regs[0][3] + days))
+ ++delta;
+ m_rtc_regs[0][3] += days;
+
+ // set overflow flag if appropriate
+ if ((1 < delta) || (BIT(m_rtc_regs[0][4], 0) && delta))
+ m_rtc_regs[0][4] |= 0x80;
+ m_rtc_regs[0][4] ^= BIT(delta, 0);
+
+ logerror(
+ "Time after applying delta %u %02u:%02u:%02u%s\n",
+ (u16(BIT(m_rtc_regs[0][4], 0)) << 8) | m_rtc_regs[0][3],
+ m_rtc_regs[0][2],
+ m_rtc_regs[0][1],
+ m_rtc_regs[0][0],
+ BIT(m_rtc_regs[0][4], 7) ? " (overflow)" : "");
+ }
+ }
+}
+
+
+void mbc3_device_base::nvram_default()
+{
+ // TODO: proper cold RTC state
+ m_machine_seconds = std::numeric_limits<s64>::min();
+ for (unsigned i = 0U; std::size(m_rtc_regs[0]) > i; ++i)
+ m_rtc_regs[0][i] = RTC_MASK[i];
+}
+
+
+bool mbc3_device_base::nvram_read(util::read_stream &file)
+{
+ if (m_has_battery)
+ {
+ // read previous machine time (seconds since epoch) and RTC registers
+ std::error_condition err;
+ std::size_t actual;
+
+ u64 seconds;
+ std::tie(err, actual) = read(file, &seconds, sizeof(seconds));
+ if (err || (sizeof(seconds) != actual))
+ return false;
+ m_machine_seconds = big_endianize_int64(seconds);
+
+ std::tie(err, actual) = read(file, &m_rtc_regs[0][0], sizeof(m_rtc_regs[0]));
+ if (err || (sizeof(m_rtc_regs[0]) != actual))
+ return false;
+ }
+ else
+ {
+ logerror("No battery present, not loading real-time clock register contents\n");
+ }
+ return true;
+}
+
+
+bool mbc3_device_base::nvram_write(util::write_stream &file)
+{
+ // save current machine time as seconds since epoch and RTC registers
+ system_time current;
+ machine().current_datetime(current);
+ u64 const seconds(big_endianize_int64(s64(std::make_signed_t<decltype(current.time)>(current.time))));
+ std::error_condition err;
+ std::size_t written;
+ std::tie(err, written) = write(file, &seconds, sizeof(seconds));
+ if (err)
+ return false;
+ std::tie(err, written) = write(file, &m_rtc_regs[0][0], sizeof(m_rtc_regs[0]));
+ if (err)
+ return false;
+ return true;
+}
+
+
+bool mbc3_device_base::nvram_can_write() const
+{
+ return m_has_battery;
+}
+
+
+TIMER_CALLBACK_MEMBER(mbc3_device_base::rtc_advance_seconds)
+{
+ if (BIT(m_rtc_regs[0][4], 6))
+ return;
+
+ if (rtc_increment(0))
+ return;
+ if (rtc_increment(1))
+ return;
+ if (rtc_increment(2))
+ return;
+ if (++m_rtc_regs[0][3])
+ return;
+
+ if (BIT(m_rtc_regs[0][4], 0))
+ {
+ LOG("Day counter overflow");
+ m_rtc_regs[0][4] |= 0x80;
+ }
+ m_rtc_regs[0][4] ^= 0x01;
+}
+
+
+void mbc3_device_base::enable_ram_rtc(u8 data)
+{
+ m_rtc_enable = (0x0a == (data & 0x0f)) ? 1U : 0U;
+ if (!m_rtc_enable)
+ {
+ LOG(
+ "%s: Cartridge RAM and RTC registers disabled\n",
+ machine().describe_context());
+ m_view_ram.disable();
+ }
+ else if (rtc_select())
+ {
+ LOG(
+ "%s: RTC register %u enabled\n",
+ machine().describe_context(),
+ rtc_register());
+ m_view_ram.select(1);
+ }
+ else
+ {
+ LOG("%s: Cartridge RAM enabled\n", machine().describe_context());
+ m_view_ram.select(0);
+ }
+}
+
+
+void mbc3_device_base::bank_switch_fine(u8 data)
+{
+ data &= 0x7f;
+ set_bank_rom_fine(data ? data : 1);
+}
+
+
+void mbc3_device_base::select_ram_rtc(u8 data)
+{
+ // TODO: what happens with the RAM bank outputs when the RTC is selected?
+ // TODO: what happens if RTC register 5-7 is selected?
+ // TODO: is the high nybble ignored altogether?
+ set_bank_rom_coarse(data & 0x07);
+ set_bank_ram(data & 0x07);
+ m_rtc_select = data;
+ if (m_rtc_enable)
+ {
+ if (BIT(data, 3))
+ {
+ LOG(
+ "%s: RTC register %u enabled\n",
+ machine().describe_context(),
+ data & 0x07);
+ m_view_ram.select(1);
+ }
+ else
+ {
+ LOG("%s: Cartridge RAM enabled\n", machine().describe_context());
+ m_view_ram.select(0);
+ }
+ }
+}
+
+
+void mbc3_device_base::latch_rtc(u8 data)
+{
+ // FIXME: does it just check the least significant bit, or does it look for 0x00 and 0x01?
+ LOG("Latch RTC 0x%02X -> 0x%02X\n", m_rtc_latch, data);
+ if (!BIT(m_rtc_latch, 0) && BIT(data, 0))
+ {
+ LOG("%s: Latching RTC registers\n", machine().describe_context());
+ std::copy(std::begin(m_rtc_regs[0]), std::end(m_rtc_regs[0]), std::begin(m_rtc_regs[1]));
+ }
+ m_rtc_latch = data;
+}
+
+
+u8 mbc3_device_base::read_rtc(address_space &space)
+{
+ u8 const reg(rtc_register());
+ if (std::size(m_rtc_regs[1]) > reg)
+ {
+ LOG(
+ "%s: Read RTC register %u = 0x%02X\n",
+ machine().describe_context(),
+ reg,
+ m_rtc_regs[1][reg]);
+ return m_rtc_regs[1][reg];
+ }
+ else
+ {
+ LOG(
+ "%s: Read invalid RTC register %u\n",
+ machine().describe_context(),
+ reg);
+ return space.unmap();
+ }
+}
+
+
+void mbc3_device_base::write_rtc(u8 data)
+{
+ u8 const reg(rtc_register());
+ if (std::size(m_rtc_regs[0]) > reg)
+ {
+ LOG(
+ "%s: Write RTC register %u = 0x%02X\n",
+ machine().describe_context(),
+ reg,
+ data);
+ if (4U == reg)
+ {
+ // TODO: are bits 5-1 physically present, and if not, what do they read as?
+ // TODO: how does halting the RTC interact with the prescaler?
+ data &= 0xc1;
+ m_rtc_regs[0][reg] = data;
+ }
+ else
+ {
+ m_rtc_regs[0][reg] = data;
+ }
+ }
+ else
+ {
+ LOG(
+ "%s: Write invalid RTC register %u = 0x%02X\n",
+ machine().describe_context(),
+ reg,
+ data);
+ }
+}
+
+
+
+//**************************************************************************
+// mbc3_device
+//**************************************************************************
+
+mbc3_device::mbc3_device(
+ machine_config const &mconfig,
+ char const *tag,
+ device_t *owner,
+ u32 clock) :
+ mbc3_device_base(mconfig, GB_ROM_MBC3, tag, owner, clock)
+{
+}
+
+
+std::error_condition mbc3_device::load(std::string &message)
+{
+ return install_memory(message, 2, 7);
+}
+
+
+
+//**************************************************************************
+// mbc30_device
+//**************************************************************************
+
+mbc30_device::mbc30_device(
+ machine_config const &mconfig,
+ char const *tag,
+ device_t *owner,
+ u32 clock) :
+ mbc3_device_base(mconfig, GB_ROM_MBC30, tag, owner, clock)
+{
+}
+
+
+std::error_condition mbc30_device::load(std::string &message)
+{
+ return install_memory(message, 3, 8);
+}
+
+
+
+//**************************************************************************
+// tfboot_device
+//**************************************************************************
+
+tfboot_device::tfboot_device(
+ machine_config const &mconfig,
+ char const *tag,
+ device_t *owner,
+ u32 clock) :
+ mbc3_device_base(mconfig, GB_ROM_TFANGBOOT, tag, owner, clock),
+ m_protection{ 0U, 0U }
+{
+}
+
+
+std::error_condition tfboot_device::load(std::string &message)
+{
+ return install_memory(message, 2, 7);
+}
+
+
+void tfboot_device::device_start()
+{
+ mbc3_device_base::device_start();
+
+ save_item(NAME(m_protection));
+}
+
+
+void tfboot_device::device_reset()
+{
+ mbc3_device_base::device_reset();
+
+ m_protection[0] = 0U;
+ m_protection[1] = 0U;
+}
+
+
+u8 tfboot_device::read_rtc(address_space &space)
+{
+ u8 const reg(rtc_register());
+ switch (reg)
+ {
+ case 0x05:
+ case 0x06:
+ return m_protection[BIT(reg, 0)];
+ case 0x07:
+ return 0U;
+ default:
+ return mbc3_device_base::read_rtc(space);
+ }
+}
+
+
+void tfboot_device::write_rtc(u8 data)
+{
+ u8 const reg(rtc_register());
+ switch (reg)
+ {
+ case 0x05:
+ case 0x06:
+ m_protection[BIT(reg, 0)] = data;
+ break;
+ case 0x07:
+ LOG("%s: Protection command 0x%02X\n", machine().describe_context(), data);
+ switch (data)
+ {
+ case 0x11:
+ case 0x12:
+ --m_protection[BIT(data, 0)];
+ break;
+ case 0x41:
+ case 0x42:
+ m_protection[BIT(data, 0)] += m_protection[BIT(~data, 0)];
+ break;
+ case 0x51:
+ case 0x52:
+ ++m_protection[BIT(data, 0)];
+ break;
+ default:
+ logerror(
+ "%s: Unknown protection command 0x%02X\n",
+ machine().describe_context(),
+ data);
+ }
+ break;
+ default:
+ mbc3_device_base::write_rtc(data);
+ }
+}
+
+} // anonymous namespace
+
+} // namespace bus::gameboy
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(GB_ROM_MBC3, device_gb_cart_interface, bus::gameboy::mbc3_device, "gb_rom_mbc3", "Game Boy MBC3 Cartridge")
+DEFINE_DEVICE_TYPE_PRIVATE(GB_ROM_MBC30, device_gb_cart_interface, bus::gameboy::mbc30_device, "gb_rom_mbc30", "Game Boy MBC30 Cartridge")
+DEFINE_DEVICE_TYPE_PRIVATE(GB_ROM_TFANGBOOT, device_gb_cart_interface, bus::gameboy::tfboot_device, "gb_rom_tfboot", "Game Boy Telefang bootleg Cartridge")
diff --git a/src/devices/bus/gameboy/mbc3.h b/src/devices/bus/gameboy/mbc3.h
new file mode 100644
index 00000000000..ffa35d26a36
--- /dev/null
+++ b/src/devices/bus/gameboy/mbc3.h
@@ -0,0 +1,20 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/***************************************************************************
+
+ Nintendo Game Boy Memory Bank Controller 3
+
+ ***************************************************************************/
+#ifndef MAME_BUS_GAMEBOY_MBC3_H
+#define MAME_BUS_GAMEBOY_MBC3_H
+
+#pragma once
+
+#include "slot.h"
+
+
+DECLARE_DEVICE_TYPE(GB_ROM_MBC3, device_gb_cart_interface)
+DECLARE_DEVICE_TYPE(GB_ROM_MBC30, device_gb_cart_interface)
+DECLARE_DEVICE_TYPE(GB_ROM_TFANGBOOT, device_gb_cart_interface)
+
+#endif // MAME_BUS_GAMEBOY_MBC3_H
diff --git a/src/devices/bus/gameboy/mbc6.cpp b/src/devices/bus/gameboy/mbc6.cpp
new file mode 100644
index 00000000000..7e1594f1b2b
--- /dev/null
+++ b/src/devices/bus/gameboy/mbc6.cpp
@@ -0,0 +1,529 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/***************************************************************************
+
+ Nintendo Game Boy Memory Bank Controller 6
+
+ Only used for one game, the cartridges contain a Macronix MX29F008TC-14
+ Flash ROM (8-bit, 1 MiB), as well as the MBC6 chip, program ROM,
+ W24257S-70LL static RAM, MM1134, and CR1616 backup cell. Supports up to
+ 1 MiB ROM (128 8 KiB pages) and 32 KiB static RAM (8 4 KiB pages).
+
+ The MBC6 chip seems to have support for an additional ROM chip, as setting
+ bit 7 of the page seems to deselect the program ROM. RAM banking lines
+ could theoretically be used for outer ROM banking, allowing up to 8 MiB
+ program ROM (1024 8 KiB pages), or 16 MiB program ROM (2048 8 KiB pages)
+ if dual ROM chips are supported.
+
+ The MX29F008TC doesn't use either of the standard "boot sector" layouts
+ used by MX29LV008CT and MX29F008CB chips. It seems to use 4 KiB sectors.
+ The reported silicon ID is 0xC2 0x81. It's not clear how write protection
+ works. The game doesn't seem to set up conventional sector protection
+ (command 0x60). It's possible the Flash chips had all sectors protected
+ before being installed in cartridges and the Flash write enable output just
+ drives RESET# to Vhv to temporarily disable sector protection.
+
+ 0x0000-3FFF R - Fixed ROM bank, always first 16 KiB of ROM.
+ 0x4000-5FFF RW - Lower selectable ROM/Flash bank.
+ 0x6000-7FFF RW - Upper selectable ROM/Flash bank.
+
+ 0xA000-AFFF RW - Lower selectable static RAM bank if enabled.
+ 0xB000-BFFF RW - Upper selectable static RAM bank if enabled.
+
+ 0x0000-03FF W - Static RAM enable - write 0x0A on low nybble to enable,
+ any other value to disable.
+ 0x0400-07FF W - Select static RAM page mapped at 0xA000.
+ 0x0800-0BFF W - Select static RAM page mapped at 0xB000.
+ 0x0C00-0FFF W - Least significant bit enables Flash access.
+ 0x1000-???? W - Least significant bit enables Flash write. Seems to be
+ required to enable or disable Flash access, too. Doesn't
+ prevent writing commands to Flash, only erasing or writing
+ data (can read the silicon ID without setting this).
+ 0x2000-27FF W - Select ROM/Flash page mapped at 0x4000.
+ 0x2800-2FFF W - Select ROM (0x00) or Flash (0x08) at 0x4000.
+ 0x3000-37FF W - Select ROM/Flash page mapped at 0x6000.
+ 0x3800-3FFF W - Select ROM (0x00) or Flash (0x08) at 0x6000.
+
+ TODO:
+ * Hook up Flash write enable.
+ * What's the correct reset state?
+ * What happens if bit 7 of the page number is set when Flash is selected?
+ * What do the unknown bits in the Flash enable register do?
+
+ ***************************************************************************/
+
+#include "emu.h"
+#include "mbc6.h"
+
+#include "cartbase.h"
+
+#include "bus/generic/slot.h"
+#include "machine/intelfsh.h"
+
+#include <string>
+
+//#define VERBOSE 1
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+
+namespace bus::gameboy {
+
+namespace {
+
+class mbc6_device : public mbc_8k_device_base
+{
+public:
+ static constexpr feature_type imperfect_features() { return feature::ROM; }
+
+ mbc6_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+ virtual std::error_condition load(std::string &message) override ATTR_COLD;
+ virtual void unload() override ATTR_COLD;
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+private:
+ static inline constexpr unsigned PAGE_RAM_SIZE = 0x1000;
+
+ template <unsigned Bank> u8 read_flash(offs_t offset);
+ template <unsigned Bank> void write_flash(offs_t offset, u8 data);
+ void bank_switch_rom(offs_t offset, u8 data);
+ void select_flash(offs_t offset, u8 data);
+ template <unsigned Bank> void bank_switch_ram(u8 data);
+ void enable_flash(u8 data);
+ void enable_flash_write(u8 data);
+ void enable_ram(u8 data);
+
+ bool check_ram(std::string &message) ATTR_COLD;
+ void install_ram() ATTR_COLD;
+
+ required_device<intelfsh8_device> m_flash;
+ memory_view m_view_rom[2];
+ memory_view m_view_ram;
+ memory_bank_array_creator<2> m_bank_ram;
+ u8 m_bank_mask_ram;
+
+ u8 m_bank_sel_rom[2];
+ u8 m_bank_sel_ram[2];
+ u8 m_flash_select[2];
+ u8 m_flash_enable;
+ u8 m_flash_writable;
+};
+
+
+mbc6_device::mbc6_device(
+ machine_config const &mconfig,
+ char const *tag,
+ device_t *owner,
+ u32 clock) :
+ mbc_8k_device_base(mconfig, GB_ROM_MBC6, tag, owner, clock),
+ m_flash(*this, "flash"),
+ m_view_rom{ { *this, "romlow"}, { *this, "romhigh" } },
+ m_view_ram(*this, "ram"),
+ m_bank_ram(*this, { "ramlow", "ramhigh" }),
+ m_bank_mask_ram(0U),
+ m_bank_sel_rom{ 0U, 0U },
+ m_bank_sel_ram{ 0U, 0U },
+ m_flash_select{ 0U, 0U },
+ m_flash_enable(0U),
+ m_flash_writable(0U)
+{
+}
+
+
+std::error_condition mbc6_device::load(std::string &message)
+{
+ // first check that ROM/RAM regions are supportable
+ set_bank_bits_rom(7);
+ if (!check_rom(message) || !check_ram(message))
+ return image_error::BADSOFTWARE;
+
+ // install views for ROM/flash and RAM
+ cart_space()->install_view(0x4000, 0x5fff, m_view_rom[0]);
+ cart_space()->install_view(0x6000, 0x7fff, m_view_rom[1]);
+ cart_space()->install_view(0xa000, 0xbfff, m_view_ram);
+
+ // set up ROM and RAM as appropriate
+ install_rom(*cart_space(), m_view_rom[0][0], m_view_rom[1][0]);
+ install_ram();
+
+ // install memory controller handlers
+ cart_space()->install_write_handler(
+ 0x0000, 0x03ff,
+ emu::rw_delegate(*this, FUNC(mbc6_device::enable_ram)));
+ cart_space()->install_write_handler(
+ 0x0400, 0x07ff,
+ emu::rw_delegate(*this, FUNC(mbc6_device::bank_switch_ram<0>)));
+ cart_space()->install_write_handler(
+ 0x0800, 0x0bff,
+ emu::rw_delegate(*this, FUNC(mbc6_device::bank_switch_ram<1>)));
+ cart_space()->install_write_handler(
+ 0x0c00, 0x0fff,
+ emu::rw_delegate(*this, FUNC(mbc6_device::enable_flash)));
+ cart_space()->install_write_handler(
+ 0x1000, 0x1000, // TODO: what range does this actually respond to?
+ emu::rw_delegate(*this, FUNC(mbc6_device::enable_flash_write)));
+ cart_space()->install_write_handler(
+ 0x2000, 0x27ff, 0x0000, 0x0000, 0x1000,
+ emu::rw_delegate(*this, FUNC(mbc6_device::bank_switch_rom)));
+ cart_space()->install_write_handler(
+ 0x2800, 0x2fff, 0x0000, 0x0000, 0x1000,
+ emu::rw_delegate(*this, FUNC(mbc6_device::select_flash)));
+
+ // install Flash handlers
+ m_view_rom[0][1].install_readwrite_handler(
+ 0x4000, 0x5fff,
+ emu::rw_delegate(*this, FUNC(mbc6_device::read_flash<0>)),
+ emu::rw_delegate(*this, FUNC(mbc6_device::write_flash<0>)));
+ m_view_rom[1][1].install_readwrite_handler(
+ 0x6000, 0x7fff,
+ emu::rw_delegate(*this, FUNC(mbc6_device::read_flash<1>)),
+ emu::rw_delegate(*this, FUNC(mbc6_device::write_flash<1>)));
+
+ // all good
+ return std::error_condition();
+}
+
+
+void mbc6_device::unload()
+{
+ memory_region *const nvramregion(cart_nvram_region());
+ if (nvramregion && nvramregion->bytes())
+ battery_save(nvramregion->base(), nvramregion->bytes());
+}
+
+
+void mbc6_device::device_add_mconfig(machine_config &config)
+{
+ MACRONIX_29F008TC(config, m_flash);
+}
+
+
+void mbc6_device::device_start()
+{
+ mbc_8k_device_base::device_start();
+
+ save_item(NAME(m_bank_sel_rom));
+ save_item(NAME(m_bank_sel_ram));
+ save_item(NAME(m_flash_select));
+ save_item(NAME(m_flash_enable));
+ save_item(NAME(m_flash_writable));
+}
+
+
+void mbc6_device::device_reset()
+{
+ mbc_8k_device_base::device_reset();
+
+ m_bank_sel_rom[0] = 0U;
+ m_bank_sel_rom[1] = 0U;
+ m_bank_sel_ram[0] = 0U;
+ m_bank_sel_ram[1] = 0U;
+ m_flash_select[0] = 0U;
+ m_flash_select[1] = 0U;
+ m_flash_enable = 0U;
+ m_flash_writable = 0U;
+
+ m_view_rom[0].select(0);
+ m_view_rom[1].select(0);
+ m_view_ram.disable();
+
+ if (m_bank_mask_ram)
+ {
+ m_bank_ram[0]->set_entry(0);
+ m_bank_ram[1]->set_entry(0);
+ }
+
+ set_bank_rom_low(0);
+ set_bank_rom_high(0);
+}
+
+
+template <unsigned Bank>
+u8 mbc6_device::read_flash(offs_t offset)
+{
+ offset |= offs_t(m_bank_sel_rom[Bank] & 0x7f) << 13;
+ return m_flash->read(offset);
+}
+
+
+template <unsigned Bank>
+void mbc6_device::write_flash(offs_t offset, u8 data)
+{
+ offset |= offs_t(m_bank_sel_rom[Bank] & 0x7f) << 13;
+ LOG(
+ "%s: Write Flash %s 0x%05X = 0x%02X\n",
+ machine().describe_context(),
+ Bank ? "high" : "low",
+ offset,
+ data);
+ m_flash->write(offset, data);
+}
+
+
+void mbc6_device::bank_switch_rom(offs_t offset, u8 data)
+{
+ auto const bank(BIT(offset, 12));
+ m_bank_sel_rom[bank] = data;
+
+ if (!m_flash_select[bank])
+ {
+ if (BIT(data, 7))
+ {
+ LOG(
+ "%s: ROM bank %s unmapped\n",
+ machine().describe_context(),
+ bank ? "high" : "low");
+ m_view_rom[bank].disable(); // is there a chip select for a second program ROM?
+ }
+ else
+ {
+ m_view_rom[bank].select(0);
+ }
+ }
+
+ if (bank)
+ set_bank_rom_high(data & 0x7f);
+ else
+ set_bank_rom_low(data & 0x7f);
+}
+
+
+void mbc6_device::select_flash(offs_t offset, u8 data)
+{
+ auto const bank(BIT(offset, 12));
+ m_flash_select[bank] = BIT(data, 3);
+ if (m_flash_select[bank])
+ {
+ LOG(
+ "%s: Flash bank %s selected (%s)\n",
+ machine().describe_context(),
+ bank ? "high" : "low",
+ m_flash_enable ? "enabled" : "disabled");
+ if (m_flash_enable)
+ m_view_rom[bank].select(1);
+ else
+ m_view_rom[bank].disable();
+ }
+ else if (BIT(m_bank_sel_rom[bank], 7))
+ {
+ LOG(
+ "%s: ROM bank %s unmapped\n",
+ machine().describe_context(),
+ bank ? "high" : "low");
+ m_view_rom[bank].disable(); // is there a chip select for a second program ROM?
+ }
+ else
+ {
+ LOG(
+ "%s: ROM bank %s selected\n",
+ machine().describe_context(),
+ bank ? "high" : "low");
+ m_view_rom[bank].select(0);
+ }
+
+ // game writes 0xc6 when selecting ROM during boot - what do the other bits do?
+ if (data & ~0x08)
+ {
+ LOG(
+ "%s: ROM/Flash select %s with unknown bits set 0x%02X\n",
+ machine().describe_context(),
+ bank ? "high" : "low",
+ data);
+ }
+}
+
+
+template <unsigned Bank>
+void mbc6_device::bank_switch_ram(u8 data)
+{
+ if (m_bank_mask_ram)
+ {
+ data &= m_bank_mask_ram;
+ LOG(
+ "%s: Set RAM bank %s = 0x%04X\n",
+ machine().describe_context(),
+ Bank ? "high" : "low",
+ data * PAGE_RAM_SIZE);
+ m_bank_ram[Bank]->set_entry(data);
+ }
+}
+
+
+void mbc6_device::enable_flash(u8 data)
+{
+ // game seems to always set Flash write enable before changing this
+ if (m_flash_writable)
+ {
+ m_flash_enable = BIT(data, 0);
+ if (m_flash_enable)
+ {
+ LOG("%s: Flash enabled\n", machine().describe_context());
+ if (m_flash_select[0])
+ m_view_rom[0].select(1);
+ if (m_flash_select[1])
+ m_view_rom[1].select(1);
+ }
+ else
+ {
+ LOG("%s: Flash disabled\n", machine().describe_context());
+ if (m_flash_select[0])
+ m_view_rom[0].disable();
+ if (m_flash_select[1])
+ m_view_rom[1].disable();
+ }
+
+ if (data & ~0x01)
+ {
+ logerror(
+ "%s: Flash enable with unknown bits set 0x%02X\n",
+ machine().describe_context(),
+ data);
+ }
+ }
+ else
+ {
+ logerror(
+ "%s: Flash enable 0x%02X when Flash write disabled\n",
+ machine().describe_context(),
+ data);
+ }
+}
+
+
+void mbc6_device::enable_flash_write(u8 data)
+{
+ // FIXME: this should also control whether Flash can be erased/written
+ m_flash_writable = BIT(data, 0);
+ LOG(
+ "%s: Flash write %s\n",
+ machine().describe_context(),
+ m_flash_writable ? "enabled" : "disabled");
+
+ if (data & ~0x01)
+ {
+ logerror(
+ "%s: Flash write enable with unknown bits set 0x%02X\n",
+ machine().describe_context(),
+ data);
+ }
+}
+
+
+void mbc6_device::enable_ram(u8 data)
+{
+ if (0x0a == (data & 0x0f))
+ {
+ LOG("%s: Cartridge RAM enabled\n", machine().describe_context());
+ m_view_ram.select(0);
+ }
+ else
+ {
+ LOG("%s: Cartridge RAM disabled\n", machine().describe_context());
+ m_view_ram.disable();
+ }
+}
+
+
+bool mbc6_device::check_ram(std::string &message)
+{
+ memory_region *const ramregion(cart_ram_region());
+ memory_region *const nvramregion(cart_nvram_region());
+ auto const rambytes(ramregion ? ramregion->bytes() : 0);
+ auto const nvrambytes(nvramregion ? nvramregion->bytes() : 0);
+ if (rambytes && nvrambytes && ((rambytes & (PAGE_RAM_SIZE - 1)) || (nvrambytes & (PAGE_RAM_SIZE - 1)) || ((nvrambytes - 1) & nvrambytes)))
+ {
+ message = "Unsupported cartridge RAM size (if not all RAM is battery-backed, battery backed RAM size must be a power of two no smaller than 4 KiB, and total RAM size must be a multiple of 4 KiB)";
+ return false;
+ }
+
+ auto const ramtotal(rambytes + nvrambytes);
+ if (((PAGE_RAM_SIZE < ramtotal) && (ramtotal & (PAGE_RAM_SIZE - 1))) && ((u32(PAGE_RAM_SIZE) << 3) < ramtotal))
+ {
+ message = "Unsupported cartridge RAM size (must be no larger than 4 KiB, or a multiple of 4 KiB no larger than 32 KiB)";
+ return false;
+ }
+
+ return true;
+}
+
+
+void mbc6_device::install_ram()
+{
+ memory_region *const ramregion(this->cart_ram_region());
+ memory_region *const nvramregion(this->cart_nvram_region());
+ auto const rambytes(ramregion ? ramregion->bytes() : 0);
+ auto const nvrambytes(nvramregion ? nvramregion->bytes() : 0);
+ auto const ramtotal(rambytes + nvrambytes);
+ u8 *const rambase(rambytes ? &ramregion->as_u8() : nullptr);
+ u8 *const nvrambase(nvrambytes ? &nvramregion->as_u8() : nullptr);
+
+ if (!ramtotal)
+ {
+ // need to avoid fatal errors
+ m_bank_mask_ram = 0U;
+ m_view_ram[0];
+ }
+ else if (PAGE_RAM_SIZE >= ramtotal)
+ {
+ // install small amounts of RAM directly - mixed volatile and non-volatile RAM is not supported
+ device_generic_cart_interface::install_non_power_of_two<0>(
+ nvrambytes ? nvrambytes : rambytes,
+ PAGE_RAM_SIZE - 1,
+ 0,
+ 0xa000,
+ [this, base = nvrambase ? nvrambase : rambase] (offs_t begin, offs_t end, offs_t mirror, offs_t src)
+ {
+ LOG(
+ "Install RAM 0x%05X-0x%05X at 0x%04X-0x%04X mirror 0x%04X\n",
+ src,
+ src + (end - begin),
+ begin,
+ end,
+ 0x1000 | mirror);
+ m_view_ram[0].install_ram(begin, end, 0x1000 | mirror, &base[src]);
+ });
+ m_bank_mask_ram = 0U;
+ }
+ else
+ {
+ // install banked RAM, assuming lower pages are battery-backed
+ m_bank_mask_ram = device_generic_cart_interface::map_non_power_of_two(
+ unsigned(ramtotal / PAGE_RAM_SIZE),
+ [this, nvrampages = nvrambytes / PAGE_RAM_SIZE, rambase, nvrambase] (unsigned entry, unsigned page)
+ {
+ bool const nonvolatile(page < nvrampages);
+ u8 *const base(nonvolatile ? nvrambase : rambase);
+ auto const offset((page - (nonvolatile ? 0 : nvrampages)) * PAGE_RAM_SIZE);
+ LOG(
+ "Install %s 0x%05X-0x%05X in bank entry %u\n",
+ nonvolatile ? "NVRAM" : "RAM",
+ offset,
+ offset + (PAGE_RAM_SIZE - 1),
+ entry);
+ m_bank_ram[0]->configure_entry(entry, &base[offset]);
+ m_bank_ram[1]->configure_entry(entry, &base[offset]);
+ });
+ m_view_ram[0].install_readwrite_bank(0xa000, 0xafff, m_bank_ram[0]);
+ m_view_ram[0].install_readwrite_bank(0xb000, 0xbfff, m_bank_ram[1]);
+ }
+
+ if (nvrambytes)
+ {
+ save_pointer(NAME(nvrambase), nvrambytes);
+ battery_load(nvrambase, nvrambytes, nullptr);
+ }
+ if (rambytes)
+ save_pointer(NAME(rambase), rambytes);
+}
+
+} // anonymous namespace
+
+} // namespace bus::gameboy
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(GB_ROM_MBC6, device_gb_cart_interface, bus::gameboy::mbc6_device, "gb_rom_mbc6", "Game Boy MBC6 Cartridge")
diff --git a/src/devices/bus/gameboy/mbc6.h b/src/devices/bus/gameboy/mbc6.h
new file mode 100644
index 00000000000..07072d72f80
--- /dev/null
+++ b/src/devices/bus/gameboy/mbc6.h
@@ -0,0 +1,18 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/***************************************************************************
+
+ Nintendo Game Boy Memory Bank Controller 6
+
+ ***************************************************************************/
+#ifndef MAME_BUS_GAMEBOY_MBC6_H
+#define MAME_BUS_GAMEBOY_MBC6_H
+
+#pragma once
+
+#include "slot.h"
+
+
+DECLARE_DEVICE_TYPE(GB_ROM_MBC6, device_gb_cart_interface)
+
+#endif // MAME_BUS_GAMEBOY_MBC7_H
diff --git a/src/devices/bus/gameboy/mbc7.cpp b/src/devices/bus/gameboy/mbc7.cpp
new file mode 100644
index 00000000000..ccf034f337b
--- /dev/null
+++ b/src/devices/bus/gameboy/mbc7.cpp
@@ -0,0 +1,379 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/***************************************************************************
+
+ Nintendo Game Boy Memory Bank Controller 7
+
+ Only used for two games, the cartridges contain an ADXL202E two-axis
+ accelerometer and a 93LC56 or 93LC66 serial EEPROM, as well as the MBC7
+ chip and program ROM. The MBC7 never seems to have been fully utilised.
+ It appears to have inputs for an additional axis sensor, and an unused
+ 8-bit port of some kind. Supports up to 2 MiB ROM (128 16 KiB pages).
+
+ 0x0000-3FFF R - Fixed ROM bank, always first page of ROM.
+ 0x4000-7FFF R - Selectable ROM bank.
+
+ 0x0000-1FFF W - I/O enable - write 0x0A on low nybble to enable, any
+ other value to disable.
+ 0x2000-3FFF W - Select ROM page mapped at 0x4000. Only low seven bits are
+ significant.
+ 0x4000-5FFF W - I/O select - presumably switches between sensors and
+ EEPROM, and some unpopulated peripheral. Write 0x40 to
+ select sensors and EEPROM. Values seen include 0x00,
+ 0x3F, 0x40 and 0x54.
+
+ When I/O is enabled:
+ 0xA.0. W - Write 0x55 to clear accelerometer values (subsequent
+ reads will return 0x8000).
+ 0xA.1. W - Write 0xAA to acquire and latch accelerometer values
+ (must be in cleared state, or no effect).
+ 0xA.2. R - Accelerometer X value least significant byte.
+ 0xA.3. R - Accelerometer X value most significant byte.
+ 0xA.4. R - Accelerometer Y value least significant byte.
+ 0xA.5. R - Accelerometer Y value most significant byte.
+ 0xA.6. R - Always 0x00 (presumably for unpopulated Z axis sensor).
+ 0xA.7. R - Always 0xFF (presumably for unpopulated Z axis sensor).
+ 0xA.8. RW - EEPROM: bit 7 = CS, bit 6 = CLK, bit 1 = DI, bit 0 = DO.
+
+ Accelerometers read 0x81D0 in neutral orientation, and 1 g produces a
+ displacement of about 0x70 in either direction. The ADXL202E is rated for
+ full-scale output at 2 g in either direction. Inputs are set up to
+ simulate up to about 1.5 g.
+
+ TODO:
+ * Can ROM page 0 be selected like MBC5, or does it map to 1 like MBC1?
+ * EEPROM initialisation from software list item 'nvram' region.
+ * Reset state for EEPROM outputs.
+ * How is direction controlled for I/O lines?
+
+ ***************************************************************************/
+
+#include "emu.h"
+#include "mbc7.h"
+
+#include "cartbase.h"
+
+#include "machine/eepromser.h"
+
+#include <string>
+
+//#define VERBOSE 1
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+
+namespace bus::gameboy {
+
+namespace {
+
+//**************************************************************************
+// Class declarations
+//**************************************************************************
+
+class mbc7_device_base : public mbc_device_base
+{
+public:
+ virtual std::error_condition load(std::string &message) override ATTR_COLD;
+
+protected:
+ mbc7_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock);
+
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ required_device<eeprom_serial_93cxx_device> m_eeprom;
+
+private:
+ void bank_rom_switch(u8 data);
+ template <unsigned N, u8 Value, u8 Mask> void enable_io(u8 data);
+ void clear_accel(u8 data);
+ void acquire_accel(u8 data);
+ template <unsigned N> u8 read_accel(offs_t offset);
+ u8 read_unknown(offs_t offset);
+ u8 read_eeprom();
+ void write_eeprom(u8 data);
+
+ required_ioport_array<2> m_accel;
+ memory_view m_view_io;
+
+ u8 m_io_enable[2];
+
+ u16 m_accel_val[2];
+ u8 m_accel_latched;
+
+ u8 m_eeprom_out;
+};
+
+
+class mbc7_2k_device : public mbc7_device_base
+{
+public:
+ mbc7_2k_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) :
+ mbc7_device_base(mconfig, GB_ROM_MBC7_2K, tag, owner, clock)
+ {
+ }
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD
+ {
+ EEPROM_93C56_16BIT(config, m_eeprom, 0);
+ }
+};
+
+
+class mbc7_4k_device : public mbc7_device_base
+{
+public:
+ mbc7_4k_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) :
+ mbc7_device_base(mconfig, GB_ROM_MBC7_4K, tag, owner, clock)
+ {
+ }
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD
+ {
+ EEPROM_93C66_16BIT(config, m_eeprom, 0);
+ }
+};
+
+
+
+//**************************************************************************
+// Input port definitions
+//**************************************************************************
+
+INPUT_PORTS_START(mbc7)
+ PORT_START("ACCELX")
+ PORT_BIT(0x01ff, 0x00c0, IPT_AD_STICK_X) PORT_REVERSE PORT_MINMAX(0x0000, 0x0180) PORT_SENSITIVITY(50) PORT_KEYDELTA(30)
+
+ PORT_START("ACCELY")
+ PORT_BIT(0x01ff, 0x00c0, IPT_AD_STICK_Y) PORT_REVERSE PORT_MINMAX(0x0000, 0x0180) PORT_SENSITIVITY(50) PORT_KEYDELTA(30)
+INPUT_PORTS_END
+
+
+
+//**************************************************************************
+// mbc7_device_base
+//**************************************************************************
+
+std::error_condition mbc7_device_base::load(std::string &message)
+{
+ // first check ROM
+ set_bank_bits_rom(7);
+ if (!check_rom(message))
+ return image_error::BADSOFTWARE;
+
+ // install ROM and handlers
+ install_rom();
+ cart_space()->install_write_handler(
+ 0x0000, 0x1fff,
+ emu::rw_delegate(*this, NAME((&mbc7_device_base::enable_io<0, 0x0a, 0x0f>))));
+ cart_space()->install_write_handler(
+ 0x2000, 0x3fff,
+ emu::rw_delegate(*this, FUNC(mbc7_device_base::bank_rom_switch)));
+ cart_space()->install_write_handler(
+ 0x4000, 0x5fff,
+ emu::rw_delegate(*this, NAME((&mbc7_device_base::enable_io<1, 0x40, 0xff>))));
+ cart_space()->install_view(
+ 0xa000, 0xafff,
+ m_view_io);
+ m_view_io[0].install_write_handler(
+ 0xa000, 0xa00f, 0x0000, 0x0f00, 0x0000,
+ emu::rw_delegate(*this, FUNC(mbc7_device_base::clear_accel)));
+ m_view_io[0].install_write_handler(
+ 0xa010, 0xa01f, 0x0000, 0x0f00, 0x0000,
+ emu::rw_delegate(*this, FUNC(mbc7_device_base::acquire_accel)));
+ m_view_io[0].install_read_handler(
+ 0xa020, 0xa03f, 0x0000, 0x0f00, 0x0000,
+ emu::rw_delegate(*this, FUNC(mbc7_device_base::read_accel<0>)));
+ m_view_io[0].install_read_handler(
+ 0xa040, 0xa05f, 0x0000, 0x0f00, 0x0000,
+ emu::rw_delegate(*this, FUNC(mbc7_device_base::read_accel<1>)));
+ m_view_io[0].install_read_handler(
+ 0xa060, 0xa07f, 0x0000, 0x0f00, 0x0000,
+ emu::rw_delegate(*this, FUNC(mbc7_device_base::read_unknown)));
+ m_view_io[0].install_readwrite_handler(
+ 0xa080, 0xa08f, 0x0000, 0x0f00, 0x0000,
+ emu::rw_delegate(*this, FUNC(mbc7_device_base::read_eeprom)),
+ emu::rw_delegate(*this, FUNC(mbc7_device_base::write_eeprom)));
+
+ // all good
+ return std::error_condition();
+}
+
+
+mbc7_device_base::mbc7_device_base(
+ machine_config const &mconfig,
+ device_type type,
+ char const *tag,
+ device_t *owner,
+ u32 clock) :
+ mbc_device_base(mconfig, type, tag, owner, clock),
+ m_eeprom(*this, "eeprom"),
+ m_accel(*this, "ACCEL%c", 'X'),
+ m_view_io(*this, "io"),
+ m_io_enable{ 0U, 0U },
+ m_accel_val{ 0U, 0U },
+ m_accel_latched(0U),
+ m_eeprom_out(0U)
+{
+}
+
+
+ioport_constructor mbc7_device_base::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(mbc7);
+}
+
+
+void mbc7_device_base::device_start()
+{
+ mbc_device_base::device_start();
+
+ save_item(NAME(m_io_enable));
+ save_item(NAME(m_accel_val));
+ save_item(NAME(m_accel_latched));
+ save_item(NAME(m_eeprom_out));
+}
+
+
+void mbc7_device_base::device_reset()
+{
+ mbc_device_base::device_reset();
+
+ std::fill(std::begin(m_io_enable), std::end(m_io_enable), 0U);
+ std::fill(std::begin(m_io_enable), std::end(m_io_enable), 0x8000U);
+ m_accel_latched = 0U;
+
+ set_bank_rom(0);
+ m_view_io.disable();
+}
+
+
+void mbc7_device_base::bank_rom_switch(u8 data)
+{
+ set_bank_rom(data & 0x7f);
+}
+
+
+template <unsigned N, u8 Value, u8 Mask>
+void mbc7_device_base::enable_io(u8 data)
+{
+ m_io_enable[N] = (Value == (data & Mask)) ? 1U : 0U;
+ bool const enable(m_io_enable[0] && m_io_enable[1]);
+ LOG(
+ "%s: I/O enable %u = 0x%02X, I/O %s\n",
+ machine().describe_context(),
+ N,
+ data,
+ enable ? "enabled" : "disabled");
+ if (enable)
+ m_view_io.select(0);
+ else
+ m_view_io.disable();
+}
+
+
+void mbc7_device_base::clear_accel(u8 data)
+{
+ if (0x55 != data)
+ {
+ logerror(
+ "%s: Ignoring unknown command 0x%02X written to accelerometer clear register\n",
+ machine().describe_context(),
+ data);
+ }
+ else
+ {
+ m_accel_val[0] = 0x8000U;
+ m_accel_val[1] = 0x8000U;
+ m_accel_latched = 0U;
+ LOG("%s: Accelerometer data cleared\n", machine().describe_context());
+ }
+}
+
+
+void mbc7_device_base::acquire_accel(u8 data)
+{
+ if (0xaa != data)
+ {
+ logerror(
+ "%s: Ignoring unknown command 0x%02X written to accelerometer acquire register\n",
+ machine().describe_context(),
+ data);
+ }
+ else if (m_accel_latched)
+ {
+ logerror(
+ "%s: Ignoring accelerometer acquire command while data latched\n",
+ machine().describe_context());
+ }
+ else
+ {
+ m_accel_val[0] = 0x81d0 - 0x00c0 + m_accel[0]->read();
+ m_accel_val[1] = 0x81d0 - 0x00c0 + m_accel[1]->read();
+ m_accel_latched = 1U;
+ LOG(
+ machine().describe_context(),
+ "%s: Accelerometer data acquired X = 0x%04X Y = 0x%04X\n",
+ m_accel_val[0],
+ m_accel_val[1]);
+ }
+}
+
+
+template <unsigned N>
+u8 mbc7_device_base::read_accel(offs_t offset)
+{
+ u8 const result(m_accel_val[N] >> (BIT(offset, 4) ? 8 : 0));
+ LOG(
+ "Read accelerometer %c %cSB = 0x%02X\n",
+ machine().describe_context(),
+ 'X' + N,
+ BIT(offset, 4) ? 'M' : 'L',
+ result);
+ return result;
+}
+
+
+u8 mbc7_device_base::read_unknown(offs_t offset)
+{
+ return BIT(offset, 4) ? 0xff : 0x00;
+}
+
+
+u8 mbc7_device_base::read_eeprom()
+{
+ u8 const dout(m_eeprom->do_read() ? 0x01U : 0x00U);
+ LOG("%s: Read EEPROM DO = %u\n", machine().describe_context(), dout);
+ return (m_eeprom_out & 0xfe) | dout;
+}
+
+
+void mbc7_device_base::write_eeprom(u8 data)
+{
+ LOG(
+ "%s: Write EEPROM CS = %u CLK = %u DI = %u\n",
+ machine().describe_context(),
+ BIT(data, 7),
+ BIT(data, 6),
+ BIT(data, 1));
+ m_eeprom_out = data;
+ m_eeprom->cs_write(BIT(data, 7));
+ m_eeprom->clk_write(BIT(data, 6));
+ m_eeprom->di_write(BIT(data, 1));
+}
+
+} // anonymous namespace
+
+} // namespace bus::gameboy
+
+
+
+//**************************************************************************
+// Device type definitions
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(GB_ROM_MBC7_2K, device_gb_cart_interface, bus::gameboy::mbc7_2k_device, "gb_rom_mbc7_2k", "Game Boy MBC7 Cartridge with 93LC56")
+DEFINE_DEVICE_TYPE_PRIVATE(GB_ROM_MBC7_4K, device_gb_cart_interface, bus::gameboy::mbc7_4k_device, "gb_rom_mbc7_4k", "Game Boy MBC7 Cartridge with 93LC66")
diff --git a/src/devices/bus/gameboy/mbc7.h b/src/devices/bus/gameboy/mbc7.h
new file mode 100644
index 00000000000..bd5952a976b
--- /dev/null
+++ b/src/devices/bus/gameboy/mbc7.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/***************************************************************************
+
+ Nintendo Game Boy Memory Bank Controller 7
+
+ ***************************************************************************/
+#ifndef MAME_BUS_GAMEBOY_MBC7_H
+#define MAME_BUS_GAMEBOY_MBC7_H
+
+#pragma once
+
+#include "slot.h"
+
+
+DECLARE_DEVICE_TYPE(GB_ROM_MBC7_2K, device_gb_cart_interface)
+DECLARE_DEVICE_TYPE(GB_ROM_MBC7_4K, device_gb_cart_interface)
+
+#endif // MAME_BUS_GAMEBOY_MBC7_H
diff --git a/src/devices/bus/gameboy/mdslot.cpp b/src/devices/bus/gameboy/mdslot.cpp
new file mode 100644
index 00000000000..7339d139c1b
--- /dev/null
+++ b/src/devices/bus/gameboy/mdslot.cpp
@@ -0,0 +1,141 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/***************************************************************************
+
+ Mega Duck cartridge slot
+
+ ***************************************************************************/
+
+#include "emu.h"
+#include "mdslot.h"
+
+#include "carts.h"
+
+#include "emuopts.h"
+#include "romload.h"
+#include "softlist.h"
+
+//#define VERBOSE 1
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+
+//**************************************************************************
+// megaduck_cart_slot_device
+//**************************************************************************
+
+megaduck_cart_slot_device::megaduck_cart_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) :
+ gb_cart_slot_device_base(mconfig, MEGADUCK_CART_SLOT, tag, owner, clock)
+{
+}
+
+
+std::string megaduck_cart_slot_device::get_default_card_software(get_default_card_software_hook &hook) const
+{
+ using namespace bus::gameboy;
+
+ if (hook.image_file())
+ {
+ // loading from file - guess banking scheme using heuristics
+ u64 length;
+ if (!hook.image_file()->length(length))
+ {
+ if (0x8000 < length)
+ {
+ osd_printf_verbose("[%s] 0x%X-byte cartridge, requires ROM banking\n", tag(), length);
+ return slotoptions::MEGADUCK_BANKED;
+ }
+ else
+ {
+ osd_printf_verbose("[%s] 0x%X-byte cartridge, assuming flat ROM\n", tag(), length);
+ return slotoptions::MEGADUCK_STD;
+ }
+ }
+ else
+ {
+ osd_printf_warning("[%s] Error getting cartridge ROM length - assuming banked ROM\n", tag());
+ return slotoptions::MEGADUCK_BANKED;
+ }
+ }
+ else
+ {
+ // loading from software list - try to find matching software part
+ std::string const image_name(mconfig().options().image_option(instance_name()).value());
+ software_part const *const part(!image_name.empty() ? find_software_item(image_name, true) : nullptr);
+ if (part)
+ {
+ osd_printf_verbose("[%s] Found software part for image name '%s'\n", tag(), image_name);
+
+ // if there's an explicit "slot" feature, use it
+ char const *const slot(part->feature("slot"));
+ if (slot)
+ {
+ osd_printf_verbose("[%s] Using specified cartridge device '%s'\n", tag(), slot);
+ return slot;
+ }
+
+ // presence or absence of a fixed bank implies banking is in use
+ char const *const fixedbank(part->feature("fixedbank"));
+ if (fixedbank)
+ {
+ osd_printf_verbose("[%s] fixedbank='%s' specified, assuming banked ROM\n", tag(), fixedbank);
+ return slotoptions::MEGADUCK_BANKED;
+ }
+
+ // fall back to guessing based on length
+ for (rom_entry const &entry : part->romdata())
+ {
+ if (ROMENTRY_ISREGION(entry) && (entry.name() == "rom"))
+ {
+ auto const length(ROMREGION_GETLENGTH(entry));
+ if (0x8000 < length)
+ {
+ osd_printf_verbose("[%s] Found 0x%X-byte 'rom' region, requires ROM banking\n", tag(), length);
+ return slotoptions::MEGADUCK_BANKED;
+ }
+ else
+ {
+ osd_printf_verbose("[%s] Found 0x%X-byte 'rom' region, assuming flat ROM\n", tag(), length);
+ return slotoptions::MEGADUCK_STD;
+ }
+ }
+ }
+
+ // a flat ROM cartridge with nothing in it is harmless
+ osd_printf_verbose("[%s] No ROM region found\n", tag());
+ return slotoptions::MEGADUCK_STD;
+ }
+ else
+ {
+ osd_printf_verbose("[%s] No software part found for image name '%s'\n", tag(), image_name);
+ }
+ }
+
+ // leave the slot empty
+ return std::string();
+}
+
+
+std::pair<std::error_condition, std::string> megaduck_cart_slot_device::load_image_file(util::random_read &file)
+{
+ auto const len = length();
+
+ if (len)
+ {
+ LOG("Allocating %u byte cartridge ROM region\n", len);
+ memory_region *const romregion = machine().memory().region_alloc(subtag("rom"), len, 1, ENDIANNESS_LITTLE);
+ auto const [err, actual] = read_at(file, 0, romregion->base(), len);
+ if (err || (len != actual))
+ std::make_pair(err ? err : std::errc::io_error, "Error reading cartridge file");
+ }
+
+ return std::make_pair(std::error_condition(), std::string());
+}
+
+
+
+//**************************************************************************
+// Device type definitions
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(MEGADUCK_CART_SLOT, megaduck_cart_slot_device, "megaduck_cart_slot", "Mega Duck Cartridge Slot")
diff --git a/src/devices/bus/gameboy/mdslot.h b/src/devices/bus/gameboy/mdslot.h
new file mode 100644
index 00000000000..d78ac6f906c
--- /dev/null
+++ b/src/devices/bus/gameboy/mdslot.h
@@ -0,0 +1,70 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/***************************************************************************
+
+ Mega Duck cartridge slot
+
+ Cartridge edge connector (0.1" pitch double-sided):
+ VCC 1 2
+ /WR 3 4 /RD
+ 5 6 A0
+ A1 7 8 A2
+ A3 9 10 A4
+ A5 11 12 A6
+ A7 13 14 A8
+ A9 15 16 A10
+ A11 17 18 A12
+ A13 19 20 A14
+ A15 21 22 D0
+ D1 23 24 D2
+ D3 25 26 D4
+ D5 27 28 D6
+ D7 29 30 /RST
+ 31 32
+ 33 34
+ GND 35 36 GND
+
+ Pinout based on cartridge connections. Unlabelled contacts may be
+ connected in console.
+
+ ***************************************************************************/
+#ifndef MAME_BUS_GAMEBOY_MDSLOT_H
+#define MAME_BUS_GAMEBOY_MDSLOT_H
+
+#pragma once
+
+#include "slot.h"
+
+#include <string>
+
+
+class megaduck_cart_slot_device : public gb_cart_slot_device_base
+{
+public:
+ template <typename T>
+ megaduck_cart_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts, char const *dflt) :
+ megaduck_cart_slot_device(mconfig, tag, owner, 0U)
+ {
+ option_reset();
+ opts(*this);
+ set_default_option(dflt);
+ set_fixed(false);
+ }
+ megaduck_cart_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+ // device_image_interface implementation
+ virtual char const *image_interface() const noexcept override { return "megaduck_cart"; }
+ virtual char const *file_extensions() const noexcept override { return "bin"; }
+
+ // device_slot_interface implementation
+ virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override ATTR_COLD;
+
+protected:
+ // gb_cart_slot_device_base implementation
+ virtual std::pair<std::error_condition, std::string> load_image_file(util::random_read &file) override ATTR_COLD;
+};
+
+
+DECLARE_DEVICE_TYPE(MEGADUCK_CART_SLOT, megaduck_cart_slot_device)
+
+#endif // MAME_BUS_GAMEBOY_MDSLOT_H
diff --git a/src/devices/bus/gameboy/mmm01.cpp b/src/devices/bus/gameboy/mmm01.cpp
new file mode 100644
index 00000000000..65bf84acbb7
--- /dev/null
+++ b/src/devices/bus/gameboy/mmm01.cpp
@@ -0,0 +1,349 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/***************************************************************************
+
+ Nintendo Game Boy MMM01 memory controller
+
+ Designed to support multi-game cartridges. Included games can vary in
+ program ROM non-volatile RAM size requirements. Starts in configuration
+ mode, where coarse ROM and RAM page selection can be configured. After
+ leaving configuration mode, the only way to re-enter it is to reset the
+ MMM01 chip.
+
+ After leaving configuration mode, the behaviour will be similar to one of
+ the two standard wiring arrangements for cartridges using the MBC1 chip.
+
+ Supports up to 8 MiB ROM (512 16 KiB pages) and 128 KiB static RAM (16
+ 8 KiB pages) total. Each included game can use up to 2 MiB ROM (128 16 KiB
+ pages) and 8 KiB static RAM (one page), or up to 512 KiB ROM (32 16 KiB
+ pages) and 32 KiB static RAM (4 8 KiB pages). In configuration mode, up to
+ 32 KiB ROM and 128 KiB static RAM (16 8 KiB pages) can be used.
+
+ The MMM01 controller only responds to A15-A13 and D6-D0, i.e. addresses are
+ effectively masked with 0xE000 and data is effectively masked with 0x7F.
+ In configuration mode, most of the control register bits that are unused by
+ the MBC1 chip are repurposed.
+
+ 0x0000-3FFF R - Low ROM bank.
+ 0x4000-7FFF R - High ROM bank.
+ 0xA000-BFFF RW - Static RAM if enabled.
+
+ 0x0000-1FFF W - -X------ * Exit configuration mode.
+ --XX---- * Static RAM bank fine protect.
+ ----XXXX Static RAM enable.
+ 0x2000-3FFF W - -XX----- * ROM bank mid (RA20-RA19) or static RAM bank
+ fine (AA14-AA13), depending on mode.
+ ---XXXXX ROM bank fine (RA18-RA14).
+ 0x4000-5FFF W - -X------ * Low bank coarse enable protect.
+ --XX---- * ROM bank coarse (RA22-RA21).
+ ----XX-- * Static RAM bank coarse (AA16-AA15).
+ ------XX Static RAM bank fine (AA14-AA13) or ROM bank
+ mid (RA20-RA19), depending on mode.
+ 0x6000-7FFF W - -X------ * ROM bank mid/RAM bank coarse select.
+ --XXXX-- * ROM bank fine protect.
+ -------X Low bank coarse enable.
+
+ * Fields only writable in configuration mode.
+
+ ***************************************************************************/
+
+#include "emu.h"
+#include "mmm01.h"
+
+#include "cartbase.ipp"
+
+#include <string>
+
+//#define VERBOSE 1
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+
+namespace bus::gameboy {
+
+namespace {
+
+class mmm01_device : public mbc_ram_device_base<mbc_dual_uniform_device_base>
+{
+public:
+ mmm01_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+ virtual std::error_condition load(std::string &message) override ATTR_COLD;
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+private:
+ void enable_ram(u8 data);
+ void bank_switch_fine(u8 data);
+ void bank_switch_coarse(u8 data);
+ void enable_bank_low_mid(u8 data);
+
+ void update_bank_rom_low()
+ {
+ u16 entry;
+ if (!m_config)
+ {
+ entry = (u16(m_bank_sel_rom_coarse) << 7) | (m_bank_sel_rom_fine & m_bank_prot_sel[1]);
+ if (!m_mode_large_prg)
+ entry |= m_bank_sel_mid[1] << 5;
+ else if (m_bank_low_mid)
+ entry |= m_bank_sel_mid[0] << 5;
+ }
+ else
+ {
+ entry = 0x01fe;
+ }
+ set_bank_rom_low(entry);
+ }
+
+ void update_bank_rom_high()
+ {
+ u16 entry;
+ if (!m_config)
+ {
+ entry = (u16(m_bank_sel_rom_coarse) << 7) | m_bank_sel_rom_fine;
+ if (!m_mode_large_prg)
+ entry |= m_bank_sel_mid[1] << 5;
+ else
+ entry |= m_bank_sel_mid[0] << 5;
+ }
+ else
+ {
+ entry = 0x01fe | m_bank_sel_rom_fine;
+ }
+ if (!(m_bank_sel_rom_fine & ~m_bank_prot_sel[1]))
+ entry |= 0x0001;
+ set_bank_rom_high(entry);
+ }
+
+ void update_bank_ram()
+ {
+ u8 entry(m_bank_sel_ram_coarse << 2);
+ if (m_mode_large_prg)
+ entry |= m_bank_sel_mid[1];
+ else if (m_bank_low_mid)
+ entry |= m_bank_sel_mid[0];
+ set_bank_ram(entry);
+ }
+
+ memory_view m_view_ram;
+
+ u8 m_config;
+ u8 m_mode_large_prg;
+ u8 m_bank_sel_mid[2];
+ u8 m_bank_sel_ram_coarse;
+ u8 m_bank_sel_rom_coarse;
+ u8 m_bank_sel_rom_fine;
+ u8 m_bank_low_mid;
+ u8 m_bank_prot_sel[2];
+ u8 m_bank_prot_low_mid;
+};
+
+
+mmm01_device::mmm01_device(
+ machine_config const &mconfig,
+ char const *tag,
+ device_t *owner,
+ u32 clock) :
+ mbc_ram_device_base<mbc_dual_uniform_device_base>(mconfig, GB_ROM_MMM01, tag, owner, clock),
+ m_view_ram(*this, "ram"),
+ m_config(0U),
+ m_mode_large_prg(0U),
+ m_bank_sel_mid{ 0U, 0U },
+ m_bank_sel_ram_coarse(0U),
+ m_bank_sel_rom_coarse(0U),
+ m_bank_sel_rom_fine(0U),
+ m_bank_low_mid(0U),
+ m_bank_prot_sel{ 0U, 0U },
+ m_bank_prot_low_mid(0U)
+{
+}
+
+
+std::error_condition mmm01_device::load(std::string &message)
+{
+ // set up ROM and RAM
+ set_bank_bits_rom(9);
+ set_bank_bits_ram(4);
+ if (!check_rom(message) || !check_ram(message))
+ return image_error::BADSOFTWARE;
+ cart_space()->install_view(0xa000, 0xbfff, m_view_ram);
+ install_rom();
+ install_ram(m_view_ram[0]);
+
+ // install memory controller handlers
+ cart_space()->install_write_handler(
+ 0x0000, 0x1fff,
+ emu::rw_delegate(*this, FUNC(mmm01_device::enable_ram)));
+ cart_space()->install_write_handler(
+ 0x2000, 0x3fff,
+ emu::rw_delegate(*this, FUNC(mmm01_device::bank_switch_fine)));
+ cart_space()->install_write_handler(
+ 0x4000, 0x5fff,
+ emu::rw_delegate(*this, FUNC(mmm01_device::bank_switch_coarse)));
+ cart_space()->install_write_handler(
+ 0x6000, 0x6fff,
+ emu::rw_delegate(*this, FUNC(mmm01_device::enable_bank_low_mid)));
+
+ // all good
+ return std::error_condition();
+}
+
+
+void mmm01_device::device_start()
+{
+ mbc_ram_device_base<mbc_dual_uniform_device_base>::device_start();
+
+ save_item(NAME(m_config));
+ save_item(NAME(m_mode_large_prg));
+ save_item(NAME(m_bank_sel_mid));
+ save_item(NAME(m_bank_sel_ram_coarse));
+ save_item(NAME(m_bank_sel_rom_coarse));
+ save_item(NAME(m_bank_sel_rom_fine));
+ save_item(NAME(m_bank_low_mid));
+ save_item(NAME(m_bank_prot_sel));
+ save_item(NAME(m_bank_prot_low_mid));
+}
+
+
+void mmm01_device::device_reset()
+{
+ mbc_ram_device_base<mbc_dual_uniform_device_base>::device_reset();
+
+ m_view_ram.disable();
+ m_config = 1U;
+ m_mode_large_prg = 0U;
+ m_bank_sel_mid[0] = 0U;
+ m_bank_sel_mid[1] = 0U;
+ m_bank_sel_ram_coarse = 0U;
+ m_bank_sel_rom_coarse = 0U;
+ m_bank_sel_rom_fine = 0U;
+ m_bank_low_mid = 0U;
+ m_bank_prot_sel[0] = 0U;
+ m_bank_prot_sel[1] = 0U;
+ m_bank_prot_low_mid = 0U;
+
+ set_bank_rom_low(0x01fe);
+ set_bank_rom_high(0x01ff);
+ set_bank_ram(0);
+}
+
+
+void mmm01_device::enable_ram(u8 data)
+{
+ if (0x0a == (data & 0x0f))
+ {
+ LOG("%s: Cartridge RAM enabled\n", machine().describe_context());
+ m_view_ram.select(0);
+ }
+ else
+ {
+ LOG("%s: Cartridge RAM disabled\n", machine().describe_context());
+ m_view_ram.disable();
+ }
+
+ if (m_config)
+ {
+ m_bank_prot_sel[0] = BIT(data, 4, 2);
+ LOG(
+ "%s: Mid bank protect = 0x%X\n",
+ machine().describe_context(),
+ m_bank_prot_sel[0]);
+ if (BIT(data, 6))
+ {
+ LOG("%s: Configuration mode disabled\n", machine().describe_context());
+ m_config = 0U;
+ update_bank_rom_low();
+ update_bank_rom_high();
+ }
+ }
+}
+
+
+void mmm01_device::bank_switch_fine(u8 data)
+{
+ m_bank_sel_rom_fine = (m_bank_sel_rom_fine & m_bank_prot_sel[1]) | (BIT(data, 0, 5) & ~m_bank_prot_sel[1]);
+ LOG(
+ "%s: Fine ROM bank = 0x%02X\n",
+ machine().describe_context(),
+ m_bank_sel_rom_fine);
+
+ if (m_config)
+ {
+ m_bank_sel_mid[1] = BIT(data, 5, 2);
+ LOG(
+ "%s: Configuration mid bank = 0x%X\n",
+ machine().describe_context(),
+ m_bank_sel_mid[1]);
+ }
+
+ update_bank_rom_high();
+ if (m_config && m_mode_large_prg)
+ update_bank_ram();
+}
+
+
+void mmm01_device::bank_switch_coarse(u8 data)
+{
+ m_bank_sel_mid[0] = (m_bank_sel_mid[0] & m_bank_prot_sel[0]) | (BIT(data, 0, 2) & ~m_bank_prot_sel[0]);
+ LOG(
+ "%s: User mid bank = 0x%X\n",
+ machine().describe_context(),
+ m_bank_sel_mid[0]);
+
+ if (m_config)
+ {
+ m_bank_sel_ram_coarse = BIT(data, 2, 2);
+ m_bank_sel_rom_coarse = BIT(data, 4, 2);
+ m_bank_prot_low_mid = BIT(data, 6);
+ LOG(
+ "%s: Coarse ROM bank = 0x%X, coarse RAM bank = 0x%X, low bank mid enable %s\n",
+ machine().describe_context(),
+ m_bank_sel_rom_coarse,
+ m_bank_sel_ram_coarse,
+ m_bank_prot_low_mid ? "locked" : "unlocked");
+ }
+
+ if (m_config || (!m_mode_large_prg && m_bank_low_mid))
+ update_bank_ram();
+}
+
+
+void mmm01_device::enable_bank_low_mid(u8 data)
+{
+ if (!m_bank_prot_low_mid)
+ {
+ m_bank_low_mid = BIT(data, 0);
+ LOG(
+ "%s: Low bank mid %s\n",
+ machine().describe_context(),
+ m_bank_low_mid ? "enabled" : "disabled");
+ }
+
+ if (m_config)
+ {
+ m_bank_prot_sel[1] = BIT(data, 2, 4) << 1;
+ m_mode_large_prg = BIT(data, 6);
+ LOG(
+ "%s: Fine ROM bank protect = 0x%02X, %s mode\n",
+ machine().describe_context(),
+ m_bank_prot_sel[1],
+ m_mode_large_prg ? "large ROM" : "banked RAM");
+ }
+
+ if (!m_bank_prot_low_mid && !m_config)
+ update_bank_rom_low();
+ if (m_config)
+ update_bank_rom_high();
+ if (!m_bank_prot_low_mid || m_config)
+ update_bank_ram();
+}
+
+} // anonymous namespace
+
+} // namespace bus::gameboy
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(GB_ROM_MMM01, device_gb_cart_interface, bus::gameboy::mmm01_device, "gb_rom_mmm01", "Game Boy MMM01 Cartridge")
diff --git a/src/devices/bus/gameboy/mmm01.h b/src/devices/bus/gameboy/mmm01.h
new file mode 100644
index 00000000000..e1540eb74fb
--- /dev/null
+++ b/src/devices/bus/gameboy/mmm01.h
@@ -0,0 +1,16 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/***************************************************************************
+
+ Nintendo Game Boy MMM01 memory controller
+
+ ***************************************************************************/
+#ifndef MAME_BUS_GAMEBOY_MMM01_H
+#define MAME_BUS_GAMEBOY_MMM01_H
+
+#include "slot.h"
+
+
+DECLARE_DEVICE_TYPE(GB_ROM_MMM01, device_gb_cart_interface)
+
+#endif // MAME_BUS_GAMEBOY_MMM01_H
diff --git a/src/devices/bus/gameboy/ntnew.cpp b/src/devices/bus/gameboy/ntnew.cpp
new file mode 100644
index 00000000000..fa54065bf2e
--- /dev/null
+++ b/src/devices/bus/gameboy/ntnew.cpp
@@ -0,0 +1,179 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/***************************************************************************
+
+ Memory controller used for newer NT/Makon games
+
+ Appears to start in a mode similar to Nintendo MBC3, with a fixed 16 KiB
+ ROM bank at 0x0000 and a switchable 16 KiB ROM bank at 0x4000, but allows
+ switching to a mode with selectable 8 KiB ROM banks at 0x4000 and 0x6000.
+
+ It isn't clear how many static RAM pages are actually supported. Many
+ cartridges included 32K*8 static RAMs despite the headers declaring smaller
+ sizes and the games using no more than 8 KiB. The maximum supported ROM
+ size is also unknown.
+
+ Pretty much everything here is guessed based on the games' behaviour. The
+ exact address ranges the memory controller responds to are unknown. There
+ may be additional features that are not emulated.
+
+ ***************************************************************************/
+
+#include "emu.h"
+#include "ntnew.h"
+
+#include "cartbase.ipp"
+
+//#define VERBOSE 1
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+
+namespace bus::gameboy {
+
+namespace {
+
+class ntnew_device : public mbc_ram_device_base<mbc_8k_device_base>
+{
+public:
+ ntnew_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+ virtual std::error_condition load(std::string &message) override ATTR_COLD;
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+private:
+ void enable_ram(offs_t offset, u8 data);
+ void bank_switch_rom(offs_t offset, u8 data);
+ void bank_switch_ram(u8 data);
+
+ memory_view m_view_ram;
+
+ u8 m_bank_8k;
+};
+
+
+ntnew_device::ntnew_device(
+ machine_config const &mconfig,
+ char const *tag,
+ device_t *owner,
+ u32 clock) :
+ mbc_ram_device_base<mbc_8k_device_base>(mconfig, GB_ROM_NTNEW, tag, owner, clock),
+ m_view_ram(*this, "ram"),
+ m_bank_8k(0U)
+{
+}
+
+
+std::error_condition ntnew_device::load(std::string &message)
+{
+ // set up ROM and RAM
+ set_bank_bits_rom(8);
+ set_bank_bits_ram(4);
+ if (!check_rom(message) || !check_ram(message))
+ return image_error::BADSOFTWARE;
+ cart_space()->install_view(0xa000, 0xbfff, m_view_ram);
+ install_rom(*cart_space(), *cart_space(), *cart_space());
+ install_ram(m_view_ram[0]);
+
+ // install handlers
+ cart_space()->install_write_handler(
+ 0x0000, 0x1fff,
+ emu::rw_delegate(*this, FUNC(ntnew_device::enable_ram)));
+ cart_space()->install_write_handler(
+ 0x2000, 0x2fff,
+ emu::rw_delegate(*this, FUNC(ntnew_device::bank_switch_rom)));
+ cart_space()->install_write_handler(
+ 0x4000, 0x5fff,
+ emu::rw_delegate(*this, FUNC(ntnew_device::bank_switch_ram)));
+
+ // all good
+ return std::error_condition();
+}
+
+
+void ntnew_device::device_start()
+{
+ mbc_ram_device_base<mbc_8k_device_base>::device_start();
+
+ save_item(NAME(m_bank_8k));
+}
+
+
+void ntnew_device::device_reset()
+{
+ mbc_ram_device_base<mbc_8k_device_base>::device_reset();
+
+ m_view_ram.disable();
+ m_bank_8k = 0U;
+
+ set_bank_rom_low(2);
+ set_bank_rom_high(3);
+ set_bank_ram(0);
+}
+
+
+void ntnew_device::enable_ram(offs_t offset, u8 data)
+{
+ // TODO: what range actually triggers this, and does it still trigger RAM enable?
+ if (((offset & 0x1f00) == 0x1400) & (0x55 == data))
+ {
+ LOG("%s: 8K ROM banking enabled\n", machine().describe_context());
+ m_bank_8k = 1U;
+ }
+
+ // TODO: how many bits are checked?
+ bool const enable(0x0a == (data & 0x0f));
+ LOG(
+ "%s: Cartridge RAM %s\n",
+ machine().describe_context(),
+ enable ? "enabled" : "disabled");
+ if (enable)
+ m_view_ram.select(0);
+ else
+ m_view_ram.disable();
+}
+
+
+void ntnew_device::bank_switch_rom(offs_t offset, u8 data)
+{
+ if (m_bank_8k)
+ {
+ // TODO: what ranges does the controller actually respond to?
+ switch (offset & 0x0f00)
+ {
+ case 0x0000:
+ if (!(data & 0xfe))
+ data |= 0x02;
+ set_bank_rom_low(data);
+ return;
+
+ case 0x0400:
+ if (!(data & 0xfe))
+ data |= 0x02;
+ set_bank_rom_high(data);
+ return;
+ }
+ }
+
+ data <<= 1;
+ if (!(data & 0xfe))
+ data |= 0x02;
+ set_bank_rom_low(data);
+ set_bank_rom_high(data | 0x01);
+}
+
+
+void ntnew_device::bank_switch_ram(u8 data)
+{
+ set_bank_ram(data & 0x0f);
+}
+
+} // anonymous namespace
+
+} // namespace bus::gameboy
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(GB_ROM_NTNEW, device_gb_cart_interface, bus::gameboy::ntnew_device, "gb_rom_ntnew", "Game Boy newer Kasheng/Makon Cartridge")
diff --git a/src/devices/bus/gameboy/ntnew.h b/src/devices/bus/gameboy/ntnew.h
new file mode 100644
index 00000000000..74c297d60f5
--- /dev/null
+++ b/src/devices/bus/gameboy/ntnew.h
@@ -0,0 +1,18 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/***************************************************************************
+
+ Memory controller used for newer NT/Makon games
+
+ ***************************************************************************/
+#ifndef MAME_BUS_GAMEBOY_NTNEW_H
+#define MAME_BUS_GAMEBOY_NTNEW_H
+
+#pragma once
+
+#include "slot.h"
+
+
+DECLARE_DEVICE_TYPE(GB_ROM_NTNEW, device_gb_cart_interface)
+
+#endif // MAME_BUS_GAMEBOY_NTNEW_H
diff --git a/src/devices/bus/gameboy/rom.cpp b/src/devices/bus/gameboy/rom.cpp
index b635a828b8c..c3c7ab0e347 100644
--- a/src/devices/bus/gameboy/rom.cpp
+++ b/src/devices/bus/gameboy/rom.cpp
@@ -1,363 +1,1144 @@
// license:BSD-3-Clause
-// copyright-holders:Fabio Priuli, Wilbert Pol
+// copyright-holders:Vas Crabb, Wilbert Pol
/***********************************************************************************************************
Game Boy cart emulation
- Here we emulate carts with no RAM and simple bankswitch
+ Here we emulate carts without RAM banking.
+ TODO:
+ - YongYong:
+ - During start there are 2 writes to 5000 and 5003, it is still unknown what these do.
+ - Story of Lasama:
+ - This should display the Gowin logo on boot on both DMG and CGB (not implemented yet)
+ - Sachen MMC2:
+ - Does it monitor the address to detect RAM writes for logo spoofing, or just /CS?
+ - ATV Racing/Rocket Games:
+ - Does it monitor the address to detect RAM writes for logo spoofing, or just /CS?
+ - How does RAM banking work? Are over-size RAM chips just inaccessible?
+
***********************************************************************************************************/
#include "emu.h"
#include "rom.h"
+#include "cartbase.ipp"
-//-------------------------------------------------
-// gb_rom_device - constructor
-//-------------------------------------------------
+#include "bus/generic/slot.h"
-DEFINE_DEVICE_TYPE(GB_STD_ROM, gb_rom_device, "gb_rom", "GB Carts")
-DEFINE_DEVICE_TYPE(GB_ROM_TAMA5, gb_rom_tama5_device, "gb_rom_tama5", "GB Tamagotchi")
-DEFINE_DEVICE_TYPE(GB_ROM_WISDOM, gb_rom_wisdom_device, "gb_rom_wisdom", "GB Wisdom Tree Carts")
-DEFINE_DEVICE_TYPE(GB_ROM_YONG, gb_rom_yong_device, "gb_rom_yong", "GB Young Yong Carts")
-DEFINE_DEVICE_TYPE(GB_ROM_ATVRAC, gb_rom_atvrac_device, "gb_rom_atvrac", "GB ATV Racin'")
-DEFINE_DEVICE_TYPE(GB_ROM_LASAMA, gb_rom_lasama_device, "gb_rom_lasama", "GB LaSaMa")
+#include "corestr.h"
-DEFINE_DEVICE_TYPE(MEGADUCK_ROM, megaduck_rom_device, "megaduck_rom", "MegaDuck Carts")
+#include <memory>
+#include <optional>
+//#define VERBOSE 1
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
-gb_rom_device::gb_rom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, type, tag, owner, clock)
- , device_gb_cart_interface(mconfig, *this)
-{
-}
-gb_rom_device::gb_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : gb_rom_device(mconfig, GB_STD_ROM, tag, owner, clock)
-{
-}
+namespace bus::gameboy {
-gb_rom_tama5_device::gb_rom_tama5_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : gb_rom_device(mconfig, GB_ROM_TAMA5, tag, owner, clock), m_tama5_data(0), m_tama5_addr(0), m_tama5_cmd(0), m_rtc_reg(0)
-{
-}
+namespace {
-gb_rom_wisdom_device::gb_rom_wisdom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : gb_rom_device(mconfig, GB_ROM_WISDOM, tag, owner, clock)
-{
-}
+//**************************************************************************
+// Sachen MMC1/MMC2 ROM banking helper class (16 KiB * 256)
+//**************************************************************************
-gb_rom_yong_device::gb_rom_yong_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : gb_rom_device(mconfig, GB_ROM_YONG, tag, owner, clock)
+class sachen_mmc_device_base : public mbc_dual_uniform_device_base
{
-}
+protected:
+ sachen_mmc_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock) :
+ mbc_dual_uniform_device_base(mconfig, type, tag, owner, clock),
+ m_bank_mux_rom(0U),
+ m_bank_sel_rom{ 0U, 0U }
+ {
+ }
-gb_rom_atvrac_device::gb_rom_atvrac_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : gb_rom_device(mconfig, GB_ROM_ATVRAC, tag, owner, clock)
-{
-}
+ virtual void device_start() override ATTR_COLD
+ {
+ mbc_dual_uniform_device_base::device_start();
-gb_rom_lasama_device::gb_rom_lasama_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : gb_rom_device(mconfig, GB_ROM_LASAMA, tag, owner, clock)
-{
-}
+ save_item(NAME(m_bank_mux_rom));
+ save_item(NAME(m_bank_sel_rom));
+ }
+ virtual void device_reset() override ATTR_COLD
+ {
+ mbc_dual_uniform_device_base::device_reset();
-megaduck_rom_device::megaduck_rom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, type, tag, owner, clock)
- , device_gb_cart_interface(mconfig, *this)
-{
-}
+ m_bank_mux_rom = 0U;
+ m_bank_sel_rom[0] = 0U;
+ m_bank_sel_rom[1] = 1U;
+ update_banks();
+ }
-megaduck_rom_device::megaduck_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : megaduck_rom_device(mconfig, MEGADUCK_ROM, tag, owner, clock)
-{
-}
+ bool check_rom(std::string &message) ATTR_COLD
+ {
+ set_bank_bits_rom(8);
+ return mbc_dual_uniform_device_base::check_rom(message);
+ }
+ void install_bank_switch_handlers() ATTR_COLD
+ {
+ // A5, A3 and A2 are not connected to the controller (effective address mask 0xffd3)
+ cart_space()->install_write_handler(0x0000, 0x1fff, emu::rw_delegate(*this, FUNC(sachen_mmc_device_base::bank_rom_switch_outer)));
+ cart_space()->install_write_handler(0x2000, 0x3fff, emu::rw_delegate(*this, FUNC(sachen_mmc_device_base::bank_rom_switch_inner)));
+ cart_space()->install_write_handler(0x4000, 0x5fff, emu::rw_delegate(*this, FUNC(sachen_mmc_device_base::bank_rom_mux)));
+ }
-//-------------------------------------------------
-// shared_start
-//-------------------------------------------------
+ u8 rom_read(offs_t offset, bool spoof)
+ {
+ // holds A7 high when spoofing the logo
+ if (spoof)
+ offset |= 0x0080;
-void gb_rom_device::shared_start()
-{
- save_item(NAME(m_latch_bank));
- save_item(NAME(m_latch_bank2));
- save_item(NAME(m_ram_bank));
-}
+ // cartridge header area has address lines scrambled - A6 swapped with A0 and A4 swapped with A1
+ if (0x0100 == (offset & 0xff00))
+ offset = (offset & 0xff80) | bitswap<7>(offset, 0, 5, 1, 3, 2, 4, 6);
-//-------------------------------------------------
-// shared_reset
-//-------------------------------------------------
+ return (BIT(offset, 14) ? bank_rom_high_base() : bank_rom_low_base())[offset & 0x3fff];
+ }
-void gb_rom_device::shared_reset()
-{
- m_ram_bank = 0;
- m_latch_bank = 0;
- m_latch_bank2 = 1;
-}
+private:
+ void bank_rom_switch_outer(u8 data)
+ {
+ if (0x30 == (m_bank_sel_rom[1] & 0x30))
+ {
+ m_bank_sel_rom[0] = data;
+ update_banks();
+ }
+ }
+
+ void bank_rom_switch_inner(u8 data)
+ {
+ m_bank_sel_rom[1] = data ? data : 1;
+ u16 const hi(bank_rom_entry_high());
+ LOG(
+ "%s: Set ROM bank high = 0x%06X (0x%02X & 0x%02X | 0x%02X & 0x%02X)\n",
+ machine().describe_context(),
+ u32(hi) * 0x4000,
+ m_bank_sel_rom[0],
+ m_bank_mux_rom,
+ m_bank_sel_rom[1],
+ ~m_bank_mux_rom);
+ set_bank_rom_high(hi);
+ }
-//-------------------------------------------------
-// mapper specific start/reset
-//-------------------------------------------------
+ void bank_rom_mux(u8 data)
+ {
+ if (0x30 == (m_bank_sel_rom[1] & 0x30))
+ {
+ m_bank_mux_rom = data;
+ update_banks();
+ }
+ }
-void gb_rom_tama5_device::device_start()
-{
- shared_start();
- save_item(NAME(m_tama5_data));
- save_item(NAME(m_tama5_addr));
- save_item(NAME(m_tama5_cmd));
- save_item(NAME(m_regs));
- save_item(NAME(m_rtc_reg));
-}
-
-void gb_rom_tama5_device::device_reset()
+ u8 bank_rom_entry_low() const
+ {
+ return m_bank_sel_rom[0] & m_bank_mux_rom;
+ }
+
+ u8 bank_rom_entry_high() const
+ {
+ return (m_bank_sel_rom[0] & m_bank_mux_rom) | (m_bank_sel_rom[1] & ~m_bank_mux_rom);
+ }
+
+ void update_banks()
+ {
+ u16 const lo(bank_rom_entry_low());
+ u16 const hi(bank_rom_entry_high());
+ LOG(
+ "%s: Set ROM banks low = 0x%1$06X (0x%3$02X & 0x%5$02X), high = 0x%2$06X (0x%3$02X & 0x%5$02X | 0x%4$02X & 0x%6$02X)\n",
+ machine().describe_context(),
+ u32(lo) * 0x4000,
+ u32(hi) * 0x4000,
+ m_bank_sel_rom[0],
+ m_bank_sel_rom[1],
+ m_bank_mux_rom,
+ ~m_bank_mux_rom);
+ set_bank_rom_low(lo);
+ set_bank_rom_high(hi);
+ }
+
+ u8 m_bank_mux_rom;
+ u8 m_bank_sel_rom[2];
+};
+
+
+
+//**************************************************************************
+// Game Boy Color logo spoof used by Sachen and Rocket Games
+//**************************************************************************
+
+template <typename Base>
+class gbc_logo_spoof_device_base : public Base
{
- shared_reset();
- m_tama5_data = 0;
- m_tama5_addr= 0;
- m_tama5_cmd = 0;
- memset(m_regs, 0xff, sizeof(m_regs));
- m_rtc_reg = 0xff;
-}
+public:
+ using Base::logerror;
+
+protected:
+ gbc_logo_spoof_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock) :
+ Base(mconfig, type, tag, owner, clock),
+ m_ram_tap(),
+ m_notif_cart_space(),
+ m_counter(0U),
+ m_spoof_logo(0U),
+ m_installing_tap(false)
+ {
+ }
+
+ virtual void device_start() override ATTR_COLD
+ {
+ Base::device_start();
+
+ this->save_item(NAME(m_counter));
+ this->save_item(NAME(m_spoof_logo));
+ }
+
+ virtual void device_reset() override ATTR_COLD
+ {
+ Base::device_reset();
+
+ m_counter = 0U;
+ m_spoof_logo = 0U;
+
+ install_ram_tap();
+ m_notif_cart_space = this->cart_space()->add_change_notifier(
+ [this] (read_or_write mode)
+ {
+ if (u32(mode) & u32(read_or_write::WRITE))
+ install_ram_tap();
+ });
+ }
+
+ bool spoof_logo() const
+ {
+ return 1U == m_spoof_logo;
+ }
+
+ void rom_access()
+ {
+ if (!this->machine().side_effects_disabled())
+ {
+ // These cartridges work by counting low-to-high transitions on A15.
+ // CPU keeps A15 high while reading internal bootstrap ROM.
+ // Doing this on ROM reads is a good enough approximation for it to work.
+ if (0x30 != m_counter)
+ {
+ ++m_counter;
+ }
+ else
+ {
+ switch (m_spoof_logo)
+ {
+ case 0U:
+ m_counter = 1U;
+ [[fallthrough]];
+ case 1U:
+ ++m_spoof_logo;
+ m_notif_cart_space.reset();
+ m_ram_tap.remove();
+ LOG(
+ "%s: Spoof logo step %u\n",
+ this->machine().describe_context(),
+ m_spoof_logo);
+ }
+ }
+ }
+ }
+
+private:
+ void install_ram_tap()
+ {
+ if (!m_installing_tap)
+ {
+ m_installing_tap = true;
+ m_ram_tap.remove();
+ if (!m_spoof_logo)
+ {
+ m_ram_tap = this->cart_space()->install_write_tap(
+ 0xc000, 0xdfff,
+ "ram_tap_w",
+ [this] (offs_t offset, u8 &data, u8 mem_mask)
+ {
+ assert(!m_spoof_logo);
+
+ if (!this->machine().side_effects_disabled())
+ {
+ m_counter = 0U;
+ ++m_spoof_logo;
+ LOG(
+ "%s: Spoof logo step %u\n",
+ this->machine().describe_context(),
+ m_spoof_logo);
+ m_notif_cart_space.reset();
+ m_ram_tap.remove();
+ }
+ },
+ &m_ram_tap);
+ }
+ else
+ {
+ m_notif_cart_space.reset();
+ }
+ m_installing_tap = false;
+ }
+ }
+
+ memory_passthrough_handler m_ram_tap;
+ util::notifier_subscription m_notif_cart_space;
+
+ u8 m_counter;
+ u8 m_spoof_logo;
+ bool m_installing_tap;
+};
+
-// these are identical to shared ones above, but megaduck cart class is not derived from gb cart class...
-void megaduck_rom_device::device_start()
+//**************************************************************************
+// Mega Duck flat ROM (max 32 KiB)
+//**************************************************************************
+
+class megaduck_flat_device : public device_t, public device_gb_cart_interface
{
- save_item(NAME(m_latch_bank));
- save_item(NAME(m_latch_bank2));
- save_item(NAME(m_ram_bank));
-}
+public:
+ megaduck_flat_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) :
+ megaduck_flat_device(mconfig, MEGADUCK_ROM_STD, tag, owner, clock)
+ {
+ }
+
+ virtual std::error_condition load(std::string &message) override ATTR_COLD
+ {
+ // if there's no ROM region, there's nothing to do
+ memory_region *const romregion(cart_rom_region());
+ if (!romregion || !romregion->bytes())
+ return std::error_condition();
+
+ // check for supported size
+ auto const bytes(romregion->bytes());
+ if (0x8000 < bytes)
+ {
+ message = "Unsupported cartridge ROM size (must be no larger than 32 KiB)";
+ return image_error::INVALIDLENGTH;
+ }
-void megaduck_rom_device::device_reset()
+ // install ROM
+ device_generic_cart_interface::install_non_power_of_two<0>(
+ bytes,
+ 0x7fff,
+ 0,
+ 0x0000,
+ [this, base = &romregion->as_u8()] (offs_t begin, offs_t end, offs_t mirror, offs_t src)
+ {
+ LOG(
+ "Install ROM 0x%04X-0x%04X at 0x%04X-0x%04X mirror 0x%04X\n",
+ src,
+ src + (end - begin),
+ begin,
+ end,
+ mirror);
+ cart_space()->install_rom(begin, end, mirror, &base[src]);
+ });
+
+ // all good
+ return std::error_condition();
+ }
+
+protected:
+ megaduck_flat_device(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock) :
+ device_t(mconfig, type, tag, owner, clock),
+ device_gb_cart_interface(mconfig, *this)
+ {
+ }
+
+ virtual void device_start() override ATTR_COLD
+ {
+ }
+};
+
+
+
+//**************************************************************************
+// Mega Duck banked ROM (16 KiB fixed + 16 KiB * 256 or 32 KiB * 256)
+//**************************************************************************
+
+class megaduck_banked_device : public device_t, public device_gb_cart_interface
{
- m_ram_bank = 0;
- m_latch_bank = 0;
- m_latch_bank2 = 1;
-}
+public:
+ megaduck_banked_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) :
+ device_t(mconfig, MEGADUCK_ROM_BANKED, tag, owner, clock),
+ device_gb_cart_interface(mconfig, *this),
+ m_bank_rom_low(*this, "low"),
+ m_bank_rom_high(*this, "high"),
+ m_bank_mask_rom{ 0U, 0U }
+ {
+ }
+ virtual std::error_condition load(std::string &message) override ATTR_COLD
+ {
+ // if there's no ROM region, there's nothing to do
+ memory_region *const romregion(cart_rom_region());
+ if (!romregion || !romregion->bytes())
+ {
+ // setting default bank on reset causes a fatal error when no banks are configured
+ message = "No ROM data found";
+ return image_error::BADSOFTWARE;
+ }
+
+ // work out whether a fixed bank is required
+ auto const bytes(romregion->bytes());
+ char const *const fixedbank_explicit(get_feature("fixedbank"));
+ std::optional<bool> fixedbank;
+ if (fixedbank_explicit)
+ {
+ // explicitly specified in software list
+ if (util::streqlower(fixedbank_explicit, "yes") || util::streqlower(fixedbank_explicit, "true"))
+ {
+ fixedbank = true;
+ }
+ else if (util::streqlower(fixedbank_explicit, "no") || util::streqlower(fixedbank_explicit, "false"))
+ {
+ fixedbank = false;
+ }
+ else
+ {
+ message = "Invalid 'fixedbank' feature value (must be yes or no)";
+ return image_error::BADSOFTWARE;
+ }
+ }
+ else if (bytes & 0x7fff)
+ {
+ // if it isn't a multiple of 32 KiB, it only makes sense with a fixed bank
+ fixedbank = true;
+ }
+ else if ((0x4000 * 0x100) < bytes)
+ {
+ // if it's larger than 4 MiB, it doesn't make sense with a fixed bank
+ fixedbank = false;
+ }
+
+ // reject unsupported sizes
+ if ((bytes & 0x3fff) || ((0x8000 * 0x100) < bytes) || (fixedbank && (*fixedbank ? ((0x4000 * 0x100) < bytes) : (bytes & 0x7fff))))
+ {
+ message = "Unsupported cartridge ROM size (must be a multiple of bank size and no larger than 256 entries)";
+ return image_error::INVALIDLENGTH;
+ }
+
+ // configure banks - low bank has 32 KiB entries, high bank has 16 KiB entries
+ auto const base(&romregion->as_u8());
+ m_bank_mask_rom[0] = device_generic_cart_interface::map_non_power_of_two(
+ unsigned(bytes / 0x8000),
+ [this, base] (unsigned entry, unsigned page)
+ {
+ LOG(
+ "Install ROM 0x%04X-0x%04X in low bank entry %u\n",
+ page * 0x8000,
+ (page * 0x8000) + 0x7fff,
+ entry);
+ m_bank_rom_low->configure_entry(entry, &base[page * 0x8000]);
+ });
+ m_bank_mask_rom[1] = device_generic_cart_interface::map_non_power_of_two(
+ unsigned(bytes / 0x4000),
+ [this, base] (unsigned entry, unsigned page)
+ {
+ LOG(
+ "Install ROM 0x%04X-0x%04X in high bank entry %u\n",
+ page * 0x4000,
+ (page * 0x4000) + 0x3fff,
+ entry);
+ m_bank_rom_high->configure_entry(entry, &base[page * 0x4000]);
+ });
+
+ // install handlers
+ if (!fixedbank)
+ {
+ // can't tell whether this cartridge has a fixed low bank, take a bet each way
+ logerror("Installing banked ROM at 0x0000-0x3FFF and 0x4000-0x7FFF\n");
+ cart_space()->install_read_bank(0x0000, 0x3fff, m_bank_rom_low);
+ cart_space()->install_read_bank(0x4000, 0x7fff, m_bank_rom_high);
+ cart_space()->install_write_handler(0x0001, 0x0001, emu::rw_delegate(*this, FUNC(megaduck_banked_device::bank_rom_switch_high)));
+ cart_space()->install_write_handler(0xb000, 0xb000, emu::rw_delegate(*this, FUNC(megaduck_banked_device::bank_rom_switch)));
+ }
+ else if (*fixedbank)
+ {
+ // fixed ROM at 0x0000-0x3fff, banked ROM at 0x4000-0x7fff
+ logerror("Installing fixed ROM at 0x0000-0x3FFF and banked ROM at 0x4000-0x7FFF\n");
+ cart_space()->install_rom(0x0000, 0x3fff, base);
+ cart_space()->install_read_bank(0x4000, 0x7fff, m_bank_rom_high);
+ cart_space()->install_write_handler(0x0001, 0x0001, emu::rw_delegate(*this, FUNC(megaduck_banked_device::bank_rom_switch_high)));
+ }
+ else
+ {
+ // banked ROM at 0x0000-0x7fff
+ logerror("Installing banked ROM at 0x0000-0x7FFF\n");
+ cart_space()->install_read_bank(0x0000, 0x7fff, m_bank_rom_low);
+ cart_space()->install_write_handler(0xb000, 0xb000, emu::rw_delegate(*this, FUNC(megaduck_banked_device::bank_rom_switch_low)));
+ }
+
+ // all good
+ return std::error_condition();
+ }
-/*-------------------------------------------------
- mapper specific handlers
- -------------------------------------------------*/
+protected:
+ virtual void device_start() override ATTR_COLD
+ {
+ }
+
+ virtual void device_reset() override ATTR_COLD
+ {
+ m_bank_rom_low->set_entry(0 & m_bank_mask_rom[0]);
+ m_bank_rom_high->set_entry(1 & m_bank_mask_rom[1]);
+ }
-uint8_t gb_rom_device::read_rom(offs_t offset)
+private:
+ void bank_rom_switch_low(u8 data)
+ {
+ u8 const lo = data & m_bank_mask_rom[0];
+ LOG(
+ "%s: Set ROM bank low = 0x%04X\n",
+ machine().describe_context(),
+ lo * 0x8000);
+ m_bank_rom_low->set_entry(lo);
+ }
+
+ void bank_rom_switch_high(u8 data)
+ {
+ u8 const hi = data & m_bank_mask_rom[1];
+ LOG(
+ "%s: Set ROM bank high = 0x%04X\n",
+ machine().describe_context(),
+ hi * 0x4000);
+ m_bank_rom_high->set_entry(hi);
+ }
+
+ void bank_rom_switch(u8 data)
+ {
+ u8 const lo = data & m_bank_mask_rom[0];
+ u8 const hi = ((data * 2) + 1) & m_bank_mask_rom[1];
+ LOG(
+ "%s: Set ROM banks low = 0x%04X, high = 0x%04X\n",
+ machine().describe_context(),
+ lo * 0x8000,
+ hi * 0x4000);
+ m_bank_rom_low->set_entry(lo);
+ m_bank_rom_high->set_entry(hi);
+ }
+
+ memory_bank_creator m_bank_rom_low;
+ memory_bank_creator m_bank_rom_high;
+ u8 m_bank_mask_rom[2];
+};
+
+
+
+//**************************************************************************
+// Game Boy flat ROM/RAM (max 32 KiB ROM, 8 KiB RAM)
+//**************************************************************************
+
+class flat_rom_ram_device : public flat_ram_device_base<megaduck_flat_device>
{
- m_latch_bank = offset / 0x4000;
- return m_rom[rom_bank_map[m_latch_bank] * 0x4000 + (offset & 0x3fff)];
-}
+public:
+ flat_rom_ram_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) :
+ flat_ram_device_base<megaduck_flat_device>(mconfig, GB_ROM_STD, tag, owner, clock)
+ {
+ }
+
+ virtual std::error_condition load(std::string &message) override ATTR_COLD
+ {
+ // first set up cartridge RAM if any
+ if (!check_ram(message))
+ return image_error::BADSOFTWARE;
+
+ // ROM is installed the same way as a Mega Duck flat ROM cartridge
+ std::error_condition const romresult(megaduck_flat_device::load(message));
+ if (romresult)
+ return romresult;
+ install_ram();
+
+ // all good
+ return std::error_condition();
+ }
+};
-uint8_t gb_rom_device::read_ram(offs_t offset)
+
+
+//**************************************************************************
+// M161 (32 KiB * 8)
+//**************************************************************************
+
+class m161_device : public flat_ram_device_base<banked_32k_device_base>
{
- if (!m_ram.empty())
- return m_ram[ram_bank_map[m_ram_bank] * 0x2000 + offset];
- else
- return 0xff;
-}
+public:
+ m161_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) :
+ flat_ram_device_base<banked_32k_device_base>(mconfig, GB_ROM_M161, tag, owner, clock),
+ m_bank_lock(0U)
+ {
+ }
+
+ virtual std::error_condition load(std::string &message) override ATTR_COLD
+ {
+ // set up ROM
+ set_bank_bits_rom(8); // 74HC161A - 3-bit bank, 1-bit lockout
+ if (!check_rom(message))
+ return image_error::BADSOFTWARE;
+ install_rom();
+ install_ram();
+
+ // install bank switch handler
+ cart_space()->install_write_handler(0x0000, 0x7fff, emu::rw_delegate(*this, FUNC(m161_device::bank_rom_switch)));
+
+ // all good
+ return std::error_condition();
+ }
-void gb_rom_device::write_ram(offs_t offset, uint8_t data)
+private:
+ virtual void device_start() override ATTR_COLD
+ {
+ flat_ram_device_base<banked_32k_device_base>::device_start();
+
+ save_item(NAME(m_bank_lock));
+ }
+
+ virtual void device_reset() override ATTR_COLD
+ {
+ flat_ram_device_base<banked_32k_device_base>::device_reset();
+
+ m_bank_lock = 0U;
+
+ set_bank_rom(0);
+ }
+
+ void bank_rom_switch(offs_t offset, u8 data)
+ {
+ if (!m_bank_lock)
+ {
+ m_bank_lock = 1U; // D connected to Vcc
+ set_bank_rom(data & 0x07); // A/B/C connected to D0/D1/D2
+ }
+ }
+
+ u8 m_bank_lock;
+};
+
+
+
+//**************************************************************************
+// Wisdom Tree (theoretical 32 KiB * 16,386, limited to 32 KiB * 256)
+//**************************************************************************
+
+class wisdom_device : public flat_ram_device_base<banked_32k_device_base>
{
- if (!m_ram.empty())
- m_ram[ram_bank_map[m_ram_bank] * 0x2000 + offset] = data;
-}
+public:
+ wisdom_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) :
+ flat_ram_device_base<banked_32k_device_base>(mconfig, GB_ROM_WISDOM, tag, owner, clock)
+ {
+ }
+ virtual std::error_condition load(std::string &message) override ATTR_COLD
+ {
+ // set up ROM
+ set_bank_bits_rom(8); // 8 MiB real-world limit with 74LS377 - change to 14 for 512 MiB theoretical limit
+ if (!check_rom(message))
+ return image_error::BADSOFTWARE;
+ install_rom();
+ install_ram();
+ set_bank_rom(0);
-// Tamagotchi
+ // install bank switch handler
+ cart_space()->install_write_handler(0x0000, 0x3fff, emu::rw_delegate(*this, FUNC(wisdom_device::bank_rom_switch)));
+
+ // all good
+ return std::error_condition();
+ }
-uint8_t gb_rom_tama5_device::read_rom(offs_t offset)
+private:
+ void bank_rom_switch(offs_t offset, u8 data)
+ {
+ set_bank_rom(offset);
+ }
+};
+
+
+
+//**************************************************************************
+// Yong Yong Pirate
+//**************************************************************************
+
+class yong_device : public flat_ram_device_base<mbc_device_base>
{
- if (offset < 0x4000)
- return m_rom[rom_bank_map[m_latch_bank] * 0x4000 + (offset & 0x3fff)];
- else
- return m_rom[rom_bank_map[m_latch_bank2] * 0x4000 + (offset & 0x3fff)];
-}
+public:
+ yong_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) :
+ flat_ram_device_base<mbc_device_base>(mconfig, GB_ROM_YONG, tag, owner, clock)
+ {
+ }
+
+ virtual std::error_condition load(std::string &message) override ATTR_COLD
+ {
+ // set up ROM/RAM
+ set_bank_bits_rom(8);
+ if (!check_rom(message))
+ return image_error::BADSOFTWARE;
+ install_rom();
+ install_ram();
-uint8_t gb_rom_tama5_device::read_ram(offs_t offset)
+ // install bank switch handler
+ cart_space()->install_write_handler(0x2000, 0x2000, emu::rw_delegate(*this, FUNC(yong_device::bank_rom_switch)));
+
+ // all good
+ return std::error_condition();
+ }
+
+protected:
+ virtual void device_reset() override ATTR_COLD
+ {
+ flat_ram_device_base<mbc_device_base>::device_reset();
+
+ set_bank_rom(1);
+ }
+
+private:
+ void bank_rom_switch(u8 data)
+ {
+ set_bank_rom(data);
+ }
+};
+
+
+
+//**************************************************************************
+// MBC1 variant used by Yong Yong for Rockman 8
+//**************************************************************************
+
+class rockman8_device : public flat_ram_device_base<mbc_device_base>
{
- return m_rtc_reg;
-}
+public:
+ rockman8_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) :
+ flat_ram_device_base<mbc_device_base>(mconfig, GB_ROM_ROCKMAN8, tag, owner, clock)
+ {
+ }
+
+ virtual std::error_condition load(std::string &message) override ATTR_COLD
+ {
+ // set up ROM/RAM
+ set_bank_bits_rom(5);
+ if (!check_rom(message))
+ return image_error::BADSOFTWARE;
+ install_rom();
+ install_ram();
+
+ // install bank switch handler
+ cart_space()->install_write_handler(0x2000, 0x3fff, emu::rw_delegate(*this, FUNC(rockman8_device::bank_rom_switch)));
+
+ // all good
+ return std::error_condition();
+ }
-void gb_rom_tama5_device::write_ram(offs_t offset, uint8_t data)
+protected:
+ virtual void device_reset() override ATTR_COLD
+ {
+ flat_ram_device_base<mbc_device_base>::device_reset();
+
+ set_bank_rom(1);
+ }
+
+private:
+ void bank_rom_switch(u8 data)
+ {
+ data &= 0x1f;
+ set_bank_rom(!data ? 1 : (0x0f < data) ? (data - 8) : data);
+ }
+};
+
+
+
+//**************************************************************************
+// MBC1 variant used by Yong Yong for Super Mario 3 Special
+//**************************************************************************
+/*
+ Mario special seems to be a 512k image (mirrored up to 1M or 2M [redump needed to establish this])
+ it consists of 13 unique 16k chunks laid out as follows
+ unique chunk --> bank in bin
+ 1st to 7th --> 0x00 to 0x06
+ 8th --> 0x08
+ 9th --> 0x0b
+ 10th --> 0x0c
+ 11th --> 0x0d
+ 12th --> 0x0f
+ 13th --> 0x13
+
+ According to old doc from Brian Provinciano, writing bit 5 in 0x5000-0x5fff should
+ change the bank layout, in the sense that writing to bank switch acts like if
+ the original ROm has a different layout (as if unique chunks were under permutations
+ (24), (365) and (8a9) with 0,1,7,b,c fixed) and the same table above is used.
+ However, no such a write ever happen (only bit 4 is written, but changing mode with
+ bit 4 breaks the graphics).
+ */
+
+class sm3sp_device : public flat_ram_device_base<mbc_device_base>
{
- switch (offset & 0x0001)
+public:
+ sm3sp_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) :
+ flat_ram_device_base<mbc_device_base>(mconfig, GB_ROM_SM3SP, tag, owner, clock),
+ m_bank_rom_mode(0U)
{
- case 0x0000: /* Write to data register */
- switch (m_tama5_cmd)
- {
- case 0x00: /* Bits 0-3 for rom bank selection */
- m_latch_bank2 = (m_latch_bank2 & 0xf0) | (data & 0x0f);
- break;
- case 0x01: /* Bit 4(-7?) for rom bank selection */
- m_latch_bank2 = (m_latch_bank2 & 0x0f) | ((data & 0x0f) << 4);
- break;
- case 0x04: /* Data to write lo */
- m_tama5_data = (m_tama5_data & 0xf0) | (data & 0x0f);
- break;
- case 0x05: /* Data to write hi */
- m_tama5_data = (m_tama5_data & 0x0f) | ((data & 0x0f) << 4);
- break;
- case 0x06: /* Address selection hi */
- m_tama5_addr = (m_tama5_addr & 0x0f) | ((data & 0x0f) << 4);
- break;
- case 0x07: /* Address selection lo */
- /* This address always seems to written last, so we'll just
- execute the command here */
- m_tama5_addr = (m_tama5_addr & 0xf0) | (data & 0x0f);
- switch (m_tama5_addr & 0xe0)
- {
- case 0x00: /* Write memory */
- //logerror( "Write tama5 memory 0x%02X <- 0x%02X\n", m_tama5_addr & 0x1f, m_tama5_data);
- m_regs[m_tama5_addr & 0x1f] = m_tama5_data;
- break;
- case 0x20: /* Read memory */
- //logerror( "Read tama5 memory 0x%02X\n", m_tama5_addr & 0x1f);
- m_tama5_data = m_regs[m_tama5_addr & 0x1f];
- break;
- case 0x40: /* Unknown, some kind of read */
- if ((m_tama5_addr & 0x1f) == 0x12)
- m_tama5_data = 0xff;
- [[fallthrough]];
- case 0x80: /* Unknown, some kind of read (when 07=01)/write (when 07=00/02) */
- default:
- logerror( "%s Unknown addressing mode\n", machine().describe_context() );
- break;
- }
- break;
- }
- break;
- case 0x0001: /* Write to control register */
- switch (data)
+ }
+
+ virtual std::error_condition load(std::string &message) override ATTR_COLD
+ {
+ // set up ROM/RAM
+ set_bank_bits_rom(5);
+ if (!check_rom(message))
+ return image_error::BADSOFTWARE;
+ install_rom();
+ install_ram();
+
+ // install bank switch handler
+ cart_space()->install_write_handler(0x2000, 0x2fff, emu::rw_delegate(*this, FUNC(sm3sp_device::bank_rom_switch)));
+ cart_space()->install_write_handler(0x5000, 0x5fff, emu::rw_delegate(*this, FUNC(sm3sp_device::bank_rom_mode)));
+
+ // all good
+ return std::error_condition();
+ }
+
+protected:
+ virtual void device_start() override ATTR_COLD
+ {
+ flat_ram_device_base<mbc_device_base>::device_start();
+
+ save_item(NAME(m_bank_rom_mode));
+ }
+
+ virtual void device_reset() override ATTR_COLD
+ {
+ flat_ram_device_base<mbc_device_base>::device_reset();
+
+ m_bank_rom_mode = 0U;
+
+ set_bank_rom(1);
+ }
+
+private:
+ void bank_rom_switch(u8 data)
+ {
+ /*
+ writing data to 0x2000-0x2fff switches bank according to the table below
+ (the value values corresponding to table[0x0f] is not confirmed, choices
+ 0,1,2,3,8,c,f freeze the game, while 4,5,6,7,b,d,0x13 work with glitches)
+
+ Table 1 confirmed...
+ 0 -> 0
+ 4 -> 2
+ 6 -> 3
+ 19 -> 5 (level 2 background graphics)
+ 1b -> 8 (level 3 background graphics)
+ 1c -> b (bonus house background graphics)
+ 1d -> d (level 4 background graphics)
+ 1e -> 6 (level 1 background graphics)
+ 1 (9 maybe, or 3)? f (5 maybe)? 2->1?
+ 16 -> 4-8? b?
+ */
+ static constexpr u8 BANK_TABLE[0x20] = {
+ 0x00,0x04,0x01,0x05, 0x02,0x06,0x03,0x05,
+ 0x08,0x0c,0x03,0x0d, 0x03,0x0b,0x0b,0x08 /* original doc put 0x0f here (i.e. 11th unique bank) */,
+ 0x05,0x06,0x0b,0x0d, 0x08,0x06,0x13,0x0b,
+ 0x08,0x05,0x05,0x08, 0x0b,0x0d,0x06,0x05 };
+
+ u8 const lookup(BANK_TABLE[data & 0x1f]);
+ u8 remap(lookup);
+ if (m_bank_rom_mode)
+ {
+ switch (lookup)
{
- case 0x00: /* Bits 0-3 for rom bank selection */
- case 0x01: /* Bits 4-7 for rom bank selection */
- case 0x04: /* Data write register lo */
- case 0x05: /* Data write register hi */
- case 0x06: /* Address register hi */
- case 0x07: /* Address register lo */
- break;
- case 0x0a: /* Are we ready for the next command? */
- m_rtc_reg = 0x01;
- break;
- case 0x0c: /* Data read register lo */
- m_rtc_reg = m_tama5_data & 0x0f;
- break;
- case 0x0d: /* Data read register hi */
- m_rtc_reg = (m_tama5_data & 0xf0) >> 4;
- break;
+ case 0x02: remap = 0x04; break;
+ case 0x03: remap = 0x06; break;
+ case 0x04: remap = 0x02; break;
+ case 0x05: remap = 0x03; break;
+ case 0x06: remap = 0x05; break;
+ case 0x0b: remap = 0x0d; break;
+ case 0x0c: remap = 0x0b; break;
+ case 0x0d: remap = 0x0c; break;
+
+ case 0x00:
+ case 0x01:
+ case 0x08:
+ case 0x0f:
+ case 0x13:
default:
- logerror( "%s Unknown tama5 command 0x%02X\n", machine().describe_context(), data );
break;
}
- m_tama5_cmd = data;
- break;
+ }
+ LOG(
+ "%s: Bank select 0x%02X -> 0x%02X -> 0x%02X\n",
+ machine().describe_context(),
+ data,
+ lookup,
+ remap);
+ set_bank_rom(remap);
}
-}
+ void bank_rom_mode(u8 data)
+ {
+ LOG("%s: Bank mode 0x%02X\n", machine().describe_context(), data);
+ m_bank_rom_mode = BIT(data, 5);
+ }
+
+ u8 m_bank_rom_mode;
+};
-// Wisdom Tree
-uint8_t gb_rom_wisdom_device::read_rom(offs_t offset)
-{
- return m_rom[rom_bank_map[m_latch_bank] * 0x4000 + offset];
-}
-void gb_rom_wisdom_device::write_bank(offs_t offset, uint8_t data)
+//**************************************************************************
+// Sachen MMC1 unlicensed
+//**************************************************************************
+
+class sachen_mmc1_device : public sachen_mmc_device_base
{
- if (offset < 0x4000)
- m_latch_bank = (offset << 1) & 0x1ff;
-}
+public:
+ sachen_mmc1_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) :
+ sachen_mmc_device_base(mconfig, GB_ROM_SACHEN1, tag, owner, clock),
+ m_counter(0U)
+ {
+ }
+ virtual std::error_condition load(std::string &message) override ATTR_COLD
+ {
+ // configure ROM banks but don't install directly
+ if (!check_rom(message))
+ return image_error::BADSOFTWARE;
+ configure_bank_rom();
-// Yong Yong pirate
+ // actually install ROM and bank switch handlers
+ logerror("Installing banked ROM at 0x0000-0x3FFF and 0x4000-0x7FFF\n");
+ cart_space()->install_read_handler(0x0000, 0x7fff, emu::rw_delegate(*this, FUNC(sachen_mmc1_device::read_rom)));
+ install_bank_switch_handlers();
-uint8_t gb_rom_yong_device::read_rom(offs_t offset)
-{
- if (offset < 0x4000)
- return m_rom[rom_bank_map[m_latch_bank] * 0x4000 + (offset & 0x3fff)];
- else
- return m_rom[rom_bank_map[m_latch_bank2] * 0x4000 + (offset & 0x3fff)];
-}
+ // all good
+ return std::error_condition();
+ }
-void gb_rom_yong_device::write_bank(offs_t offset, uint8_t data)
-{
- if (offset == 0x2000)
- m_latch_bank2 = data;
-}
+protected:
+ virtual void device_start() override ATTR_COLD
+ {
+ sachen_mmc_device_base::device_start();
+
+ save_item(NAME(m_counter));
+ }
+ virtual void device_reset() override ATTR_COLD
+ {
+ sachen_mmc_device_base::device_reset();
-// ATV Racin pirate (incomplete)
+ m_counter = 0U;
+ }
-uint8_t gb_rom_atvrac_device::read_rom(offs_t offset)
-{
- if (offset < 0x4000)
- return m_rom[rom_bank_map[m_latch_bank] * 0x4000 + (offset & 0x3fff)];
- else
- return m_rom[rom_bank_map[m_latch_bank2] * 0x4000 + (offset & 0x3fff)];
-}
+private:
+ u8 read_rom(offs_t offset)
+ {
+ if (!machine().side_effects_disabled())
+ {
+ // These cartridges work by counting low-to-high transitions on A15.
+ // CPU keeps A15 high while reading internal bootstrap ROM.
+ // Doing this on ROM reads is a good enough approximation for it to work.
+ if (0x31 != m_counter)
+ ++m_counter;
+ }
+
+ return rom_read(offset, 0x31 != m_counter);
+ }
+
+ u8 m_counter;
+};
+
+
+
+//**************************************************************************
+// Sachen MMC2 unlicensed
+//**************************************************************************
-void gb_rom_atvrac_device::write_bank(offs_t offset, uint8_t data)
+class sachen_mmc2_device : public gbc_logo_spoof_device_base<sachen_mmc_device_base>
{
- if (offset == 0x3f00)
+public:
+ sachen_mmc2_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) :
+ gbc_logo_spoof_device_base<sachen_mmc_device_base>(mconfig, GB_ROM_SACHEN2, tag, owner, clock)
{
- if (data == 0)
- data = 1;
- m_latch_bank2 = m_latch_bank | data;
}
- if (offset == 0x3fc0)
- m_latch_bank = data * 16;
-}
-// La Sa Ma pirate (incomplete)
+ virtual std::error_condition load(std::string &message) override ATTR_COLD
+ {
+ // configure ROM banks but don't install directly
+ if (!check_rom(message))
+ return image_error::BADSOFTWARE;
+ configure_bank_rom();
+
+ // actually install ROM and bank switch handlers
+ logerror("Installing banked ROM at 0x0000-0x3FFF and 0x4000-0x7FFF\n");
+ cart_space()->install_read_handler(0x0000, 0x7fff, emu::rw_delegate(*this, FUNC(sachen_mmc2_device::read_rom)));
+ install_bank_switch_handlers();
+
+ // all good
+ return std::error_condition();
+ }
+
+private:
+ u8 read_rom(offs_t offset)
+ {
+ rom_access();
+ return rom_read(offset, spoof_logo());
+ }
+};
+
+
+
+//**************************************************************************
+// Rocket Games unlicensed (incomplete)
+//**************************************************************************
-uint8_t gb_rom_lasama_device::read_rom(offs_t offset)
+class rocket_device : public flat_ram_device_base<gbc_logo_spoof_device_base<mbc_dual_device_base> >
{
- if (offset < 0x4000)
- return m_rom[rom_bank_map[m_latch_bank] * 0x4000 + (offset & 0x3fff)];
- else
- return m_rom[rom_bank_map[m_latch_bank2] * 0x4000 + (offset & 0x3fff)];
-}
+public:
+ rocket_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) :
+ flat_ram_device_base<gbc_logo_spoof_device_base<mbc_dual_device_base> >(mconfig, GB_ROM_ROCKET, tag, owner, clock)
+ {
+ }
+
+ virtual std::error_condition load(std::string &message) override ATTR_COLD
+ {
+ // configure ROM banks but don't install directly
+ set_bank_bits_rom(8, 4);
+ if (!check_rom(message))
+ return image_error::BADSOFTWARE;
+ configure_bank_rom();
+ install_ram();
+
+ // actually install ROM and bank switch handlers
+ logerror("Installing banked ROM at 0x0000-0x3FFF and 0x4000-0x7FFF\n");
+ cart_space()->install_read_handler(0x0000, 0x7fff, emu::rw_delegate(*this, FUNC(rocket_device::read_rom)));
+ cart_space()->install_write_handler(0x3f00, 0x3f00, emu::rw_delegate(*this, FUNC(rocket_device::bank_rom_switch_fine)));
+ cart_space()->install_write_handler(0x3fc0, 0x3fc0, emu::rw_delegate(*this, FUNC(rocket_device::bank_rom_switch_coarse)));
+
+ // all good
+ return std::error_condition();
+ }
+
+protected:
+ virtual void device_reset() override ATTR_COLD
+ {
+ flat_ram_device_base<gbc_logo_spoof_device_base<mbc_dual_device_base> >::device_reset();
+
+ set_bank_rom_coarse(0);
+ set_bank_rom_fine(1);
+ }
+
+private:
+ u8 read_rom(offs_t offset)
+ {
+ // logo spoofing logic
+ rom_access();
+
+ // fetch the banked ROM data
+ u8 const data((BIT(offset, 14) ? bank_rom_high_base() : bank_rom_low_base())[offset & 0x3fff]);
+ if (spoof_logo() && (0x0104 <= offset) && (0x133 >= offset))
+ {
+ static constexpr u8 TRANSFORM[] = {
+ 0xdf, 0xce, 0x97, 0x78, 0xcd, 0x2f, 0xf0, 0x0b, 0x0b, 0xea, 0x78, 0x83, 0x08, 0x1d, 0x9a, 0x45,
+ 0x11, 0x2b, 0xe1, 0x11, 0xf8, 0x88, 0xf8, 0x8e, 0xfe, 0x88, 0x2a, 0xc4, 0xff, 0xfc, 0xd9, 0x87,
+ 0x22, 0xab, 0x67, 0x7d, 0x77, 0x2c, 0xa8, 0xee, 0xff, 0x9b, 0x99, 0x91, 0xaa, 0x9b, 0x33, 0x3e };
+ return data ^ TRANSFORM[offset - 0x104];
+ }
+ else
+ {
+ return data;
+ }
+ }
+
+ void bank_rom_switch_fine(u8 data)
+ {
+ set_bank_rom_fine(data ? data : 1);
+ }
+
+ void bank_rom_switch_coarse(u8 data)
+ {
+ set_bank_rom_coarse(data);
+ }
+};
+
+
-void gb_rom_lasama_device::write_bank(offs_t offset, uint8_t data)
+//**************************************************************************
+// Story of Lasama pirate (incomplete)
+//**************************************************************************
+
+class lasama_device : public flat_ram_device_base<mbc_dual_device_base>
{
- if (offset == 0x2080)
+public:
+ lasama_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock) :
+ flat_ram_device_base<mbc_dual_device_base>(mconfig, GB_ROM_LASAMA, tag, owner, clock)
+ {
+ }
+
+ virtual std::error_condition load(std::string &message) override ATTR_COLD
+ {
+ // set up ROM/RAM
+ set_bank_bits_rom(1, 2);
+ if (!check_rom(message))
+ return image_error::BADSOFTWARE;
+ install_rom();
+ install_ram();
+
+ // install bank switch handlers
+ cart_space()->install_write_handler(0x2080, 0x2080, emu::rw_delegate(*this, FUNC(lasama_device::ctrl_2080_w)));
+ cart_space()->install_write_handler(0x6000, 0x6000, emu::rw_delegate(*this, FUNC(lasama_device::ctrl_6000_w)));
+
+ // all good
+ return std::error_condition();
+ }
+
+protected:
+ virtual void device_reset() override ATTR_COLD
+ {
+ flat_ram_device_base<mbc_dual_device_base>::device_reset();
+
+ set_bank_rom_coarse(0);
+ set_bank_rom_fine(1);
+ }
+
+private:
+ void ctrl_2080_w(u8 data)
{
- // Actual banking?
- m_latch_bank2 = m_latch_bank | (data & 0x03);
+ // high ROM fine bank?
+ set_bank_rom_fine(data & 0x03);
}
- if (offset == 0x6000)
+
+ void ctrl_6000_w(u8 data)
{
// On boot the following two get written right after each other:
// 02
// BE
- // Disable logo switching?
- if (!(data & 0x80))
- m_latch_bank = (data & 0x02) << 1;
+ // disable logo switching?
+ if (!BIT(data, 7))
+ set_bank_rom_coarse(BIT(data, 1));
}
-}
+};
+} // anonymous namespace
-// MegaDuck carts
+} // namespace bus::gameboy
-uint8_t megaduck_rom_device::read_rom(offs_t offset)
-{
- if (offset < 0x4000)
- return m_rom[rom_bank_map[m_latch_bank] * 0x4000 + (offset & 0x3fff)];
- else
- return m_rom[rom_bank_map[m_latch_bank2] * 0x4000 + (offset & 0x3fff)];
-}
-void megaduck_rom_device::write_bank(offs_t offset, uint8_t data)
-{
- if (offset == 0x0001)
- m_latch_bank2 = data;
-}
+// device type definition
+DEFINE_DEVICE_TYPE_PRIVATE(MEGADUCK_ROM_STD, device_gb_cart_interface, bus::gameboy::megaduck_flat_device, "megaduck_rom", "Mega Duck Flat ROM Cartridge")
+DEFINE_DEVICE_TYPE_PRIVATE(MEGADUCK_ROM_BANKED, device_gb_cart_interface, bus::gameboy::megaduck_banked_device, "megaduck_rom_banked", "Mega Duck Banked ROM Cartridge")
-void megaduck_rom_device::write_ram(offs_t offset, uint8_t data)
-{
- m_latch_bank = data * 2;
- m_latch_bank2 = data * 2 + 1;
-}
+DEFINE_DEVICE_TYPE_PRIVATE(GB_ROM_STD, device_gb_cart_interface, bus::gameboy::flat_rom_ram_device, "gb_rom", "Game Boy Flat ROM Cartridge")
+DEFINE_DEVICE_TYPE_PRIVATE(GB_ROM_M161, device_gb_cart_interface, bus::gameboy::m161_device, "gb_rom_m161", "Game Boy M161 Cartridge")
+DEFINE_DEVICE_TYPE_PRIVATE(GB_ROM_WISDOM, device_gb_cart_interface, bus::gameboy::wisdom_device, "gb_rom_wisdom", "Game Boy Wisdom Tree Cartridge")
+DEFINE_DEVICE_TYPE_PRIVATE(GB_ROM_YONG, device_gb_cart_interface, bus::gameboy::yong_device, "gb_rom_yong", "Game Boy Young Yong Cartridge")
+DEFINE_DEVICE_TYPE_PRIVATE(GB_ROM_ROCKMAN8, device_gb_cart_interface, bus::gameboy::rockman8_device, "gb_rom_rockman8", "Game Boy Rockman 8 Cartridge")
+DEFINE_DEVICE_TYPE_PRIVATE(GB_ROM_SM3SP, device_gb_cart_interface, bus::gameboy::sm3sp_device, "gb_rom_sm3sp", "Game Boy Super Mario 3 Special Cartridge")
+DEFINE_DEVICE_TYPE_PRIVATE(GB_ROM_SACHEN1, device_gb_cart_interface, bus::gameboy::sachen_mmc1_device, "gb_rom_sachen1", "Game Boy Sachen MMC1 Cartridge")
+DEFINE_DEVICE_TYPE_PRIVATE(GB_ROM_SACHEN2, device_gb_cart_interface, bus::gameboy::sachen_mmc2_device, "gb_rom_sachen2", "Game Boy Sachen MMC2 Cartridge")
+DEFINE_DEVICE_TYPE_PRIVATE(GB_ROM_ROCKET, device_gb_cart_interface, bus::gameboy::rocket_device, "gb_rom_rocket", "Game Boy Rocket Games Cartridge")
+DEFINE_DEVICE_TYPE_PRIVATE(GB_ROM_LASAMA, device_gb_cart_interface, bus::gameboy::lasama_device, "gb_rom_lasama", "Game Boy Story of Lasama Cartridge")
diff --git a/src/devices/bus/gameboy/rom.h b/src/devices/bus/gameboy/rom.h
index f2388446863..e1cc56444cd 100644
--- a/src/devices/bus/gameboy/rom.h
+++ b/src/devices/bus/gameboy/rom.h
@@ -1,156 +1,22 @@
// license:BSD-3-Clause
-// copyright-holders:Fabio Priuli, Wilbert Pol
+// copyright-holders:Vas Crabb, Wilbert Pol
#ifndef MAME_BUS_GAMEBOY_ROM_H
#define MAME_BUS_GAMEBOY_ROM_H
-#include "gb_slot.h"
-
-
-// ======================> gb_rom_device
-
-class gb_rom_device : public device_t,
- public device_gb_cart_interface
-{
-public:
- // construction/destruction
- gb_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- // reading and writing
- virtual uint8_t read_rom(offs_t offset) override;
- virtual uint8_t read_ram(offs_t offset) override;
- virtual void write_ram(offs_t offset, uint8_t data) override;
-
-protected:
- gb_rom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
-
- // device-level overrides
- virtual void device_start() override { shared_start(); }
- virtual void device_reset() override { shared_reset(); }
-
- void shared_start();
- void shared_reset();
-};
-
-// ======================> gb_rom_tama5_device
-class gb_rom_tama5_device : public gb_rom_device
-{
-public:
- // construction/destruction
- gb_rom_tama5_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- // reading and writing
- virtual uint8_t read_rom(offs_t offset) override;
- virtual uint8_t read_ram(offs_t offset) override;
- virtual void write_ram(offs_t offset, uint8_t data) override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
-
- uint16_t m_tama5_data, m_tama5_addr, m_tama5_cmd;
- uint8_t m_regs[32];
- uint8_t m_rtc_reg;
-};
-
-// ======================> gb_rom_wisdom_device
-class gb_rom_wisdom_device : public gb_rom_device
-{
-public:
- // construction/destruction
- gb_rom_wisdom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- // reading and writing
- virtual uint8_t read_rom(offs_t offset) override;
- virtual void write_bank(offs_t offset, uint8_t data) override;
-
-protected:
- // device-level overrides
- virtual void device_start() override { shared_start(); }
- virtual void device_reset() override { shared_reset(); }
-};
-
-// ======================> gb_rom_yong_device
-class gb_rom_yong_device : public gb_rom_device
-{
-public:
- // construction/destruction
- gb_rom_yong_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- // reading and writing
- virtual uint8_t read_rom(offs_t offset) override;
- virtual void write_bank(offs_t offset, uint8_t data) override;
-
-protected:
- // device-level overrides
- virtual void device_start() override { shared_start(); }
- virtual void device_reset() override { shared_reset(); }
-};
-
-// ======================> gb_rom_atvrac_device
-class gb_rom_atvrac_device : public gb_rom_device
-{
-public:
- // construction/destruction
- gb_rom_atvrac_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- // reading and writing
- virtual uint8_t read_rom(offs_t offset) override;
- virtual void write_bank(offs_t offset, uint8_t data) override;
-
-protected:
- // device-level overrides
- virtual void device_start() override { shared_start(); }
- virtual void device_reset() override { shared_reset(); }
-};
-
-// ======================> gb_rom_lasama_device
-class gb_rom_lasama_device : public gb_rom_device
-{
-public:
- // construction/destruction
- gb_rom_lasama_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- // reading and writing
- virtual uint8_t read_rom(offs_t offset) override;
- virtual void write_bank(offs_t offset, uint8_t data) override;
-
-protected:
- // device-level overrides
- virtual void device_start() override { shared_start(); }
- virtual void device_reset() override { shared_reset(); }
-};
-
-
-// ======================> megaduck_rom_device
-class megaduck_rom_device :public device_t,
- public device_gb_cart_interface
-{
-public:
- // construction/destruction
- megaduck_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- // reading and writing
- virtual uint8_t read_rom(offs_t offset) override;
- virtual void write_bank(offs_t offset, uint8_t data) override;
- virtual void write_ram(offs_t offset, uint8_t data) override;
-
-protected:
- megaduck_rom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
-
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
-};
-
-// device type definition
-DECLARE_DEVICE_TYPE(GB_STD_ROM, gb_rom_device)
-DECLARE_DEVICE_TYPE(GB_ROM_TAMA5, gb_rom_tama5_device)
-DECLARE_DEVICE_TYPE(GB_ROM_WISDOM, gb_rom_wisdom_device)
-DECLARE_DEVICE_TYPE(GB_ROM_YONG, gb_rom_yong_device)
-DECLARE_DEVICE_TYPE(GB_ROM_ATVRAC, gb_rom_atvrac_device)
-DECLARE_DEVICE_TYPE(GB_ROM_LASAMA, gb_rom_lasama_device)
-
-DECLARE_DEVICE_TYPE(MEGADUCK_ROM, megaduck_rom_device)
+#include "slot.h"
+
+DECLARE_DEVICE_TYPE(MEGADUCK_ROM_STD, device_gb_cart_interface)
+DECLARE_DEVICE_TYPE(MEGADUCK_ROM_BANKED, device_gb_cart_interface)
+
+DECLARE_DEVICE_TYPE(GB_ROM_STD, device_gb_cart_interface)
+DECLARE_DEVICE_TYPE(GB_ROM_M161, device_gb_cart_interface)
+DECLARE_DEVICE_TYPE(GB_ROM_WISDOM, device_gb_cart_interface)
+DECLARE_DEVICE_TYPE(GB_ROM_YONG, device_gb_cart_interface)
+DECLARE_DEVICE_TYPE(GB_ROM_ROCKMAN8, device_gb_cart_interface)
+DECLARE_DEVICE_TYPE(GB_ROM_SM3SP, device_gb_cart_interface)
+DECLARE_DEVICE_TYPE(GB_ROM_SACHEN1, device_gb_cart_interface)
+DECLARE_DEVICE_TYPE(GB_ROM_SACHEN2, device_gb_cart_interface)
+DECLARE_DEVICE_TYPE(GB_ROM_ROCKET, device_gb_cart_interface)
+DECLARE_DEVICE_TYPE(GB_ROM_LASAMA, device_gb_cart_interface)
#endif // MAME_BUS_GAMEBOY_ROM_H
diff --git a/src/devices/bus/gameboy/slmulti.cpp b/src/devices/bus/gameboy/slmulti.cpp
new file mode 100644
index 00000000000..b5e824829d8
--- /dev/null
+++ b/src/devices/bus/gameboy/slmulti.cpp
@@ -0,0 +1,417 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/***************************************************************************
+
+ Chinese multi-game cartridges by SL and possibly others
+
+ Supports collections containing very large numbers of games designed for
+ MBC1 and MBC5 cartridges. Supports ROM sizes up to 16 MiB ROM (1024 16 KiB
+ pages) and 128 KiB static RAM (16 8 KiB pages). Included MBC1 games can
+ use 32 KiB to at least 512 KiB ROM (2 to 32 pages) and 8 KiB or 32 KiB
+ static RAM (1 or 4 pages). Included MBC5 games can use 32 KiB to 4 MiB ROM
+ (2 to 256 pages) and 8 KiB or 32 KiB static RAM (1 or 4 pages). Static RAM
+ can be disabled for games that don't use it to avoid corrupting save data
+ for other games.
+
+ The controller starts in configuration mode. After setting up ROM and
+ static RAM for the selected game, the controller asserts the reset line on
+ the cartridge edge connector to reset the Game Boy CPU and PPU. This is
+ necessary to get out of CGB mode on a Game Boy Color for games that don't
+ have CGB support. The ROM and static RAM configuration settings aren't
+ affected by the soft reset.
+
+ Changes to the base ROM page seem to take effect immediately. The Vast
+ Fame games switch the base page when starting the menu program. Changes to
+ static RAM configuration presumably take effect immediately, although the
+ menu program doesn't use static RAM.
+
+ The menu program sets up the code to switch to the selected game's ROM and
+ static RAM configuration in WRAM. The register write to complete setup,
+ exit configuration mode and reset the system is followed by a nop and a
+ jp $100. This will jump to the game's entry point if the system fails to
+ reset, although many games don't work properly if this happens, as they
+ expect the system state set up by the bootstrap ROM.
+
+ 0x0000-3FFF R - Low ROM bank.
+ 0x4000-7FFF R - High ROM bank.
+ 0xA000-BFFF RW - Static RAM if enabled.
+
+ 0x0000-1FFF W - Enable (0x0A) or disable (not 0x0A) static RAM.
+ 0x2000-2FFF W - Set ROM A21-A14 for 0x4000-7FFF as allowed by mask.
+ 0x3000-3FFF W - Same as 0x2000 in MBC1 mode, ignored in MBC5 mode.
+ 0x4000-5FFF W - Set static RAM A14-A13 0xA000-BFFF as allowed by mask.
+
+ 0x5000-5FFF * W - Set command for next write to 0x7000-7FFF.
+ 0x7000-7FFF * W - Argument for last command written to 0x5000-5FFF.
+
+ * Registers only writable in configuration mode.
+
+ 0x55 - X------- Exit configuration mode and reset system if set?
+ -XX----- Dumped software writes 11 for MBC1 mode, or 00 for MBC5
+ mode.
+ ---X---- Unknown.
+ ----X--- Set ROM base A23.
+ -----XXX Set number of A21-A15 lines controlled by ROM base setting.
+ 0xAA - XXXXXXXX Set ROM base A22-A15 as allowed by mask.
+ 0xBB - XX------ Unknown - dumped software always write 00.
+ --X----- Allow static RAM to be enabled if set.
+ ---X---- Set static RAM base page mask to A16-A13 if set, or A16-A15
+ if clear.
+ ----XXXX Set static RAM A16-A13 as allowed by mask.
+
+ The Vast Fame cartridges write 0x07 to the 0x7000 area after writing the
+ base ROM page for the previous 0xAA command without an intervening write to
+ the 0x5000 area. It isn't clear what this is supposed to do. It seems to
+ be save to ignore.
+
+ TODO:
+ * What is the exact effect of bit 7 of the 0x55 command argument?
+ * Does bit 4 of the 0x55 command argument have a purpose? Does it control
+ an output for ROM A24 to support 32 MiB ROMs?
+ * The two bits used for setting MBC1 mode probably have separate effects
+ that can be controlled independently.
+ * Can MBC1 games larger than 512 KiB be supported? Does 0x6000-7FFF
+ switch between coarse ROM banking and static RAM banking in MBC1 mode?
+ * Do the two most significant bits of the 0xBB command argument have a
+ purpose?
+
+ ***************************************************************************/
+
+#include "emu.h"
+#include "slmulti.h"
+
+#include "cartbase.ipp"
+
+#include <string>
+
+//#define VERBOSE 1
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+
+namespace bus::gameboy {
+
+namespace {
+
+class slmulti_device : public mbc_ram_device_base<mbc_dual_uniform_device_base>
+{
+public:
+ slmulti_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+ virtual std::error_condition load(std::string &message) override ATTR_COLD;
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+private:
+ void enable_ram(u8 data);
+ void bank_switch_rom_fine(u8 data);
+ void bank_switch_rom_coarse(u8 data);
+ void bank_switch_ram(u8 data);
+ void set_config_cmd(u8 data);
+ void do_config_cmd(u8 data);
+
+ TIMER_CALLBACK_MEMBER(do_reset);
+
+ void update_bank_rom_high()
+ {
+ u16 const page(bank_rom_entry_high());
+ LOG(
+ "%s: Set high ROM page 0x%03X (0x%06X)\n",
+ machine().describe_context(),
+ page,
+ u32(page) << 14);
+ set_bank_rom_high(page);
+ }
+
+ void update_bank_ram()
+ {
+ u16 const page(bank_ram_entry());
+ LOG(
+ "%s: Set RAM page 0x%X (0x%05X)\n",
+ machine().describe_context(),
+ page,
+ u32(page) << 13);
+ set_bank_ram(page);
+ }
+
+ u16 bank_rom_entry_high() const noexcept
+ {
+ u16 const hi(m_high_page_rom & m_page_mask_rom);
+ return (m_base_page_rom & ~m_page_mask_rom) | (hi ? hi : (m_zero_remap_rom & m_page_mask_rom));
+ }
+
+ u8 bank_ram_entry() const noexcept
+ {
+ return (m_base_page_ram & ~m_page_mask_ram) | (m_page_ram & m_page_mask_ram);
+ }
+
+ memory_view m_view_ctrl;
+ memory_view m_view_ram;
+
+ u16 m_config_cmd;
+
+ u16 m_base_page_rom;
+ u16 m_high_page_rom;
+ u16 m_page_mask_rom;
+ u16 m_zero_remap_rom;
+
+ u8 m_enable_ram;
+ u8 m_base_page_ram;
+ u8 m_page_ram;
+ u8 m_page_mask_ram;
+};
+
+
+slmulti_device::slmulti_device(
+ machine_config const &mconfig,
+ char const *tag,
+ device_t *owner,
+ u32 clock) :
+ mbc_ram_device_base<mbc_dual_uniform_device_base>(mconfig, GB_ROM_SLMULTI, tag, owner, clock),
+ m_view_ctrl(*this, "ctrl"),
+ m_view_ram(*this, "ram"),
+ m_config_cmd(0U),
+ m_base_page_rom(0U),
+ m_high_page_rom(0U),
+ m_page_mask_rom(0U),
+ m_zero_remap_rom(0U),
+ m_enable_ram(0U),
+ m_base_page_ram(0U),
+ m_page_ram(0U),
+ m_page_mask_ram(0U)
+{
+}
+
+
+std::error_condition slmulti_device::load(std::string &message)
+{
+ // set up ROM and RAM
+ set_bank_bits_rom(10);
+ set_bank_bits_ram(4);
+ if (!check_rom(message) || !check_ram(message))
+ return image_error::BADSOFTWARE;
+ cart_space()->install_view(0xa000, 0xbfff, m_view_ram);
+ install_rom();
+ install_ram(m_view_ram[0]);
+
+ // install memory mapping control handlers
+ cart_space()->install_write_handler(
+ 0x0000, 0x1fff,
+ emu::rw_delegate(*this, FUNC(slmulti_device::enable_ram)));
+ cart_space()->install_write_handler(
+ 0x2000, 0x3fff,
+ emu::rw_delegate(*this, FUNC(slmulti_device::bank_switch_rom_fine)));
+ cart_space()->install_write_handler(
+ 0x4000, 0x5fff,
+ emu::rw_delegate(*this, FUNC(slmulti_device::bank_switch_ram)));
+
+ // configuration mode and MBC5 mode partially overlay the normal handlers
+ cart_space()->install_view(
+ 0x2000, 0x7fff,
+ m_view_ctrl);
+
+ // this is for MBC5 games
+ m_view_ctrl[0].install_write_handler(
+ 0x3000, 0x3fff,
+ emu::rw_delegate(*this, FUNC(slmulti_device::bank_switch_rom_coarse)));
+
+ // install configuration handlers over the top
+ m_view_ctrl[1].install_write_handler(
+ 0x5000, 0x5fff,
+ emu::rw_delegate(*this, FUNC(slmulti_device::set_config_cmd)));
+ m_view_ctrl[1].install_write_handler(
+ 0x7000, 0x7fff,
+ emu::rw_delegate(*this, FUNC(slmulti_device::do_config_cmd)));
+
+ // do this here - the menu program apparently does a system reset to get into DMG mode
+ m_view_ctrl.select(1);
+
+ // all good
+ return std::error_condition();
+}
+
+
+void slmulti_device::device_start()
+{
+ mbc_ram_device_base<mbc_dual_uniform_device_base>::device_start();
+
+ m_config_cmd = 0x0100U;
+
+ m_base_page_rom = 0U;
+ m_high_page_rom = 0U;
+ m_page_mask_rom = 1U;
+ m_zero_remap_rom = 0U;
+
+ m_enable_ram = 0U;
+ m_base_page_ram = 0U;
+ m_page_ram = 0U;
+ m_page_mask_ram = 0U;
+
+ save_item(NAME(m_config_cmd));
+ save_item(NAME(m_base_page_rom));
+ save_item(NAME(m_high_page_rom));
+ save_item(NAME(m_page_mask_rom));
+ save_item(NAME(m_zero_remap_rom));
+ save_item(NAME(m_enable_ram));
+ save_item(NAME(m_base_page_ram));
+ save_item(NAME(m_page_ram));
+ save_item(NAME(m_page_mask_ram));
+}
+
+
+void slmulti_device::device_reset()
+{
+ mbc_ram_device_base<mbc_dual_uniform_device_base>::device_reset();
+
+ // TODO: proper reset state
+ m_high_page_rom = 1U;
+
+ m_view_ram.disable();
+
+ set_bank_rom_low(m_base_page_rom & ~m_page_mask_rom);
+ update_bank_rom_high();
+ update_bank_ram();
+}
+
+
+void slmulti_device::enable_ram(u8 data)
+{
+ // TODO: how many bits are checked?
+ if ((0x0a == (data & 0x0f)) && m_enable_ram)
+ {
+ LOG("%s: Cartridge RAM enabled\n", machine().describe_context());
+ m_view_ram.select(0);
+ }
+ else
+ {
+ LOG("%s: Cartridge RAM disabled\n", machine().describe_context());
+ m_view_ram.disable();
+ }
+}
+
+
+void slmulti_device::bank_switch_rom_fine(u8 data)
+{
+ m_high_page_rom = data;
+ update_bank_rom_high();
+}
+
+
+void slmulti_device::bank_switch_rom_coarse(u8 data)
+{
+ // there's no way to specify a 9-bit page mask, so MBC5 games larger than 4 MiB can't be supported
+ LOG("%s Set coarse ROM bank 0x%02X\n", machine().describe_context(), data);
+}
+
+
+void slmulti_device::set_config_cmd(u8 data)
+{
+ LOG("%s: Set configuration command 0x%02X\n", machine().describe_context(), data);
+ m_config_cmd = data;
+}
+
+
+void slmulti_device::bank_switch_ram(u8 data)
+{
+ m_page_ram = data & 0x0f;
+ update_bank_ram();
+}
+
+
+void slmulti_device::do_config_cmd(u8 data)
+{
+ LOG(
+ "%s: Execute configuration command 0x%02X with argument 0x%02X\n",
+ machine().describe_context(),
+ m_config_cmd,
+ data);
+ switch (m_config_cmd)
+ {
+ case 0x55:
+ // bit 4 unknown
+ m_base_page_rom = (m_base_page_rom & ~0x0200) | (u16(BIT(data, 3)) << 9);
+ m_page_mask_rom = (2U << BIT(~data, 0, 3)) - 1;
+ switch (BIT(data, 5, 2))
+ {
+ case 0x0: // used for MBC5 games
+ m_zero_remap_rom = 0U;
+ m_view_ctrl.select(0);
+ break;
+ case 0x3: // used for MBC1 games
+ m_zero_remap_rom = 1U;
+ m_view_ctrl.disable();
+ break;
+ default:
+ logerror(
+ "%s: Unknown memory mapping mode 0x%X\n",
+ machine().describe_context(),
+ BIT(data, 5, 2));
+ m_view_ctrl.disable();
+ }
+ LOG(
+ "%s: Set base ROM page = 0x%03X (0x%06X), page mask = 0x%03X, zero remap = 0x%03X%s\n",
+ machine().describe_context(),
+ m_base_page_rom,
+ u32(m_base_page_rom) << 14,
+ m_page_mask_rom,
+ m_zero_remap_rom,
+ BIT(data, 7) ? ", reset" : "");
+ set_bank_rom_low(m_base_page_rom & ~m_page_mask_rom);
+ update_bank_rom_high();
+ if (BIT(data, 7))
+ machine().scheduler().synchronize(timer_expired_delegate(FUNC(slmulti_device::do_reset), this));
+ break;
+
+ case 0xaa:
+ m_base_page_rom = (m_base_page_rom & ~0x01fe) | (u16(data) << 1);
+ LOG(
+ "%s: Set base ROM page = 0x%03X (0x%06X)\n",
+ machine().describe_context(),
+ m_base_page_rom,
+ u32(m_base_page_rom) << 14);
+ set_bank_rom_low(m_base_page_rom & ~m_page_mask_rom);
+ update_bank_rom_high();
+ break;
+
+ case 0xbb:
+ // TODO: can this cause RAM to be enabled if 0x0a was previously written to 0x0000-0x1fff?
+ m_enable_ram = BIT(data, 5);
+ m_base_page_ram = BIT(data, 0, 4);
+ m_page_mask_ram = BIT(data, 4) ? 0x00 : 0x03;
+ LOG(
+ "%s: Set RAM %s, base page = 0x%X, page mask = 0x%X\n",
+ machine().describe_context(),
+ m_enable_ram ? "enabled" : "disabled",
+ m_base_page_ram,
+ m_page_mask_ram);
+ update_bank_ram();
+ if (!m_enable_ram)
+ m_view_ram.disable();
+ break;
+
+ default:
+ logerror(
+ "%s: Unknown configuration command 0x%02X with argument 0x%02X\n",
+ machine().describe_context(),
+ m_config_cmd,
+ data);
+ }
+
+ // gbcolor:vf12in1 immediately writes 0x07 without writing to 0x5000 in between
+ m_config_cmd = 0x0100;
+}
+
+
+TIMER_CALLBACK_MEMBER(slmulti_device::do_reset)
+{
+ machine().root_device().reset(); // TODO: expose reset line on cartridge interface
+}
+
+} // anonymous namespace
+
+} // namespace bus::gameboy
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(GB_ROM_SLMULTI, device_gb_cart_interface, bus::gameboy::slmulti_device, "gb_rom_slmulti", "Game Boy SL Multi-Game Cartridge")
diff --git a/src/devices/bus/gameboy/slmulti.h b/src/devices/bus/gameboy/slmulti.h
new file mode 100644
index 00000000000..9ae716de72c
--- /dev/null
+++ b/src/devices/bus/gameboy/slmulti.h
@@ -0,0 +1,18 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/***************************************************************************
+
+ Chinese multi-game cartridges by SL and possibly others
+
+ ***************************************************************************/
+#ifndef MAME_BUS_GAMEBOY_SLMULTI_H
+#define MAME_BUS_GAMEBOY_SLMULTI_H
+
+#pragma once
+
+#include "slot.h"
+
+
+DECLARE_DEVICE_TYPE(GB_ROM_SLMULTI, device_gb_cart_interface)
+
+#endif // MAME_BUS_GAMEBOY_SLMULTI_H
diff --git a/src/devices/bus/gameboy/slot.cpp b/src/devices/bus/gameboy/slot.cpp
new file mode 100644
index 00000000000..a38ebf4bd33
--- /dev/null
+++ b/src/devices/bus/gameboy/slot.cpp
@@ -0,0 +1,88 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/***************************************************************************
+
+ Game Boy/Mega Duck cartridge slot interface
+
+ The following ranges are available for use by the cartridge:
+ * 0x0000-0x7FFF - Game Boy boot ROM expects to find header at 0x0100.
+ Writes typically used to control memory mapping.
+ * 0xA000-0xBFFF - Typically used for additional RAM, sometimes
+ battery-backed. Sometimes used for I/O.
+
+ **************************************************************************/
+
+#include "emu.h"
+#include "slot.h"
+
+//#define VERBOSE 1
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+
+//**************************************************************************
+// gb_cart_slot_device_base
+//**************************************************************************
+
+void gb_cart_slot_device_base::call_unload()
+{
+ if (m_cart)
+ m_cart->unload();
+}
+
+
+gb_cart_slot_device_base::gb_cart_slot_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock) :
+ device_t(mconfig, type, tag, owner, clock),
+ device_cartrom_image_interface(mconfig, *this),
+ device_single_card_slot_interface<device_gb_cart_interface>(mconfig, *this),
+ m_space(*this, finder_base::DUMMY_TAG, 8),
+ m_cart(nullptr)
+{
+}
+
+
+void gb_cart_slot_device_base::device_start()
+{
+ m_cart = get_card_device();
+}
+
+
+std::pair<std::error_condition, std::string> gb_cart_slot_device_base::call_load()
+{
+ if (!m_cart)
+ return std::make_pair(std::error_condition(), std::string());
+
+ std::error_condition result;
+ std::string message;
+ if (!loaded_through_softlist())
+ {
+ std::tie(result, message) = load_image_file(image_core_file());
+ if (result)
+ return std::make_pair(result, message);
+ }
+
+ result = m_cart->load(message);
+ if (result)
+ {
+ if (result == image_error::BADSOFTWARE && !loaded_through_softlist())
+ result = image_error::INVALIDIMAGE;
+ }
+ return std::make_pair(result, message);
+}
+
+
+
+//**************************************************************************
+// device_gb_cart_interface
+//**************************************************************************
+
+void device_gb_cart_interface::unload()
+{
+}
+
+
+device_gb_cart_interface::device_gb_cart_interface(machine_config const &mconfig, device_t &device) :
+ device_interface(device, "gameboycart"),
+ m_slot(dynamic_cast<gb_cart_slot_device_base *>(device.owner()))
+{
+}
diff --git a/src/devices/bus/gameboy/slot.h b/src/devices/bus/gameboy/slot.h
new file mode 100644
index 00000000000..e3094f61f09
--- /dev/null
+++ b/src/devices/bus/gameboy/slot.h
@@ -0,0 +1,92 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/***************************************************************************
+
+ Game Boy/Mega Duck cartridge slot interface
+
+ ***************************************************************************/
+#ifndef MAME_BUS_GAMEBOY_SLOT_H
+#define MAME_BUS_GAMEBOY_SLOT_H
+
+#include "imagedev/cartrom.h"
+
+#include <cassert>
+#include <string>
+#include <string_view>
+#include <utility>
+
+
+//**************************************************************************
+// FORWARD DECLARATIONS
+//**************************************************************************
+
+class device_gb_cart_interface;
+
+
+
+//**************************************************************************
+// CLASS DECLARATIONS
+//**************************************************************************
+
+class gb_cart_slot_device_base :
+ public device_t,
+ public device_cartrom_image_interface,
+ public device_single_card_slot_interface<device_gb_cart_interface>
+{
+public:
+ // configuration
+ template <typename... T> void set_space(T &&... args) { m_space.set_tag(std::forward<T>(args)...); }
+
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override ATTR_COLD;
+ virtual void call_unload() override ATTR_COLD;
+ virtual bool is_reset_on_load() const noexcept override { return true; }
+
+protected:
+ gb_cart_slot_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock);
+
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
+
+ virtual std::pair<std::error_condition, std::string> load_image_file(util::random_read &file) = 0;
+
+ address_space &cart_space() noexcept { return *m_space; }
+
+private:
+ required_address_space m_space;
+
+ device_gb_cart_interface *m_cart;
+
+ friend class device_gb_cart_interface;
+};
+
+
+class device_gb_cart_interface : public device_interface
+{
+public:
+ virtual std::error_condition load(std::string &message) ATTR_COLD = 0;
+ virtual void unload() ATTR_COLD;
+
+protected:
+ device_gb_cart_interface(machine_config const &mconfig, device_t &device);
+
+ bool has_slot() const noexcept { return bool(m_slot); }
+ address_space *cart_space() noexcept { return m_slot ? m_slot->m_space.target() : nullptr; }
+
+ bool loaded_through_softlist() const { return m_slot && m_slot->loaded_through_softlist(); }
+ char const *get_feature(std::string_view feature_name) const { return m_slot ? m_slot->get_feature(feature_name) : nullptr; }
+
+ memory_region *cart_rom_region() { return m_slot ? m_slot->memregion("rom") : nullptr; }
+ memory_region *cart_ram_region() { return m_slot ? m_slot->memregion("ram") : nullptr; }
+ memory_region *cart_nvram_region() { return m_slot ? m_slot->memregion("nvram") : nullptr; }
+ memory_region *gbx_footer_region() { return m_slot ? m_slot->memregion("gbx") : nullptr; }
+
+ void battery_load(void *buffer, int length, int fill) { assert(m_slot); m_slot->battery_load(buffer, length, fill); }
+ void battery_load(void *buffer, int length, void *def_buffer) { assert(m_slot); m_slot->battery_load(buffer, length, def_buffer); }
+ void battery_save(void const *buffer, int length) { assert(m_slot); m_slot->battery_save(buffer, length); }
+
+private:
+ gb_cart_slot_device_base *const m_slot;
+};
+
+#endif // MAME_BUS_GAMEBOY_SLOT_H
diff --git a/src/devices/bus/gameboy/tama5.cpp b/src/devices/bus/gameboy/tama5.cpp
new file mode 100644
index 00000000000..b00db830b9e
--- /dev/null
+++ b/src/devices/bus/gameboy/tama5.cpp
@@ -0,0 +1,269 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb, Wilbert Pol
+/***************************************************************************
+
+ TAMA5 Mapper (Used by Tamagotchi 3)
+ ============
+
+ Cartridge contains the following chips:
+ * TAMA5 Game Boy bus interface
+ * TAMA6 Toshiba TMP47C243M TLCS-47 microcontroller
+ * TAMA7 mask ROM
+ * Toshiba TC8521AM real-time clock
+ * Toshiba M62021P system reset IC with switch for memory backup
+
+ The MCU acts as an interface between the TAMA5 and the RTC. The MCU can
+ drive a piezo speaker (in response to alarms from the RTC). There is a
+ mechanical switch that disconnects power from the piezo speaker. The RTC,
+ MCU and piezo speaker have backup power supplied by a user-replaceable
+ CR2016 coin cell.
+
+ The TAMA5 chip only responds to A15, A14, A0, and D3-D0, i.e. addresses are
+ effectively masked with 0xC001, and data is effectively masked with 0x0F.
+
+ Status: partially supported.
+
+ The TAMA5 mapper includes a special RTC chip which communicates through the
+ RAM area (0xA000-0xBFFF); most notably addresses 0xA000 and 0xA001 seem to
+ be used. In this setup 0xA001 acts like a control register and 0xA000 like
+ a data register.
+
+ Accepted values by the TAMA5 control register:
+ 0x00 - Writing to 0xA000 will set bits 3-0 for ROM bank selection.
+ 0x01 - Writing to 0xA000 will set bits (7-?)4 for ROM bank selection.
+
+ 0x04 - Bits 3-0 of the value to write
+ 0x05 - Bits 4-7 of the value to write
+ 0x06 - Address control hi
+ bit 0 - Bit 4 for the address
+ bit 3-1 - 000 - Write a byte to the 32 byte memory. The data to be
+ written must be set in registers 0x04 (lo nibble) and
+ 0x05 (hi nibble).
+ - 001 - Read a byte from the 32 byte memory. The data read
+ will be available in registers 0x0C (lo nibble) and
+ 0x0D (hi nibble).
+ - 010 - Unknown (occurs just after having started a game and
+ entered a date) (execution at address 1A19)
+ - 011 - Unknown (not encountered yet)
+ - 100 - Unknown (occurs during booting a game; appears to be
+ some kind of read command as it is followed by a read
+ of the 0x0C register) (execution at address 1B5B)
+ - 101 - Unknown (not encountered yet)
+ - 110 - Unknown (not encountered yet)
+ - 111 - Unknown (not encountered yet)
+ 0x07 - Address control lo
+ bit 3-0 - bits 3-0 for the address
+
+ 0x0A - After writing this the lowest 2 bits of A000 determine whether the
+ TAMA5 chip is ready to accept the next command. If the lowest 2 bits
+ hold the value 01 then the TAMA5 chip is ready for the next command.
+
+ 0x0C - Reading from A000 will return bits 3-0 of the data
+ 0x0D - Reading from A000 will return bits 7-4 of the data
+
+ 0x04 - RTC controls? -> RTC/memory?
+ 0x05 - Write time/memomry?
+ 0x06 - RTC controls?
+ 0x07 - RTC controls?
+
+ Unknown sequences:
+ During booting a game (1B5B:
+ 04 <- 00, 06 <- 08, 07 <- 01, followed by read 0C
+ when value read from 0C equals 00 followed by the sequence:
+ 04 <- 01, 06 <- 08, 07 <- 01, followed by read 0C
+ the value read from 0C is checked for non-zero, don't know the consequences for either
+ yet.
+
+ Initialization after starting a game:
+ At address 1A19:
+ 06 <- 05, 07 <- 02, followed by read 0C, if != 0F => OK, otherwise do something.
+
+ ***************************************************************************/
+
+#include "emu.h"
+#include "tama5.h"
+
+#include "cartbase.h"
+
+//#define VERBOSE 1
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+
+namespace bus::gameboy {
+
+namespace {
+
+class tama5_device : public mbc_device_base
+{
+public:
+ static constexpr feature_type unemulated_features() { return feature::SOUND; }
+
+ tama5_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+ virtual std::error_condition load(std::string &message) override ATTR_COLD;
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+private:
+ u8 data_r(address_space &space);
+ void data_w(u8 data);
+ void command_w(u8 data);
+
+ u8 m_bank_sel_rom;
+
+ u8 m_registers[0x20];
+ u8 m_response;
+ u8 m_command;
+ u8 m_data;
+ u8 m_address;
+};
+
+
+tama5_device::tama5_device(
+ machine_config const &mconfig,
+ char const *tag,
+ device_t *owner,
+ u32 clock) :
+ mbc_device_base(mconfig, GB_ROM_TAMA5, tag, owner, clock),
+ m_bank_sel_rom(0U),
+ m_response(0U),
+ m_command(0U),
+ m_data(0U),
+ m_address(0U)
+{
+}
+
+
+std::error_condition tama5_device::load(std::string &message)
+{
+ // set up ROM
+ set_bank_bits_rom(5);
+ if (!check_rom(message))
+ return image_error::BADSOFTWARE;
+ install_rom();
+
+ // install I/O
+ cart_space()->install_read_handler(0xa000, 0xa000, 0x0000, 0x1fff, 0x0000, emu::rw_delegate(*this, FUNC(tama5_device::data_r)));
+ cart_space()->install_write_handler(0xa000, 0xa000, 0x0000, 0x1ffe, 0x0000, emu::rw_delegate(*this, FUNC(tama5_device::data_w)));
+ cart_space()->install_write_handler(0xa001, 0xa001, 0x0000, 0x1ffe, 0x0000, emu::rw_delegate(*this, FUNC(tama5_device::command_w)));
+
+ // all good
+ return std::error_condition();
+}
+
+
+void tama5_device::device_start()
+{
+ mbc_device_base::device_start();
+
+ save_item(NAME(m_bank_sel_rom));
+ save_item(NAME(m_registers));
+ save_item(NAME(m_response));
+ save_item(NAME(m_command));
+ save_item(NAME(m_data));
+ save_item(NAME(m_address));
+}
+
+
+void tama5_device::device_reset()
+{
+ mbc_device_base::device_reset();
+
+ m_bank_sel_rom = 1;
+
+ std::fill(std::begin(m_registers), std::end(m_registers), 0xffU);
+ m_response = 0xffU;
+ m_command = 0x00U;
+ m_data = 0x00U;
+ m_address = 0x00U;
+
+ set_bank_rom(m_bank_sel_rom);
+}
+
+
+u8 tama5_device::data_r(address_space &space)
+{
+ return (space.unmap() & 0xf0) | (m_response & 0x0f);
+}
+
+
+void tama5_device::data_w(u8 data)
+{
+ switch (m_command)
+ {
+ case 0x00: // ROM bank low
+ m_bank_sel_rom = (m_bank_sel_rom & 0x10) | (data & 0x0f);
+ set_bank_rom(m_bank_sel_rom);
+ break;
+ case 0x01: // ROM bank high
+ m_bank_sel_rom = (m_bank_sel_rom & 0x0f) | ((data & 0x01) << 4);
+ set_bank_rom(m_bank_sel_rom);
+ break;
+ case 0x04: // value low
+ m_data = (m_data & 0xf0) | (data & 0x0f);
+ break;
+ case 0x05: // value high
+ m_data = (m_data & 0x0f) | (data << 4);
+ break;
+ case 0x06: // address high
+ m_address = (m_address & 0x0f) | (data << 4);
+ break;
+ case 0x07: // address low/trigger
+ m_address = (m_address & 0xf0) | (data & 0x0f);
+ switch (m_address & 0xe0)
+ {
+ case 0x00:
+ LOG("%s: write register 0x%02X = 0x%02X\n", machine().describe_context(), m_address & 0x1f, m_data);
+ m_registers[m_address & 0x1f] = m_data;
+ break;
+ case 0x20:
+ LOG("%s: read register 0x%02X\n", machine().describe_context(), m_address & 0x1f);
+ m_data = m_registers[m_address & 0x1f];
+ break;
+ case 0x40: // unknown - some kind of read
+ if ((m_address & 0x1f) == 0x12)
+ m_data = 0xff;
+ [[fallthrough]];
+ case 0x80: // unknown - some kind of read when 0x07=0x01, or write when 0x07=0x00 or 0x07=0x02
+ default:
+ logerror("%s: Unknown access 0x%02X = 0x%02X\n", machine().describe_context(), m_address, m_data);
+ }
+ }
+}
+
+
+void tama5_device::command_w(u8 data)
+{
+ switch (data)
+ {
+ case 0x00: // ROM bank low
+ case 0x01: // ROM bank high
+ case 0x04: // value low
+ case 0x05: // value high
+ case 0x06: // address high
+ case 0x07: // address low/trigger
+ break;
+ case 0x0a: // ready status in least significant bit
+ m_response = 0x01U;
+ break;
+ case 0x0c: // read value low
+ m_response = m_data & 0x0f;
+ break;
+ case 0x0d: // read value high
+ m_response = m_data >> 4;
+ break;
+ default:
+ logerror("%s: Unknown command 0x%02X\n", machine().describe_context(), data);
+ }
+ m_command = data;
+}
+
+} // anonymous namespace
+
+} // namespace bus::gameboy
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(GB_ROM_TAMA5, device_gb_cart_interface, bus::gameboy::tama5_device, "gb_rom_tama5", "Game Boy Bandai Tamagotchi Cartridge")
diff --git a/src/devices/bus/gameboy/tama5.h b/src/devices/bus/gameboy/tama5.h
new file mode 100644
index 00000000000..26187fcede6
--- /dev/null
+++ b/src/devices/bus/gameboy/tama5.h
@@ -0,0 +1,11 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb, Wilbert Pol
+#ifndef MAME_BUS_GAMEBOY_TAMA5_H
+#define MAME_BUS_GAMEBOY_TAMA5_H
+
+#include "slot.h"
+
+
+DECLARE_DEVICE_TYPE(GB_ROM_TAMA5, device_gb_cart_interface)
+
+#endif // MAME_BUS_GAMEBOY_TAMA5_H
diff --git a/src/devices/bus/gamegear/ggext.cpp b/src/devices/bus/gamegear/ggext.cpp
deleted file mode 100644
index dad471f1f9b..00000000000
--- a/src/devices/bus/gamegear/ggext.cpp
+++ /dev/null
@@ -1,118 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Fabio Priuli
-/**********************************************************************
-
- Sega Game Gear EXT port emulation
- Also known as Gear-to-Gear (or VS, in Japan) cable connector
-
-**********************************************************************/
-
-#include "emu.h"
-#include "screen.h"
-#include "ggext.h"
-// slot devices
-#include "smsctrladp.h"
-
-
-
-//**************************************************************************
-// GLOBAL VARIABLES
-//**************************************************************************
-
-DEFINE_DEVICE_TYPE(GG_EXT_PORT, gg_ext_port_device, "gg_ext_port", "Game Gear EXT Port")
-
-
-
-//**************************************************************************
-// CARD INTERFACE
-//**************************************************************************
-
-//-------------------------------------------------
-// device_gg_ext_port_interface - constructor
-//-------------------------------------------------
-
-device_gg_ext_port_interface::device_gg_ext_port_interface(const machine_config &mconfig, device_t &device) :
- device_interface(device, "gamegearext")
-{
- m_port = dynamic_cast<gg_ext_port_device *>(device.owner());
-}
-
-
-//-------------------------------------------------
-// ~device_gg_ext_port_interface - destructor
-//-------------------------------------------------
-
-device_gg_ext_port_interface::~device_gg_ext_port_interface()
-{
-}
-
-
-
-//**************************************************************************
-// LIVE DEVICE
-//**************************************************************************
-
-//-------------------------------------------------
-// gg_ext_port_device - constructor
-//-------------------------------------------------
-
-gg_ext_port_device::gg_ext_port_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, GG_EXT_PORT, tag, owner, clock),
- device_single_card_slot_interface<device_gg_ext_port_interface>(mconfig, *this),
- m_screen(*this, finder_base::DUMMY_TAG),
- m_device(nullptr),
- m_th_pin_handler(*this)
-{
-}
-
-
-//-------------------------------------------------
-// gg_ext_port_device - destructor
-//-------------------------------------------------
-
-gg_ext_port_device::~gg_ext_port_device()
-{
-}
-
-
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-
-void gg_ext_port_device::device_start()
-{
- m_device = get_card_device();
-
- m_th_pin_handler.resolve_safe();
-}
-
-
-uint8_t gg_ext_port_device::port_r()
-{
- uint8_t data = 0xff;
- if (m_device)
- data = m_device->peripheral_r();
- return data;
-}
-
-void gg_ext_port_device::port_w( uint8_t data )
-{
- if (m_device)
- m_device->peripheral_w(data);
-}
-
-
-void gg_ext_port_device::th_pin_w(int state)
-{
- m_th_pin_handler(state);
-}
-
-
-//-------------------------------------------------
-// SLOT_INTERFACE( gg_ext_port_devices )
-//-------------------------------------------------
-
-void gg_ext_port_devices(device_slot_interface &device)
-{
- device.option_add("smsctrladp", SMS_CTRL_ADAPTOR);
-}
diff --git a/src/devices/bus/gamegear/ggext.h b/src/devices/bus/gamegear/ggext.h
deleted file mode 100644
index 04d802eca02..00000000000
--- a/src/devices/bus/gamegear/ggext.h
+++ /dev/null
@@ -1,109 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Fabio Priuli
-/**********************************************************************
-
- Sega Game Gear EXT port emulation
- Also known as Gear-to-Gear (or VS, in Japan) cable connector
-
-**********************************************************************
-
-
-**********************************************************************/
-
-#ifndef MAME_BUS_GAMEGEAR_GGEXT_H
-#define MAME_BUS_GAMEGEAR_GGEXT_H
-
-#pragma once
-
-
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-// ======================> gg_ext_port_device
-
-class device_gg_ext_port_interface;
-
-class gg_ext_port_device : public device_t, public device_single_card_slot_interface<device_gg_ext_port_interface>
-{
-public:
- // construction/destruction
- template <typename T>
- gg_ext_port_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts, char const *dflt)
- : gg_ext_port_device(mconfig, tag, owner, 0)
- {
- option_reset();
- opts(*this);
- set_default_option(dflt);
- set_fixed(false);
- }
-
- gg_ext_port_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
- virtual ~gg_ext_port_device();
-
- // static configuration helpers
- auto th_input_handler() { return m_th_pin_handler.bind(); }
-
- // Currently, only the support for SMS Controller Adaptor is emulated,
- // for when SMS Compatibility mode is enabled. In that mode, the 10 pins
- // of the EXT port follows the same numbering of a SMS Control port.
-
- // Data returned by the port_r methods:
- // bit 0 - pin 1 - Up
- // bit 1 - pin 2 - Down
- // bit 2 - pin 3 - Left
- // bit 3 - pin 4 - Right
- // bit 4 - pin 5 - Vcc (no data)
- // bit 5 - pin 6 - TL (Button 1/Light Phaser Trigger)
- // bit 6 - pin 7 - TH (Light Phaser sensor)
- // pin 8 - GND
- // bit 7 - pin 9 - TR (Button 2)
- // pin 10 - Not connected
- //
- uint8_t port_r();
- void port_w( uint8_t data );
-
- void th_pin_w(int state);
-
- template <typename T> void set_screen_tag(T &&tag) { m_screen.set_tag(std::forward<T>(tag)); }
-
- // for peripherals that interact with the machine's screen
- required_device<screen_device> m_screen;
-
-//protected:
- // device-level overrides
- virtual void device_start() override;
-
- device_gg_ext_port_interface *m_device;
-
-private:
- devcb_write_line m_th_pin_handler;
-};
-
-
-// ======================> device_gg_ext_port_interface
-
-// class representing interface-specific live sms_expansion card
-class device_gg_ext_port_interface : public device_interface
-{
-public:
- // construction/destruction
- virtual ~device_gg_ext_port_interface();
-
- virtual uint8_t peripheral_r() { return 0xff; }
- virtual void peripheral_w(uint8_t data) { }
-
-protected:
- device_gg_ext_port_interface(const machine_config &mconfig, device_t &device);
-
- gg_ext_port_device *m_port;
-};
-
-
-// device type definition
-DECLARE_DEVICE_TYPE(GG_EXT_PORT, gg_ext_port_device)
-
-
-void gg_ext_port_devices(device_slot_interface &device);
-
-#endif // MAME_BUS_GAMEGEAR_GGEXT_H
diff --git a/src/devices/bus/gamegear/smsctrladp.h b/src/devices/bus/gamegear/smsctrladp.h
deleted file mode 100644
index 46646bde0f0..00000000000
--- a/src/devices/bus/gamegear/smsctrladp.h
+++ /dev/null
@@ -1,54 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Fabio Priuli
-/**********************************************************************
-
- Sega Game Gear "SMS Controller Adaptor" emulation
- Also known as "Master Link" cable.
-
-**********************************************************************/
-
-#ifndef MAME_BUS_GAMEGEAR_SMSCRTLADP_H
-#define MAME_BUS_GAMEGEAR_SMSCRTLADP_H
-
-#pragma once
-
-
-#include "ggext.h"
-#include "bus/sms_ctrl/smsctrl.h"
-
-
-
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-// ======================> sms_ctrl_adaptor_device
-
-class sms_ctrl_adaptor_device : public device_t,
- public device_gg_ext_port_interface
-{
-public:
- // construction/destruction
- sms_ctrl_adaptor_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_add_mconfig(machine_config &config) override;
-
- // device_gg_ext_port_interface overrides
- virtual uint8_t peripheral_r() override;
- virtual void peripheral_w(uint8_t data) override;
-
-private:
- DECLARE_WRITE_LINE_MEMBER(th_pin_w);
-
- required_device<sms_control_port_device> m_subctrl_port;
-};
-
-
-// device type definition
-DECLARE_DEVICE_TYPE(SMS_CTRL_ADAPTOR, sms_ctrl_adaptor_device)
-
-
-#endif // MAME_BUS_GAMEGEAR_SMSCRTLADP_H
diff --git a/src/devices/bus/gba/gba_slot.cpp b/src/devices/bus/gba/gba_slot.cpp
index d4630c9c325..e36c7a2650d 100644
--- a/src/devices/bus/gba/gba_slot.cpp
+++ b/src/devices/bus/gba/gba_slot.cpp
@@ -504,11 +504,11 @@ void device_gba_cart_interface::rom_alloc(uint32_t size, const char *tag)
{
if (size < 0x4000000)
// we always alloc 32MB of rom region!
- m_rom = (uint32_t *)device().machine().memory().region_alloc(std::string(tag).append(GBASLOT_ROM_REGION_TAG).c_str(), 0x2000000, 4, ENDIANNESS_LITTLE)->base();
+ m_rom = (uint32_t *)device().machine().memory().region_alloc(std::string(tag).append(GBASLOT_ROM_REGION_TAG), 0x2000000, 4, ENDIANNESS_LITTLE)->base();
else
{
- m_rom = (uint32_t *)device().machine().memory().region_alloc(std::string(tag).append(GBASLOT_ROM_REGION_TAG).c_str(), 0x4000000, 4, ENDIANNESS_LITTLE)->base();
- m_romhlp = (uint32_t *)device().machine().memory().region_alloc(std::string(tag).append(GBAHELP_ROM_REGION_TAG).c_str(), 0x2000000, 4, ENDIANNESS_LITTLE)->base();
+ m_rom = (uint32_t *)device().machine().memory().region_alloc(std::string(tag).append(GBASLOT_ROM_REGION_TAG), 0x4000000, 4, ENDIANNESS_LITTLE)->base();
+ m_romhlp = (uint32_t *)device().machine().memory().region_alloc(std::string(tag).append(GBAHELP_ROM_REGION_TAG), 0x2000000, 4, ENDIANNESS_LITTLE)->base();
}
m_rom_size = size;
}
@@ -617,20 +617,16 @@ static const char *gba_get_slot(int type)
call load
-------------------------------------------------*/
-image_init_result gba_cart_slot_device::call_load()
+std::pair<std::error_condition, std::string> gba_cart_slot_device::call_load()
{
if (m_cart)
{
- uint8_t *ROM;
- uint32_t size = loaded_through_softlist() ? get_software_region_length("rom") : length();
- if (size > 0x4000000)
- {
- seterror(image_error::INVALIDIMAGE, "Attempted loading a cart larger than 64MB");
- return image_init_result::FAIL;
- }
+ uint32_t const size = loaded_through_softlist() ? get_software_region_length("rom") : length();
+ if (size > 0x400'0000)
+ return std::make_pair(image_error::INVALIDLENGTH, "Cartridges larger than 64MB are not supported");
m_cart->rom_alloc(size, tag());
- ROM = (uint8_t *)m_cart->get_rom_base();
+ uint8_t *const ROM = (uint8_t *)m_cart->get_rom_base();
if (!loaded_through_softlist())
{
@@ -670,9 +666,9 @@ image_init_result gba_cart_slot_device::call_load()
memcpy(ROM + 0x1000000, ROM, 0x1000000);
break;
}
- if (size == 0x4000000)
+ if (size == 0x400'0000)
{
- memcpy((uint8_t *)m_cart->get_romhlp_base(), ROM, 0x2000000);
+ memcpy(m_cart->get_romhlp_base(), ROM, 0x2000000);
for (uint32_t i = 0; i < 16; i++)
{
memcpy((uint8_t *)m_cart->get_romhlp_base() + i * 0x1000, ROM + 0x200, 0x1000);
@@ -682,11 +678,9 @@ image_init_result gba_cart_slot_device::call_load()
if (m_cart->get_nvram_size())
battery_load(m_cart->get_nvram_base(), m_cart->get_nvram_size(), 0x00);
-
- return image_init_result::PASS;
}
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
@@ -887,8 +881,7 @@ std::string gba_cart_slot_device::get_default_card_software(get_default_card_sof
hook.image_file()->length(len); // FIXME: check error return, guard against excessively large files
std::vector<uint8_t> rom(len);
- size_t actual;
- hook.image_file()->read(&rom[0], len, actual); // FIXME: check error return or read returning short
+ read(*hook.image_file(), &rom[0], len); // FIXME: check error return or read returning short
int const type = get_cart_type(&rom[0], len);
char const *const slot_string = gba_get_slot(type);
diff --git a/src/devices/bus/gba/gba_slot.h b/src/devices/bus/gba/gba_slot.h
index 70fad8e4581..0a7e66ca957 100644
--- a/src/devices/bus/gba/gba_slot.h
+++ b/src/devices/bus/gba/gba_slot.h
@@ -97,15 +97,15 @@ public:
gba_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
virtual ~gba_cart_slot_device();
- // image-level overrides
- virtual image_init_result call_load() override;
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
virtual void call_unload() override;
virtual bool is_reset_on_load() const noexcept override { return true; }
virtual const char *image_interface() const noexcept override { return "gba_cart"; }
virtual const char *file_extensions() const noexcept override { return "gba,bin"; }
- // slot interface overrides
+ // device_slot_interface implementation
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
int get_type() { return m_type; }
@@ -125,7 +125,7 @@ public:
virtual void write_mapper(offs_t offset, uint32_t data) { if (m_cart) m_cart->write_mapper(offset, data); }
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
int m_type;
diff --git a/src/devices/bus/generic/slot.cpp b/src/devices/bus/generic/slot.cpp
index 73a47bfd0e0..f2e86809a66 100644
--- a/src/devices/bus/generic/slot.cpp
+++ b/src/devices/bus/generic/slot.cpp
@@ -95,7 +95,7 @@ void device_generic_cart_interface::rom_alloc(u32 size, int width, endianness_t
std::string fulltag(tag);
fulltag.append(GENERIC_ROM_REGION_TAG);
device().logerror("Allocating %u byte ROM region with tag '%s' (width %d)\n", size, fulltag, width);
- m_rom = device().machine().memory().region_alloc(fulltag.c_str(), size, width, endian)->base();
+ m_rom = device().machine().memory().region_alloc(fulltag, size, width, endian)->base();
m_rom_size = size;
}
@@ -148,6 +148,14 @@ generic_slot_device::~generic_slot_device()
{
}
+generic_socket_device::~generic_socket_device()
+{
+}
+
+generic_cartslot_device::~generic_cartslot_device()
+{
+}
+
void generic_slot_device::device_start()
{
m_cart = get_card_device();
@@ -160,24 +168,25 @@ void generic_slot_device::device_start()
call load
-------------------------------------------------*/
-image_init_result generic_slot_device::call_load()
+std::pair<std::error_condition, std::string> generic_slot_device::call_load()
{
- if (m_cart)
+ if (!m_cart)
{
- if (!m_device_image_load.isnull())
- return m_device_image_load(*this);
- else
- {
- u32 len = common_get_size("rom");
+ return std::make_pair(std::error_condition(), std::string());
+ }
+ else if (!m_device_image_load.isnull())
+ {
+ return m_device_image_load(*this);
+ }
+ else
+ {
+ u32 const len = common_get_size("rom");
- rom_alloc(len, m_width, m_endianness);
- common_load_rom(get_rom_base(), len, "rom");
+ rom_alloc(len, m_width, m_endianness);
+ common_load_rom(get_rom_base(), len, "rom");
- return image_init_result::PASS;
- }
+ return std::make_pair(std::error_condition(), std::string());
}
-
- return image_init_result::PASS;
}
diff --git a/src/devices/bus/generic/slot.h b/src/devices/bus/generic/slot.h
index da1e7e21988..06bab9424cc 100644
--- a/src/devices/bus/generic/slot.h
+++ b/src/devices/bus/generic/slot.h
@@ -10,9 +10,20 @@
#include <cassert>
-/***************************************************************************
- TYPE DEFINITIONS
- ***************************************************************************/
+//**************************************************************************
+// MACROS
+//**************************************************************************
+
+#define DEVICE_IMAGE_LOAD_MEMBER(_name) std::pair<std::error_condition, std::string> _name(device_image_interface &image)
+#define DECLARE_DEVICE_IMAGE_LOAD_MEMBER(_name) DEVICE_IMAGE_LOAD_MEMBER(_name)
+
+#define DEVICE_IMAGE_UNLOAD_MEMBER(_name) void _name(device_image_interface &image)
+#define DECLARE_DEVICE_IMAGE_UNLOAD_MEMBER(_name) DEVICE_IMAGE_UNLOAD_MEMBER(_name)
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
class device_generic_cart_interface : public device_interface
{
@@ -52,6 +63,65 @@ public:
}
}
+ // TODO: find a better home for this helper
+ template <unsigned Shift, typename T>
+ static void install_non_power_of_two(
+ offs_t length,
+ offs_t decode_limit,
+ offs_t decode_offset,
+ offs_t base,
+ T &&install)
+ {
+ offs_t decode_mask(length - 1);
+ for (unsigned i = 31 - count_leading_zeros_32(decode_mask); 0U < i; --i)
+ {
+ if (!BIT(decode_mask, i - 1))
+ {
+ decode_mask &= ~((offs_t(1) << i) - 1);
+ break;
+ }
+ }
+ install_non_power_of_two<Shift, T>(
+ length,
+ decode_limit,
+ decode_mask,
+ decode_offset,
+ base,
+ std::forward<T>(install));
+ }
+
+ // TODO: find a better home for this helper
+ template <typename T, typename U>
+ static T map_non_power_of_two(T count, U &&map)
+ {
+ if (T(0) >= count)
+ return T(0);
+
+ T const max(count - 1);
+ T mask(max);
+ for (unsigned i = 1U; (sizeof(T) * 8) > i; i <<= 1)
+ mask = T(std::make_unsigned_t<T>(mask) | (std::make_unsigned_t<T>(mask) >> i));
+ int bits(0);
+ while (BIT(mask, bits))
+ ++bits;
+
+ for (T entry = T(0); mask >= entry; ++entry)
+ {
+ T mapped(entry);
+ int b(bits - 1);
+ while (max < mapped)
+ {
+ while (BIT(max, b))
+ --b;
+ assert(0 <= b);
+ mapped = T(std::make_unsigned_t<T>(mapped) & ~(std::make_unsigned_t<T>(1) << b--));
+ }
+ map(entry, mapped);
+ }
+
+ return mask;
+ }
+
// construction/destruction
virtual ~device_generic_cart_interface();
@@ -106,6 +176,9 @@ class generic_slot_device : public device_t,
public device_single_card_slot_interface<device_generic_cart_interface>
{
public:
+ typedef device_delegate<std::pair<std::error_condition, std::string> (device_image_interface &)> load_delegate;
+ typedef device_delegate<void (device_image_interface &)> unload_delegate;
+
virtual ~generic_slot_device();
template <typename... T> void set_device_load(T &&... args) { m_device_image_load.set(std::forward<T>(args)...); }
@@ -118,7 +191,7 @@ public:
void set_endian(endianness_t end) { m_endianness = end; }
// device_image_interface implementation
- virtual image_init_result call_load() override;
+ virtual std::pair<std::error_condition, std::string> call_load() override;
virtual void call_unload() override;
virtual bool is_reset_on_load() const noexcept override { return true; }
virtual char const *image_interface() const noexcept override { return m_interface; }
@@ -194,6 +267,7 @@ public:
}
generic_socket_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock = 0);
+ virtual ~generic_socket_device();
virtual const char *image_type_name() const noexcept override { return "romimage"; }
virtual const char *image_brief_type_name() const noexcept override { return "rom"; }
@@ -214,6 +288,7 @@ public:
}
generic_cartslot_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock = 0);
+ virtual ~generic_cartslot_device();
virtual const char *image_type_name() const noexcept override { return "cartridge"; }
virtual const char *image_brief_type_name() const noexcept override { return "cart"; }
diff --git a/src/devices/bus/gio64/gio64.cpp b/src/devices/bus/gio64/gio64.cpp
index 589e2fdf6d7..ccd309251eb 100644
--- a/src/devices/bus/gio64/gio64.cpp
+++ b/src/devices/bus/gio64/gio64.cpp
@@ -73,11 +73,6 @@ gio64_device::gio64_device(const machine_config &mconfig, device_type type, cons
{
}
-void gio64_device::device_resolve_objects()
-{
- m_interrupt_cb.resolve_all_safe();
-}
-
void gio64_device::device_start()
{
std::fill(std::begin(m_device_list), std::end(m_device_list), nullptr);
diff --git a/src/devices/bus/gio64/gio64.h b/src/devices/bus/gio64/gio64.h
index df99dc70dd9..486f419ca25 100644
--- a/src/devices/bus/gio64/gio64.h
+++ b/src/devices/bus/gio64/gio64.h
@@ -37,7 +37,7 @@ public:
gio64_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, slot_type_t slot_type = GIO64_SLOT_EXP0);
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_validity_check(validity_checker &valid) const override;
virtual void device_resolve_objects() override;
virtual void device_start() override;
@@ -107,7 +107,7 @@ public:
}
}
- template <int N> DECLARE_WRITE_LINE_MEMBER(interrupt) { m_interrupt_cb[N](state); }
+ template <int N> void interrupt(int state) { m_interrupt_cb[N](state); }
u64 read(offs_t offset, u64 mem_mask);
void write(offs_t offset, u64 data, u64 mem_mask);
@@ -115,8 +115,7 @@ public:
protected:
gio64_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
- // device-level overrides
- virtual void device_resolve_objects() override;
+ // device_t implementation
virtual void device_start() override;
// internal state
diff --git a/src/devices/bus/gio64/newport.cpp b/src/devices/bus/gio64/newport.cpp
index ab796ba3645..9a644c89c6c 100644
--- a/src/devices/bus/gio64/newport.cpp
+++ b/src/devices/bus/gio64/newport.cpp
@@ -37,14 +37,14 @@
#include "emu.h"
#include "newport.h"
-#define LOG_UNKNOWN (1 << 0)
-#define LOG_VC2 (1 << 1)
-#define LOG_CMAP (1 << 2)
-#define LOG_XMAP (1 << 4)
-#define LOG_REX3 (1 << 6)
-#define LOG_RAMDAC (1 << 7)
-#define LOG_COMMANDS (1 << 8)
-#define LOG_REJECTS (1 << 9)
+#define LOG_UNKNOWN (1U << 1)
+#define LOG_VC2 (1U << 2)
+#define LOG_CMAP (1U << 3)
+#define LOG_XMAP (1U << 4)
+#define LOG_REX3 (1U << 5)
+#define LOG_RAMDAC (1U << 6)
+#define LOG_COMMANDS (1U << 7)
+#define LOG_REJECTS (1U << 8)
#define LOG_ALL (LOG_UNKNOWN | LOG_VC2 | LOG_CMAP | LOG_XMAP | LOG_REX3 | LOG_RAMDAC | LOG_COMMANDS | LOG_REJECTS)
#define VERBOSE (0)
@@ -306,9 +306,6 @@ vc2_device::vc2_device(const machine_config &mconfig, const char *tag, device_t
void vc2_device::device_start()
{
- m_vert_int.resolve_safe();
- m_screen_timing_changed.resolve_safe();
-
m_ram = std::make_unique<uint16_t[]>(RAM_SIZE);
m_vt_table = make_unique_clear<uint32_t[]>(2048 * 2048);
@@ -816,7 +813,7 @@ uint8_t vc2_device::get_cursor_pixel(int x, int y)
}
}
-WRITE_LINE_MEMBER(vc2_device::vblank_w)
+void vc2_device::vblank_w(int state)
{
if (state)
{
@@ -913,7 +910,8 @@ void rb2_device::deserialize(FILE *file)
uint32_t rb2_device::expand_to_all_lanes(uint32_t src)
{
- switch (m_draw_depth) {
+ switch (m_draw_depth)
+ {
case 0:
src |= src << 4;
src |= src << 8;
@@ -1091,7 +1089,7 @@ newport_base_device::newport_base_device(const machine_config &mconfig, device_t
, m_draw_flags_w(*this)
, m_set_address(*this)
, m_write_pixel(*this)
- , m_read_pixel(*this)
+ , m_read_pixel(*this, 0)
{
}
@@ -1202,12 +1200,6 @@ void newport_base_device::device_start()
save_item(NAME(m_ramdac_lut_g));
save_item(NAME(m_ramdac_lut_b));
save_item(NAME(m_ramdac_lut_index));
-
- m_write_mask_w.resolve_safe();
- m_draw_flags_w.resolve_safe();
- m_set_address.resolve_safe();
- m_write_pixel.resolve_safe();
- m_read_pixel.resolve_safe(0);
}
//-------------------------------------------------
@@ -1705,7 +1697,7 @@ void newport_base_device::ramdac_write(uint32_t data)
}
}
-WRITE_LINE_MEMBER(newport_base_device::vrint_w)
+void newport_base_device::vrint_w(int state)
{
if (state)
{
@@ -1715,7 +1707,7 @@ WRITE_LINE_MEMBER(newport_base_device::vrint_w)
}
// TOOD: Figure out a better way of doing this
-WRITE_LINE_MEMBER(newport_base_device::update_screen_size)
+void newport_base_device::update_screen_size(int state)
{
const int x_start = m_vc2->readout_x0();
const int y_start = m_vc2->readout_y0();
@@ -2700,28 +2692,58 @@ uint32_t newport_base_device::get_rgb_color(int16_t x, int16_t y)
uint8_t newport_base_device::get_octant(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t dx, int32_t dy)
{
- if (x1 < x2)
- {
- if (y2 < y1)
- return (dx > dy) ? 0 : 1;
- else
- return (dx > dy) ? 7 : 6;
- }
- else
- {
- if (y2 < y1)
- return (dx > dy) ? 3 : 2;
- else
- return (dx > dy) ? 4 : 5;
- }
+ uint8_t octant = 0;
+
+ // Octant format: {MSB, 2nd, LSB} = {XMAJOR, XDEC, YDEC}
+ // Mapping of hardware octant to peseudocode octant in manual
+ // | Pseudocode | hardware | hardware(dec) |
+ // | 1 | 3'b101 | 5 |
+ // | 2 | 3'b001 | 1 |
+ // | 3 | 3'b011 | 3 |
+ // | 4 | 3'b111 | 7 |
+ // | 5 | 3'b110 | 6 |
+ // | 6 | 3'b010 | 2 |
+ // | 7 | 3'b000 | 0 |
+ // | 8 | 3'b100 | 4 |
+
+ /* YDEC */
+ if (y1 > y2)
+ octant |= (1 << 0); // Bit 0
+
+ /* XDEC */
+ if (x1 > x2)
+ octant |= (1 << 1); // Bit 1
+
+ /* XMAJOR */
+ if (dx > dy)
+ octant |= (1 << 2); // Bit 2
+
+ return octant;
+}
+
+void newport_base_device::do_setup(void)
+{
+ const int32_t x1 = util::sext(m_rex3.m_x_start >> 7, 20);
+ const int32_t y1 = util::sext(m_rex3.m_y_start >> 7, 20);
+ const int32_t x2 = util::sext(m_rex3.m_x_end >> 7, 20);
+ const int32_t y2 = util::sext(m_rex3.m_y_end >> 7, 20);
+ const int32_t dx = abs(x1 - x2);
+ const int32_t dy = abs(y1 - y2);
+
+ /* octant for line and block, span */
+ const uint8_t octant = get_octant(x1, y1, x2, y2, dx, dy);
+ m_rex3.m_bres_octant_inc1 &= ~(0x7 << 24);
+ m_rex3.m_bres_octant_inc1 |= (uint32_t)octant << 24;
+ /* FIXME: error terms (incr1, incr2) and Bresenham terms (d) */
+ LOGMASKED(LOG_REX3, "do_setup: octant = %d, x1 = %d, y1 = %d, x2 = %d, y2 = %d, dx = %d, dy = %d\n", octant, x1, y1, x2, y2, dx, dy);
}
void newport_base_device::do_fline(uint32_t color)
{
- const int32_t x1 = (int32_t)((m_rex3.m_x_start >> 7) << 12) >> 12;
- const int32_t y1 = (int32_t)((m_rex3.m_y_start >> 7) << 12) >> 12;
- const int32_t x2 = (int32_t)((m_rex3.m_x_end >> 7) << 12) >> 12;
- const int32_t y2 = (int32_t)((m_rex3.m_y_end >> 7) << 12) >> 12;
+ const int32_t x1 = util::sext(m_rex3.m_x_start >> 7, 20);
+ const int32_t y1 = util::sext(m_rex3.m_y_start >> 7, 20);
+ const int32_t x2 = util::sext(m_rex3.m_x_end >> 7, 20);
+ const int32_t y2 = util::sext(m_rex3.m_y_end >> 7, 20);
const int32_t x10 = x1 & ~0xf;
const int32_t y10 = y1 & ~0xf;
@@ -2748,17 +2770,17 @@ void newport_base_device::do_fline(uint32_t color)
static const bresenham_octant_info_t s_bresenham_infos[8] =
{
- { 1, 1, 0, 1, 0 },
- { 0, 1, 1, 1, 1 },
- { 0, -1, 1, 1, 1 },
- { -1, -1, 0, 1, 0 },
- { -1, -1, 0, -1, 0 },
- { 0, -1, -1, -1, 1 },
- { 0, 1, -1, -1, 1 },
- { 1, 1, 0, -1, 0 }
+ { 0, 1, -1, -1, 1 }, // Pseudo 7
+ { 0, 1, 1, 1, 1 }, // Pseudo 2
+ { 0, -1, -1, -1, 1 }, // Pseudo 6
+ { 0, -1, 1, 1, 1 }, // Pseudo 3
+ { 1, 1, 0, -1, 0 }, // Pseudo 8
+ { 1, 1, 0, 1, 0 }, // Pseudo 1
+ { -1, -1, 0, -1, 0 }, // Pseudo 5
+ { -1, -1, 0, 1, 0 } // Pseudo 4
};
- const uint8_t octant = get_octant(x1, y1, x2, y2, dx, dy);
+ const uint8_t octant = (m_rex3.m_bres_octant_inc1 >> 24) & 0x7;
const int32_t incrx1 = s_bresenham_infos[octant].incrx1;
const int32_t incrx2 = s_bresenham_infos[octant].incrx2;
const int32_t incry1 = s_bresenham_infos[octant].incry1;
@@ -2774,10 +2796,10 @@ void newport_base_device::do_fline(uint32_t color)
switch (octant)
{
- case 0:
+ case 5: // Pseudo 1
// Nothing special needed
break;
- case 1:
+ case 1: // Pseudo 2
{
const int16_t temp_fract = x1_fract;
x1_fract = y1_fract;
@@ -2787,7 +2809,7 @@ void newport_base_device::do_fline(uint32_t color)
dy = temp_d;
break;
}
- case 2:
+ case 3: // Pseudo 3
{
const int16_t temp_fract = 0x10 - x1_fract;
x1_fract = y1_fract;
@@ -2797,14 +2819,14 @@ void newport_base_device::do_fline(uint32_t color)
dy = temp_d;
break;
}
- case 3:
+ case 7: // Pseudo 4
x1_fract = 0x10 - x1_fract;
break;
- case 4:
+ case 6: // Pseudo 5
x1_fract = 0x10 - x1_fract;
y1_fract = 0x10 - y1_fract;
break;
- case 5:
+ case 2: // Pseudo 6
{
const int16_t temp_fract = 0x10 - x1_fract;
x1_fract = 0x10 - y1_fract;
@@ -2814,7 +2836,7 @@ void newport_base_device::do_fline(uint32_t color)
dy = temp_d;
break;
}
- case 6:
+ case 0: // Pseudo 7
{
const int16_t temp_fract = 0x10 - y1_fract;
y1_fract = x1_fract;
@@ -2824,7 +2846,7 @@ void newport_base_device::do_fline(uint32_t color)
dy = temp_d;
break;
}
- case 7:
+ case 4: // Pseudo 8
y1_fract = 0x10 - y1_fract;
break;
}
@@ -2939,17 +2961,17 @@ void newport_base_device::do_iline(uint32_t color)
static const bresenham_octant_info_t s_bresenham_infos[8] =
{
- { 1, 1, 0, 1, 0 },
- { 0, 1, 1, 1, 1 },
- { 0, -1, 1, 1, 1 },
- { -1, -1, 0, 1, 0 },
- { -1, -1, 0, -1, 0 },
- { 0, -1, -1, -1, 1 },
- { 0, 1, -1, -1, 1 },
- { 1, 1, 0, -1, 0 }
+ { 0, 1, -1, -1, 1 }, // Pseudo 7
+ { 0, 1, 1, 1, 1 }, // Pseudo 2
+ { 0, -1, -1, -1, 1 }, // Pseudo 6
+ { 0, -1, 1, 1, 1 }, // Pseudo 3
+ { 1, 1, 0, -1, 0 }, // Pseudo 8
+ { 1, 1, 0, 1, 0 }, // Pseudo 1
+ { -1, -1, 0, -1, 0 }, // Pseudo 5
+ { -1, -1, 0, 1, 0 } // Pseudo 4
};
- const uint8_t octant = get_octant(x1, y1, x2, y2, dx, dy);
+ const uint8_t octant = (m_rex3.m_bres_octant_inc1 >> 24) & 0x7;
const int32_t incrx1 = s_bresenham_infos[octant].incrx1;
const int32_t incrx2 = s_bresenham_infos[octant].incrx2;
const int32_t incry1 = s_bresenham_infos[octant].incry1;
@@ -3048,7 +3070,6 @@ void newport_base_device::do_iline(uint32_t color)
uint32_t newport_base_device::do_pixel_read()
{
- m_rex3.m_bres_octant_inc1 = 0;
const int16_t src_x = m_rex3.m_x_start_i + m_rex3.m_x_window - 0x1000;
const int16_t src_y = m_rex3.m_y_start_i + m_rex3.m_y_window - 0x1000;
uint32_t ret = 0;
@@ -3191,13 +3212,13 @@ uint64_t newport_base_device::do_pixel_word_read()
void newport_base_device::iterate_shade()
{
if (m_rex3.m_slope_red & 0x7fffff)
- m_rex3.m_curr_color_red += (m_rex3.m_slope_red << 8) >> 8;
+ m_rex3.m_curr_color_red += util::sext(m_rex3.m_slope_red, 24);
if (m_rex3.m_slope_green & 0x7ffff)
- m_rex3.m_curr_color_green += (m_rex3.m_slope_green << 12) >> 12;
+ m_rex3.m_curr_color_green += util::sext(m_rex3.m_slope_green, 20);
if (m_rex3.m_slope_blue & 0x7ffff)
- m_rex3.m_curr_color_blue += (m_rex3.m_slope_blue << 12) >> 12;
+ m_rex3.m_curr_color_blue += util::sext(m_rex3.m_slope_blue, 20);
if (m_rex3.m_slope_alpha & 0x7ffff)
- m_rex3.m_curr_color_alpha += (m_rex3.m_slope_alpha << 12) >> 12;
+ m_rex3.m_curr_color_alpha += util::sext(m_rex3.m_slope_alpha, 20);
if (BIT(m_rex3.m_draw_mode0, 21)) // CIClamp
{
@@ -3297,10 +3318,10 @@ void newport_base_device::do_rex3_command()
int16_t start_y = m_rex3.m_y_start_i;
int16_t end_x = m_rex3.m_x_end_i;
int16_t end_y = m_rex3.m_y_end_i;
- int16_t dx = start_x > end_x ? -1 : 1;
- int16_t dy = start_y > end_y ? -1 : 1;
+ int16_t dx = 1, dy = 1;
+ int8_t octant;
- LOGMASKED(LOG_COMMANDS, "REX3 Command: %08x|%08x - %s %s\n", mode0, mode1, s_opcode_str[mode0 & 3], s_adrmode_str[(mode0 >> 2) & 7]);
+ LOGMASKED(LOG_COMMANDS, "REX3 Command: %08x|%08x - %s %s %s\n", mode0, mode1, s_opcode_str[mode0 & 3], s_adrmode_str[(mode0 >> 2) & 7], BIT(mode0, 5) ? "Setup" : "NoSetup");
const uint8_t opcode = mode0 & 3;
const uint8_t adrmode = (mode0 >> 2) & 7;
@@ -3310,9 +3331,18 @@ void newport_base_device::do_rex3_command()
case 0: // NoOp
break;
case 1: // Read
+ if (BIT(mode0, 5))
+ do_setup();
+ // Our do_pixel_word_read does not use octant, but seems like hardware is still updating it
m_rex3.m_host_dataport = do_pixel_word_read();
break;
case 2: // Draw
+ if (BIT(mode0, 5))
+ do_setup();
+ octant = (m_rex3.m_bres_octant_inc1 >> 24) & 0x7;
+ dx = BIT(octant, 1) ? -1 : 1;
+ dy = BIT(octant, 0) ? -1 : 1;
+
switch (adrmode)
{
case 0: // Span
@@ -3483,6 +3513,12 @@ void newport_base_device::do_rex3_command()
const bool stop_on_x = BIT(mode0, 8);
const bool stop_on_y = BIT(mode0, 9);
+ if (BIT(mode0, 5))
+ do_setup();
+ octant = (m_rex3.m_bres_octant_inc1 >> 24) & 0x7;
+ dx = BIT(octant, 1) ? -1 : 1;
+ dy = BIT(octant, 0) ? -1 : 1;
+
end_x += dx;
end_y += dy;
@@ -3898,6 +3934,7 @@ void newport_base_device::rex3_w(offs_t offset, uint64_t data, uint64_t mem_mask
{
LOGMASKED(LOG_REX3, "REX3 Line/Span Setup Write: %08x\n", (uint32_t)(data >> 32));
m_rex3.m_setup = (uint32_t)(data >> 32);
+ do_setup();
}
if (ACCESSING_BITS_0_31)
{
diff --git a/src/devices/bus/gio64/newport.h b/src/devices/bus/gio64/newport.h
index 101ca7a6e61..61df96dbe8f 100644
--- a/src/devices/bus/gio64/newport.h
+++ b/src/devices/bus/gio64/newport.h
@@ -102,7 +102,7 @@ private:
virtual void device_reset() override;
// device_palette_interface overrides
- virtual uint32_t palette_entries() const override { return 0x2000; }
+ virtual uint32_t palette_entries() const noexcept override { return 0x2000; }
// Initializers
void set_revision(uint32_t revision) { m_revision = revision; }
@@ -139,7 +139,7 @@ public:
uint16_t next_did_line_entry();
uint8_t get_cursor_pixel(int x, int y);
- DECLARE_WRITE_LINE_MEMBER(vblank_w);
+ void vblank_w(int state);
auto vert_int() { return m_vert_int.bind(); }
auto screen_timing_changed() { return m_screen_timing_changed.bind(); } // Hack. TODO: Figure out a better way
@@ -297,8 +297,8 @@ public:
uint32_t screen_update(screen_device &device, bitmap_rgb32 &bitmap, const rectangle &cliprect);
- DECLARE_WRITE_LINE_MEMBER(vrint_w);
- DECLARE_WRITE_LINE_MEMBER(update_screen_size);
+ void vrint_w(int state);
+ void update_screen_size(int state);
auto write_mask() { return m_write_mask_w.bind(); }
auto draw_flags() { return m_draw_flags_w.bind(); }
@@ -484,6 +484,7 @@ protected:
uint8_t loop;
};
uint8_t get_octant(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t dx, int32_t dy);
+ void do_setup();
void do_fline(uint32_t color);
void do_iline(uint32_t color);
diff --git a/src/devices/bus/hexbus/hexbus.cpp b/src/devices/bus/hexbus/hexbus.cpp
index 40189262457..110739b5fcf 100644
--- a/src/devices/bus/hexbus/hexbus.cpp
+++ b/src/devices/bus/hexbus/hexbus.cpp
@@ -150,10 +150,10 @@
// Devices
#include "hx5102.h"
-#define LOG_LINES (1U<<1) // Line changes
-#define LOG_ENABLED (1U<<2) // Enabled
+#define LOG_LINES (1U << 1) // Line changes
+#define LOG_ENABLED (1U << 2) // Enabled
-#define VERBOSE ( LOG_GENERAL )
+#define VERBOSE (LOG_GENERAL)
#include "logmacro.h"
diff --git a/src/devices/bus/hexbus/hexbus.h b/src/devices/bus/hexbus/hexbus.h
index 1d225c55749..34bbea63193 100644
--- a/src/devices/bus/hexbus/hexbus.h
+++ b/src/devices/bus/hexbus/hexbus.h
@@ -161,7 +161,7 @@ public:
void write(int dir, uint8_t data);
protected:
- void device_start() override;
+ virtual void device_start() override;
device_hexbus_interface *m_next_dev;
private:
diff --git a/src/devices/bus/hexbus/hx5102.cpp b/src/devices/bus/hexbus/hx5102.cpp
index 740b5f93f4c..999df7fe520 100644
--- a/src/devices/bus/hexbus/hx5102.cpp
+++ b/src/devices/bus/hexbus/hx5102.cpp
@@ -75,20 +75,21 @@
#include "hx5102.h"
#include "formats/ti99_dsk.h"
-#define LOG_HEXBUS (1U<<1) // Hexbus operation
-#define LOG_RESET (1U<<2) // Reset
-#define LOG_WARN (1U<<3) // Warnings
-#define LOG_READY (1U<<4) // READY
-#define LOG_SIGNALS (1U<<5) // IRQ/DRQ
-#define LOG_CRU (1U<<6) // CRU
-#define LOG_RAM (1U<<7) // RAM
-#define LOG_DMA (1U<<8) // DMA
-#define LOG_MOTOR (1U<<9) // Motor activity
-#define LOG_STATUS (1U<<10) // Main status register
-#define LOG_FIFO (1U<<11) // Data register
+#define LOG_HEXBUS (1U << 1) // Hexbus operation
+#define LOG_RESET (1U << 2) // Reset
+#define LOG_WARN (1U << 3) // Warnings
+#define LOG_READY (1U << 4) // READY
+#define LOG_SIGNALS (1U << 5) // IRQ/DRQ
+#define LOG_CRU (1U << 6) // CRU
+#define LOG_RAM (1U << 7) // RAM
+#define LOG_DMA (1U << 8) // DMA
+#define LOG_MOTOR (1U << 9) // Motor activity
+#define LOG_STATUS (1U << 10) // Main status register
+#define LOG_FIFO (1U << 11) // Data register
+#define LOG_CONFIG (1U << 12) // Configuration
// Minimum log should be config and warnings
-#define VERBOSE ( LOG_GENERAL | LOG_WARN )
+#define VERBOSE (LOG_GENERAL | LOG_WARN | LOG_CONFIG)
#include "logmacro.h"
@@ -104,6 +105,9 @@
#define ROM1_TAG "u25_rom"
#define ROM2_TAG "u29_rom"
+#define FLOP0 "d0"
+#define FLOP1 "d1"
+
#define MOTOR_TIMER 1
#define UNDEF -1
@@ -133,10 +137,13 @@ hx5102_device::hx5102_device(const machine_config &mconfig, const char *tag, dev
m_motor_on(false),
m_mspeed_on(false),
m_pending_int(false),
+ m_pending_drq(false),
m_dcs(false),
m_dack(false),
m_dacken(false),
m_wait(false),
+ m_flopcon0(*this, FLOP0),
+ m_flopcon1(*this, FLOP1),
m_current_floppy(nullptr),
m_floppy_select(0),
m_floppy_select_last(UNDEF),
@@ -299,7 +306,7 @@ void hx5102_device::write(offs_t offset, uint8_t data)
/*
Clock line from the CPU. Used to control wait state generation.
*/
-WRITE_LINE_MEMBER( hx5102_device::clock_out )
+void hx5102_device::clock_out(int state)
{
m_readyff->clock_w(state);
}
@@ -316,7 +323,7 @@ void hx5102_device::hexbus_value_changed(uint8_t data)
Propagate READY signals to the CPU. This is used to hold the CPU
during DMA accesses.
*/
-WRITE_LINE_MEMBER( hx5102_device::board_ready )
+void hx5102_device::board_ready(int state)
{
if (m_ready_old != state)
{
@@ -330,7 +337,7 @@ WRITE_LINE_MEMBER( hx5102_device::board_ready )
/*
Trigger RESET.
*/
-WRITE_LINE_MEMBER( hx5102_device::board_reset )
+void hx5102_device::board_reset(int state)
{
LOGMASKED(LOG_RESET, "Incoming RESET line = %d\n", state);
@@ -345,7 +352,7 @@ WRITE_LINE_MEMBER( hx5102_device::board_reset )
/*
Effect from the motor monoflop.
*/
-WRITE_LINE_MEMBER( hx5102_device::motor_w )
+void hx5102_device::motor_w(int state)
{
m_motor_on = (state==ASSERT_LINE);
LOGMASKED(LOG_MOTOR, "Motor %s\n", m_motor_on? "start" : "stop");
@@ -359,7 +366,7 @@ WRITE_LINE_MEMBER( hx5102_device::motor_w )
Effect from the speed monoflop. This is essentially a watchdog to
check whether the lock on the CPU must be released due to an error.
*/
-WRITE_LINE_MEMBER( hx5102_device::mspeed_w )
+void hx5102_device::mspeed_w(int state)
{
m_mspeed_on = (state==ASSERT_LINE);
LOGMASKED(LOG_READY, "Speedcheck %s\n", m_mspeed_on? "on" : "off");
@@ -448,7 +455,7 @@ void hx5102_device::hexbus_out(uint8_t data)
/*
Latch the HSK* to low.
*/
-WRITE_LINE_MEMBER(hx5102_device::hsklatch_out)
+void hx5102_device::hsklatch_out(int state)
{
LOGMASKED(LOG_HEXBUS, "Latching HSK*\n");
m_myvalue &= ~HEXBUS_LINE_HSK;
@@ -483,27 +490,27 @@ uint8_t hx5102_device::cruread(offs_t offset)
/*
CRU write access.
*/
-WRITE_LINE_MEMBER(hx5102_device::nocomp_w)
+void hx5102_device::nocomp_w(int state)
{
// unused right now
LOGMASKED(LOG_CRU, "Set precompensation = %d\n", state);
}
-WRITE_LINE_MEMBER(hx5102_device::diren_w)
+void hx5102_device::diren_w(int state)
{
LOGMASKED(LOG_CRU, "Set step direction = %d\n", state);
if (m_current_floppy != nullptr)
m_current_floppy->dir_w((state==0)? 1 : 0);
}
-WRITE_LINE_MEMBER(hx5102_device::dacken_w)
+void hx5102_device::dacken_w(int state)
{
if (state==1)
LOGMASKED(LOG_CRU, "Assert DACK*\n");
m_dacken = (state != 0);
}
-WRITE_LINE_MEMBER(hx5102_device::stepen_w)
+void hx5102_device::stepen_w(int state)
{
if (state==1)
LOGMASKED(LOG_CRU, "Step pulse\n");
@@ -511,7 +518,7 @@ WRITE_LINE_MEMBER(hx5102_device::stepen_w)
m_current_floppy->stp_w((state==0)? 1 : 0);
}
-WRITE_LINE_MEMBER(hx5102_device::ds1_w)
+void hx5102_device::ds1_w(int state)
{
LOGMASKED(LOG_CRU, "Set drive select 0 to %d\n", state);
if (state == 1)
@@ -521,7 +528,7 @@ WRITE_LINE_MEMBER(hx5102_device::ds1_w)
update_drive_select();
}
-WRITE_LINE_MEMBER(hx5102_device::ds2_w)
+void hx5102_device::ds2_w(int state)
{
LOGMASKED(LOG_CRU, "Set drive select 1 to %d\n", state);
if (state == 1)
@@ -531,25 +538,25 @@ WRITE_LINE_MEMBER(hx5102_device::ds2_w)
update_drive_select();
}
-WRITE_LINE_MEMBER(hx5102_device::ds3_w)
+void hx5102_device::ds3_w(int state)
{
// External drive; not implemented
LOGMASKED(LOG_CRU, "Set drive select 2 to %d\n", state);
}
-WRITE_LINE_MEMBER(hx5102_device::ds4_w)
+void hx5102_device::ds4_w(int state)
{
// External drive; not implemented
LOGMASKED(LOG_CRU, "Set drive select 3 to %d\n", state);
}
-WRITE_LINE_MEMBER(hx5102_device::aux_motor_w)
+void hx5102_device::aux_motor_w(int state)
{
// External drive; not implemented
LOGMASKED(LOG_CRU, "Set auxiliary motor line to %d\n", state);
}
-WRITE_LINE_MEMBER(hx5102_device::wait_w)
+void hx5102_device::wait_w(int state)
{
m_wait = (state!=0);
LOGMASKED(LOG_CRU, "READY circuit %s\n", m_wait? "active" : "inactive" );
@@ -580,13 +587,21 @@ void hx5102_device::update_drive_select()
*/
void hx5102_device::device_start()
{
- m_floppy[0] = m_floppy[1] = nullptr;
-
- if (subdevice("d0")!=nullptr) m_floppy[0] = static_cast<floppy_image_device*>(subdevice("d0")->subdevices().first());
- if (subdevice("d1")!=nullptr) m_floppy[1] = static_cast<floppy_image_device*>(subdevice("d1")->subdevices().first());
-
m_rom1 = (uint8_t*)memregion(DSR_TAG)->base();
m_rom2 = (uint8_t*)memregion(DSR_TAG)->base() + 0x2000;
+
+ m_floppy[0] = m_flopcon0->get_device();
+ m_floppy[1] = m_flopcon1->get_device();
+
+ if (m_floppy[0] != nullptr)
+ LOGMASKED(LOG_CONFIG, "Internal floppy drive connected\n");
+ else
+ LOGMASKED(LOG_WARN, "Internal floppy drive not found\n");
+
+ if (m_floppy[1] != nullptr)
+ LOGMASKED(LOG_CONFIG, "External floppy drive connected\n");
+ else
+ LOGMASKED(LOG_CONFIG, "External floppy drive not connected\n");
}
/*
@@ -602,7 +617,7 @@ void hx5102_device::device_reset()
Callbacks from the i8272A chip
Interrupt
*/
-WRITE_LINE_MEMBER( hx5102_device::fdc_irq_w )
+void hx5102_device::fdc_irq_w(int state)
{
line_state irq = state? ASSERT_LINE : CLEAR_LINE;
LOGMASKED(LOG_SIGNALS, "INTRQ callback = %d\n", irq);
@@ -614,7 +629,7 @@ WRITE_LINE_MEMBER( hx5102_device::fdc_irq_w )
Callbacks from the i8272A chip
DMA request
*/
-WRITE_LINE_MEMBER( hx5102_device::fdc_drq_w )
+void hx5102_device::fdc_drq_w(int state)
{
line_state drq = state? ASSERT_LINE : CLEAR_LINE;
LOGMASKED(LOG_SIGNALS, "DRQ callback = %d\n", drq);
@@ -685,8 +700,8 @@ void hx5102_device::device_add_mconfig(machine_config& config)
m_floppy_ctrl->intrq_wr_callback().set(FUNC(hx5102_device::fdc_irq_w));
m_floppy_ctrl->drq_wr_callback().set(FUNC(hx5102_device::fdc_drq_w));
- FLOPPY_CONNECTOR(config, "d0", hx5102_drive, "525dd", hx5102_device::floppy_formats).enable_sound(true);
- FLOPPY_CONNECTOR(config, "d1", hx5102_drive, nullptr, hx5102_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_flopcon0, hx5102_drive, "525dd", hx5102_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_flopcon1, hx5102_drive, nullptr, hx5102_device::floppy_formats).enable_sound(true);
// Addressable latches
LS259(config, m_crulatch[0]); // U18
diff --git a/src/devices/bus/hexbus/hx5102.h b/src/devices/bus/hexbus/hx5102.h
index 15d717bd028..b0e490237d8 100644
--- a/src/devices/bus/hexbus/hx5102.h
+++ b/src/devices/bus/hexbus/hx5102.h
@@ -38,18 +38,18 @@ public:
protected:
virtual const tiny_rom_entry *device_rom_region() const override;
virtual void device_add_mconfig(machine_config &config) override;
- ioport_constructor device_input_ports() const override;
+ virtual ioport_constructor device_input_ports() const override;
void crumap(address_map &map);
void memmap(address_map &map);
void external_operation(offs_t offset, uint8_t data);
- DECLARE_WRITE_LINE_MEMBER( clock_out );
- DECLARE_WRITE_LINE_MEMBER( board_ready );
- DECLARE_WRITE_LINE_MEMBER( board_reset );
+ void clock_out(int state);
+ void board_ready(int state);
+ void board_reset(int state);
static void floppy_formats(format_registration &fr);
- void device_start() override;
- void device_reset() override;
+ virtual void device_start() override;
+ virtual void device_reset() override;
virtual void hexbus_value_changed(uint8_t data) override;
private:
@@ -59,29 +59,29 @@ private:
uint8_t read(offs_t offset);
void write(offs_t offset, uint8_t data);
- DECLARE_WRITE_LINE_MEMBER(fdc_irq_w);
- DECLARE_WRITE_LINE_MEMBER(fdc_drq_w);
- DECLARE_WRITE_LINE_MEMBER(motor_w);
- DECLARE_WRITE_LINE_MEMBER(mspeed_w);
+ void fdc_irq_w(int state);
+ void fdc_drq_w(int state);
+ void motor_w(int state);
+ void mspeed_w(int state);
uint8_t fdc_read(offs_t offset);
void fdc_write(offs_t offset, uint8_t data);
uint8_t ibc_read(offs_t offset);
void ibc_write(offs_t offset, uint8_t data);
void hexbus_out(uint8_t data);
- DECLARE_WRITE_LINE_MEMBER(hsklatch_out);
+ void hsklatch_out(int state);
uint8_t cruread(offs_t offset);
- DECLARE_WRITE_LINE_MEMBER(nocomp_w);
- DECLARE_WRITE_LINE_MEMBER(diren_w);
- DECLARE_WRITE_LINE_MEMBER(dacken_w);
- DECLARE_WRITE_LINE_MEMBER(stepen_w);
- DECLARE_WRITE_LINE_MEMBER(ds1_w);
- DECLARE_WRITE_LINE_MEMBER(ds2_w);
- DECLARE_WRITE_LINE_MEMBER(ds3_w);
- DECLARE_WRITE_LINE_MEMBER(ds4_w);
- DECLARE_WRITE_LINE_MEMBER(aux_motor_w);
- DECLARE_WRITE_LINE_MEMBER(wait_w);
+ void nocomp_w(int state);
+ void diren_w(int state);
+ void dacken_w(int state);
+ void stepen_w(int state);
+ void ds1_w(int state);
+ void ds2_w(int state);
+ void ds3_w(int state);
+ void ds4_w(int state);
+ void aux_motor_w(int state);
+ void wait_w(int state);
void update_drive_select();
// Operate the floppy motors
@@ -101,6 +101,8 @@ private:
void update_readyff_input();
// Link to the attached floppy drives
+ required_device<floppy_connector> m_flopcon0;
+ required_device<floppy_connector> m_flopcon1;
floppy_image_device* m_floppy[2];
floppy_image_device* m_current_floppy;
int m_floppy_select, m_floppy_select_last;
diff --git a/src/devices/bus/hexbus/tp0370.cpp b/src/devices/bus/hexbus/tp0370.cpp
index e4d1ac50863..d5aed93015e 100644
--- a/src/devices/bus/hexbus/tp0370.cpp
+++ b/src/devices/bus/hexbus/tp0370.cpp
@@ -106,15 +106,15 @@
// Devices
#include "tp0370.h"
-#define LOG_DATA (1U<<1) // Data transfer
-#define LOG_DETAIL (1U<<2)
-#define LOG_WRITE (1U<<3)
-#define LOG_LINES (1U<<4)
-#define LOG_STATUS (1U<<5)
-#define LOG_MODE (1U<<6)
+#define LOG_DATA (1U << 1) // Data transfer
+#define LOG_DETAIL (1U << 2)
+#define LOG_WRITE (1U << 3)
+#define LOG_LINES (1U << 4)
+#define LOG_STATUS (1U << 5)
+#define LOG_MODE (1U << 6)
// Minimum log should be config and warnings
-#define VERBOSE ( LOG_GENERAL )
+#define VERBOSE (LOG_GENERAL)
enum
{
@@ -347,9 +347,6 @@ void ibc_device::update_lines(bool bav, bool hsk)
void ibc_device::device_start()
{
- m_int.resolve_safe();
- m_hexout.resolve_safe();
- m_latch.resolve_safe();
}
void ibc_device::device_reset()
diff --git a/src/devices/bus/hp80_io/82900.cpp b/src/devices/bus/hp80_io/82900.cpp
index 72b9c08c092..b910e36b1c6 100644
--- a/src/devices/bus/hp80_io/82900.cpp
+++ b/src/devices/bus/hp80_io/82900.cpp
@@ -85,7 +85,7 @@ ROM_START(hp82900)
ROM_LOAD("82900-60002.bin" , 0 , 0x800 , CRC(48745bbb) SHA1(fb4427f729eedba5ac01809718b841c7bdd85e1f))
ROM_END
-WRITE_LINE_MEMBER(hp82900_io_card_device::reset_w)
+void hp82900_io_card_device::reset_w(int state)
{
LOG("reset_w %d\n" , state);
m_cpu->set_input_line(INPUT_LINE_RESET , state);
diff --git a/src/devices/bus/hp80_io/82900.h b/src/devices/bus/hp80_io/82900.h
index 613783cbc3f..8abd63a1519 100644
--- a/src/devices/bus/hp80_io/82900.h
+++ b/src/devices/bus/hp80_io/82900.h
@@ -51,7 +51,7 @@ private:
bool m_rom_enabled;
uint8_t m_addr_latch;
- DECLARE_WRITE_LINE_MEMBER(reset_w);
+ void reset_w(int state);
uint8_t cpu_mem_r(offs_t offset);
void cpu_mem_w(offs_t offset, uint8_t data);
uint8_t cpu_io_r(offs_t offset);
diff --git a/src/devices/bus/hp80_io/82937.cpp b/src/devices/bus/hp80_io/82937.cpp
index 24fae1d68c6..31fe00e8272 100644
--- a/src/devices/bus/hp80_io/82937.cpp
+++ b/src/devices/bus/hp80_io/82937.cpp
@@ -83,7 +83,7 @@ void hp82937_io_card_device::clear_service()
m_translator->clear_service();
}
-WRITE_LINE_MEMBER(hp82937_io_card_device::reset_w)
+void hp82937_io_card_device::reset_w(int state)
{
m_cpu->set_input_line(INPUT_LINE_RESET , state);
if (state) {
@@ -92,7 +92,7 @@ WRITE_LINE_MEMBER(hp82937_io_card_device::reset_w)
}
}
-READ_LINE_MEMBER(hp82937_io_card_device::t0_r)
+int hp82937_io_card_device::t0_r()
{
return m_iatn;
}
@@ -179,7 +179,7 @@ void hp82937_io_card_device::latch_w(uint8_t data)
update_data_out();
}
-WRITE_LINE_MEMBER(hp82937_io_card_device::ieee488_ctrl_w)
+void hp82937_io_card_device::ieee488_ctrl_w(int state)
{
update_signals();
update_data_out();
diff --git a/src/devices/bus/hp80_io/82937.h b/src/devices/bus/hp80_io/82937.h
index 07f3dec991a..9847f1a94b2 100644
--- a/src/devices/bus/hp80_io/82937.h
+++ b/src/devices/bus/hp80_io/82937.h
@@ -51,13 +51,13 @@ private:
uint8_t m_latch; // U3
bool m_updating;
- DECLARE_WRITE_LINE_MEMBER(reset_w);
- DECLARE_READ_LINE_MEMBER(t0_r);
+ void reset_w(int state);
+ int t0_r();
uint8_t p1_r();
void p1_w(uint8_t data);
uint8_t dio_r();
void dio_w(uint8_t data);
- DECLARE_WRITE_LINE_MEMBER(ieee488_ctrl_w);
+ void ieee488_ctrl_w(int state);
uint8_t switch_r();
void latch_w(uint8_t data);
diff --git a/src/devices/bus/hp80_io/hp80_io.cpp b/src/devices/bus/hp80_io/hp80_io.cpp
index 591435bafac..5ca970060bf 100644
--- a/src/devices/bus/hp80_io/hp80_io.cpp
+++ b/src/devices/bus/hp80_io/hp80_io.cpp
@@ -36,17 +36,15 @@ hp80_io_slot_device::~hp80_io_slot_device()
void hp80_io_slot_device::device_start()
{
- m_irl_cb_func.resolve_safe();
- m_halt_cb_func.resolve_safe();
}
-WRITE_LINE_MEMBER(hp80_io_slot_device::irl_w)
+void hp80_io_slot_device::irl_w(int state)
{
LOG("irl_w slot %u=%d\n" , m_slot_no , state);
m_irl_cb_func(m_slot_no , state , 0xff);
}
-WRITE_LINE_MEMBER(hp80_io_slot_device::halt_w)
+void hp80_io_slot_device::halt_w(int state)
{
LOG("halt_w slot %u=%d\n" , m_slot_no , state);
m_halt_cb_func(m_slot_no , state , 0xff);
@@ -128,14 +126,14 @@ device_hp80_io_interface::~device_hp80_io_interface()
{
}
-WRITE_LINE_MEMBER(device_hp80_io_interface::irl_w)
+void device_hp80_io_interface::irl_w(int state)
{
if (VERBOSE & LOG_GENERAL) device().logerror("irl_w card=%d\n" , state);
hp80_io_slot_device *slot = downcast<hp80_io_slot_device *>(device().owner());
slot->irl_w(state);
}
-WRITE_LINE_MEMBER(device_hp80_io_interface::halt_w)
+void device_hp80_io_interface::halt_w(int state)
{
if (VERBOSE & LOG_GENERAL) device().logerror("halt_w card=%d\n" , state);
hp80_io_slot_device *slot = downcast<hp80_io_slot_device *>(device().owner());
diff --git a/src/devices/bus/hp80_io/hp80_io.h b/src/devices/bus/hp80_io/hp80_io.h
index 3963d56d29e..a65b298309d 100644
--- a/src/devices/bus/hp80_io/hp80_io.h
+++ b/src/devices/bus/hp80_io/hp80_io.h
@@ -62,8 +62,8 @@ public:
void install_read_write_handlers(address_space& space);
- DECLARE_WRITE_LINE_MEMBER(irl_w);
- DECLARE_WRITE_LINE_MEMBER(halt_w);
+ void irl_w(int state);
+ void halt_w(int state);
void inten();
void clear_service();
@@ -97,8 +97,8 @@ protected:
required_ioport m_select_code_port;
// card device handling
- DECLARE_WRITE_LINE_MEMBER(irl_w);
- DECLARE_WRITE_LINE_MEMBER(halt_w);
+ void irl_w(int state);
+ void halt_w(int state);
};
// device type definition
diff --git a/src/devices/bus/hp9845_io/98032.cpp b/src/devices/bus/hp9845_io/98032.cpp
index ecfc92ba706..c6052d40fad 100644
--- a/src/devices/bus/hp9845_io/98032.cpp
+++ b/src/devices/bus/hp9845_io/98032.cpp
@@ -13,8 +13,11 @@
#include "emu.h"
#include "98032.h"
+
+#include "hp9871.h"
#include "hp9885.h"
+
// Debugging
#define VERBOSE 0
#include "logmacro.h"
@@ -94,6 +97,7 @@ void hp98032_io_card_device::device_reset()
m_int_en = false;
m_dma_en = false;
m_busy = true; // Force reset
+ m_pready = false;
m_auto_ah = false;
set_busy(false);
update_irq();
@@ -236,7 +240,7 @@ void hp98032_io_card_device::reg_w(address_space &space, offs_t offset, uint16_t
}
}
-WRITE_LINE_MEMBER(hp98032_io_card_device::pflg_w)
+void hp98032_io_card_device::pflg_w(int state)
{
bool prev_pready = m_pready;
m_pready = state;
@@ -261,7 +265,7 @@ WRITE_LINE_MEMBER(hp98032_io_card_device::pflg_w)
}
}
-WRITE_LINE_MEMBER(hp98032_io_card_device::psts_w)
+void hp98032_io_card_device::psts_w(int state)
{
bool sts = !state;
if (m_gpio->is_jumper_present(hp98032_gpio_slot_device::JUMPER_5)) {
@@ -271,7 +275,7 @@ WRITE_LINE_MEMBER(hp98032_io_card_device::psts_w)
sts_w(sts);
}
-WRITE_LINE_MEMBER(hp98032_io_card_device::eir_w)
+void hp98032_io_card_device::eir_w(int state)
{
m_eir = state;
LOG("eir = %d\n" , m_eir);
@@ -356,6 +360,7 @@ hp98032_gpio_slot_device::hp98032_gpio_slot_device(const machine_config &mconfig
{
option_reset();
option_add("loopback" , HP98032_GPIO_LOOPBACK);
+ option_add("hp9871" , HP9871);
option_add("hp9885" , HP9885);
set_default_option(nullptr);
set_fixed(false);
@@ -411,22 +416,22 @@ void hp98032_gpio_slot_device::ext_control_w(uint8_t data)
}
}
-WRITE_LINE_MEMBER(hp98032_gpio_slot_device::pflg_w)
+void hp98032_gpio_slot_device::pflg_w(int state)
{
m_pflg_handler(state);
}
-WRITE_LINE_MEMBER(hp98032_gpio_slot_device::psts_w)
+void hp98032_gpio_slot_device::psts_w(int state)
{
m_psts_handler(state);
}
-WRITE_LINE_MEMBER(hp98032_gpio_slot_device::eir_w)
+void hp98032_gpio_slot_device::eir_w(int state)
{
m_eir_handler(state);
}
-WRITE_LINE_MEMBER(hp98032_gpio_slot_device::pctl_w)
+void hp98032_gpio_slot_device::pctl_w(int state)
{
device_hp98032_gpio_interface *card = get_card_device();
if (card != nullptr) {
@@ -434,7 +439,7 @@ WRITE_LINE_MEMBER(hp98032_gpio_slot_device::pctl_w)
}
}
-WRITE_LINE_MEMBER(hp98032_gpio_slot_device::io_w)
+void hp98032_gpio_slot_device::io_w(int state)
{
device_hp98032_gpio_interface *card = get_card_device();
if (card != nullptr) {
@@ -442,7 +447,7 @@ WRITE_LINE_MEMBER(hp98032_gpio_slot_device::io_w)
}
}
-WRITE_LINE_MEMBER(hp98032_gpio_slot_device::preset_w)
+void hp98032_gpio_slot_device::preset_w(int state)
{
device_hp98032_gpio_interface *card = get_card_device();
if (card != nullptr) {
@@ -452,9 +457,6 @@ WRITE_LINE_MEMBER(hp98032_gpio_slot_device::preset_w)
void hp98032_gpio_slot_device::device_start()
{
- m_pflg_handler.resolve_safe();
- m_psts_handler.resolve_safe();
- m_eir_handler.resolve_safe();
}
void hp98032_gpio_slot_device::device_reset()
@@ -480,19 +482,19 @@ device_hp98032_gpio_interface::~device_hp98032_gpio_interface()
{
}
-WRITE_LINE_MEMBER(device_hp98032_gpio_interface::pflg_w)
+void device_hp98032_gpio_interface::pflg_w(int state)
{
hp98032_gpio_slot_device *slot = downcast<hp98032_gpio_slot_device*>(device().owner());
slot->pflg_w(state);
}
-WRITE_LINE_MEMBER(device_hp98032_gpio_interface::psts_w)
+void device_hp98032_gpio_interface::psts_w(int state)
{
hp98032_gpio_slot_device *slot = downcast<hp98032_gpio_slot_device*>(device().owner());
slot->psts_w(state);
}
-WRITE_LINE_MEMBER(device_hp98032_gpio_interface::eir_w)
+void device_hp98032_gpio_interface::eir_w(int state)
{
hp98032_gpio_slot_device *slot = downcast<hp98032_gpio_slot_device*>(device().owner());
slot->eir_w(state);
@@ -548,17 +550,17 @@ void hp98032_gpio_loopback_device::ext_control_w(uint8_t data)
m_ext_control = data;
}
-WRITE_LINE_MEMBER(hp98032_gpio_loopback_device::pctl_w)
+void hp98032_gpio_loopback_device::pctl_w(int state)
{
pflg_w(state);
}
-WRITE_LINE_MEMBER(hp98032_gpio_loopback_device::io_w)
+void hp98032_gpio_loopback_device::io_w(int state)
{
m_io = state;
}
-WRITE_LINE_MEMBER(hp98032_gpio_loopback_device::preset_w)
+void hp98032_gpio_loopback_device::preset_w(int state)
{
eir_w(state);
}
diff --git a/src/devices/bus/hp9845_io/98032.h b/src/devices/bus/hp9845_io/98032.h
index 059b0248ae9..9da205d1baf 100644
--- a/src/devices/bus/hp9845_io/98032.h
+++ b/src/devices/bus/hp9845_io/98032.h
@@ -48,9 +48,9 @@ private:
bool m_auto_ah;
bool m_eir;
- DECLARE_WRITE_LINE_MEMBER(pflg_w);
- DECLARE_WRITE_LINE_MEMBER(psts_w);
- DECLARE_WRITE_LINE_MEMBER(eir_w);
+ void pflg_w(int state);
+ void psts_w(int state);
+ void eir_w(int state);
void start_hs();
void set_busy(bool state);
@@ -114,14 +114,14 @@ public:
auto eir_cb() { return m_eir_handler.bind(); }
// Write to input signals (for card devices)
- DECLARE_WRITE_LINE_MEMBER(pflg_w);
- DECLARE_WRITE_LINE_MEMBER(psts_w);
- DECLARE_WRITE_LINE_MEMBER(eir_w);
+ void pflg_w(int state);
+ void psts_w(int state);
+ void eir_w(int state);
// Write to output signals
- DECLARE_WRITE_LINE_MEMBER(pctl_w);
- DECLARE_WRITE_LINE_MEMBER(io_w);
- DECLARE_WRITE_LINE_MEMBER(preset_w);
+ void pctl_w(int state);
+ void io_w(int state);
+ void preset_w(int state);
protected:
// device-level overrides
@@ -146,16 +146,16 @@ public:
virtual uint8_t ext_status_r() const = 0;
virtual void output_w(uint16_t data) = 0;
virtual void ext_control_w(uint8_t data) = 0;
- virtual DECLARE_WRITE_LINE_MEMBER(pctl_w) = 0;
- virtual DECLARE_WRITE_LINE_MEMBER(io_w) = 0;
- virtual DECLARE_WRITE_LINE_MEMBER(preset_w) = 0;
+ virtual void pctl_w(int state) = 0;
+ virtual void io_w(int state) = 0;
+ virtual void preset_w(int state) = 0;
protected:
device_hp98032_gpio_interface(const machine_config &mconfig, device_t &device);
- DECLARE_WRITE_LINE_MEMBER(pflg_w);
- DECLARE_WRITE_LINE_MEMBER(psts_w);
- DECLARE_WRITE_LINE_MEMBER(eir_w);
+ void pflg_w(int state);
+ void psts_w(int state);
+ void eir_w(int state);
};
// GPIO loopback connector for HP98032
@@ -171,9 +171,9 @@ public:
virtual uint8_t ext_status_r() const override;
virtual void output_w(uint16_t data) override;
virtual void ext_control_w(uint8_t data) override;
- virtual DECLARE_WRITE_LINE_MEMBER(pctl_w) override;
- virtual DECLARE_WRITE_LINE_MEMBER(io_w) override;
- virtual DECLARE_WRITE_LINE_MEMBER(preset_w) override;
+ virtual void pctl_w(int state) override;
+ virtual void io_w(int state) override;
+ virtual void preset_w(int state) override;
protected:
// device-level overrides
diff --git a/src/devices/bus/hp9845_io/98034.cpp b/src/devices/bus/hp9845_io/98034.cpp
index b629617a0da..61658c1ecf1 100644
--- a/src/devices/bus/hp9845_io/98034.cpp
+++ b/src/devices/bus/hp9845_io/98034.cpp
@@ -146,7 +146,7 @@ uint16_t hp98034_io_card_device::reg_r(address_space &space, offs_t offset)
// This is meant to gain some margin to NP in the race with
// CPU (in real hw the margin was probably no more than a
// couple of µs).
- machine().scheduler().boost_interleave(attotime::from_usec(5) , attotime::from_usec(100));
+ machine().scheduler().add_quantum(attotime::from_usec(5) , attotime::from_usec(100));
space.device().execute().spin();
machine().scheduler().synchronize();
LOG("%.06f RD R%u=%04x %s\n" , machine().time().as_double() , offset + 4 , res , machine().describe_context());
@@ -169,7 +169,7 @@ void hp98034_io_card_device::reg_w(address_space &space, offs_t offset, uint16_t
update_flg();
// See reg_r above
- machine().scheduler().boost_interleave(attotime::from_usec(5) , attotime::from_usec(100));
+ machine().scheduler().add_quantum(attotime::from_usec(5) , attotime::from_usec(100));
space.device().execute().spin();
machine().scheduler().synchronize();
LOG("%.06f WR R%u=%04x %s\n" , machine().time().as_double() , offset + 4 , data , machine().describe_context());
@@ -270,7 +270,7 @@ void hp98034_io_card_device::mode_reg_clear_w(uint8_t data)
m_force_flg = false;
if (update_flg()) {
// See reg_r above
- machine().scheduler().boost_interleave(attotime::zero , attotime::from_usec(100));
+ machine().scheduler().perfect_quantum(attotime::from_usec(100));
machine().scheduler().synchronize();
}
}
@@ -291,7 +291,7 @@ uint8_t hp98034_io_card_device::int_ack_r()
return res;
}
-WRITE_LINE_MEMBER(hp98034_io_card_device::ieee488_ctrl_w)
+void hp98034_io_card_device::ieee488_ctrl_w(int state)
{
update_clr_hpib();
}
@@ -302,7 +302,7 @@ void hp98034_io_card_device::update_dc()
sts_w(BIT(m_dc , 4));
if (update_flg()) {
// See reg_r above
- machine().scheduler().boost_interleave(attotime::zero , attotime::from_usec(100));
+ machine().scheduler().perfect_quantum(attotime::from_usec(100));
machine().scheduler().synchronize();
}
update_clr_hpib();
diff --git a/src/devices/bus/hp9845_io/98034.h b/src/devices/bus/hp9845_io/98034.h
index c8cb5ff8765..d1fa42c5f0a 100644
--- a/src/devices/bus/hp9845_io/98034.h
+++ b/src/devices/bus/hp9845_io/98034.h
@@ -54,7 +54,7 @@ private:
void np_io_map(address_map &map);
void np_program_map(address_map &map);
- DECLARE_WRITE_LINE_MEMBER(ieee488_ctrl_w);
+ void ieee488_ctrl_w(int state);
required_device<hp_nanoprocessor_device> m_cpu;
required_ioport m_sw1;
diff --git a/src/devices/bus/hp9845_io/98036.cpp b/src/devices/bus/hp9845_io/98036.cpp
index 6f328062152..cd1544b0379 100644
--- a/src/devices/bus/hp9845_io/98036.cpp
+++ b/src/devices/bus/hp9845_io/98036.cpp
@@ -299,7 +299,7 @@ void hp98036_io_card_device::device_reset()
int_reset();
}
-WRITE_LINE_MEMBER(hp98036_io_card_device::bit_rate_clock)
+void hp98036_io_card_device::bit_rate_clock(int state)
{
if (m_half_baud) {
if (state) {
@@ -313,7 +313,7 @@ WRITE_LINE_MEMBER(hp98036_io_card_device::bit_rate_clock)
}
}
-WRITE_LINE_MEMBER(hp98036_io_card_device::slow_clock)
+void hp98036_io_card_device::slow_clock(int state)
{
switch (m_init_state) {
case 0:
@@ -347,7 +347,7 @@ WRITE_LINE_MEMBER(hp98036_io_card_device::slow_clock)
}
}
-WRITE_LINE_MEMBER(hp98036_io_card_device::txd_w)
+void hp98036_io_card_device::txd_w(int state)
{
if (m_loopback) {
m_uart->write_rxd(state);
@@ -356,7 +356,7 @@ WRITE_LINE_MEMBER(hp98036_io_card_device::txd_w)
}
}
-WRITE_LINE_MEMBER(hp98036_io_card_device::dtr_w)
+void hp98036_io_card_device::dtr_w(int state)
{
if (m_loopback) {
m_uart->write_dsr(state);
@@ -365,7 +365,7 @@ WRITE_LINE_MEMBER(hp98036_io_card_device::dtr_w)
}
}
-WRITE_LINE_MEMBER(hp98036_io_card_device::rts_w)
+void hp98036_io_card_device::rts_w(int state)
{
if (m_loopback) {
m_uart->write_cts(state);
@@ -374,7 +374,7 @@ WRITE_LINE_MEMBER(hp98036_io_card_device::rts_w)
}
}
-WRITE_LINE_MEMBER(hp98036_io_card_device::txrdy_w)
+void hp98036_io_card_device::txrdy_w(int state)
{
if (m_txrdy != state) {
m_txrdy = state;
@@ -385,7 +385,7 @@ WRITE_LINE_MEMBER(hp98036_io_card_device::txrdy_w)
}
}
-WRITE_LINE_MEMBER(hp98036_io_card_device::rxrdy_w)
+void hp98036_io_card_device::rxrdy_w(int state)
{
if (m_rxrdy != state) {
m_rxrdy = state;
@@ -396,21 +396,21 @@ WRITE_LINE_MEMBER(hp98036_io_card_device::rxrdy_w)
}
}
-WRITE_LINE_MEMBER(hp98036_io_card_device::rxd_w)
+void hp98036_io_card_device::rxd_w(int state)
{
if (!m_loopback) {
m_uart->write_rxd(state);
}
}
-WRITE_LINE_MEMBER(hp98036_io_card_device::dsr_w)
+void hp98036_io_card_device::dsr_w(int state)
{
if (!m_loopback) {
m_uart->write_dsr(state);
}
}
-WRITE_LINE_MEMBER(hp98036_io_card_device::cts_w)
+void hp98036_io_card_device::cts_w(int state)
{
if (!m_loopback && !BIT(m_s2_input->read(), 0)) {
m_uart->write_cts(state);
diff --git a/src/devices/bus/hp9845_io/98036.h b/src/devices/bus/hp9845_io/98036.h
index c1ee6b351bd..b1c150a57fc 100644
--- a/src/devices/bus/hp9845_io/98036.h
+++ b/src/devices/bus/hp9845_io/98036.h
@@ -45,16 +45,16 @@ private:
required_ioport m_jumper_input;
required_ioport m_loopback_en;
- DECLARE_WRITE_LINE_MEMBER(bit_rate_clock);
- DECLARE_WRITE_LINE_MEMBER(slow_clock);
- DECLARE_WRITE_LINE_MEMBER(txd_w);
- DECLARE_WRITE_LINE_MEMBER(dtr_w);
- DECLARE_WRITE_LINE_MEMBER(rts_w);
- DECLARE_WRITE_LINE_MEMBER(txrdy_w);
- DECLARE_WRITE_LINE_MEMBER(rxrdy_w);
- DECLARE_WRITE_LINE_MEMBER(rxd_w);
- DECLARE_WRITE_LINE_MEMBER(dsr_w);
- DECLARE_WRITE_LINE_MEMBER(cts_w);
+ void bit_rate_clock(int state);
+ void slow_clock(int state);
+ void txd_w(int state);
+ void dtr_w(int state);
+ void rts_w(int state);
+ void txrdy_w(int state);
+ void rxrdy_w(int state);
+ void rxd_w(int state);
+ void dsr_w(int state);
+ void cts_w(int state);
// State of initialization FSM
// State U11A-Q U11B-Q
diff --git a/src/devices/bus/hp9845_io/98046.cpp b/src/devices/bus/hp9845_io/98046.cpp
index 8b7e601f0f4..4b40850d95d 100644
--- a/src/devices/bus/hp9845_io/98046.cpp
+++ b/src/devices/bus/hp9845_io/98046.cpp
@@ -446,7 +446,7 @@ void hp98046_io_card_device::p2_w(uint8_t data)
}
}
-WRITE_LINE_MEMBER(hp98046_io_card_device::sio_int_w)
+void hp98046_io_card_device::sio_int_w(int state)
{
if (m_sio_int != state) {
LOG_SIO("SIO int=%d\n" , state);
@@ -454,7 +454,7 @@ WRITE_LINE_MEMBER(hp98046_io_card_device::sio_int_w)
m_sio_int = state;
}
-WRITE_LINE_MEMBER(hp98046_io_card_device::sio_txd_w)
+void hp98046_io_card_device::sio_txd_w(int state)
{
m_sio->rxb_w(state);
if (m_loopback) {
@@ -464,42 +464,42 @@ WRITE_LINE_MEMBER(hp98046_io_card_device::sio_txd_w)
}
}
-WRITE_LINE_MEMBER(hp98046_io_card_device::rs232_rxd_w)
+void hp98046_io_card_device::rs232_rxd_w(int state)
{
if (!m_loopback) {
m_sio->rxa_w(state);
}
}
-WRITE_LINE_MEMBER(hp98046_io_card_device::rs232_dcd_w)
+void hp98046_io_card_device::rs232_dcd_w(int state)
{
if (!m_loopback) {
m_sio->dcda_w(state);
}
}
-WRITE_LINE_MEMBER(hp98046_io_card_device::rs232_dsr_w)
+void hp98046_io_card_device::rs232_dsr_w(int state)
{
if (!m_loopback) {
m_sio->dcdb_w(state);
}
}
-WRITE_LINE_MEMBER(hp98046_io_card_device::rs232_cts_w)
+void hp98046_io_card_device::rs232_cts_w(int state)
{
if (!m_loopback) {
m_sio->ctsa_w(state);
}
}
-WRITE_LINE_MEMBER(hp98046_io_card_device::rs232_rxc_w)
+void hp98046_io_card_device::rs232_rxc_w(int state)
{
if (!m_loopback) {
machine().scheduler().synchronize(timer_expired_delegate(FUNC(hp98046_io_card_device::sync_rx_im_w) , this) , state);
}
}
-WRITE_LINE_MEMBER(hp98046_io_card_device::rs232_txc_w)
+void hp98046_io_card_device::rs232_txc_w(int state)
{
if (!m_loopback) {
machine().scheduler().synchronize(timer_expired_delegate(FUNC(hp98046_io_card_device::sync_tx_im_w) , this) , state);
@@ -630,7 +630,7 @@ uint8_t hp98046_io_card_device::get_hs_input() const
return res;
}
-WRITE_LINE_MEMBER(hp98046_io_card_device::rxc_w)
+void hp98046_io_card_device::rxc_w(int state)
{
if (m_last_rxc != bool(state)) {
m_last_rxc = bool(state);
@@ -641,7 +641,7 @@ WRITE_LINE_MEMBER(hp98046_io_card_device::rxc_w)
}
}
-WRITE_LINE_MEMBER(hp98046_io_card_device::txc_w)
+void hp98046_io_card_device::txc_w(int state)
{
if (m_last_txc != bool(state)) {
m_last_txc = bool(state);
diff --git a/src/devices/bus/hp9845_io/98046.h b/src/devices/bus/hp9845_io/98046.h
index 90debbb8c03..dd19c6f29a0 100644
--- a/src/devices/bus/hp9845_io/98046.h
+++ b/src/devices/bus/hp9845_io/98046.h
@@ -79,14 +79,14 @@ private:
void cpu_w(offs_t offset, uint8_t data);
uint8_t p1_r();
void p2_w(uint8_t data);
- DECLARE_WRITE_LINE_MEMBER(sio_int_w);
- DECLARE_WRITE_LINE_MEMBER(sio_txd_w);
- DECLARE_WRITE_LINE_MEMBER(rs232_rxd_w);
- DECLARE_WRITE_LINE_MEMBER(rs232_dcd_w);
- DECLARE_WRITE_LINE_MEMBER(rs232_dsr_w);
- DECLARE_WRITE_LINE_MEMBER(rs232_cts_w);
- DECLARE_WRITE_LINE_MEMBER(rs232_rxc_w);
- DECLARE_WRITE_LINE_MEMBER(rs232_txc_w);
+ void sio_int_w(int state);
+ void sio_txd_w(int state);
+ void rs232_rxd_w(int state);
+ void rs232_dcd_w(int state);
+ void rs232_dsr_w(int state);
+ void rs232_cts_w(int state);
+ void rs232_rxc_w(int state);
+ void rs232_txc_w(int state);
bool rx_fifo_flag() const;
bool tx_fifo_flag() const;
void update_flg();
@@ -96,8 +96,8 @@ private:
void load_tx_fifo();
void set_r6_r7_pending(bool state);
uint8_t get_hs_input() const;
- DECLARE_WRITE_LINE_MEMBER(rxc_w);
- DECLARE_WRITE_LINE_MEMBER(txc_w);
+ void rxc_w(int state);
+ void txc_w(int state);
TIMER_CALLBACK_MEMBER(sync_rx_im_w);
TIMER_CALLBACK_MEMBER(sync_tx_im_w);
};
diff --git a/src/devices/bus/hp9845_io/hp9845_io.cpp b/src/devices/bus/hp9845_io/hp9845_io.cpp
index bf304622f24..6962dea066e 100644
--- a/src/devices/bus/hp9845_io/hp9845_io.cpp
+++ b/src/devices/bus/hp9845_io/hp9845_io.cpp
@@ -10,12 +10,14 @@
#include "emu.h"
#include "hp9845_io.h"
+
#include "98032.h"
#include "98035.h"
#include "98036.h"
#include "98034.h"
#include "98046.h"
+
// device type definition
DEFINE_DEVICE_TYPE(HP9845_IO_SLOT, hp9845_io_slot_device, "hp98x5_io_slot", "HP98x5 I/O Slot")
@@ -49,14 +51,6 @@ hp9845_io_slot_device::~hp9845_io_slot_device()
void hp9845_io_slot_device::device_start()
{
- m_irq_cb_func.resolve_safe();
- m_sts_cb_func.resolve_safe();
- m_flg_cb_func.resolve_safe();
- m_irq_nextsc_cb_func.resolve_safe();
- m_sts_nextsc_cb_func.resolve_safe();
- m_flg_nextsc_cb_func.resolve_safe();
- m_dmar_cb_func.resolve_safe();
-
device_hp9845_io_interface *card = get_card_device();
if (card != nullptr) {
@@ -64,37 +58,37 @@ void hp9845_io_slot_device::device_start()
}
}
-WRITE_LINE_MEMBER(hp9845_io_slot_device::irq_w)
+void hp9845_io_slot_device::irq_w(int state)
{
m_irq_cb_func(state);
}
-WRITE_LINE_MEMBER(hp9845_io_slot_device::sts_w)
+void hp9845_io_slot_device::sts_w(int state)
{
m_sts_cb_func(state);
}
-WRITE_LINE_MEMBER(hp9845_io_slot_device::flg_w)
+void hp9845_io_slot_device::flg_w(int state)
{
m_flg_cb_func(state);
}
-WRITE_LINE_MEMBER(hp9845_io_slot_device::irq_nextsc_w)
+void hp9845_io_slot_device::irq_nextsc_w(int state)
{
m_irq_nextsc_cb_func(state);
}
-WRITE_LINE_MEMBER(hp9845_io_slot_device::sts_nextsc_w)
+void hp9845_io_slot_device::sts_nextsc_w(int state)
{
m_sts_nextsc_cb_func(state);
}
-WRITE_LINE_MEMBER(hp9845_io_slot_device::flg_nextsc_w)
+void hp9845_io_slot_device::flg_nextsc_w(int state)
{
m_flg_nextsc_cb_func(state);
}
-WRITE_LINE_MEMBER(hp9845_io_slot_device::dmar_w)
+void hp9845_io_slot_device::dmar_w(int state)
{
m_dmar_cb_func(state);
}
@@ -158,49 +152,49 @@ void device_hp9845_io_interface::interface_pre_start()
throw device_missing_dependencies();
}
-WRITE_LINE_MEMBER(device_hp9845_io_interface::irq_w)
+void device_hp9845_io_interface::irq_w(int state)
{
if (m_slot_dev) {
m_slot_dev->irq_w(state);
}
}
-WRITE_LINE_MEMBER(device_hp9845_io_interface::sts_w)
+void device_hp9845_io_interface::sts_w(int state)
{
if (m_slot_dev) {
m_slot_dev->sts_w(state);
}
}
-WRITE_LINE_MEMBER(device_hp9845_io_interface::flg_w)
+void device_hp9845_io_interface::flg_w(int state)
{
if (m_slot_dev) {
m_slot_dev->flg_w(state);
}
}
-WRITE_LINE_MEMBER(device_hp9845_io_interface::irq_nextsc_w)
+void device_hp9845_io_interface::irq_nextsc_w(int state)
{
if (m_slot_dev) {
m_slot_dev->irq_nextsc_w(state);
}
}
-WRITE_LINE_MEMBER(device_hp9845_io_interface::sts_nextsc_w)
+void device_hp9845_io_interface::sts_nextsc_w(int state)
{
if (m_slot_dev) {
m_slot_dev->sts_nextsc_w(state);
}
}
-WRITE_LINE_MEMBER(device_hp9845_io_interface::flg_nextsc_w)
+void device_hp9845_io_interface::flg_nextsc_w(int state)
{
if (m_slot_dev) {
m_slot_dev->flg_nextsc_w(state);
}
}
-WRITE_LINE_MEMBER(device_hp9845_io_interface::dmar_w)
+void device_hp9845_io_interface::dmar_w(int state)
{
if (m_slot_dev) {
m_slot_dev->dmar_w(state);
diff --git a/src/devices/bus/hp9845_io/hp9845_io.h b/src/devices/bus/hp9845_io/hp9845_io.h
index bebe12c3408..4821c1cd5c9 100644
--- a/src/devices/bus/hp9845_io/hp9845_io.h
+++ b/src/devices/bus/hp9845_io/hp9845_io.h
@@ -51,13 +51,13 @@ public:
auto dmar() { return m_dmar_cb_func.bind(); }
// irq/sts/flg/dmar signal handlers for card devices
- DECLARE_WRITE_LINE_MEMBER(irq_w);
- DECLARE_WRITE_LINE_MEMBER(sts_w);
- DECLARE_WRITE_LINE_MEMBER(flg_w);
- DECLARE_WRITE_LINE_MEMBER(irq_nextsc_w);
- DECLARE_WRITE_LINE_MEMBER(sts_nextsc_w);
- DECLARE_WRITE_LINE_MEMBER(flg_nextsc_w);
- DECLARE_WRITE_LINE_MEMBER(dmar_w);
+ void irq_w(int state);
+ void sts_w(int state);
+ void flg_w(int state);
+ void irq_nextsc_w(int state);
+ void sts_nextsc_w(int state);
+ void flg_nextsc_w(int state);
+ void dmar_w(int state);
// getter for r/w handlers
// return value is SC (negative if no card is attached to slot)
@@ -103,13 +103,13 @@ protected:
required_ioport m_select_code_port;
// card device handling
- DECLARE_WRITE_LINE_MEMBER(irq_w);
- DECLARE_WRITE_LINE_MEMBER(sts_w);
- DECLARE_WRITE_LINE_MEMBER(flg_w);
- DECLARE_WRITE_LINE_MEMBER(irq_nextsc_w);
- DECLARE_WRITE_LINE_MEMBER(sts_nextsc_w);
- DECLARE_WRITE_LINE_MEMBER(flg_nextsc_w);
- DECLARE_WRITE_LINE_MEMBER(dmar_w);
+ void irq_w(int state);
+ void sts_w(int state);
+ void flg_w(int state);
+ void irq_nextsc_w(int state);
+ void sts_nextsc_w(int state);
+ void flg_nextsc_w(int state);
+ void dmar_w(int state);
};
// device type definition
diff --git a/src/devices/bus/hp9845_io/hp9871.cpp b/src/devices/bus/hp9845_io/hp9871.cpp
new file mode 100644
index 00000000000..a1eabbb8b91
--- /dev/null
+++ b/src/devices/bus/hp9845_io/hp9871.cpp
@@ -0,0 +1,116 @@
+// license:BSD-3-Clause
+// copyright-holders: F. Ulivi
+/*********************************************************************
+
+ hp9871.cpp
+
+ HP9871 daisy-wheel printer
+
+*********************************************************************/
+
+#include "emu.h"
+#include "hp9871.h"
+
+// device type definition
+DEFINE_DEVICE_TYPE(HP9871, hp9871_device, "hp9871" , "HP9871 printer")
+
+hp9871_device::hp9871_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, HP9871, tag, owner, clock)
+ , device_hp98032_gpio_interface(mconfig, *this)
+ , m_printer(*this, "printer")
+{
+}
+
+hp9871_device::~hp9871_device()
+{
+}
+
+uint16_t hp9871_device::get_jumpers() const
+{
+ return hp98032_gpio_slot_device::JUMPER_3 |
+ hp98032_gpio_slot_device::JUMPER_5;
+}
+
+uint16_t hp9871_device::input_r() const
+{
+ return 0;
+}
+
+uint8_t hp9871_device::ext_status_r() const
+{
+ // Bit 0: Buffer space available (1)
+ // Bit 1: Ready (0)
+ uint8_t res = 0;
+
+ if (m_printer->is_ready()) {
+ res |= 2;
+ }
+
+ return res;
+}
+
+void hp9871_device::output_w(uint16_t data)
+{
+ m_data = uint8_t(data);
+}
+
+void hp9871_device::ext_control_w(uint8_t data)
+{
+ // N/U
+}
+
+void hp9871_device::pctl_w(int state)
+{
+ if (!state) {
+ m_ibf = true;
+ update_busy();
+ } else {
+ output(m_printer->is_ready());
+ }
+}
+
+void hp9871_device::io_w(int state)
+{
+ // N/U
+}
+
+void hp9871_device::preset_w(int state)
+{
+ // N/U
+}
+
+void hp9871_device::device_add_mconfig(machine_config &config)
+{
+ PRINTER(config, m_printer, 0);
+ m_printer->online_callback().set(FUNC(hp9871_device::printer_online));
+}
+
+void hp9871_device::device_start()
+{
+}
+
+void hp9871_device::device_reset()
+{
+ m_ibf = false;
+ update_busy();
+ psts_w(1);
+}
+
+void hp9871_device::printer_online(int state)
+{
+ output(state);
+}
+
+void hp9871_device::update_busy()
+{
+ pflg_w(!m_ibf);
+}
+
+void hp9871_device::output(bool printer_ready)
+{
+ if (m_ibf && printer_ready) {
+ m_printer->output(m_data);
+ m_ibf = false;
+ update_busy();
+ }
+}
diff --git a/src/devices/bus/hp9845_io/hp9871.h b/src/devices/bus/hp9845_io/hp9871.h
new file mode 100644
index 00000000000..1321c8a69f2
--- /dev/null
+++ b/src/devices/bus/hp9845_io/hp9871.h
@@ -0,0 +1,54 @@
+// license:BSD-3-Clause
+// copyright-holders: F. Ulivi
+/*********************************************************************
+
+ hp9871.h
+
+ HP9871 daisy-wheel printer
+
+*********************************************************************/
+
+#ifndef MAME_BUS_HP9845_IO_HP9871_H
+#define MAME_BUS_HP9845_IO_HP9871_H
+
+#pragma once
+
+#include "98032.h"
+#include "imagedev/printer.h"
+
+class hp9871_device : public device_t, public device_hp98032_gpio_interface
+{
+public:
+ hp9871_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ virtual ~hp9871_device();
+
+ // hp98032_gpio_card_device overrides
+ virtual uint16_t get_jumpers() const override;
+ virtual uint16_t input_r() const override;
+ virtual uint8_t ext_status_r() const override;
+ virtual void output_w(uint16_t data) override;
+ virtual void ext_control_w(uint8_t data) override;
+ virtual void pctl_w(int state) override;
+ virtual void io_w(int state) override;
+ virtual void preset_w(int state) override;
+
+protected:
+ // device-level overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+private:
+ required_device<printer_image_device> m_printer;
+
+ uint8_t m_data;
+ bool m_ibf;
+
+ void printer_online(int state);
+ void update_busy();
+ void output(bool printer_ready);
+};
+
+DECLARE_DEVICE_TYPE(HP9871 , hp9871_device)
+
+#endif /* MAME_BUS_HP9845_IO_HP9871_H */
diff --git a/src/devices/bus/hp9845_io/hp9885.cpp b/src/devices/bus/hp9845_io/hp9885.cpp
index 1fadbc54679..5e5ad89482a 100644
--- a/src/devices/bus/hp9845_io/hp9885.cpp
+++ b/src/devices/bus/hp9845_io/hp9885.cpp
@@ -56,7 +56,7 @@
| 1 1|Unit#| Track # [0..76] |Sector#[0..29]|
+-----+-----+--------------------+--------------+
- *FORMAT TRACK* (not implemented yet)
+ *FORMAT TRACK*
+-----------------------------------------------+
|15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0|
@@ -116,20 +116,20 @@
=====================
Images can be in two formats: MFI & HPI.
- A pre-formatted image must be used as formatting is not supported.
- It's not possible to format images for two reasons: the format
- command is not implemented yet and no dump of the disk system tape
- cartridge (HP part no. 09885-90035) is available.
- The latter is needed during format operation to create the so-called
- bootstraps on disk, which in turn are needed by 9825 systems.
+ 9825 systems with 98217 mass storage ROM store the code of most disk commands
+ on the disk itself in the so-called bootstrap area. Initializing this area
+ during formatting is not supported at the moment as no dump of the disk system
+ tape cartridge (HP part no. 09885-90035) is available. This tape holds the
+ code to be copied into the bootstrap area.
A pre-formatted image (9825_empty.hpi) is available here:
http://www.hpmuseum.net/software/9825_discs.zip
+ Other combinations of system and mass storage ROM (e.g. 9825 with 98228 ROM)
+ do not use bootstrap area at all.
TODO
====
- + Implement missing commands
- + PRESET
+ + Implement missing command
Acknowledgments
===============
@@ -146,6 +146,7 @@
#include "emu.h"
#include "hp9885.h"
+#include "formats/fs_hp98x5.h"
#include "formats/hpi_dsk.h"
// Debugging
@@ -184,13 +185,6 @@ namespace {
// device type definition
DEFINE_DEVICE_TYPE(HP9885, hp9885_device, "hp9885" , "HP9885 floppy drive")
-// Timers
-enum {
- FSM_TMR_ID,
- HEAD_TMR_ID,
- BIT_BYTE_TMR_ID
-};
-
// Constants
constexpr unsigned MAX_TRACK = 76; // Maximum valid track
constexpr unsigned MAX_SECTOR = 29; // Maximum valid sector
@@ -203,6 +197,7 @@ constexpr uint16_t PASSWORD = 0xae87; // "Password" to enable commands
constexpr unsigned HALF_CELL_US = 1; // Half bit cell duration (µs)
constexpr unsigned STATUS_DELAY_US = 100; // Status delay (µs)
constexpr unsigned MISSED_ID_REVS = 2; // Disk rotations to stop ID search
+constexpr uint16_t FORMAT_DATA = 0xc6c6; // Data written into sectors when formatting
// Bits in status word
constexpr unsigned STS_DISK_CHANGED = 2; // Disk changed
@@ -268,7 +263,9 @@ void hp9885_device::output_w(uint16_t data)
void hp9885_device::ext_control_w(uint8_t data)
{
LOG_HS("EXT CTRL %u\n" , data);
- if (BIT(data , 0) &&
+ if (BIT(data, 1)) {
+ device_reset();
+ } else if (BIT(data , 0) &&
!BIT(m_status , STS_XFER_COMPLETE) &&
(m_op == OP_READ || m_op == OP_WRITE)) {
// CTL0 terminates current data transfer
@@ -279,7 +276,7 @@ void hp9885_device::ext_control_w(uint8_t data)
}
}
-WRITE_LINE_MEMBER(hp9885_device::pctl_w)
+void hp9885_device::pctl_w(int state)
{
m_pctl = state;
if (m_pctl) {
@@ -293,19 +290,25 @@ WRITE_LINE_MEMBER(hp9885_device::pctl_w)
update_busy();
}
-WRITE_LINE_MEMBER(hp9885_device::io_w)
+void hp9885_device::io_w(int state)
{
LOG_HS("I/O = %d\n" , state);
}
-WRITE_LINE_MEMBER(hp9885_device::preset_w)
+void hp9885_device::preset_w(int state)
{
LOG("PRESET = %d\n" , state);
+ if (state) {
+ device_reset();
+ }
}
static void hp9885_floppy_formats(format_registration &fr)
{
fr.add(FLOPPY_HPI_FORMAT);
+ fr.add(fs::HP9825);
+ fr.add(fs::HP9831);
+ fr.add(fs::HP9845);
};
void hp9885_device::device_add_mconfig(machine_config &config)
@@ -333,6 +336,7 @@ void hp9885_device::device_start()
save_item(NAME(m_sector_cnt));
save_item(NAME(m_word_cnt));
save_item(NAME(m_rev_cnt));
+ save_item(NAME(m_format_track));
save_item(NAME(m_am_detector));
save_item(NAME(m_crc));
@@ -348,6 +352,7 @@ void hp9885_device::device_start()
void hp9885_device::device_reset()
{
+ LOG("Reset\n");
eir_w(0);
psts_w(1);
m_dskchg = true;
@@ -356,33 +361,36 @@ void hp9885_device::device_reset()
m_seek_track = 0;
m_seek_sector = 0;
m_fsm_state = FSM_RECALIBRATING;
+ m_head_state = HEAD_UNLOADED;
+ m_head_timer->reset();
+ m_op = OP_NONE;
set_state(FSM_IDLE);
}
TIMER_CALLBACK_MEMBER(hp9885_device::fsm_tick)
{
- LOG_TIMER("Tmr %.06f ID %d FSM %d HD %d\n" , machine().time().as_double() , FSM_TMR_ID , m_fsm_state , m_head_state);
+ LOG_TIMER("FSM Tmr %s %d HD %d\n" , machine().time().as_string(6) , m_fsm_state , m_head_state);
do_FSM();
}
TIMER_CALLBACK_MEMBER(hp9885_device::head_tick)
{
- LOG_TIMER("Tmr %.06f ID %d FSM %d HD %d\n" , machine().time().as_double() , HEAD_TMR_ID , m_fsm_state , m_head_state);
+ LOG_TIMER("HD Tmr %s FSM %d HD %d\n" , machine().time().as_string(6) , m_fsm_state , m_head_state);
if (m_head_state == HEAD_SETTLING) {
- LOG_HEAD("%.06f Head loaded\n" , machine().time().as_double());
+ LOG_HEAD("%s Head loaded\n" , machine().time().as_string(6));
m_head_state = HEAD_LOADED;
// Trigger actions to be done on head loading
do_FSM();
m_head_timer->adjust(attotime::from_msec(HEAD_TO_MS - HD_SETTLE_MS));
} else {
- LOG_HEAD("%.06f Head unloaded\n" , machine().time().as_double());
+ LOG_HEAD("%s Head unloaded\n" , machine().time().as_string(6));
m_head_state = HEAD_UNLOADED;
}
}
TIMER_CALLBACK_MEMBER(hp9885_device::bit_byte_tick)
{
- LOG_TIMER("Tmr %.06f ID %d FSM %d HD %d\n" , machine().time().as_double() , BIT_BYTE_TMR_ID , m_fsm_state , m_head_state);
+ LOG_TIMER("BIT Tmr %s FSM %d HD %d\n" , machine().time().as_string(6) , m_fsm_state , m_head_state);
switch (m_fsm_state) {
case FSM_WAIT_ID_AM:
@@ -517,6 +525,79 @@ TIMER_CALLBACK_MEMBER(hp9885_device::bit_byte_tick)
}
break;
+ case FSM_FORMATTING:
+ {
+ // m_word_cnt when formatting one sector
+ // =================
+ // 168 Sync 0000
+ // 167 Sync 0000
+ // 166 Sync FFFF
+ // 165 Sync FFFF
+ // 164 ID AM 70/0E
+ // 163 Sec/Trk
+ // 162 ID CRC
+ // 161 ID post-amble
+ // 160..153
+ // Gap 1 0000
+ // 152 Sync 0000
+ // 151 Sync 0000
+ // 150 Sync FFFF
+ // 149 Sync FFFF
+ // 148 DATA AM 50/0E
+ // 147..20
+ // Sector C6C6
+ // 19 Data CRC
+ // 18 Data post-amble
+ // 17..1
+ // Gap 2 0000
+ if (m_word_cnt == 164) {
+ wr_byte(0x70, 0x0e);
+ } else if (m_word_cnt == 148) {
+ wr_byte(0x50, 0x0e);
+ } else {
+ uint16_t word = 0;
+ if (m_word_cnt == 163 ||
+ m_word_cnt == 147) {
+ preset_crc();
+ }
+ if (m_word_cnt == 166 ||
+ m_word_cnt == 165 ||
+ m_word_cnt == 150 ||
+ m_word_cnt == 149) {
+ word = 0xffff;
+ } else if (m_word_cnt == 163) {
+ // Get sector # from CPU
+ LOG("Format: sector %u\n" , m_input);
+ word = ((m_input & 0xff) << 8) | (m_format_track & 0xff);
+ if (m_sector_cnt < MAX_SECTOR) {
+ set_ibf(false);
+ }
+ } else if (m_word_cnt == 162 ||
+ m_word_cnt == 19) {
+ word = m_crc;
+ } else if (20 <= m_word_cnt &&
+ m_word_cnt <= 147) {
+ word = FORMAT_DATA;
+ }
+ wr_word(word);
+ }
+ if (--m_word_cnt == 0) {
+ if (++m_sector_cnt > MAX_SECTOR) {
+ LOG("Format: final gap\n");
+ set_state(FSM_FORMAT_END);
+ } else {
+ // Next sector
+ m_word_cnt = 168;
+ }
+ }
+ }
+ break;
+
+ case FSM_FORMAT_END:
+ // Keep writing 0s until index pulse comes
+ wr_word(0);
+ break;
+
default:
LOG("Invalid FSM state %d\n" , m_fsm_state);
set_state(FSM_IDLE);
@@ -536,19 +617,39 @@ void hp9885_device::floppy_ready_cb(floppy_image_device *floppy , int state)
void hp9885_device::floppy_index_cb(floppy_image_device *floppy , int state)
{
- if (state && m_rev_cnt && --m_rev_cnt == 0) {
- // Sector not found
- LOG("Sector not found\n");
- stop_rdwr();
- set_error(ERR_ID_ERROR);
- output_status(true);
+ if (state) {
+ if (m_fsm_state == FSM_WAIT_INDEX) {
+ LOG("Format: got index\n");
+ set_state(FSM_FORMATTING);
+ // See bit_byte_tick function
+ m_word_cnt = 167;
+ m_pll.set_clock(attotime::from_usec(HALF_CELL_US));
+ m_pll.start_writing(machine().time());
+ m_pll.read_reset(machine().time());
+ m_had_transition = false;
+ // Start by writing 1st sync word
+ wr_word(0);
+ m_sector_cnt = 0;
+ m_bit_byte_timer->adjust(m_pll.ctime - machine().time());
+ } else if (m_fsm_state == FSM_FORMAT_END) {
+ LOG("Format: ended\n");
+ m_pll.stop_writing(m_drive , m_pll.ctime);
+ BIT_SET(m_status , STS_XFER_COMPLETE);
+ output_status();
+ } else if (m_rev_cnt && --m_rev_cnt == 0) {
+ // Sector not found
+ LOG("Sector not found\n");
+ stop_rdwr();
+ set_error(ERR_ID_ERROR);
+ output_status(true);
+ }
}
}
void hp9885_device::set_state(int new_state)
{
if (m_fsm_state != new_state) {
- LOG("%.06f FSM %d->%d\n" , machine().time().as_double() , m_fsm_state , new_state);
+ LOG("%s FSM %d->%d\n" , machine().time().as_string(6) , m_fsm_state , new_state);
m_fsm_state = new_state;
if (m_fsm_state == FSM_IDLE) {
m_op = OP_NONE;
@@ -669,8 +770,20 @@ void hp9885_device::new_word()
uint8_t sect_no = m_input & 0x1f;
if (sect_no == 0x1e) {
// Format
- LOG("Format\n");
- // TODO:
+ LOG("Format track %u\n", track_no);
+ init_status(unit_no);
+ if (!BIT(m_status , STS_NOT_RDY) && !BIT(m_status , STS_WRITE_PROTECT)) {
+ m_op = OP_FORMAT;
+ m_format_track = track_no;
+ set_state(FSM_POSITIONING);
+ if (load_head()) {
+ m_fsm_timer->adjust(attotime::zero);
+ }
+ set_ibf(false);
+ } else {
+ encode_error(true);
+ output_status(true);
+ }
} else if (sect_no == 0x1f) {
switch (track_no) {
case 0x7c:
@@ -744,7 +857,7 @@ void hp9885_device::new_word()
break;
default:
- if (m_op != OP_WRITE) {
+ if (m_op != OP_WRITE && m_op != OP_FORMAT) {
LOG("Got data in state %d!\n" , m_fsm_state);
}
}
@@ -781,6 +894,10 @@ void hp9885_device::do_FSM()
// Set seek complete
BIT_SET(m_status , STS_SEEK_COMPLETE);
output_status();
+ } else if (m_op == OP_FORMAT) {
+ // Format
+ LOG("Format: waiting for index\n");
+ set_state(FSM_WAIT_INDEX);
} else {
// Get status
output_status();
@@ -826,13 +943,13 @@ bool hp9885_device::load_head()
switch (m_head_state) {
case HEAD_UNLOADED:
case HEAD_SETTLING:
- LOG_HEAD("%.06f Loading head..\n" , machine().time().as_double());
+ LOG_HEAD("%s Loading head..\n" , machine().time().as_string(6));
m_head_state = HEAD_SETTLING;
m_head_timer->adjust(attotime::from_msec(HD_SETTLE_MS));
return false;
case HEAD_LOADED:
- LOG_HEAD("%.06f Keep head loaded\n" , machine().time().as_double());
+ LOG_HEAD("%s Keep head loaded\n" , machine().time().as_string(6));
m_head_timer->adjust(attotime::from_msec(HEAD_TO_MS));
return true;
@@ -859,7 +976,7 @@ void hp9885_device::one_step(bool outward)
m_track++;
}
}
- LOG_HEAD("%.06f Step to trk %u\n" , machine().time().as_double() , m_track);
+ LOG_HEAD("%s Step to trk %u\n" , machine().time().as_string(6) , m_track);
m_drive->dir_w(outward);
m_drive->stp_w(0);
m_drive->stp_w(1);
@@ -909,11 +1026,11 @@ uint16_t hp9885_device::rd_word()
return word;
}
-void hp9885_device::wr_word(uint16_t word)
+void hp9885_device::wr_byte(uint8_t data, uint8_t clock)
{
- for (unsigned i = 0; i < 16; ++i) {
- bool data_bit = BIT(word , i);
- bool clock_bit = !data_bit && !m_had_transition;
+ for (unsigned i = 0; i < 8; ++i) {
+ bool data_bit = BIT(data , i);
+ bool clock_bit = !data_bit && (BIT(clock, i) || !m_had_transition);
m_had_transition = data_bit || clock_bit;
attotime dummy;
@@ -924,6 +1041,12 @@ void hp9885_device::wr_word(uint16_t word)
m_pll.commit(m_drive , m_pll.ctime);
}
+void hp9885_device::wr_word(uint16_t word)
+{
+ wr_byte(uint8_t(word & 0xff), 0);
+ wr_byte(uint8_t(word >> 8), 0);
+}
+
void hp9885_device::preset_crc()
{
m_crc = ~0;
diff --git a/src/devices/bus/hp9845_io/hp9885.h b/src/devices/bus/hp9845_io/hp9885.h
index 1c9af5c3066..414f34688e2 100644
--- a/src/devices/bus/hp9845_io/hp9885.h
+++ b/src/devices/bus/hp9845_io/hp9885.h
@@ -29,9 +29,9 @@ public:
virtual uint8_t ext_status_r() const override;
virtual void output_w(uint16_t data) override;
virtual void ext_control_w(uint8_t data) override;
- virtual DECLARE_WRITE_LINE_MEMBER(pctl_w) override;
- virtual DECLARE_WRITE_LINE_MEMBER(io_w) override;
- virtual DECLARE_WRITE_LINE_MEMBER(preset_w) override;
+ virtual void pctl_w(int state) override;
+ virtual void io_w(int state) override;
+ virtual void preset_w(int state) override;
protected:
// device-level overrides
@@ -55,7 +55,10 @@ private:
FSM_RD_ID,
FSM_WAIT_DATA_AM,
FSM_RD_DATA,
- FSM_WR_DATA
+ FSM_WR_DATA,
+ FSM_WAIT_INDEX,
+ FSM_FORMATTING,
+ FSM_FORMAT_END
};
// Head states
@@ -71,7 +74,8 @@ private:
OP_READ,
OP_WRITE,
OP_STEP_IN,
- OP_GET_STATUS
+ OP_GET_STATUS,
+ OP_FORMAT
};
required_device<floppy_connector> m_drive_connector;
@@ -94,6 +98,7 @@ private:
unsigned m_sector_cnt;
unsigned m_word_cnt;
unsigned m_rev_cnt;
+ unsigned m_format_track;
uint32_t m_am_detector;
uint16_t m_crc; // x^15 is stored in LSB
@@ -125,6 +130,7 @@ private:
void start_rd();
void stop_rdwr();
uint16_t rd_word();
+ void wr_byte(uint8_t data, uint8_t clock);
void wr_word(uint16_t word);
void preset_crc();
void update_crc(bool bit);
diff --git a/src/devices/bus/hp_dio/hp98265a.cpp b/src/devices/bus/hp_dio/hp98265a.cpp
index 5ca9d128b53..e52a72ca032 100644
--- a/src/devices/bus/hp_dio/hp98265a.cpp
+++ b/src/devices/bus/hp_dio/hp98265a.cpp
@@ -253,7 +253,7 @@ void dio16_98265a_device::update_irq(bool state)
irq6_out(state && irq_level == 3);
}
-WRITE_LINE_MEMBER(dio16_98265a_device::irq_w)
+void dio16_98265a_device::irq_w(int state)
{
LOG("%s: %s\n", __FUNCTION__, state ? "true" : "false");
@@ -288,7 +288,7 @@ void dio16_98265a_device::update_dma()
dmar0_out((m_control & REG_CONTROL_DE0) && m_dmar0);
dmar1_out((m_control & REG_CONTROL_DE1) && m_dmar0);
}
-WRITE_LINE_MEMBER(dio16_98265a_device::dmar0_w)
+void dio16_98265a_device::dmar0_w(int state)
{
m_dmar0 = state;
update_dma();
diff --git a/src/devices/bus/hp_dio/hp98265a.h b/src/devices/bus/hp_dio/hp98265a.h
index 8246f9bb743..c21ad6e5bbe 100644
--- a/src/devices/bus/hp_dio/hp98265a.h
+++ b/src/devices/bus/hp_dio/hp98265a.h
@@ -40,9 +40,9 @@ protected:
void dmack_w_in(int channel, uint8_t data) override;
uint8_t dmack_r_in(int channel) override;
- DECLARE_WRITE_LINE_MEMBER(dmar0_w);
+ void dmar0_w(int state);
- DECLARE_WRITE_LINE_MEMBER(irq_w);
+ void irq_w(int state);
required_device<nscsi_bus_device> m_scsibus;
required_device<mb87030_device> m_spc;
diff --git a/src/devices/bus/hp_dio/hp98543.cpp b/src/devices/bus/hp_dio/hp98543.cpp
index a2bfb82f5ee..a84abd856d8 100644
--- a/src/devices/bus/hp_dio/hp98543.cpp
+++ b/src/devices/bus/hp_dio/hp98543.cpp
@@ -166,31 +166,31 @@ void dio16_98543_device::vram_w(offs_t offset, uint16_t data, uint16_t mem_mask)
tc->vram_w(offset, data, mem_mask);
}
-WRITE_LINE_MEMBER(dio16_98543_device::vblank_w)
+void dio16_98543_device::vblank_w(int state)
{
for (auto &tc: m_topcat)
tc->vblank_w(state);
}
-WRITE_LINE_MEMBER(dio16_98543_device::int0_w)
+void dio16_98543_device::int0_w(int state)
{
m_ints[0] = state;
update_int();
}
-WRITE_LINE_MEMBER(dio16_98543_device::int1_w)
+void dio16_98543_device::int1_w(int state)
{
m_ints[1] = state;
update_int();
}
-WRITE_LINE_MEMBER(dio16_98543_device::int2_w)
+void dio16_98543_device::int2_w(int state)
{
m_ints[2] = state;
update_int();
}
-WRITE_LINE_MEMBER(dio16_98543_device::int3_w)
+void dio16_98543_device::int3_w(int state)
{
m_ints[3] = state;
diff --git a/src/devices/bus/hp_dio/hp98543.h b/src/devices/bus/hp_dio/hp98543.h
index c1e86126880..56eb194d7e3 100644
--- a/src/devices/bus/hp_dio/hp98543.h
+++ b/src/devices/bus/hp_dio/hp98543.h
@@ -47,11 +47,11 @@ protected:
virtual space_config_vector memory_space_config() const override;
private:
- WRITE_LINE_MEMBER(vblank_w);
- WRITE_LINE_MEMBER(int0_w);
- WRITE_LINE_MEMBER(int1_w);
- WRITE_LINE_MEMBER(int2_w);
- WRITE_LINE_MEMBER(int3_w);
+ void vblank_w(int state);
+ void int0_w(int state);
+ void int1_w(int state);
+ void int2_w(int state);
+ void int3_w(int state);
const address_space_config m_space_config;
void map(address_map &map);
diff --git a/src/devices/bus/hp_dio/hp98544.cpp b/src/devices/bus/hp_dio/hp98544.cpp
index 420dc93919f..ab566822293 100644
--- a/src/devices/bus/hp_dio/hp98544.cpp
+++ b/src/devices/bus/hp_dio/hp98544.cpp
@@ -138,12 +138,12 @@ void dio16_98544_device::rom_w(offs_t offset, uint16_t data)
}
}
-WRITE_LINE_MEMBER(dio16_98544_device::vblank_w)
+void dio16_98544_device::vblank_w(int state)
{
m_topcat->vblank_w(state);
}
-WRITE_LINE_MEMBER(dio16_98544_device::int_w)
+void dio16_98544_device::int_w(int state)
{
int line = (m_intreg >> 3) & 7;
diff --git a/src/devices/bus/hp_dio/hp98544.h b/src/devices/bus/hp_dio/hp98544.h
index a490f765c84..8f18d54d76b 100644
--- a/src/devices/bus/hp_dio/hp98544.h
+++ b/src/devices/bus/hp_dio/hp98544.h
@@ -43,8 +43,8 @@ public:
virtual space_config_vector memory_space_config() const override;
private:
- WRITE_LINE_MEMBER(vblank_w);
- WRITE_LINE_MEMBER(int_w);
+ void vblank_w(int state);
+ void int_w(int state);
static constexpr int m_v_pix = 768;
static constexpr int m_h_pix = 1024;
diff --git a/src/devices/bus/hp_dio/hp98550.cpp b/src/devices/bus/hp_dio/hp98550.cpp
index 54b89418680..935c03eea6c 100644
--- a/src/devices/bus/hp_dio/hp98550.cpp
+++ b/src/devices/bus/hp_dio/hp98550.cpp
@@ -174,7 +174,7 @@ void dio32_98550_device::vram_w(offs_t offset, uint16_t data, uint16_t mem_mask)
ce->vram_w(offset, data, mem_mask);
}
-WRITE_LINE_MEMBER(dio32_98550_device::vblank_w)
+void dio32_98550_device::vblank_w(int state)
{
for (auto &ce: m_catseye)
ce->vblank_w(state);
diff --git a/src/devices/bus/hp_dio/hp98550.h b/src/devices/bus/hp_dio/hp98550.h
index eca4da5bed6..a577cdb6388 100644
--- a/src/devices/bus/hp_dio/hp98550.h
+++ b/src/devices/bus/hp_dio/hp98550.h
@@ -48,7 +48,7 @@ protected:
virtual space_config_vector memory_space_config() const override;
- DECLARE_WRITE_LINE_MEMBER(vblank_w);
+ void vblank_w(int state);
void int_w(offs_t offset, uint8_t data);
const address_space_config m_space_config;
diff --git a/src/devices/bus/hp_dio/hp98620.cpp b/src/devices/bus/hp_dio/hp98620.cpp
index 88a8491fae8..0dc7add46c7 100644
--- a/src/devices/bus/hp_dio/hp98620.cpp
+++ b/src/devices/bus/hp_dio/hp98620.cpp
@@ -354,7 +354,7 @@ void dio16_98620_device::dma_transfer(int channel)
m_regs[channel].subcount--;
}
-WRITE_LINE_MEMBER(dio16_98620_device::dmar0_in)
+void dio16_98620_device::dmar0_in(int state)
{
LOG("%s: %d\n", __FUNCTION__, state);
m_dmar[0] = state;
@@ -364,7 +364,7 @@ WRITE_LINE_MEMBER(dio16_98620_device::dmar0_in)
dma_transfer(0);
}
-WRITE_LINE_MEMBER(dio16_98620_device::dmar1_in)
+void dio16_98620_device::dmar1_in(int state)
{
LOG("%s: %d\n", __FUNCTION__, state);
m_dmar[1] = state;
diff --git a/src/devices/bus/hp_dio/hp98620.h b/src/devices/bus/hp_dio/hp98620.h
index d8779f0e852..7a4b65f34f0 100644
--- a/src/devices/bus/hp_dio/hp98620.h
+++ b/src/devices/bus/hp_dio/hp98620.h
@@ -29,7 +29,7 @@ protected:
uint16_t dma_r(offs_t offset);
void dma_w(offs_t offset, uint16_t data);
- DECLARE_WRITE_LINE_MEMBER(irq_w);
+ void irq_w(int state);
private:
@@ -89,8 +89,8 @@ private:
static constexpr int REG1_1TQ4_CONTROL = 0x208;
static constexpr int REG1_1TQ4_STATUS = 0x20a;
- WRITE_LINE_MEMBER(dmar0_in) override;
- WRITE_LINE_MEMBER(dmar1_in) override;
+ void dmar0_in(int state) override;
+ void dmar1_in(int state) override;
void dma_transfer(int channel);
void update_irq();
diff --git a/src/devices/bus/hp_dio/hp98643.cpp b/src/devices/bus/hp_dio/hp98643.cpp
index f665303097a..1d8934f739a 100644
--- a/src/devices/bus/hp_dio/hp98643.cpp
+++ b/src/devices/bus/hp_dio/hp98643.cpp
@@ -114,7 +114,7 @@ void dio16_98643_device::device_reset()
m_sc |= get_irq_line() << 4;
}
-WRITE_LINE_MEMBER(dio16_98643_device::lance_int_w)
+void dio16_98643_device::lance_int_w(int state)
{
if (state)
m_sc &= ~REG_SC_IP;
diff --git a/src/devices/bus/hp_dio/hp98643.h b/src/devices/bus/hp_dio/hp98643.h
index c1944bb1b8f..e58a973ae8f 100644
--- a/src/devices/bus/hp_dio/hp98643.h
+++ b/src/devices/bus/hp_dio/hp98643.h
@@ -62,7 +62,7 @@ private:
uint16_t novram_r(offs_t offset);
void novram_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
- DECLARE_WRITE_LINE_MEMBER(lance_int_w);
+ void lance_int_w(int state);
void lance_dma_out(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
uint16_t lance_dma_in(offs_t offset);
diff --git a/src/devices/bus/hp_dio/hp98644.cpp b/src/devices/bus/hp_dio/hp98644.cpp
index d74b8c02fea..5551d537bf3 100644
--- a/src/devices/bus/hp_dio/hp98644.cpp
+++ b/src/devices/bus/hp_dio/hp98644.cpp
@@ -186,7 +186,7 @@ uint16_t dio16_98644_device::io_r(offs_t offset)
break;
case 1:
- ret = m_control | m_control << 8 | \
+ ret = m_control | m_control << 8 |
(((m_switches->read() >> REG_SWITCHES_INT_LEVEL_SHIFT) & REG_SWITCHES_INT_LEVEL_MASK) << 4);
break;
diff --git a/src/devices/bus/hp_dio/hp_dio.cpp b/src/devices/bus/hp_dio/hp_dio.cpp
index 647b28f83c9..6406b572b3b 100644
--- a/src/devices/bus/hp_dio/hp_dio.cpp
+++ b/src/devices/bus/hp_dio/hp_dio.cpp
@@ -127,16 +127,6 @@ dio16_device::dio16_device(const machine_config &mconfig, device_type type, cons
void dio16_device::device_start()
{
- m_irq1_out_cb.resolve_safe();
- m_irq2_out_cb.resolve_safe();
- m_irq3_out_cb.resolve_safe();
- m_irq4_out_cb.resolve_safe();
- m_irq5_out_cb.resolve_safe();
- m_irq6_out_cb.resolve_safe();
- m_irq7_out_cb.resolve_safe();
- m_dmar0_out_cb.resolve_safe();
- m_dmar1_out_cb.resolve_safe();
-
m_prgwidth = m_prgspace->data_width();
save_item(NAME(m_irq));
@@ -245,7 +235,7 @@ uint8_t dio16_device::dmack_r_out(int index, int channel)
return ret;
}
-WRITE_LINE_MEMBER(dio16_device::reset_in)
+void dio16_device::reset_in(int state)
{
for (auto &card : m_cards) {
if (card->get_index() != m_bus_index)
diff --git a/src/devices/bus/hp_dio/hp_dio.h b/src/devices/bus/hp_dio/hp_dio.h
index c3ad5e0d178..1b8c850c1c4 100644
--- a/src/devices/bus/hp_dio/hp_dio.h
+++ b/src/devices/bus/hp_dio/hp_dio.h
@@ -93,27 +93,27 @@ public:
// IRQs 1, 2, and 7 are reserved for non-bus usage.
// input lines
- DECLARE_WRITE_LINE_MEMBER(dmar0_in) { set_dmar(m_bus_index, 0, state); }
- DECLARE_WRITE_LINE_MEMBER(dmar1_in) { set_dmar(m_bus_index, 1, state); }
- DECLARE_WRITE_LINE_MEMBER(irq1_in) { set_irq(m_bus_index, 0, state); }
- DECLARE_WRITE_LINE_MEMBER(irq2_in) { set_irq(m_bus_index, 1, state); }
- DECLARE_WRITE_LINE_MEMBER(irq3_in) { set_irq(m_bus_index, 2, state); }
- DECLARE_WRITE_LINE_MEMBER(irq4_in) { set_irq(m_bus_index, 3, state); }
- DECLARE_WRITE_LINE_MEMBER(irq5_in) { set_irq(m_bus_index, 4, state); }
- DECLARE_WRITE_LINE_MEMBER(irq6_in) { set_irq(m_bus_index, 5, state); }
- DECLARE_WRITE_LINE_MEMBER(irq7_in) { set_irq(m_bus_index, 6, state); }
- DECLARE_WRITE_LINE_MEMBER(reset_in);
+ void dmar0_in(int state) { set_dmar(m_bus_index, 0, state); }
+ void dmar1_in(int state) { set_dmar(m_bus_index, 1, state); }
+ void irq1_in(int state) { set_irq(m_bus_index, 0, state); }
+ void irq2_in(int state) { set_irq(m_bus_index, 1, state); }
+ void irq3_in(int state) { set_irq(m_bus_index, 2, state); }
+ void irq4_in(int state) { set_irq(m_bus_index, 3, state); }
+ void irq5_in(int state) { set_irq(m_bus_index, 4, state); }
+ void irq6_in(int state) { set_irq(m_bus_index, 5, state); }
+ void irq7_in(int state) { set_irq(m_bus_index, 6, state); }
+ void reset_in(int state);
// output lines
- DECLARE_READ_LINE_MEMBER(irq1_out) const { return (m_irq[0] & ~m_bus_index) ? 1 : 0; }
- DECLARE_READ_LINE_MEMBER(irq2_out) const { return (m_irq[1] & ~m_bus_index) ? 1 : 0; }
- DECLARE_READ_LINE_MEMBER(irq3_out) const { return (m_irq[2] & ~m_bus_index) ? 1 : 0; }
- DECLARE_READ_LINE_MEMBER(irq4_out) const { return (m_irq[3] & ~m_bus_index) ? 1 : 0; }
- DECLARE_READ_LINE_MEMBER(irq5_out) const { return (m_irq[4] & ~m_bus_index) ? 1 : 0; }
- DECLARE_READ_LINE_MEMBER(irq6_out) const { return (m_irq[5] & ~m_bus_index) ? 1 : 0; }
- DECLARE_READ_LINE_MEMBER(irq7_out) const { return (m_irq[6] & ~m_bus_index) ? 1 : 0; }
- DECLARE_READ_LINE_MEMBER(dmar0_out) const { return dmar0_r(); }
- DECLARE_READ_LINE_MEMBER(dmar1_out) const { return dmar1_r(); }
+ int irq1_out() const { return (m_irq[0] & ~m_bus_index) ? 1 : 0; }
+ int irq2_out() const { return (m_irq[1] & ~m_bus_index) ? 1 : 0; }
+ int irq3_out() const { return (m_irq[2] & ~m_bus_index) ? 1 : 0; }
+ int irq4_out() const { return (m_irq[3] & ~m_bus_index) ? 1 : 0; }
+ int irq5_out() const { return (m_irq[4] & ~m_bus_index) ? 1 : 0; }
+ int irq6_out() const { return (m_irq[5] & ~m_bus_index) ? 1 : 0; }
+ int irq7_out() const { return (m_irq[6] & ~m_bus_index) ? 1 : 0; }
+ int dmar0_out() const { return dmar0_r(); }
+ int dmar1_out() const { return dmar1_r(); }
bool dmar0_r() const { return (m_dmar[0] & ~m_bus_index) ? 1 : 0; }
bool dmar1_r() const { return (m_dmar[1] & ~m_bus_index) ? 1 : 0; }
@@ -187,32 +187,32 @@ protected:
int get_index() { return m_index; }
address_space &program_space() { return m_dio_dev->program_space(); }
- DECLARE_WRITE_LINE_MEMBER(irq1_out) { m_dio_dev->set_irq(m_index, 0, state); }
- DECLARE_WRITE_LINE_MEMBER(irq2_out) { m_dio_dev->set_irq(m_index, 1, state); }
- DECLARE_WRITE_LINE_MEMBER(irq3_out) { m_dio_dev->set_irq(m_index, 2, state); }
- DECLARE_WRITE_LINE_MEMBER(irq4_out) { m_dio_dev->set_irq(m_index, 3, state); }
- DECLARE_WRITE_LINE_MEMBER(irq5_out) { m_dio_dev->set_irq(m_index, 4, state); }
- DECLARE_WRITE_LINE_MEMBER(irq6_out) { m_dio_dev->set_irq(m_index, 5, state); }
- DECLARE_WRITE_LINE_MEMBER(irq7_out) { m_dio_dev->set_irq(m_index, 6, state); }
- DECLARE_WRITE_LINE_MEMBER(dmar0_out) { m_dio_dev->set_dmar(m_index, 0, state); }
- DECLARE_WRITE_LINE_MEMBER(dmar1_out) { m_dio_dev->set_dmar(m_index, 1, state); }
-
- virtual DECLARE_WRITE_LINE_MEMBER(irq1_in) {}
- virtual DECLARE_WRITE_LINE_MEMBER(irq2_in) {}
- virtual DECLARE_WRITE_LINE_MEMBER(irq3_in) {}
- virtual DECLARE_WRITE_LINE_MEMBER(irq4_in) {}
- virtual DECLARE_WRITE_LINE_MEMBER(irq5_in) {}
- virtual DECLARE_WRITE_LINE_MEMBER(irq6_in) {}
- virtual DECLARE_WRITE_LINE_MEMBER(irq7_in) {}
- virtual DECLARE_WRITE_LINE_MEMBER(dmar0_in) {}
- virtual DECLARE_WRITE_LINE_MEMBER(dmar1_in) {}
+ void irq1_out(int state) { m_dio_dev->set_irq(m_index, 0, state); }
+ void irq2_out(int state) { m_dio_dev->set_irq(m_index, 1, state); }
+ void irq3_out(int state) { m_dio_dev->set_irq(m_index, 2, state); }
+ void irq4_out(int state) { m_dio_dev->set_irq(m_index, 3, state); }
+ void irq5_out(int state) { m_dio_dev->set_irq(m_index, 4, state); }
+ void irq6_out(int state) { m_dio_dev->set_irq(m_index, 5, state); }
+ void irq7_out(int state) { m_dio_dev->set_irq(m_index, 6, state); }
+ void dmar0_out(int state) { m_dio_dev->set_dmar(m_index, 0, state); }
+ void dmar1_out(int state) { m_dio_dev->set_dmar(m_index, 1, state); }
+
+ virtual void irq1_in(int state) {}
+ virtual void irq2_in(int state) {}
+ virtual void irq3_in(int state) {}
+ virtual void irq4_in(int state) {}
+ virtual void irq5_in(int state) {}
+ virtual void irq6_in(int state) {}
+ virtual void irq7_in(int state) {}
+ virtual void dmar0_in(int state) {}
+ virtual void dmar1_in(int state) {}
virtual uint8_t dmack_r_out(int channel) { return m_dio_dev->dmack_r_out(m_index, channel); }
virtual void dmack_w_out(int channel, uint8_t data) { m_dio_dev->dmack_w_out(m_index, channel, data); }
virtual uint8_t dmack_r_in(int channel) { return 0xff; }
virtual void dmack_w_in(int channel, uint8_t data) {}
- virtual DECLARE_WRITE_LINE_MEMBER(reset_in) {}
+ virtual void reset_in(int state) {}
bool dmar0_r() const { return m_dio_dev->dmar0_r(); }
bool dmar1_r() const { return m_dio_dev->dmar1_r(); }
diff --git a/src/devices/bus/hp_dio/human_interface.cpp b/src/devices/bus/hp_dio/human_interface.cpp
index a0957977f10..669c77e4ffb 100644
--- a/src/devices/bus/hp_dio/human_interface.cpp
+++ b/src/devices/bus/hp_dio/human_interface.cpp
@@ -166,7 +166,7 @@ void human_interface_device::device_reset()
m_iocpu->reset();
}
-WRITE_LINE_MEMBER(human_interface_device::reset_in)
+void human_interface_device::reset_in(int state)
{
if (state)
device_reset();
@@ -178,7 +178,7 @@ void human_interface_device::update_gpib_irq()
((m_ppoll_sc & (PPOLL_IR|PPOLL_IE)) == (PPOLL_IR|PPOLL_IE))) ? ASSERT_LINE : CLEAR_LINE);
}
-WRITE_LINE_MEMBER(human_interface_device::gpib_irq)
+void human_interface_device::gpib_irq(int state)
{
m_gpib_irq_line = state;
update_gpib_irq();
@@ -189,7 +189,7 @@ void human_interface_device::update_gpib_dma()
dmar0_out(m_gpib_dma_enable && m_gpib_dma_line);
}
-WRITE_LINE_MEMBER(human_interface_device::gpib_dreq)
+void human_interface_device::gpib_dreq(int state)
{
m_gpib_dma_line = state;
update_gpib_dma();
@@ -338,7 +338,7 @@ uint8_t human_interface_device::iocpu_test0_r()
return !m_mlc->get_int();
}
-WRITE_LINE_MEMBER(human_interface_device::rtc_d0_w)
+void human_interface_device::rtc_d0_w(int state)
{
if (state)
m_rtc_data |= 1;
@@ -347,7 +347,7 @@ WRITE_LINE_MEMBER(human_interface_device::rtc_d0_w)
}
-WRITE_LINE_MEMBER(human_interface_device::rtc_d1_w)
+void human_interface_device::rtc_d1_w(int state)
{
if (state)
m_rtc_data |= 2;
@@ -355,7 +355,7 @@ WRITE_LINE_MEMBER(human_interface_device::rtc_d1_w)
m_rtc_data &= ~2;
}
-WRITE_LINE_MEMBER(human_interface_device::rtc_d2_w)
+void human_interface_device::rtc_d2_w(int state)
{
if (state)
m_rtc_data |= 4;
@@ -364,7 +364,7 @@ WRITE_LINE_MEMBER(human_interface_device::rtc_d2_w)
}
-WRITE_LINE_MEMBER(human_interface_device::rtc_d3_w)
+void human_interface_device::rtc_d3_w(int state)
{
if (state)
m_rtc_data |= 8;
diff --git a/src/devices/bus/hp_dio/human_interface.h b/src/devices/bus/hp_dio/human_interface.h
index 2e1d1376211..0f6f3d04106 100644
--- a/src/devices/bus/hp_dio/human_interface.h
+++ b/src/devices/bus/hp_dio/human_interface.h
@@ -46,16 +46,16 @@ private:
void gpib_w(offs_t offset, uint8_t data);
void ieee488_dio_w(uint8_t data);
- DECLARE_WRITE_LINE_MEMBER(gpib_irq);
- DECLARE_WRITE_LINE_MEMBER(gpib_dreq);
+ void gpib_irq(int state);
+ void gpib_dreq(int state);
/* RTC */
- DECLARE_WRITE_LINE_MEMBER(rtc_d0_w);
- DECLARE_WRITE_LINE_MEMBER(rtc_d1_w);
- DECLARE_WRITE_LINE_MEMBER(rtc_d2_w);
- DECLARE_WRITE_LINE_MEMBER(rtc_d3_w);
+ void rtc_d0_w(int state);
+ void rtc_d1_w(int state);
+ void rtc_d2_w(int state);
+ void rtc_d3_w(int state);
- DECLARE_WRITE_LINE_MEMBER(reset_in) override;
+ void reset_in(int state) override;
void dmack_w_in(int channel, uint8_t data) override;
uint8_t dmack_r_in(int channel) override;
diff --git a/src/devices/bus/hp_hil/hp_hil.cpp b/src/devices/bus/hp_hil/hp_hil.cpp
index e86b9b24a9c..e1e477b5d58 100644
--- a/src/devices/bus/hp_hil/hp_hil.cpp
+++ b/src/devices/bus/hp_hil/hp_hil.cpp
@@ -79,10 +79,6 @@ void hp_hil_mlc_device::add_hp_hil_device(device_hp_hil_interface *device)
//-------------------------------------------------
void hp_hil_mlc_device::device_start()
{
- // resolve callbacks
- int_cb.resolve_safe();
- nmi_cb.resolve_safe();
-
save_item(NAME(m_r2));
save_item(NAME(m_r3));
save_item(NAME(m_w1));
@@ -225,7 +221,7 @@ void hp_hil_mlc_device::hil_write(uint16_t data)
}
}
-WRITE_LINE_MEMBER(hp_hil_mlc_device::ap_w)
+void hp_hil_mlc_device::ap_w(int state)
{
uint16_t data = HPMLC_W1_C | HPHIL_POL;
if (state && (m_w3 & HPMLC_W3_APE))
diff --git a/src/devices/bus/hp_hil/hp_hil.h b/src/devices/bus/hp_hil/hp_hil.h
index c50c4742340..b4302ac1895 100644
--- a/src/devices/bus/hp_hil/hp_hil.h
+++ b/src/devices/bus/hp_hil/hp_hil.h
@@ -127,7 +127,7 @@ public:
uint8_t read(offs_t offset);
void write(offs_t offset, uint8_t data);
- DECLARE_WRITE_LINE_MEMBER(ap_w);
+ void ap_w(int state);
void hil_write(uint16_t data);
diff --git a/src/devices/bus/hp_ipc_io/82919.cpp b/src/devices/bus/hp_ipc_io/82919.cpp
index e5835ebafc7..901350f5bdd 100644
--- a/src/devices/bus/hp_ipc_io/82919.cpp
+++ b/src/devices/bus/hp_ipc_io/82919.cpp
@@ -82,13 +82,13 @@ void hp82919_io_card_device::write(offs_t addr , uint8_t data)
}
}
-WRITE_LINE_MEMBER(hp82919_io_card_device::uart_irq)
+void hp82919_io_card_device::uart_irq(int state)
{
m_uart_int = state;
update_irq();
}
-WRITE_LINE_MEMBER(hp82919_io_card_device::uart_a_tx)
+void hp82919_io_card_device::uart_a_tx(int state)
{
m_rs232_prim->write_txd(state);
if (m_loopback) {
@@ -96,7 +96,7 @@ WRITE_LINE_MEMBER(hp82919_io_card_device::uart_a_tx)
}
}
-WRITE_LINE_MEMBER(hp82919_io_card_device::uart_b_tx)
+void hp82919_io_card_device::uart_b_tx(int state)
{
m_rs232_sec->write_txd(state);
if (m_loopback) {
@@ -121,56 +121,56 @@ void hp82919_io_card_device::uart_output(uint8_t data)
}
}
-WRITE_LINE_MEMBER(hp82919_io_card_device::prim_rxd)
+void hp82919_io_card_device::prim_rxd(int state)
{
if (!m_loopback) {
m_uart->rx_a_w(state);
}
}
-WRITE_LINE_MEMBER(hp82919_io_card_device::prim_dcd)
+void hp82919_io_card_device::prim_dcd(int state)
{
if (!m_loopback) {
m_uart->ip3_w(state);
}
}
-WRITE_LINE_MEMBER(hp82919_io_card_device::prim_dsr)
+void hp82919_io_card_device::prim_dsr(int state)
{
if (!m_loopback) {
m_uart->ip1_w(state);
}
}
-WRITE_LINE_MEMBER(hp82919_io_card_device::prim_ri)
+void hp82919_io_card_device::prim_ri(int state)
{
if (!m_loopback) {
m_uart->ip2_w(state);
}
}
-WRITE_LINE_MEMBER(hp82919_io_card_device::prim_cts)
+void hp82919_io_card_device::prim_cts(int state)
{
if (!m_loopback) {
m_uart->ip0_w(state);
}
}
-WRITE_LINE_MEMBER(hp82919_io_card_device::sec_rxd)
+void hp82919_io_card_device::sec_rxd(int state)
{
if (!m_loopback) {
m_uart->rx_b_w(state);
}
}
-WRITE_LINE_MEMBER(hp82919_io_card_device::sec_dcd)
+void hp82919_io_card_device::sec_dcd(int state)
{
if (!m_loopback) {
m_uart->ip5_w(state);
}
}
-WRITE_LINE_MEMBER(hp82919_io_card_device::sec_cts)
+void hp82919_io_card_device::sec_cts(int state)
{
if (!m_loopback) {
m_uart->ip4_w(state);
diff --git a/src/devices/bus/hp_ipc_io/82919.h b/src/devices/bus/hp_ipc_io/82919.h
index 331a42b0b00..b6ff3ffa301 100644
--- a/src/devices/bus/hp_ipc_io/82919.h
+++ b/src/devices/bus/hp_ipc_io/82919.h
@@ -27,18 +27,18 @@ public:
uint8_t read(offs_t addr);
void write(offs_t addr , uint8_t data);
- DECLARE_WRITE_LINE_MEMBER(uart_irq);
- DECLARE_WRITE_LINE_MEMBER(uart_a_tx);
- DECLARE_WRITE_LINE_MEMBER(uart_b_tx);
+ void uart_irq(int state);
+ void uart_a_tx(int state);
+ void uart_b_tx(int state);
void uart_output(uint8_t data);
- DECLARE_WRITE_LINE_MEMBER(prim_rxd);
- DECLARE_WRITE_LINE_MEMBER(prim_dcd);
- DECLARE_WRITE_LINE_MEMBER(prim_dsr);
- DECLARE_WRITE_LINE_MEMBER(prim_ri);
- DECLARE_WRITE_LINE_MEMBER(prim_cts);
- DECLARE_WRITE_LINE_MEMBER(sec_rxd);
- DECLARE_WRITE_LINE_MEMBER(sec_dcd);
- DECLARE_WRITE_LINE_MEMBER(sec_cts);
+ void prim_rxd(int state);
+ void prim_dcd(int state);
+ void prim_dsr(int state);
+ void prim_ri(int state);
+ void prim_cts(int state);
+ void sec_rxd(int state);
+ void sec_dcd(int state);
+ void sec_cts(int state);
protected:
virtual void device_start() override;
diff --git a/src/devices/bus/hp_ipc_io/hp_ipc_io.cpp b/src/devices/bus/hp_ipc_io/hp_ipc_io.cpp
index 8d5648754bf..94b51b2f178 100644
--- a/src/devices/bus/hp_ipc_io/hp_ipc_io.cpp
+++ b/src/devices/bus/hp_ipc_io/hp_ipc_io.cpp
@@ -35,7 +35,6 @@ hp_ipc_io_slot_device::~hp_ipc_io_slot_device()
void hp_ipc_io_slot_device::device_start()
{
- m_irq_cb_func.resolve_all_safe();
}
uint32_t hp_ipc_io_slot_device::get_slot_base_addr() const
diff --git a/src/devices/bus/idpartner/bus.cpp b/src/devices/bus/idpartner/bus.cpp
new file mode 100644
index 00000000000..2c426f39991
--- /dev/null
+++ b/src/devices/bus/idpartner/bus.cpp
@@ -0,0 +1,87 @@
+// license:BSD-3-Clause
+// copyright-holders:Miodrag Milanovic
+/**********************************************************************
+
+ Iskra Delta Partner Bus
+
+**********************************************************************/
+
+#include "emu.h"
+#include "bus.h"
+
+DEFINE_DEVICE_TYPE(IDPARTNER_BUS, bus::idpartner::bus_device, "idpartner_bus_device", "Iskra Delta Partner Bus")
+DEFINE_DEVICE_TYPE(IDPARTNER_BUS_CONNECTOR, bus::idpartner::bus_connector_device, "idpartner_bus_connector", "Iskra Delta Partner Bus Connector")
+
+namespace bus::idpartner {
+
+/***********************************************************************
+ CARD INTERFACE
+***********************************************************************/
+
+device_exp_card_interface::device_exp_card_interface(const machine_config &mconfig, device_t &device)
+ : device_interface(device, "idpartner_card")
+ , m_bus(nullptr)
+{
+}
+
+/***********************************************************************
+ SLOT DEVICE
+***********************************************************************/
+
+bus_connector_device::bus_connector_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, IDPARTNER_BUS_CONNECTOR, tag, owner, clock)
+ , device_single_card_slot_interface<device_exp_card_interface>(mconfig, *this)
+ , m_bus(*this, finder_base::DUMMY_TAG)
+{
+}
+
+/*----------------------------------
+ device_t implementation
+----------------------------------*/
+
+void bus_connector_device::device_resolve_objects()
+{
+ device_exp_card_interface *const exp_card = get_card_device();
+ if (exp_card)
+ exp_card->set_bus(m_bus);
+}
+
+void bus_connector_device::device_start()
+{
+}
+
+/***********************************************************************
+ BUS DEVICE
+***********************************************************************/
+
+bus_device::bus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, IDPARTNER_BUS, tag, owner, clock)
+ , m_io(*this, finder_base::DUMMY_TAG, -1)
+ , m_int_handler(*this)
+ , m_nmi_handler(*this)
+ , m_drq_handler(*this)
+{
+}
+
+/*----------------------------------
+ device_t implementation
+----------------------------------*/
+
+void bus_device::device_start()
+{
+}
+
+void bus_device::device_reset()
+{
+}
+
+} // namespace bus::idpartner
+
+#include "gdp.h"
+#include "sasi.h"
+
+void idpartner_exp_devices(device_slot_interface &device)
+{
+ device.option_add("gdp", IDPARTNER_GDP);
+ device.option_add("sasi", IDPARTNER_SASI);
+}
diff --git a/src/devices/bus/idpartner/bus.h b/src/devices/bus/idpartner/bus.h
new file mode 100644
index 00000000000..51521e946db
--- /dev/null
+++ b/src/devices/bus/idpartner/bus.h
@@ -0,0 +1,141 @@
+// license:BSD-3-Clause
+// copyright-holders:Miodrag Milanovic
+/*********************************************************************
+
+ Iskra Delta Partner BUS
+
+**********************************************************************
+
+ Pinout:
+
+ *********
+ GND 1 * . | . * 1 GND
+ GND 2 * . | . * 2 GND
+ -12V 3 * . | . * 3 -12V
+ +5V 4 * . | . * 4 +5V
+ +5V 5 * . | . * 5 +5V
+ +12V 6 * . | . * 6 +12V
+ NC 7 * . | . * 7 NC
+ NC 8 * . | . * 8 IEDB
+ /BUSACKB 9 * . | . * 9 /DMARQ
+ NC 10 * . | . * 10 NC
+ /RESETB 11 * . | . * 11 NC
+ NC 12 * . | . * 12 /M1B
+ /MREQB 13 * . | . * 13 /NMI
+ NC 14 * . | . * 14 /BUSRQ
+ /INTB 15 * . | . * 15 /HALTB
+ /WAITB 16 * . | . * 16 /RDB
+ phiB 17 * . | . * 17 A0B
+ /IORQB 18 * . | . * 18 A1B
+ /WTB 19 * . | . * 19 A2B
+ /RFSHB 20 * . | . * 20 A3B
+ NC 21 * . | . * 21 A4B
+ /BINB 22 * . | . * 22 A5B
+ NC 23 * . | . * 23 A6B
+ NC 24 * . | . * 24 A7B
+ /D0B 25 * . | . * 25 NC
+ /D1B 26 * . | . * 26 NC
+ /D2B 27 * . | . * 27 NC
+ /D3B 28 * . | . * 28 NC
+ /D4B 29 * . | . * 29 NC
+ /D5B 30 * . | . * 30 NC
+ /D6B 31 * . | . * 31 NC
+ /D7B 32 * . | . * 32 NC
+ *********
+
+**********************************************************************/
+
+#ifndef MAME_BUS_IDPARTNER_BUS_H
+#define MAME_BUS_IDPARTNER_BUS_H
+
+#pragma once
+
+namespace bus::idpartner {
+
+class bus_device;
+class device_exp_card_interface;
+
+class bus_connector_device : public device_t, public device_single_card_slot_interface<device_exp_card_interface>
+{
+public:
+ // construction/destruction
+ template <typename T, typename U>
+ bus_connector_device(const machine_config &mconfig, const char *tag, device_t *owner, T &&bus_tag, U &&opts, const char *dflt)
+ : bus_connector_device(mconfig, tag, owner)
+ {
+ option_reset();
+ opts(*this);
+ set_default_option(dflt);
+ set_fixed(false);
+ m_bus.set_tag(std::forward<T>(bus_tag));
+ }
+
+ bus_connector_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock = 0);
+
+protected:
+ // device_t implementation
+ virtual void device_resolve_objects() override;
+ virtual void device_start() override;
+
+ // configuration
+ required_device<bus_device> m_bus;
+};
+
+class bus_device : public device_t
+{
+public:
+ // construction/destruction
+ bus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ // inline configuration
+ template <typename T> void set_io_space(T &&tag, int spacenum) { m_io.set_tag(std::forward<T>(tag), spacenum); }
+
+ // callbacks
+ auto int_handler() { return m_int_handler.bind(); }
+ auto nmi_handler() { return m_nmi_handler.bind(); }
+ auto drq_handler() { return m_drq_handler.bind(); }
+
+ // called from expansion device
+ void int_w(int state) { m_int_handler(state); }
+ void nmi_w(int state) { m_nmi_handler(state); }
+ void drq_w(int state) { m_drq_handler(state); }
+
+ address_space &io() { return *m_io; }
+
+private:
+ // device_t implementation
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ // internal state
+ required_address_space m_io;
+
+ devcb_write_line m_int_handler;
+ devcb_write_line m_nmi_handler;
+ devcb_write_line m_drq_handler;
+};
+
+// ======================> device_exp_card_interface
+
+class device_exp_card_interface : public device_interface
+{
+protected:
+ // construction/destruction
+ device_exp_card_interface(const machine_config &mconfig, device_t &device);
+
+public:
+ // inline configuration
+ void set_bus(bus_device *bus) { m_bus = bus; }
+
+protected:
+ bus_device *m_bus;
+};
+
+} // namespace bus::idpartner
+
+DECLARE_DEVICE_TYPE_NS(IDPARTNER_BUS, bus::idpartner, bus_device)
+DECLARE_DEVICE_TYPE_NS(IDPARTNER_BUS_CONNECTOR, bus::idpartner, bus_connector_device)
+
+void idpartner_exp_devices(device_slot_interface &device);
+
+#endif // MAME_BUS_IDPARTNER_BUS_H
diff --git a/src/devices/bus/idpartner/gdp.cpp b/src/devices/bus/idpartner/gdp.cpp
new file mode 100644
index 00000000000..72e3fc7d931
--- /dev/null
+++ b/src/devices/bus/idpartner/gdp.cpp
@@ -0,0 +1,239 @@
+// license:BSD-3-Clause
+// copyright-holders:Miodrag Milanovic
+/**********************************************************************
+
+ Iskra Delta GDP Card
+
+**********************************************************************/
+
+#include "emu.h"
+#include "gdp.h"
+
+#include "machine/timer.h"
+#include "machine/z80pio.h"
+#include "video/ef9365.h"
+#include "video/scn2674.h"
+
+#include "screen.h"
+
+namespace {
+
+class idpartner_gdp_device :
+ public device_t,
+ public bus::idpartner::device_exp_card_interface
+{
+public:
+ // construction/destruction
+ idpartner_gdp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device_t implementation
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+private:
+ void char_w(u8 data) { m_avdc->buffer_w(data); }
+ void attr_w(u8 data) { m_avdc->attr_buffer_w(data); }
+ void scroll_w(u8 data) { m_scroll = data; }
+ u8 common_r() { m_common ^= 0x10; return m_common; }
+ void porta_w(u8 data);
+ void portb_w(u8 data);
+ void vram_w(offs_t offset, u8 data);
+ u8 vram_r(offs_t offset);
+ void msl_w(u8 data);
+ void gdc_map(address_map &map);
+ void int_w(int state) { m_bus->int_w(state); }
+ void nmi_w(int state) { m_bus->nmi_w(state); }
+
+ SCN2674_DRAW_CHARACTER_MEMBER(draw_character);
+ TIMER_DEVICE_CALLBACK_MEMBER(scanline) { m_gdc->update_scanline(param); }
+
+ void char_map(address_map &map);
+ void attr_map(address_map &map);
+
+ required_device<ef9365_device> m_gdc;
+ memory_share_creator<u8> m_vram;
+ required_device<scn2674_device> m_avdc;
+ required_device<z80pio_device> m_pio;
+ required_device<palette_device> m_palette;
+ required_region_ptr<u8> m_p_chargen;
+
+ u8 m_scroll;
+ u8 m_common;
+};
+
+
+idpartner_gdp_device::idpartner_gdp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, IDPARTNER_GDP, tag, owner, clock)
+ , bus::idpartner::device_exp_card_interface(mconfig, *this)
+ , m_gdc(*this, "gdc")
+ , m_vram(*this, "vram", 0x20000, ENDIANNESS_LITTLE)
+ , m_avdc(*this, "avdc")
+ , m_pio(*this, "pio")
+ , m_palette(*this, "palette")
+ , m_p_chargen(*this, "chargen")
+ , m_scroll(0)
+ , m_common(0)
+{
+}
+
+/*----------------------------------
+ device_t implementation
+----------------------------------*/
+
+void idpartner_gdp_device::device_start()
+{
+ save_item(NAME(m_scroll));
+}
+
+void idpartner_gdp_device::device_reset()
+{
+ m_bus->io().install_read_handler (0x20, 0x2f, emu::rw_delegate(m_gdc, FUNC(ef9365_device::data_r))); // Thomson GDP EF9367
+ m_bus->io().install_write_handler(0x20, 0x2f, emu::rw_delegate(m_gdc, FUNC(ef9365_device::data_w))); // Thomson GDP EF9367
+ m_bus->io().install_read_handler (0x30, 0x33, emu::rw_delegate(m_pio, FUNC(z80pio_device::read_alt))); // PIO - Graphics
+ m_bus->io().install_write_handler(0x30, 0x33, emu::rw_delegate(m_pio, FUNC(z80pio_device::write_alt))); // PIO - Graphics
+ m_bus->io().install_write_handler(0x34, 0x34, emu::rw_delegate(*this, FUNC(idpartner_gdp_device::char_w))); // char reg
+ m_bus->io().install_write_handler(0x35, 0x35, emu::rw_delegate(*this, FUNC(idpartner_gdp_device::attr_w))); // attr reg
+ m_bus->io().install_write_handler(0x36, 0x36, emu::rw_delegate(*this, FUNC(idpartner_gdp_device::scroll_w))); // scroll reg/common input
+ m_bus->io().install_read_handler (0x36, 0x36, emu::rw_delegate(*this, FUNC(idpartner_gdp_device::common_r))); // common input
+ m_bus->io().install_read_handler (0x38, 0x3f, emu::rw_delegate(m_avdc, FUNC(scn2674_device::read))); // AVDC SCN2674
+ m_bus->io().install_write_handler(0x38, 0x3f, emu::rw_delegate(m_avdc, FUNC(scn2674_device::write))); // AVDC SCN2674
+}
+
+void idpartner_gdp_device::porta_w(u8 data)
+{
+ //printf("porta_w:%02x\n",data);
+}
+
+void idpartner_gdp_device::portb_w(u8 data)
+{
+ //printf("portb_w:%02x\n",data);
+}
+
+void idpartner_gdp_device::msl_w(u8 data)
+{
+ //printf("msl_w:%02x\n",data);
+}
+
+void idpartner_gdp_device::vram_w(offs_t offset, u8 data)
+{
+ u16 addr = (m_scroll << 7) - offset;
+ m_vram[addr] = data;
+}
+
+u8 idpartner_gdp_device::vram_r(offs_t offset)
+{
+ u16 addr = (m_scroll << 7) - offset;
+ return m_vram[addr];
+}
+
+// 16 * 4164 DRAM
+void idpartner_gdp_device::gdc_map(address_map &map)
+{
+ map(0x0000, 0x1ffff).rw(FUNC(idpartner_gdp_device::vram_r), FUNC(idpartner_gdp_device::vram_w));
+}
+
+
+// 2 * 6116 SRAM for chars
+void idpartner_gdp_device::char_map(address_map &map)
+{
+ map(0x0000, 0x0fff).ram().share("charram");
+ map(0x1000, 0x2fff).ram(); // TODO: Check in schematics
+}
+
+// 2 * 6116 SRAM for attributes
+void idpartner_gdp_device::attr_map(address_map &map)
+{
+ map(0x0000, 0x0fff).ram().share("attrmap");
+ map(0x1000, 0x2fff).ram(); // TODO: Check in schematics
+}
+
+/* F4 Character Displayer */
+static const gfx_layout gdp_charlayout =
+{
+ 8, 12, /* 8 x 12 characters */
+ 256, /* 128 characters */
+ 1, /* 1 bits per pixel */
+ { 0 }, /* no bitplanes */
+ /* x offsets */
+ { 7, 6, 5, 4, 3, 2, 1, 0 },
+ /* y offsets */
+ { 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8, 8*8, 9*8, 10*8, 11*8 },
+ 8*16 /* every char takes 16 bytes */
+};
+
+static GFXDECODE_START( gfx_partner )
+ GFXDECODE_ENTRY( "chargen", 0x0000, gdp_charlayout, 0, 1 )
+GFXDECODE_END
+
+// one 2732 EPROM for chargen
+ROM_START(gdp_char_rom)
+ ROM_REGION( 0x1000, "chargen",0 )
+ ROM_LOAD( "gdp_chgi.ic46", 0x0000, 0x1000, CRC(f4aaf0dd) SHA1(7c7c2d855fdfb90c86ed47c1b33c354c922ed4d0))
+ROM_END
+
+const tiny_rom_entry *idpartner_gdp_device::device_rom_region() const
+{
+ return ROM_NAME( gdp_char_rom );
+}
+
+SCN2674_DRAW_CHARACTER_MEMBER( idpartner_gdp_device::draw_character )
+{
+ uint16_t data = m_p_chargen[charcode << 4 | linecount];
+ const pen_t *const pen = m_palette->pens();
+
+ if (cursor)
+ data = ~data;
+
+ // draw 9 pixels of the character
+ for (int i = 0; i < 9; i++)
+ bitmap.pix(y, x + i) = BIT(data, i) ? pen[0] : pen[1];
+}
+
+void idpartner_gdp_device::device_add_mconfig(machine_config &config)
+{
+ screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER, rgb_t::green()));
+ screen.set_screen_update(m_gdc, FUNC(ef9365_device::screen_update));
+ screen.set_size(1024, 512);
+ screen.set_visarea(0, 1024-1, 0, 512-1);
+ screen.set_refresh_hz(50);
+ PALETTE(config, "palette", palette_device::MONOCHROME_INVERTED);
+
+
+ screen_device &screen2(SCREEN(config, "screen2", SCREEN_TYPE_RASTER, rgb_t::green()));
+ screen2.set_screen_update(m_avdc, FUNC(scn2674_device::screen_update));
+ screen2.set_size(1024, 512);
+ screen2.set_visarea(0, 1024-1, 0, 512-1);
+ screen2.set_refresh_hz(50);
+
+ GFXDECODE(config, "gfxdecode", "palette", gfx_partner);
+
+ EF9365(config, m_gdc, XTAL(24'000'000) / 16); // EF9367 1.5 MHz
+ m_gdc->set_screen("screen");
+ m_gdc->set_addrmap(0, &idpartner_gdp_device::gdc_map);
+ m_gdc->set_palette_tag("palette");
+ m_gdc->set_nb_bitplanes(1);
+ m_gdc->set_display_mode(ef9365_device::DISPLAY_MODE_1024x512);
+ m_gdc->write_msl().set(FUNC(idpartner_gdp_device::msl_w));
+
+ TIMER(config, "scanline").configure_scanline(FUNC(idpartner_gdp_device::scanline), "screen", 0, 1);
+
+ SCN2674(config, m_avdc, XTAL(24'000'000) / 16); // SCN2674B
+ m_avdc->set_screen("screen2");
+ m_avdc->set_character_width(12);
+ m_avdc->set_addrmap(0, &idpartner_gdp_device::char_map);
+ m_avdc->set_addrmap(1, &idpartner_gdp_device::attr_map);
+ m_avdc->set_display_callback(FUNC(idpartner_gdp_device::draw_character));
+ //m_avdc->intr_callback().set(FUNC(idpartner_gdp_device::nmi_w));
+
+ Z80PIO(config, m_pio, XTAL(8'000'000) / 2);
+ m_pio->out_int_callback().set(FUNC(idpartner_gdp_device::int_w));
+ m_pio->out_pa_callback().set(FUNC(idpartner_gdp_device::porta_w));
+ m_pio->out_pb_callback().set(FUNC(idpartner_gdp_device::portb_w));
+}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(IDPARTNER_GDP, bus::idpartner::device_exp_card_interface, idpartner_gdp_device, "partner_gdp", "Iskra Delta Partner GDP")
diff --git a/src/devices/bus/idpartner/gdp.h b/src/devices/bus/idpartner/gdp.h
new file mode 100644
index 00000000000..ecef433e7fa
--- /dev/null
+++ b/src/devices/bus/idpartner/gdp.h
@@ -0,0 +1,12 @@
+// license:BSD-3-Clause
+// copyright-holders:Miodrag Milanovic
+#ifndef MAME_BUS_IDPARTNER_GDP_H
+#define MAME_BUS_IDPARTNER_GDP_H
+
+#pragma once
+
+#include "bus.h"
+
+DECLARE_DEVICE_TYPE_NS(IDPARTNER_GDP, bus::idpartner, device_exp_card_interface)
+
+#endif // MAME_BUS_IDPARTNER_GDP_H
diff --git a/src/devices/bus/idpartner/sasi.cpp b/src/devices/bus/idpartner/sasi.cpp
new file mode 100644
index 00000000000..7fdeb141e88
--- /dev/null
+++ b/src/devices/bus/idpartner/sasi.cpp
@@ -0,0 +1,180 @@
+// license:BSD-3-Clause
+// copyright-holders:Miodrag Milanovic
+/**********************************************************************
+
+ Iskra Delta SASI Adapter
+
+**********************************************************************/
+
+#include "emu.h"
+#include "sasi.h"
+
+#include "bus/nscsi/devices.h"
+#include "machine/nscsi_bus.h"
+#include "machine/nscsi_cb.h"
+
+namespace {
+
+class idpartner_sasi_device :
+ public device_t,
+ public bus::idpartner::device_exp_card_interface
+{
+public:
+ // construction/destruction
+ idpartner_sasi_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device_t implementation
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+
+ u8 stat_r();
+ u8 data_r();
+ void ctrl_w(u8 data);
+ void data_w(u8 data);
+ void reset_w(u8 data);
+
+ void req_w(int state);
+ void io_w(int state);
+
+private:
+ required_device<nscsi_bus_device> m_sasibus;
+ required_device<nscsi_callback_device> m_sasi;
+
+ int m_drq_enable;
+ int m_data_enable;
+ int m_prev_daq;
+};
+
+
+idpartner_sasi_device::idpartner_sasi_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, IDPARTNER_SASI, tag, owner, clock)
+ , bus::idpartner::device_exp_card_interface(mconfig, *this)
+ , m_sasibus(*this, "sasibus")
+ , m_sasi(*this, "sasibus:7:scsicb")
+ , m_drq_enable(0)
+ , m_data_enable(0)
+ , m_prev_daq(0)
+{
+}
+
+/*----------------------------------
+ device_t implementation
+----------------------------------*/
+
+void idpartner_sasi_device::device_start()
+{
+ m_bus->io().install_read_handler (0x10, 0x10, emu::rw_delegate(*this, FUNC(idpartner_sasi_device::stat_r))); // RDSTAT
+ m_bus->io().install_read_handler (0x11, 0x11, emu::rw_delegate(*this, FUNC(idpartner_sasi_device::data_r))); // RDDATA
+ m_bus->io().install_write_handler(0x10, 0x10, emu::rw_delegate(*this, FUNC(idpartner_sasi_device::ctrl_w))); // WRCONTR
+ m_bus->io().install_write_handler(0x11, 0x11, emu::rw_delegate(*this, FUNC(idpartner_sasi_device::data_w))); // WRDATA
+ m_bus->io().install_write_handler(0x12, 0x12, emu::rw_delegate(*this, FUNC(idpartner_sasi_device::reset_w))); // RESET
+
+ save_item(NAME(m_drq_enable));
+ save_item(NAME(m_data_enable));
+ save_item(NAME(m_prev_daq));
+}
+
+void idpartner_sasi_device::device_reset()
+{
+ m_drq_enable = 0;
+ m_data_enable = 0;
+ m_prev_daq = 0;
+ m_bus->drq_w(0);
+}
+
+u8 idpartner_sasi_device::stat_r()
+{
+ u8 data = (m_sasi->req_r() << 7)
+ | (m_sasi->io_r() << 6)
+ | (m_sasi->msg_r() << 5)
+ | (m_sasi->cd_r() << 4)
+ | (m_sasi->bsy_r() << 3);
+ return data;
+}
+
+u8 idpartner_sasi_device::data_r()
+{
+ u8 data = m_sasi->read();
+ if (m_data_enable)
+ {
+ m_sasi->ack_w(1);
+ if (m_drq_enable)
+ {
+ m_bus->drq_w(0);
+ m_prev_daq = 0;
+ }
+ }
+ return data;
+}
+
+void idpartner_sasi_device::ctrl_w(u8 data)
+{
+ m_sasi->write(BIT(data,0));
+ m_sasi->sel_w(BIT(data,0));
+ m_data_enable = BIT(data,1);
+ m_drq_enable = BIT(data,5);
+ if (m_data_enable && m_drq_enable)
+ {
+ m_bus->drq_w(m_sasi->req_r());
+ m_prev_daq = m_sasi->req_r();
+ } else {
+ if (m_prev_daq)
+ m_bus->drq_w(0);
+ m_prev_daq = 0;
+ }
+}
+
+void idpartner_sasi_device::data_w(u8 data)
+{
+ m_sasi->write(data);
+ if (m_data_enable)
+ {
+ m_sasi->ack_w(1);
+ if (m_drq_enable)
+ {
+ m_bus->drq_w(0);
+ m_prev_daq = 0;
+ }
+ }
+}
+
+void idpartner_sasi_device::reset_w(u8 data)
+{
+ m_sasi->rst_w(1);
+ m_sasi->rst_w(0);
+}
+
+void idpartner_sasi_device::req_w(int state)
+{
+ m_sasi->ack_w(0);
+ if (m_data_enable && m_drq_enable)
+ {
+ m_bus->drq_w(state);
+ m_prev_daq = state;
+ }
+}
+
+void idpartner_sasi_device::io_w(int state)
+{
+ if (state)
+ m_sasi->write(0); // clears lateched data
+}
+
+void idpartner_sasi_device::device_add_mconfig(machine_config &config)
+{
+ NSCSI_BUS(config, m_sasibus);
+ NSCSI_CONNECTOR(config, "sasibus:0", default_scsi_devices, "s1410", true);
+ NSCSI_CONNECTOR(config, "sasibus:7", default_scsi_devices, "scsicb", true)
+ .option_add_internal("scsicb", NSCSI_CB)
+ .machine_config(
+ [this] (device_t* device)
+ {
+ downcast<nscsi_callback_device&>(*device).req_callback().set(*this, FUNC(idpartner_sasi_device::req_w));
+ downcast<nscsi_callback_device&>(*device).io_callback().set(*this, FUNC(idpartner_sasi_device::io_w));
+ });
+ }
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(IDPARTNER_SASI, bus::idpartner::device_exp_card_interface, idpartner_sasi_device, "partner_sai", "Iskra Delta Partner SASI card")
diff --git a/src/devices/bus/idpartner/sasi.h b/src/devices/bus/idpartner/sasi.h
new file mode 100644
index 00000000000..645c8baed3d
--- /dev/null
+++ b/src/devices/bus/idpartner/sasi.h
@@ -0,0 +1,12 @@
+// license:BSD-3-Clause
+// copyright-holders:Miodrag Milanovic
+#ifndef MAME_BUS_IDPARTNER_SASI_H
+#define MAME_BUS_IDPARTNER_SASI_H
+
+#pragma once
+
+#include "bus.h"
+
+DECLARE_DEVICE_TYPE_NS(IDPARTNER_SASI, bus::idpartner, device_exp_card_interface)
+
+#endif // MAME_BUS_IDPARTNER_SASI_H
diff --git a/src/devices/bus/ieee488/c2031.cpp b/src/devices/bus/ieee488/c2031.cpp
index 4efdd03e7b5..fa96ba01266 100644
--- a/src/devices/bus/ieee488/c2031.cpp
+++ b/src/devices/bus/ieee488/c2031.cpp
@@ -9,6 +9,8 @@
#include "emu.h"
#include "c2031.h"
+#include "formats/d64_dsk.h"
+#include "formats/g64_dsk.h"
//**************************************************************************
@@ -70,7 +72,7 @@ void c2031_device::c2031_mem(address_map &map)
}
-WRITE_LINE_MEMBER( c2031_device::via0_irq_w )
+void c2031_device::via0_irq_w(int state)
{
m_via0_irq = state;
@@ -202,7 +204,7 @@ void c2031_device::via0_pb_w(uint8_t data)
}
-WRITE_LINE_MEMBER( c2031_device::via1_irq_w )
+void c2031_device::via1_irq_w(int state)
{
m_via1_irq = state;
@@ -272,7 +274,7 @@ void c2031_device::via1_pb_w(uint8_t data)
// C64H156_INTERFACE( ga_intf )
//-------------------------------------------------
-WRITE_LINE_MEMBER( c2031_device::byte_w )
+void c2031_device::byte_w(int state)
{
m_maincpu->set_input_line(M6502_SET_OVERFLOW, state);
@@ -299,7 +301,6 @@ void c2031_device::device_add_mconfig(machine_config &config)
{
M6502(config, m_maincpu, XTAL(16'000'000)/16);
m_maincpu->set_addrmap(AS_PROGRAM, &c2031_device::c2031_mem);
- //config.set_perfect_quantum(m_maincpu); FIXME: not safe in a slot device - add barriers
MOS6522(config, m_via0, XTAL(16'000'000)/16);
m_via0->readpa_handler().set(FUNC(c2031_device::via0_pa_r));
diff --git a/src/devices/bus/ieee488/c2031.h b/src/devices/bus/ieee488/c2031.h
index f3a0dc02074..8d2a646133b 100644
--- a/src/devices/bus/ieee488/c2031.h
+++ b/src/devices/bus/ieee488/c2031.h
@@ -49,15 +49,15 @@ protected:
private:
inline int get_device_number();
- DECLARE_WRITE_LINE_MEMBER( via0_irq_w );
+ void via0_irq_w(int state);
uint8_t via0_pa_r();
void via0_pa_w(uint8_t data);
uint8_t via0_pb_r();
void via0_pb_w(uint8_t data);
- DECLARE_WRITE_LINE_MEMBER( via1_irq_w );
+ void via1_irq_w(int state);
uint8_t via1_pb_r();
void via1_pb_w(uint8_t data);
- DECLARE_WRITE_LINE_MEMBER( byte_w );
+ void byte_w(int state);
void c2031_mem(address_map &map);
diff --git a/src/devices/bus/ieee488/c2040.cpp b/src/devices/bus/ieee488/c2040.cpp
index 886dd01bbf2..06779fe8ee0 100644
--- a/src/devices/bus/ieee488/c2040.cpp
+++ b/src/devices/bus/ieee488/c2040.cpp
@@ -50,6 +50,11 @@
#include "emu.h"
#include "c2040.h"
+#include "formats/c3040_dsk.h"
+#include "formats/c4040_dsk.h"
+#include "formats/d64_dsk.h"
+#include "formats/g64_dsk.h"
+
//**************************************************************************
@@ -171,10 +176,10 @@ const tiny_rom_entry *c4040_device::device_rom_region() const
void c2040_device::c2040_main_mem(address_map &map)
{
map.global_mask(0x7fff);
- map(0x0000, 0x007f).mirror(0x0100).m(M6532_0_TAG, FUNC(mos6532_new_device::ram_map));
- map(0x0080, 0x00ff).mirror(0x0100).m(M6532_1_TAG, FUNC(mos6532_new_device::ram_map));
- map(0x0200, 0x021f).mirror(0x0d60).m(M6532_0_TAG, FUNC(mos6532_new_device::io_map));
- map(0x0280, 0x029f).mirror(0x0d60).m(M6532_1_TAG, FUNC(mos6532_new_device::io_map));
+ map(0x0000, 0x007f).mirror(0x0100).m(M6532_0_TAG, FUNC(mos6532_device::ram_map));
+ map(0x0080, 0x00ff).mirror(0x0100).m(M6532_1_TAG, FUNC(mos6532_device::ram_map));
+ map(0x0200, 0x021f).mirror(0x0d60).m(M6532_0_TAG, FUNC(mos6532_device::io_map));
+ map(0x0280, 0x029f).mirror(0x0d60).m(M6532_1_TAG, FUNC(mos6532_device::io_map));
map(0x1000, 0x13ff).mirror(0x0c00).ram().share("share1");
map(0x2000, 0x23ff).mirror(0x0c00).ram().share("share2");
map(0x3000, 0x33ff).mirror(0x0c00).ram().share("share3");
@@ -190,9 +195,9 @@ void c2040_device::c2040_main_mem(address_map &map)
void c2040_device::c2040_fdc_mem(address_map &map)
{
map.global_mask(0x1fff);
- map(0x0000, 0x003f).mirror(0x0300).m(M6530_TAG, FUNC(mos6530_new_device::ram_map));
+ map(0x0000, 0x003f).mirror(0x0300).m(M6530_TAG, FUNC(mos6530_device::ram_map));
map(0x0040, 0x004f).mirror(0x0330).m(M6522_TAG, FUNC(via6522_device::map));
- map(0x0080, 0x008f).mirror(0x0330).m(M6530_TAG, FUNC(mos6530_new_device::io_map));
+ map(0x0080, 0x008f).mirror(0x0330).m(M6530_TAG, FUNC(mos6530_device::io_map));
map(0x0400, 0x07ff).ram().share("share1");
map(0x0800, 0x0bff).ram().share("share2");
map(0x0c00, 0x0fff).ram().share("share3");
@@ -459,11 +464,11 @@ void c2040_device::add_common_devices(machine_config &config)
M6502(config, m_maincpu, XTAL(16'000'000)/16);
m_maincpu->set_addrmap(AS_PROGRAM, &c2040_device::c2040_main_mem);
- MOS6532_NEW(config, m_riot0, XTAL(16'000'000)/16);
+ MOS6532(config, m_riot0, XTAL(16'000'000)/16);
m_riot0->pa_rd_callback().set(FUNC(c2040_device::dio_r));
m_riot0->pb_wr_callback().set(FUNC(c2040_device::dio_w));
- MOS6532_NEW(config, m_riot1, XTAL(16'000'000)/16);
+ MOS6532(config, m_riot1, XTAL(16'000'000)/16);
m_riot1->pa_rd_callback().set(FUNC(c2040_device::riot1_pa_r));
m_riot1->pa_wr_callback().set(FUNC(c2040_device::riot1_pa_w));
m_riot1->pb_rd_callback().set(FUNC(c2040_device::riot1_pb_r));
@@ -480,16 +485,16 @@ void c2040_device::add_common_devices(machine_config &config)
m_via->ca2_handler().set(m_fdc, FUNC(c2040_fdc_device::mode_sel_w));
m_via->cb2_handler().set(m_fdc, FUNC(c2040_fdc_device::rw_sel_w));
- MOS6530_NEW(config, m_miot, XTAL(16'000'000)/16);
+ MOS6530(config, m_miot, XTAL(16'000'000)/16);
m_miot->pa_wr_callback().set(m_fdc, FUNC(c2040_fdc_device::write));
m_miot->pb_wr_callback<0>().set(m_fdc, FUNC(c2040_fdc_device::drv_sel_w));
m_miot->pb_wr_callback<1>().set(m_fdc, FUNC(c2040_fdc_device::ds0_w));
m_miot->pb_wr_callback<2>().set(m_fdc, FUNC(c2040_fdc_device::ds1_w));
- m_miot->pb_wr_callback<7>().set_inputline(m_fdccpu, M6502_IRQ_LINE);
m_miot->pb_rd_callback<3>().set(m_fdc, FUNC(c2040_fdc_device::wps_r));
+ m_miot->irq_wr_callback().set_inputline(m_fdccpu, M6502_IRQ_LINE);
C2040_FDC(config, m_fdc, XTAL(16'000'000));
- m_fdc->sync_wr_callback().set(m_miot, FUNC(mos6530_new_device::pb6_w));
+ m_fdc->sync_wr_callback().set(m_miot, FUNC(mos6530_device::pb_bit_w<6>));
m_fdc->ready_wr_callback().set(m_via, FUNC(via6522_device::write_ca1));
m_fdc->error_wr_callback().set(m_via, FUNC(via6522_device::write_cb1));
}
@@ -658,7 +663,7 @@ void c2040_device::device_reset()
m_miot->reset();
m_via->reset();
- m_riot1->pa7_w(0);
+ m_riot1->pa_bit_w<7>(0);
// turn off spindle motors
m_fdc->mtr0_w(1);
@@ -674,7 +679,7 @@ void c2040_device::ieee488_atn(int state)
{
update_ieee_signals();
- m_riot1->pa7_w(!state);
+ m_riot1->pa_bit_w<7>(!state);
}
diff --git a/src/devices/bus/ieee488/c2040.h b/src/devices/bus/ieee488/c2040.h
index 41f4f4f967e..010f055d392 100644
--- a/src/devices/bus/ieee488/c2040.h
+++ b/src/devices/bus/ieee488/c2040.h
@@ -16,7 +16,7 @@
#include "cpu/m6502/m6502.h"
#include "cpu/m6502/m6504.h"
#include "machine/6522via.h"
-#include "machine/mos6530n.h"
+#include "machine/mos6530.h"
@@ -73,9 +73,9 @@ protected:
required_device<m6502_device> m_maincpu;
required_device<m6504_device> m_fdccpu;
- required_device<mos6532_new_device> m_riot0;
- required_device<mos6532_new_device> m_riot1;
- required_device<mos6530_new_device> m_miot;
+ required_device<mos6532_device> m_riot0;
+ required_device<mos6532_device> m_riot1;
+ required_device<mos6530_device> m_miot;
required_device<via6522_device> m_via;
required_device<floppy_image_device> m_floppy0;
optional_device<floppy_image_device> m_floppy1;
diff --git a/src/devices/bus/ieee488/c2040fdc.cpp b/src/devices/bus/ieee488/c2040fdc.cpp
index 18c02bba831..fa9ec6205a3 100644
--- a/src/devices/bus/ieee488/c2040fdc.cpp
+++ b/src/devices/bus/ieee488/c2040fdc.cpp
@@ -105,11 +105,6 @@ c2040_fdc_device::c2040_fdc_device(const machine_config &mconfig, const char *ta
void c2040_fdc_device::device_start()
{
- // resolve callbacks
- m_write_sync.resolve_safe();
- m_write_ready.resolve_safe();
- m_write_error.resolve_safe();
-
// allocate timer
t_gen = timer_alloc(FUNC(c2040_fdc_device::update_state), this);
@@ -467,19 +462,19 @@ void c2040_fdc_device::write(uint8_t data)
}
}
-WRITE_LINE_MEMBER( c2040_fdc_device::ds0_w )
+void c2040_fdc_device::ds0_w(int state)
{
m_ds0 = state;
}
-WRITE_LINE_MEMBER( c2040_fdc_device::ds1_w )
+void c2040_fdc_device::ds1_w(int state)
{
m_ds1 = state;
ds_w(m_ds1 << 1 | m_ds0);
}
-WRITE_LINE_MEMBER( c2040_fdc_device::drv_sel_w )
+void c2040_fdc_device::drv_sel_w(int state)
{
if (m_drv_sel != state)
{
@@ -491,7 +486,7 @@ WRITE_LINE_MEMBER( c2040_fdc_device::drv_sel_w )
}
}
-WRITE_LINE_MEMBER( c2040_fdc_device::mode_sel_w )
+void c2040_fdc_device::mode_sel_w(int state)
{
if (m_mode_sel != state)
{
@@ -503,7 +498,7 @@ WRITE_LINE_MEMBER( c2040_fdc_device::mode_sel_w )
}
}
-WRITE_LINE_MEMBER( c2040_fdc_device::rw_sel_w )
+void c2040_fdc_device::rw_sel_w(int state)
{
if (m_rw_sel != state)
{
@@ -520,7 +515,7 @@ WRITE_LINE_MEMBER( c2040_fdc_device::rw_sel_w )
}
}
-WRITE_LINE_MEMBER( c2040_fdc_device::mtr0_w )
+void c2040_fdc_device::mtr0_w(int state)
{
if (m_mtr0 != state)
{
@@ -542,7 +537,7 @@ WRITE_LINE_MEMBER( c2040_fdc_device::mtr0_w )
}
}
-WRITE_LINE_MEMBER( c2040_fdc_device::mtr1_w )
+void c2040_fdc_device::mtr1_w(int state)
{
if (m_mtr1 != state)
{
diff --git a/src/devices/bus/ieee488/c2040fdc.h b/src/devices/bus/ieee488/c2040fdc.h
index 2198f6aa738..cd3b277c82b 100644
--- a/src/devices/bus/ieee488/c2040fdc.h
+++ b/src/devices/bus/ieee488/c2040fdc.h
@@ -11,10 +11,6 @@
#pragma once
-#include "formats/c3040_dsk.h"
-#include "formats/c4040_dsk.h"
-#include "formats/d64_dsk.h"
-#include "formats/g64_dsk.h"
#include "imagedev/floppy.h"
@@ -37,16 +33,16 @@ public:
uint8_t read();
void write(uint8_t data);
- DECLARE_WRITE_LINE_MEMBER( ds0_w );
- DECLARE_WRITE_LINE_MEMBER( ds1_w );
- DECLARE_WRITE_LINE_MEMBER( drv_sel_w );
- DECLARE_WRITE_LINE_MEMBER( mode_sel_w );
- DECLARE_WRITE_LINE_MEMBER( rw_sel_w );
- DECLARE_WRITE_LINE_MEMBER( mtr0_w );
- DECLARE_WRITE_LINE_MEMBER( mtr1_w );
+ void ds0_w(int state);
+ void ds1_w(int state);
+ void drv_sel_w(int state);
+ void mode_sel_w(int state);
+ void rw_sel_w(int state);
+ void mtr0_w(int state);
+ void mtr1_w(int state);
- DECLARE_READ_LINE_MEMBER( wps_r ) { return checkpoint_live.drv_sel ? m_floppy1->wpt_r() : m_floppy0->wpt_r(); }
- DECLARE_READ_LINE_MEMBER( sync_r ) { return checkpoint_live.sync; }
+ int wps_r() { return checkpoint_live.drv_sel ? m_floppy1->wpt_r() : m_floppy0->wpt_r(); }
+ int sync_r() { return checkpoint_live.sync; }
void stp0_w(int stp);
void stp1_w(int stp);
diff --git a/src/devices/bus/ieee488/c8050.cpp b/src/devices/bus/ieee488/c8050.cpp
index 60358de4944..d6ed177c356 100644
--- a/src/devices/bus/ieee488/c8050.cpp
+++ b/src/devices/bus/ieee488/c8050.cpp
@@ -25,6 +25,9 @@
#include "emu.h"
#include "c8050.h"
+#include "formats/d80_dsk.h"
+#include "formats/d82_dsk.h"
+
//**************************************************************************
@@ -53,10 +56,10 @@ enum
// DEVICE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(C8050, c8050_device, "c8050", "Commodore 8050")
-DEFINE_DEVICE_TYPE(C8250, c8250_device, "c8250", "Commodore 8250")
-DEFINE_DEVICE_TYPE(C8250LP, c8250lp_device, "c8250lp", "Commodore 8250LP")
-DEFINE_DEVICE_TYPE(SFD1001, sfd1001_device, "sfd10001", "Commodore SFD-1001")
+DEFINE_DEVICE_TYPE(C8050, c8050_device, "c8050", "Commodore 8050")
+DEFINE_DEVICE_TYPE(C8250, c8250_device, "c8250", "Commodore 8250")
+DEFINE_DEVICE_TYPE(C8250LP, c8250lp_device, "c8250lp", "Commodore 8250LP")
+DEFINE_DEVICE_TYPE(SFD1001, sfd1001_device, "sfd1001", "Commodore SFD-1001")
//-------------------------------------------------
@@ -187,10 +190,10 @@ const tiny_rom_entry *sfd1001_device::device_rom_region() const
void c8050_device::c8050_main_mem(address_map &map)
{
- map(0x0000, 0x007f).mirror(0x0100).m(M6532_0_TAG, FUNC(mos6532_new_device::ram_map));
- map(0x0080, 0x00ff).mirror(0x0100).m(M6532_1_TAG, FUNC(mos6532_new_device::ram_map));
- map(0x0200, 0x021f).mirror(0x0d60).m(M6532_0_TAG, FUNC(mos6532_new_device::io_map));
- map(0x0280, 0x029f).mirror(0x0d60).m(M6532_1_TAG, FUNC(mos6532_new_device::io_map));
+ map(0x0000, 0x007f).mirror(0x0100).m(M6532_0_TAG, FUNC(mos6532_device::ram_map));
+ map(0x0080, 0x00ff).mirror(0x0100).m(M6532_1_TAG, FUNC(mos6532_device::ram_map));
+ map(0x0200, 0x021f).mirror(0x0d60).m(M6532_0_TAG, FUNC(mos6532_device::io_map));
+ map(0x0280, 0x029f).mirror(0x0d60).m(M6532_1_TAG, FUNC(mos6532_device::io_map));
map(0x1000, 0x13ff).mirror(0x0c00).ram().share("share1");
map(0x2000, 0x23ff).mirror(0x0c00).ram().share("share2");
map(0x3000, 0x33ff).mirror(0x0c00).ram().share("share3");
@@ -206,14 +209,14 @@ void c8050_device::c8050_main_mem(address_map &map)
void c8050_device::c8050_fdc_mem(address_map &map)
{
map.global_mask(0x1fff);
- map(0x0000, 0x003f).mirror(0x0300).m(m_miot, FUNC(mos6530_new_device::ram_map));
+ map(0x0000, 0x003f).mirror(0x0300).m(m_miot, FUNC(mos6530_device::ram_map));
map(0x0040, 0x004f).mirror(0x0330).m(m_via, FUNC(via6522_device::map));
- map(0x0080, 0x008f).mirror(0x0330).m(m_miot, FUNC(mos6530_new_device::io_map));
+ map(0x0080, 0x008f).mirror(0x0330).m(m_miot, FUNC(mos6530_device::io_map));
map(0x0400, 0x07ff).ram().share("share1");
map(0x0800, 0x0bff).ram().share("share2");
map(0x0c00, 0x0fff).ram().share("share3");
map(0x1000, 0x13ff).ram().share("share4");
- map(0x1c00, 0x1fff).m(m_miot, FUNC(mos6530_new_device::rom_map));
+ map(0x1c00, 0x1fff).m(m_miot, FUNC(mos6530_device::rom_map));
}
@@ -224,9 +227,9 @@ void c8050_device::c8050_fdc_mem(address_map &map)
void c8050_device::c8250lp_fdc_mem(address_map &map)
{
map.global_mask(0x1fff);
- map(0x0000, 0x003f).mirror(0x0300).m(m_miot, FUNC(mos6530_new_device::ram_map));
+ map(0x0000, 0x003f).mirror(0x0300).m(m_miot, FUNC(mos6530_device::ram_map));
map(0x0040, 0x004f).mirror(0x0330).m(m_via, FUNC(via6522_device::map));
- map(0x0080, 0x008f).mirror(0x0330).m(m_miot, FUNC(mos6530_new_device::io_map));
+ map(0x0080, 0x008f).mirror(0x0330).m(m_miot, FUNC(mos6530_device::io_map));
map(0x0400, 0x07ff).ram().share("share1");
map(0x0800, 0x0bff).ram().share("share2");
map(0x0c00, 0x0fff).ram().share("share3");
@@ -242,9 +245,9 @@ void c8050_device::c8250lp_fdc_mem(address_map &map)
void c8050_device::sfd1001_fdc_mem(address_map &map)
{
map.global_mask(0x1fff);
- map(0x0000, 0x003f).mirror(0x0300).m(m_miot, FUNC(mos6530_new_device::ram_map));
+ map(0x0000, 0x003f).mirror(0x0300).m(m_miot, FUNC(mos6530_device::ram_map));
map(0x0040, 0x004f).mirror(0x0330).m(m_via, FUNC(via6522_device::map));
- map(0x0080, 0x008f).mirror(0x0330).m(m_miot, FUNC(mos6530_new_device::io_map));
+ map(0x0080, 0x008f).mirror(0x0330).m(m_miot, FUNC(mos6530_device::io_map));
map(0x0400, 0x07ff).ram().share("share1");
map(0x0800, 0x0bff).ram().share("share2");
map(0x0c00, 0x0fff).ram().share("share3");
@@ -538,11 +541,11 @@ void c8050_device::add_common_devices(machine_config &config)
M6502(config, m_maincpu, XTAL(12'000'000)/12);
m_maincpu->set_addrmap(AS_PROGRAM, &c8050_device::c8050_main_mem);
- MOS6532_NEW(config, m_riot0, XTAL(12'000'000)/12);
+ MOS6532(config, m_riot0, XTAL(12'000'000)/12);
m_riot0->pa_rd_callback().set(FUNC(c8050_device::dio_r));
m_riot0->pb_wr_callback().set(FUNC(c8050_device::dio_w));
- MOS6532_NEW(config, m_riot1, XTAL(12'000'000)/12);
+ MOS6532(config, m_riot1, XTAL(12'000'000)/12);
m_riot1->pa_rd_callback().set(FUNC(c8050_device::riot1_pa_r));
m_riot1->pa_wr_callback().set(FUNC(c8050_device::riot1_pa_w));
m_riot1->pb_rd_callback().set(FUNC(c8050_device::riot1_pb_r));
@@ -558,13 +561,13 @@ void c8050_device::add_common_devices(machine_config &config)
m_via->ca2_handler().set(m_fdc, FUNC(c8050_fdc_device::mode_sel_w));
m_via->cb2_handler().set(m_fdc, FUNC(c8050_fdc_device::rw_sel_w));
- MOS6530_NEW(config, m_miot, XTAL(12'000'000)/12);
+ MOS6530(config, m_miot, XTAL(12'000'000)/12);
m_miot->pa_wr_callback().set(m_fdc, FUNC(c8050_fdc_device::write));
m_miot->pb_wr_callback<1>().set(m_fdc, FUNC(c8050_fdc_device::ds0_w));
m_miot->pb_wr_callback<2>().set(m_fdc, FUNC(c8050_fdc_device::ds1_w));
m_miot->pb_rd_callback<3>().set(m_fdc, FUNC(c8050_fdc_device::wps_r));
m_miot->pb_rd_callback<6>().set_constant(1); // SINGLE SIDED
- m_miot->pb_wr_callback<7>().set_inputline(m_fdccpu, M6502_IRQ_LINE);
+ m_miot->irq_wr_callback().set_inputline(m_fdccpu, M6502_IRQ_LINE);
C8050_FDC(config, m_fdc, XTAL(12'000'000)/2);
m_fdc->sync_wr_callback().set(m_via, FUNC(via6522_device::write_pb7));
@@ -774,7 +777,7 @@ void c8050_device::device_reset()
m_miot->reset();
m_via->reset();
- m_riot1->pa7_w(1);
+ m_riot1->pa_bit_w<7>(1);
// turn off spindle motors
m_fdc->mtr0_w(1);
@@ -790,7 +793,7 @@ void c8050_device::ieee488_atn(int state)
{
update_ieee_signals();
- m_riot1->pa7_w(state);
+ m_riot1->pa_bit_w<7>(state);
}
diff --git a/src/devices/bus/ieee488/c8050.h b/src/devices/bus/ieee488/c8050.h
index a8047617408..3277444e37a 100644
--- a/src/devices/bus/ieee488/c8050.h
+++ b/src/devices/bus/ieee488/c8050.h
@@ -16,7 +16,7 @@
#include "cpu/m6502/m6502.h"
#include "cpu/m6502/m6504.h"
#include "machine/6522via.h"
-#include "machine/mos6530n.h"
+#include "machine/mos6530.h"
@@ -65,9 +65,9 @@ protected:
required_device<m6502_device> m_maincpu;
required_device<m6504_device> m_fdccpu;
- required_device<mos6532_new_device> m_riot0;
- required_device<mos6532_new_device> m_riot1;
- required_device<mos6530_new_device> m_miot;
+ required_device<mos6532_device> m_riot0;
+ required_device<mos6532_device> m_riot1;
+ required_device<mos6530_device> m_miot;
required_device<via6522_device> m_via;
required_device<floppy_connector> m_floppy0;
optional_device<floppy_connector> m_floppy1;
diff --git a/src/devices/bus/ieee488/c8050fdc.cpp b/src/devices/bus/ieee488/c8050fdc.cpp
index eea107417c9..3fc1adc37de 100644
--- a/src/devices/bus/ieee488/c8050fdc.cpp
+++ b/src/devices/bus/ieee488/c8050fdc.cpp
@@ -24,9 +24,10 @@
// MACROS / CONSTANTS
//**************************************************************************
-#define LOG 0
-#define LOG_MORE 0
-#define LOG_BITS 0
+#define LOG_MORE (1U << 1)
+#define LOG_BITS (1U << 2)
+#define VERBOSE (0)
+#include "logmacro.h"
#define GCR_DECODE(_e, _i) \
((BIT(_e, 6) << 7) | (BIT(_i, 7) << 6) | (_e & 0x33) | (BIT(_e, 2) << 3) | (_i & 0x04))
@@ -105,12 +106,6 @@ c8050_fdc_device::c8050_fdc_device(const machine_config &mconfig, const char *ta
void c8050_fdc_device::device_start()
{
- // resolve callbacks
- m_write_sync.resolve_safe();
- m_write_ready.resolve_safe();
- m_write_brdy.resolve_safe();
- m_write_error.resolve_safe();
-
// allocate timer
t_gen = timer_alloc(FUNC(c8050_fdc_device::update_state), this);
@@ -214,7 +209,7 @@ void c8050_fdc_device::ds_w(int ds)
live_sync();
m_ds = cur_live.ds = ds;
pll_reset(cur_live.tm);
- if (LOG) logerror("%s %s DS %u\n", machine().time().as_string(), machine().describe_context(), ds);
+ LOG("%s %s DS %u\n", machine().time().as_string(), machine().describe_context(), ds);
checkpoint();
live_run();
}
@@ -432,19 +427,17 @@ void c8050_fdc_device::live_run(const attotime &limit)
// GCR error
int error = !(ready || BIT(cur_live.e, 3));
- if (LOG_BITS) {
- if (cur_live.rw_sel) {
- logerror("%s cyl %u bit %u sync %u bc %u sr %03x i %03x e %02x\n",cur_live.tm.as_string(),get_floppy()->get_cyl(),bit,sync,cur_live.bit_counter,cur_live.shift_reg,cur_live.i,cur_live.e);
- } else {
- logerror("%s cyl %u writing bit %u bc %u sr %03x i %03x e %02x\n",cur_live.tm.as_string(),get_floppy()->get_cyl(),write_bit,cur_live.bit_counter,cur_live.shift_reg_write,cur_live.i,cur_live.e);
- }
+ if (cur_live.rw_sel) {
+ LOGMASKED(LOG_BITS, "%s cyl %u bit %u sync %u bc %u sr %03x i %03x e %02x\n",cur_live.tm.as_string(),get_floppy()->get_cyl(),bit,sync,cur_live.bit_counter,cur_live.shift_reg,cur_live.i,cur_live.e);
+ } else {
+ LOGMASKED(LOG_BITS, "%s cyl %u writing bit %u bc %u sr %03x i %03x e %02x\n",cur_live.tm.as_string(),get_floppy()->get_cyl(),write_bit,cur_live.bit_counter,cur_live.shift_reg_write,cur_live.i,cur_live.e);
}
if (!ready) {
// load write shift register
cur_live.shift_reg_write = GCR_ENCODE(cur_live.e, cur_live.i);
- if (LOG_BITS) logerror("%s load write shift register %03x\n",cur_live.tm.as_string(),cur_live.shift_reg_write);
+ LOGMASKED(LOG_BITS, "%s load write shift register %03x\n",cur_live.tm.as_string(),cur_live.shift_reg_write);
} else {
// clock write shift register
cur_live.shift_reg_write <<= 1;
@@ -453,25 +446,25 @@ void c8050_fdc_device::live_run(const attotime &limit)
if (ready != cur_live.ready) {
if (cur_live.rw_sel && !ready)
- if (LOG) logerror("%s READY %u : %02x\n", cur_live.tm.as_string(),ready,GCR_DECODE(cur_live.e, cur_live.i));
+ LOG("%s READY %u : %02x\n", cur_live.tm.as_string(),ready,GCR_DECODE(cur_live.e, cur_live.i));
cur_live.ready = ready;
syncpoint = true;
}
if (brdy != cur_live.brdy) {
- if (LOG_MORE) logerror("%s BRDY %u\n", cur_live.tm.as_string(), brdy);
+ LOGMASKED(LOG_MORE, "%s BRDY %u\n", cur_live.tm.as_string(), brdy);
cur_live.brdy = brdy;
syncpoint = true;
}
if (sync != cur_live.sync) {
- if (LOG) logerror("%s SYNC %u\n", cur_live.tm.as_string(), sync);
+ LOG("%s SYNC %u\n", cur_live.tm.as_string(), sync);
cur_live.sync = sync;
syncpoint = true;
}
if (error != cur_live.error) {
- if (LOG_MORE) logerror("%s ERROR %u\n", cur_live.tm.as_string(), error);
+ LOGMASKED(LOG_MORE, "%s ERROR %u\n", cur_live.tm.as_string(), error);
cur_live.error = error;
syncpoint = true;
}
@@ -507,7 +500,7 @@ uint8_t c8050_fdc_device::read()
void c8050_fdc_device::write(uint8_t data)
{
- if (LOG) logerror("%s %s PI %02x\n", machine().time().as_string(), machine().describe_context(), data);
+ LOG("%s %s PI %02x\n", machine().time().as_string(), machine().describe_context(), data);
if (m_pi != data)
{
@@ -518,50 +511,50 @@ void c8050_fdc_device::write(uint8_t data)
}
}
-WRITE_LINE_MEMBER( c8050_fdc_device::ds0_w )
+void c8050_fdc_device::ds0_w(int state)
{
m_ds0 = state;
}
-WRITE_LINE_MEMBER( c8050_fdc_device::ds1_w )
+void c8050_fdc_device::ds1_w(int state)
{
m_ds1 = state;
ds_w(m_ds1 << 1 | m_ds0);
}
-WRITE_LINE_MEMBER( c8050_fdc_device::drv_sel_w )
+void c8050_fdc_device::drv_sel_w(int state)
{
if (m_drv_sel != state)
{
live_sync();
m_drv_sel = cur_live.drv_sel = state;
checkpoint();
- if (LOG) logerror("%s %s DRV SEL %u\n", machine().time().as_string(), machine().describe_context(), state);
+ LOG("%s %s DRV SEL %u\n", machine().time().as_string(), machine().describe_context(), state);
live_run();
}
}
-WRITE_LINE_MEMBER( c8050_fdc_device::mode_sel_w )
+void c8050_fdc_device::mode_sel_w(int state)
{
if (m_mode_sel != state)
{
live_sync();
m_mode_sel = cur_live.mode_sel = state;
checkpoint();
- if (LOG) logerror("%s %s MODE SEL %u\n", machine().time().as_string(), machine().describe_context(), state);
+ LOG("%s %s MODE SEL %u\n", machine().time().as_string(), machine().describe_context(), state);
live_run();
}
}
-WRITE_LINE_MEMBER( c8050_fdc_device::rw_sel_w )
+void c8050_fdc_device::rw_sel_w(int state)
{
if (m_rw_sel != state)
{
live_sync();
m_rw_sel = cur_live.rw_sel = state;
checkpoint();
- if (LOG) logerror("%s %s RW SEL %u\n", machine().time().as_string(), machine().describe_context(), state);
+ LOG("%s %s RW SEL %u\n", machine().time().as_string(), machine().describe_context(), state);
if (m_rw_sel) {
pll_stop_writing(get_floppy(), cur_live.tm);
} else {
@@ -571,13 +564,13 @@ WRITE_LINE_MEMBER( c8050_fdc_device::rw_sel_w )
}
}
-WRITE_LINE_MEMBER( c8050_fdc_device::mtr0_w )
+void c8050_fdc_device::mtr0_w(int state)
{
if (m_mtr0 != state)
{
live_sync();
m_mtr0 = state;
- if (LOG) logerror("%s %s MTR0 %u\n", machine().time().as_string(), machine().describe_context(), state);
+ LOG("%s %s MTR0 %u\n", machine().time().as_string(), machine().describe_context(), state);
m_floppy0->mon_w(state);
checkpoint();
@@ -593,13 +586,13 @@ WRITE_LINE_MEMBER( c8050_fdc_device::mtr0_w )
}
}
-WRITE_LINE_MEMBER( c8050_fdc_device::mtr1_w )
+void c8050_fdc_device::mtr1_w(int state)
{
if (m_mtr1 != state)
{
live_sync();
m_mtr1 = state;
- if (LOG) logerror("%s %s MTR1 %u\n", machine().time().as_string(), machine().describe_context(), state);
+ LOG("%s %s MTR1 %u\n", machine().time().as_string(), machine().describe_context(), state);
if (m_floppy1) m_floppy1->mon_w(state);
checkpoint();
@@ -615,13 +608,13 @@ WRITE_LINE_MEMBER( c8050_fdc_device::mtr1_w )
}
}
-WRITE_LINE_MEMBER( c8050_fdc_device::odd_hd_w )
+void c8050_fdc_device::odd_hd_w(int state)
{
if (m_odd_hd != state)
{
live_sync();
m_odd_hd = cur_live.odd_hd = state;
- if (LOG) logerror("%s %s ODD HD %u\n", machine().time().as_string(), machine().describe_context(), state);
+ LOG("%s %s ODD HD %u\n", machine().time().as_string(), machine().describe_context(), state);
m_floppy0->ss_w(!state);
if (m_floppy1) m_floppy1->ss_w(!state);
checkpoint();
@@ -629,7 +622,7 @@ WRITE_LINE_MEMBER( c8050_fdc_device::odd_hd_w )
}
}
-WRITE_LINE_MEMBER( c8050_fdc_device::pull_sync_w )
+void c8050_fdc_device::pull_sync_w(int state)
{
- if (LOG_MORE) logerror("%s %s PULL SYNC %u\n", machine().time().as_string(), machine().describe_context(), state);
+ LOGMASKED(LOG_MORE, "%s %s PULL SYNC %u\n", machine().time().as_string(), machine().describe_context(), state);
}
diff --git a/src/devices/bus/ieee488/c8050fdc.h b/src/devices/bus/ieee488/c8050fdc.h
index dd390b1b7c5..0f1ecfc4918 100644
--- a/src/devices/bus/ieee488/c8050fdc.h
+++ b/src/devices/bus/ieee488/c8050fdc.h
@@ -11,8 +11,6 @@
#pragma once
-#include "formats/d80_dsk.h"
-#include "formats/d82_dsk.h"
#include "imagedev/floppy.h"
#include "machine/fdc_pll.h"
@@ -38,17 +36,17 @@ public:
uint8_t read();
void write(uint8_t data);
- DECLARE_WRITE_LINE_MEMBER( ds0_w );
- DECLARE_WRITE_LINE_MEMBER( ds1_w );
- DECLARE_WRITE_LINE_MEMBER( drv_sel_w );
- DECLARE_WRITE_LINE_MEMBER( mode_sel_w );
- DECLARE_WRITE_LINE_MEMBER( rw_sel_w );
- DECLARE_WRITE_LINE_MEMBER( mtr0_w );
- DECLARE_WRITE_LINE_MEMBER( mtr1_w );
- DECLARE_WRITE_LINE_MEMBER( odd_hd_w );
- DECLARE_WRITE_LINE_MEMBER( pull_sync_w );
-
- DECLARE_READ_LINE_MEMBER( wps_r ) { return checkpoint_live.drv_sel ? m_floppy1->wpt_r() : m_floppy0->wpt_r(); }
+ void ds0_w(int state);
+ void ds1_w(int state);
+ void drv_sel_w(int state);
+ void mode_sel_w(int state);
+ void rw_sel_w(int state);
+ void mtr0_w(int state);
+ void mtr1_w(int state);
+ void odd_hd_w(int state);
+ void pull_sync_w(int state);
+
+ int wps_r() { return checkpoint_live.drv_sel ? m_floppy1->wpt_r() : m_floppy0->wpt_r(); }
void stp0_w(int stp);
void stp1_w(int stp);
diff --git a/src/devices/bus/ieee488/c8280.cpp b/src/devices/bus/ieee488/c8280.cpp
index 1d9eb476110..ba90235d30c 100644
--- a/src/devices/bus/ieee488/c8280.cpp
+++ b/src/devices/bus/ieee488/c8280.cpp
@@ -9,6 +9,10 @@
#include "emu.h"
#include "c8280.h"
+#include "cpu/m6502/m6502.h"
+#include "formats/c8280_dsk.h"
+
+
//**************************************************************************
@@ -76,10 +80,10 @@ const tiny_rom_entry *c8280_device::device_rom_region() const
void c8280_device::c8280_main_mem(address_map &map)
{
- map(0x0000, 0x007f).mirror(0x100).m(M6532_0_TAG, FUNC(mos6532_new_device::ram_map));
- map(0x0080, 0x00ff).mirror(0x100).m(M6532_1_TAG, FUNC(mos6532_new_device::ram_map));
- map(0x0200, 0x021f).mirror(0xd60).m(M6532_0_TAG, FUNC(mos6532_new_device::io_map));
- map(0x0280, 0x029f).mirror(0xd60).m(M6532_1_TAG, FUNC(mos6532_new_device::io_map));
+ map(0x0000, 0x007f).mirror(0x100).m(M6532_0_TAG, FUNC(mos6532_device::ram_map));
+ map(0x0080, 0x00ff).mirror(0x100).m(M6532_1_TAG, FUNC(mos6532_device::ram_map));
+ map(0x0200, 0x021f).mirror(0xd60).m(M6532_0_TAG, FUNC(mos6532_device::io_map));
+ map(0x0280, 0x029f).mirror(0xd60).m(M6532_1_TAG, FUNC(mos6532_device::io_map));
map(0x1000, 0x13ff).mirror(0xc00).ram().share("share1");
map(0x2000, 0x23ff).mirror(0xc00).ram().share("share2");
map(0x3000, 0x33ff).mirror(0xc00).ram().share("share3");
@@ -300,11 +304,11 @@ void c8280_device::device_add_mconfig(machine_config &config)
M6502(config, m_maincpu, XTAL(12'000'000)/8);
m_maincpu->set_addrmap(AS_PROGRAM, &c8280_device::c8280_main_mem);
- MOS6532_NEW(config, m_riot0, XTAL(12'000'000)/8);
+ MOS6532(config, m_riot0, XTAL(12'000'000)/8);
m_riot0->pa_rd_callback().set(FUNC(c8280_device::dio_r));
m_riot0->pb_wr_callback().set(FUNC(c8280_device::dio_w));
- MOS6532_NEW(config, m_riot1, XTAL(12'000'000)/8);
+ MOS6532(config, m_riot1, XTAL(12'000'000)/8);
m_riot1->pa_rd_callback().set(FUNC(c8280_device::riot1_pa_r));
m_riot1->pa_wr_callback().set(FUNC(c8280_device::riot1_pa_w));
m_riot1->pb_rd_callback().set(FUNC(c8280_device::riot1_pb_r));
@@ -317,8 +321,9 @@ void c8280_device::device_add_mconfig(machine_config &config)
FD1797(config, m_fdc, XTAL(12'000'000)/6);
m_fdc->intrq_wr_callback().set_inputline(m_fdccpu, M6502_IRQ_LINE);
m_fdc->drq_wr_callback().set_inputline(m_fdccpu, M6502_SET_OVERFLOW);
- FLOPPY_CONNECTOR(config, m_floppy0, c8280_floppies, "8dsdd", c8280_device::floppy_formats);
- FLOPPY_CONNECTOR(config, m_floppy1, c8280_floppies, "8dsdd", c8280_device::floppy_formats);
+
+ for (auto &floppy : m_floppy)
+ FLOPPY_CONNECTOR(config, floppy, c8280_floppies, "8dsdd", c8280_device::floppy_formats);
}
@@ -387,10 +392,9 @@ c8280_device::c8280_device(const machine_config &mconfig, const char *tag, devic
m_riot0(*this, M6532_0_TAG),
m_riot1(*this, M6532_1_TAG),
m_fdc(*this, WD1797_TAG),
- m_floppy0(*this, WD1797_TAG ":0"),
- m_floppy1(*this, WD1797_TAG ":1"),
+ m_floppy(*this, WD1797_TAG ":%u", 0U),
m_address(*this, "ADDRESS"),
- m_floppy(nullptr),
+ m_selected_floppy(nullptr),
m_leds(*this, "led%u", 0U),
m_rfdo(1),
m_daco(1),
@@ -434,11 +438,11 @@ void c8280_device::device_reset()
m_riot1->reset();
m_fdc->reset();
- m_riot1->pa7_w(1);
+ m_riot1->pa_bit_w<7>(1);
m_fk5 = 0;
- m_floppy = nullptr;
- m_fdc->set_floppy(m_floppy);
+ m_selected_floppy = nullptr;
+ m_fdc->set_floppy(m_selected_floppy);
m_fdc->dden_w(0);
}
@@ -451,7 +455,7 @@ void c8280_device::ieee488_atn(int state)
{
update_ieee_signals();
- m_riot1->pa7_w(state);
+ m_riot1->pa_bit_w<7>(state);
}
@@ -488,8 +492,8 @@ uint8_t c8280_device::fk5_r()
uint8_t data = m_fk5;
- data |= (m_floppy ? m_floppy->dskchg_r() : 1) << 3;
- data |= (m_floppy ? m_floppy->twosid_r() : 1) << 4;
+ data |= (m_selected_floppy ? m_selected_floppy->dskchg_r() : 1) << 3;
+ data |= (m_selected_floppy ? m_selected_floppy->twosid_r() : 1) << 4;
return data;
}
@@ -514,14 +518,17 @@ void c8280_device::fk5_w(uint8_t data)
m_fk5 = data & 0x27;
// drive select
- m_floppy = nullptr;
-
- if (BIT(data, 0)) m_floppy = m_floppy0->get_device();
- if (BIT(data, 1)) m_floppy = m_floppy1->get_device();
+ m_selected_floppy = nullptr;
+ for (int n = 0; n < 2; n++)
+ {
+ if (BIT(data, n))
+ m_selected_floppy = m_floppy[n]->get_device();
+ }
- m_fdc->set_floppy(m_floppy);
+ m_fdc->set_floppy(m_selected_floppy);
- if (m_floppy) m_floppy->mon_w(!BIT(data, 5));
+ if (m_selected_floppy)
+ m_selected_floppy->mon_w(!BIT(data, 5));
// density select
m_fdc->dden_w(BIT(data, 2));
diff --git a/src/devices/bus/ieee488/c8280.h b/src/devices/bus/ieee488/c8280.h
index 1317a6c13f7..fc6a4f92dec 100644
--- a/src/devices/bus/ieee488/c8280.h
+++ b/src/devices/bus/ieee488/c8280.h
@@ -12,10 +12,8 @@
#pragma once
#include "ieee488.h"
-#include "cpu/m6502/m6502.h"
-#include "formats/c8280_dsk.h"
#include "imagedev/floppy.h"
-#include "machine/mos6530n.h"
+#include "machine/mos6530.h"
#include "machine/wd_fdc.h"
@@ -65,13 +63,12 @@ private:
required_device<cpu_device> m_maincpu;
required_device<cpu_device> m_fdccpu;
- required_device<mos6532_new_device> m_riot0;
- required_device<mos6532_new_device> m_riot1;
+ required_device<mos6532_device> m_riot0;
+ required_device<mos6532_device> m_riot1;
required_device<fd1797_device> m_fdc;
- required_device<floppy_connector> m_floppy0;
- required_device<floppy_connector> m_floppy1;
+ required_device_array<floppy_connector, 2> m_floppy;
required_ioport m_address;
- floppy_image_device *m_floppy;
+ floppy_image_device *m_selected_floppy;
output_finder<4> m_leds;
// IEEE-488 bus
diff --git a/src/devices/bus/ieee488/d9060.cpp b/src/devices/bus/ieee488/d9060.cpp
index 464db8cc902..3020fa41f42 100644
--- a/src/devices/bus/ieee488/d9060.cpp
+++ b/src/devices/bus/ieee488/d9060.cpp
@@ -107,10 +107,10 @@ const tiny_rom_entry *d9060_device_base::device_rom_region() const
void d9060_device_base::main_mem(address_map &map)
{
- map(0x0000, 0x007f).mirror(0x0100).m(m_riot0, FUNC(mos6532_new_device::ram_map));
- map(0x0080, 0x00ff).mirror(0x0100).m(m_riot1, FUNC(mos6532_new_device::ram_map));
- map(0x0200, 0x021f).mirror(0x0d60).m(m_riot0, FUNC(mos6532_new_device::io_map));
- map(0x0280, 0x029f).mirror(0x0d60).m(m_riot1, FUNC(mos6532_new_device::io_map));
+ map(0x0000, 0x007f).mirror(0x0100).m(m_riot0, FUNC(mos6532_device::ram_map));
+ map(0x0080, 0x00ff).mirror(0x0100).m(m_riot1, FUNC(mos6532_device::ram_map));
+ map(0x0200, 0x021f).mirror(0x0d60).m(m_riot0, FUNC(mos6532_device::io_map));
+ map(0x0280, 0x029f).mirror(0x0d60).m(m_riot1, FUNC(mos6532_device::io_map));
map(0x1000, 0x13ff).mirror(0x0c00).ram().share("share1");
map(0x2000, 0x23ff).mirror(0x0c00).ram().share("share2");
map(0x3000, 0x33ff).mirror(0x0c00).ram().share("share3");
@@ -328,12 +328,12 @@ void d9060_device_base::via_pb_w(uint8_t data)
m_sasibus->write_rst(BIT(data, 1));
}
-WRITE_LINE_MEMBER( d9060_device_base::ack_w )
+void d9060_device_base::ack_w(int state)
{
m_sasibus->write_ack(!state);
}
-WRITE_LINE_MEMBER( d9060_device_base::enable_w )
+void d9060_device_base::enable_w(int state)
{
m_enable = state;
@@ -368,11 +368,11 @@ void d9060_device_base::device_add_mconfig(machine_config &config)
M6502(config, m_maincpu, XTAL(4'000'000)/4);
m_maincpu->set_addrmap(AS_PROGRAM, &d9060_device::main_mem);
- MOS6532_NEW(config, m_riot0, XTAL(4'000'000)/4);
+ MOS6532(config, m_riot0, XTAL(4'000'000)/4);
m_riot0->pa_rd_callback().set(FUNC(d9060_device_base::dio_r));
m_riot0->pb_wr_callback().set(FUNC(d9060_device_base::dio_w));
- MOS6532_NEW(config, m_riot1, XTAL(4'000'000)/4);
+ MOS6532(config, m_riot1, XTAL(4'000'000)/4);
m_riot1->pa_rd_callback().set(FUNC(d9060_device_base::riot1_pa_r));
m_riot1->pa_wr_callback().set(FUNC(d9060_device_base::riot1_pa_w));
m_riot1->pb_rd_callback().set(FUNC(d9060_device_base::riot1_pb_r));
@@ -542,7 +542,7 @@ void d9060_device_base::device_reset()
m_hdccpu->set_input_line(M6502_SET_OVERFLOW, ASSERT_LINE);
- m_riot1->pa7_w(1);
+ m_riot1->pa_bit_w<7>(1);
}
@@ -554,7 +554,7 @@ void d9060_device_base::ieee488_atn(int state)
{
update_ieee_signals();
- m_riot1->pa7_w(state);
+ m_riot1->pa_bit_w<7>(state);
}
diff --git a/src/devices/bus/ieee488/d9060.h b/src/devices/bus/ieee488/d9060.h
index a5da444dbcf..6e137dba478 100644
--- a/src/devices/bus/ieee488/d9060.h
+++ b/src/devices/bus/ieee488/d9060.h
@@ -14,7 +14,7 @@
#include "ieee488.h"
#include "cpu/m6502/m6502.h"
#include "machine/6522via.h"
-#include "machine/mos6530n.h"
+#include "machine/mos6530.h"
#include "bus/scsi/scsi.h"
@@ -61,14 +61,14 @@ private:
uint8_t riot1_pb_r();
void riot1_pb_w(uint8_t data);
void via_pb_w(uint8_t data);
- DECLARE_WRITE_LINE_MEMBER( ack_w );
- DECLARE_WRITE_LINE_MEMBER( enable_w );
+ void ack_w(int state);
+ void enable_w(int state);
void scsi_data_w(uint8_t data);
required_device<m6502_device> m_maincpu;
required_device<m6502_device> m_hdccpu;
- required_device<mos6532_new_device> m_riot0;
- required_device<mos6532_new_device> m_riot1;
+ required_device<mos6532_device> m_riot0;
+ required_device<mos6532_device> m_riot1;
required_device<via6522_device> m_via;
required_device<scsi_port_device> m_sasibus;
required_device<output_latch_device> m_sasi_data_out;
diff --git a/src/devices/bus/ieee488/hp9122c.cpp b/src/devices/bus/ieee488/hp9122c.cpp
index f9619617ca1..f533ecb8b11 100644
--- a/src/devices/bus/ieee488/hp9122c.cpp
+++ b/src/devices/bus/ieee488/hp9122c.cpp
@@ -13,6 +13,7 @@
#include "cpu/m6809/m6809.h"
#include "machine/i8291a.h"
#include "machine/wd_fdc.h"
+#include "formats/flopimg.h"
#include "hp9122c.lh"
DEFINE_DEVICE_TYPE(HP9122C, hp9122c_device, "hp9122c", "HP9122C Dual High density disk drive")
@@ -155,65 +156,65 @@ void hp9122c_device::ieee488_ren(int state)
m_i8291a->ren_w(state);
}
-WRITE_LINE_MEMBER(hp9122c_device::i8291a_eoi_w)
+void hp9122c_device::i8291a_eoi_w(int state)
{
m_bus->eoi_w(this, state);
}
-WRITE_LINE_MEMBER(hp9122c_device::i8291a_dav_w)
+void hp9122c_device::i8291a_dav_w(int state)
{
m_bus->dav_w(this, state);
}
-WRITE_LINE_MEMBER(hp9122c_device::i8291a_nrfd_w)
+void hp9122c_device::i8291a_nrfd_w(int state)
{
m_bus->nrfd_w(this, state);
}
-WRITE_LINE_MEMBER(hp9122c_device::i8291a_ndac_w)
+void hp9122c_device::i8291a_ndac_w(int state)
{
m_bus->ndac_w(this, state);
}
-WRITE_LINE_MEMBER(hp9122c_device::i8291a_ifc_w)
+void hp9122c_device::i8291a_ifc_w(int state)
{
m_bus->ifc_w(this, state);
}
-WRITE_LINE_MEMBER(hp9122c_device::i8291a_srq_w)
+void hp9122c_device::i8291a_srq_w(int state)
{
m_bus->srq_w(this, state);
}
-WRITE_LINE_MEMBER(hp9122c_device::i8291a_atn_w)
+void hp9122c_device::i8291a_atn_w(int state)
{
m_bus->atn_w(this, state);
}
-WRITE_LINE_MEMBER(hp9122c_device::i8291a_ren_w)
+void hp9122c_device::i8291a_ren_w(int state)
{
m_bus->ren_w(this, state);
}
-WRITE_LINE_MEMBER(hp9122c_device::i8291a_int_w)
+void hp9122c_device::i8291a_int_w(int state)
{
m_i8291a_irq = state;
update_intsel();
}
-WRITE_LINE_MEMBER(hp9122c_device::i8291a_dreq_w)
+void hp9122c_device::i8291a_dreq_w(int state)
{
m_i8291a_drq = state;
update_intsel();
}
-WRITE_LINE_MEMBER(hp9122c_device::fdc_intrq_w)
+void hp9122c_device::fdc_intrq_w(int state)
{
m_fdc_irq = state;
update_intsel();
}
-WRITE_LINE_MEMBER(hp9122c_device::fdc_drq_w)
+void hp9122c_device::fdc_drq_w(int state)
{
m_fdc_drq = state;
update_intsel();
diff --git a/src/devices/bus/ieee488/hp9122c.h b/src/devices/bus/ieee488/hp9122c.h
index 0c2d4854251..d763124cf98 100644
--- a/src/devices/bus/ieee488/hp9122c.h
+++ b/src/devices/bus/ieee488/hp9122c.h
@@ -91,23 +91,23 @@ private:
constexpr static int REG_STATUS_DISKCHG = 1 << 5;
constexpr static int REG_STATUS_LOW_DENSITY = 1 << 7;
- DECLARE_WRITE_LINE_MEMBER(i8291a_eoi_w);
- DECLARE_WRITE_LINE_MEMBER(i8291a_dav_w);
- DECLARE_WRITE_LINE_MEMBER(i8291a_nrfd_w);
- DECLARE_WRITE_LINE_MEMBER(i8291a_ndac_w);
- DECLARE_WRITE_LINE_MEMBER(i8291a_ifc_w);
- DECLARE_WRITE_LINE_MEMBER(i8291a_srq_w);
- DECLARE_WRITE_LINE_MEMBER(i8291a_atn_w);
- DECLARE_WRITE_LINE_MEMBER(i8291a_ren_w);
+ void i8291a_eoi_w(int state);
+ void i8291a_dav_w(int state);
+ void i8291a_nrfd_w(int state);
+ void i8291a_ndac_w(int state);
+ void i8291a_ifc_w(int state);
+ void i8291a_srq_w(int state);
+ void i8291a_atn_w(int state);
+ void i8291a_ren_w(int state);
uint8_t i8291a_dio_r();
void i8291a_dio_w(uint8_t data);
- DECLARE_WRITE_LINE_MEMBER(i8291a_int_w);
- DECLARE_WRITE_LINE_MEMBER(i8291a_dreq_w);
+ void i8291a_int_w(int state);
+ void i8291a_dreq_w(int state);
- DECLARE_WRITE_LINE_MEMBER(fdc_intrq_w);
- DECLARE_WRITE_LINE_MEMBER(fdc_drq_w);
+ void fdc_intrq_w(int state);
+ void fdc_drq_w(int state);
void cmd_w(uint8_t data);
uint8_t status_r();
diff --git a/src/devices/bus/ieee488/hp9895.cpp b/src/devices/bus/ieee488/hp9895.cpp
index aead54c0a18..ffc7ae29d70 100644
--- a/src/devices/bus/ieee488/hp9895.cpp
+++ b/src/devices/bus/ieee488/hp9895.cpp
@@ -56,6 +56,7 @@
#include "emu.h"
#include "hp9895.h"
+#include "formats/fs_hp98x5.h"
#include "formats/hpi_dsk.h"
#define LOG_LEVEL0 (0x1U << 1)
@@ -137,7 +138,7 @@ hp9895_device::hp9895_device(const machine_config &mconfig, const char *tag, dev
device_ieee488_interface(mconfig, *this),
m_cpu(*this , "cpu"),
m_phi(*this , "phi"),
- m_drives{{*this , "floppy0"} , {*this , "floppy1"}},
+ m_drives(*this , "floppy%u" , 0U),
m_switches{*this , "switches"}
{
}
@@ -415,42 +416,42 @@ void hp9895_device::ieee488_ren(int state)
m_phi->ren_w(state);
}
-WRITE_LINE_MEMBER(hp9895_device::phi_eoi_w)
+void hp9895_device::phi_eoi_w(int state)
{
m_bus->eoi_w(this , state);
}
-WRITE_LINE_MEMBER(hp9895_device::phi_dav_w)
+void hp9895_device::phi_dav_w(int state)
{
m_bus->dav_w(this , state);
}
-WRITE_LINE_MEMBER(hp9895_device::phi_nrfd_w)
+void hp9895_device::phi_nrfd_w(int state)
{
m_bus->nrfd_w(this , state);
}
-WRITE_LINE_MEMBER(hp9895_device::phi_ndac_w)
+void hp9895_device::phi_ndac_w(int state)
{
m_bus->ndac_w(this , state);
}
-WRITE_LINE_MEMBER(hp9895_device::phi_ifc_w)
+void hp9895_device::phi_ifc_w(int state)
{
m_bus->ifc_w(this , state);
}
-WRITE_LINE_MEMBER(hp9895_device::phi_srq_w)
+void hp9895_device::phi_srq_w(int state)
{
m_bus->srq_w(this , state);
}
-WRITE_LINE_MEMBER(hp9895_device::phi_atn_w)
+void hp9895_device::phi_atn_w(int state)
{
m_bus->atn_w(this , state);
}
-WRITE_LINE_MEMBER(hp9895_device::phi_ren_w)
+void hp9895_device::phi_ren_w(int state)
{
m_bus->ren_w(this , state);
}
@@ -465,7 +466,7 @@ void hp9895_device::phi_dio_w(uint8_t data)
m_bus->dio_w(this , data);
}
-WRITE_LINE_MEMBER(hp9895_device::phi_int_w)
+void hp9895_device::phi_int_w(int state)
{
m_cpu->set_input_line(INPUT_LINE_NMI , state);
if (state) {
@@ -861,6 +862,8 @@ static void hp9895_floppies(device_slot_interface &device)
static void hp9895_floppy_formats(format_registration &fr)
{
fr.add(FLOPPY_HPI_FORMAT);
+ fr.add(fs::HP9825);
+ fr.add(fs::HP9845);
};
const tiny_rom_entry *hp9895_device::device_rom_region() const
diff --git a/src/devices/bus/ieee488/hp9895.h b/src/devices/bus/ieee488/hp9895.h
index 1cb77d60090..0f33b543929 100644
--- a/src/devices/bus/ieee488/hp9895.h
+++ b/src/devices/bus/ieee488/hp9895.h
@@ -47,21 +47,21 @@ protected:
private:
// PHI write CBs
- DECLARE_WRITE_LINE_MEMBER(phi_eoi_w);
- DECLARE_WRITE_LINE_MEMBER(phi_dav_w);
- DECLARE_WRITE_LINE_MEMBER(phi_nrfd_w);
- DECLARE_WRITE_LINE_MEMBER(phi_ndac_w);
- DECLARE_WRITE_LINE_MEMBER(phi_ifc_w);
- DECLARE_WRITE_LINE_MEMBER(phi_srq_w);
- DECLARE_WRITE_LINE_MEMBER(phi_atn_w);
- DECLARE_WRITE_LINE_MEMBER(phi_ren_w);
+ void phi_eoi_w(int state);
+ void phi_dav_w(int state);
+ void phi_nrfd_w(int state);
+ void phi_ndac_w(int state);
+ void phi_ifc_w(int state);
+ void phi_srq_w(int state);
+ void phi_atn_w(int state);
+ void phi_ren_w(int state);
// PHI DIO r/w CBs
uint8_t phi_dio_r();
void phi_dio_w(uint8_t data);
// PHI IRQ/Z80 NMI
- DECLARE_WRITE_LINE_MEMBER(phi_int_w);
+ void phi_int_w(int state);
// Z80 IRQ
void z80_m1_w(uint8_t data);
@@ -105,7 +105,7 @@ private:
required_device<z80_device> m_cpu;
required_device<phi_device> m_phi;
- required_device<floppy_connector> m_drives[ 2 ];
+ required_device_array<floppy_connector, 2> m_drives;
required_ioport m_switches;
bool m_cpu_irq;
diff --git a/src/devices/bus/ieee488/ieee488.cpp b/src/devices/bus/ieee488/ieee488.cpp
index 947aad2d1f7..94a93e424e4 100644
--- a/src/devices/bus/ieee488/ieee488.cpp
+++ b/src/devices/bus/ieee488/ieee488.cpp
@@ -135,16 +135,6 @@ ieee488_device::ieee488_device(const machine_config &mconfig, const char *tag, d
void ieee488_device::device_start()
{
- // resolve callbacks
- m_write_eoi.resolve_safe();
- m_write_dav.resolve_safe();
- m_write_nrfd.resolve_safe();
- m_write_ndac.resolve_safe();
- m_write_ifc.resolve_safe();
- m_write_srq.resolve_safe();
- m_write_atn.resolve_safe();
- m_write_ren.resolve_safe();
- m_write_dio.resolve_safe();
}
diff --git a/src/devices/bus/ieee488/ieee488.h b/src/devices/bus/ieee488/ieee488.h
index 5a83d0fe927..3635c105de6 100644
--- a/src/devices/bus/ieee488/ieee488.h
+++ b/src/devices/bus/ieee488/ieee488.h
@@ -62,25 +62,25 @@ public:
// reads for both host and peripherals
uint8_t dio_r() { return get_data(); }
- DECLARE_READ_LINE_MEMBER( eoi_r ) { return get_signal(EOI); }
- DECLARE_READ_LINE_MEMBER( dav_r ) { return get_signal(DAV); }
- DECLARE_READ_LINE_MEMBER( nrfd_r ) { return get_signal(NRFD); }
- DECLARE_READ_LINE_MEMBER( ndac_r ) { return get_signal(NDAC); }
- DECLARE_READ_LINE_MEMBER( ifc_r ) { return get_signal(IFC); }
- DECLARE_READ_LINE_MEMBER( srq_r ) { return get_signal(SRQ); }
- DECLARE_READ_LINE_MEMBER( atn_r ) { return get_signal(ATN); }
- DECLARE_READ_LINE_MEMBER( ren_r ) { return get_signal(REN); }
+ int eoi_r() { return get_signal(EOI); }
+ int dav_r() { return get_signal(DAV); }
+ int nrfd_r() { return get_signal(NRFD); }
+ int ndac_r() { return get_signal(NDAC); }
+ int ifc_r() { return get_signal(IFC); }
+ int srq_r() { return get_signal(SRQ); }
+ int atn_r() { return get_signal(ATN); }
+ int ren_r() { return get_signal(REN); }
// writes for host (driver_device)
void host_dio_w(uint8_t data) { set_data(this, data); }
- DECLARE_WRITE_LINE_MEMBER( host_eoi_w ) { set_signal(this, EOI, state); }
- DECLARE_WRITE_LINE_MEMBER( host_dav_w ) { set_signal(this, DAV, state); }
- DECLARE_WRITE_LINE_MEMBER( host_nrfd_w ) { set_signal(this, NRFD, state); }
- DECLARE_WRITE_LINE_MEMBER( host_ndac_w ) { set_signal(this, NDAC, state); }
- DECLARE_WRITE_LINE_MEMBER( host_ifc_w ) { set_signal(this, IFC, state); }
- DECLARE_WRITE_LINE_MEMBER( host_srq_w ) { set_signal(this, SRQ, state); }
- DECLARE_WRITE_LINE_MEMBER( host_atn_w ) { set_signal(this, ATN, state); }
- DECLARE_WRITE_LINE_MEMBER( host_ren_w ) { set_signal(this, REN, state); }
+ void host_eoi_w(int state) { set_signal(this, EOI, state); }
+ void host_dav_w(int state) { set_signal(this, DAV, state); }
+ void host_nrfd_w(int state) { set_signal(this, NRFD, state); }
+ void host_ndac_w(int state) { set_signal(this, NDAC, state); }
+ void host_ifc_w(int state) { set_signal(this, IFC, state); }
+ void host_srq_w(int state) { set_signal(this, SRQ, state); }
+ void host_atn_w(int state) { set_signal(this, ATN, state); }
+ void host_ren_w(int state) { set_signal(this, REN, state); }
// writes for peripherals (device_t)
void dio_w(device_t *device, uint8_t data) { set_data(device, data); }
diff --git a/src/devices/bus/imi7000/imi5000h.cpp b/src/devices/bus/imi7000/imi5000h.cpp
index f32e7fdf2b3..fe70dcba6ac 100644
--- a/src/devices/bus/imi7000/imi5000h.cpp
+++ b/src/devices/bus/imi7000/imi5000h.cpp
@@ -108,18 +108,18 @@ static const z80_daisy_config z80_daisy_chain[] =
// Z80CTC
//-------------------------------------------------
-WRITE_LINE_MEMBER( imi5000h_device::ctc_z0_w )
+void imi5000h_device::ctc_z0_w(int state)
{
m_ctc->trg1(state);
}
-WRITE_LINE_MEMBER( imi5000h_device::ctc_z1_w )
+void imi5000h_device::ctc_z1_w(int state)
{
m_ctc->trg2(state);
m_ctc->trg3(state);
}
-WRITE_LINE_MEMBER( imi5000h_device::ctc_z2_w )
+void imi5000h_device::ctc_z2_w(int state)
{
//m_memory_enable = state;
m_maincpu->set_input_line(INPUT_LINE_NMI, state);
diff --git a/src/devices/bus/imi7000/imi5000h.h b/src/devices/bus/imi7000/imi5000h.h
index 77d276b154b..1680677056a 100644
--- a/src/devices/bus/imi7000/imi5000h.h
+++ b/src/devices/bus/imi7000/imi5000h.h
@@ -45,9 +45,9 @@ protected:
virtual ioport_constructor device_input_ports() const override;
private:
- DECLARE_WRITE_LINE_MEMBER( ctc_z0_w );
- DECLARE_WRITE_LINE_MEMBER( ctc_z1_w );
- DECLARE_WRITE_LINE_MEMBER( ctc_z2_w );
+ void ctc_z0_w(int state);
+ void ctc_z1_w(int state);
+ void ctc_z2_w(int state);
uint8_t pio0_pa_r();
void pio0_pa_w(uint8_t data);
diff --git a/src/devices/bus/imi7000/imi7000.h b/src/devices/bus/imi7000/imi7000.h
index c1cf590091c..ce76033f30a 100644
--- a/src/devices/bus/imi7000/imi7000.h
+++ b/src/devices/bus/imi7000/imi7000.h
@@ -80,10 +80,10 @@ public:
template <typename T, typename U, typename V, typename W>
void set_slot_default_options(T &&def1, U &&def2, V &&def3, W &&def4)
{
- subdevice<imi7000_slot_device>(m_units[0].finder_tag())->set_default_option(std::forward<T>(def1));
- subdevice<imi7000_slot_device>(m_units[1].finder_tag())->set_default_option(std::forward<U>(def2));
- subdevice<imi7000_slot_device>(m_units[2].finder_tag())->set_default_option(std::forward<V>(def3));
- subdevice<imi7000_slot_device>(m_units[3].finder_tag())->set_default_option(std::forward<W>(def4));
+ m_units[0].lookup()->set_default_option(std::forward<T>(def1));
+ m_units[1].lookup()->set_default_option(std::forward<U>(def2));
+ m_units[2].lookup()->set_default_option(std::forward<V>(def3));
+ m_units[3].lookup()->set_default_option(std::forward<W>(def4));
}
protected:
diff --git a/src/devices/bus/intellec4/insdatastor.cpp b/src/devices/bus/intellec4/insdatastor.cpp
index 81bbf713db7..ccbac01904e 100644
--- a/src/devices/bus/intellec4/insdatastor.cpp
+++ b/src/devices/bus/intellec4/insdatastor.cpp
@@ -168,7 +168,7 @@ class imm4_22_device
public:
imm4_22_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
- virtual image_init_result call_load() override;
+ virtual std::pair<std::error_condition, std::string> call_load() override;
virtual void call_unload() override;
virtual bool is_readable() const noexcept override { return true; }
@@ -184,7 +184,7 @@ protected:
virtual void device_start() override;
virtual void device_reset() override;
- virtual DECLARE_WRITE_LINE_MEMBER(reset_4002_in) override;
+ virtual void reset_4002_in(int state) override;
private:
void ram_out(offs_t offset, u8 data);
@@ -222,18 +222,22 @@ imm4_22_device::imm4_22_device(machine_config const &mconfig, char const *tag, d
}
-image_init_result imm4_22_device::call_load()
+std::pair<std::error_condition, std::string> imm4_22_device::call_load()
{
if ((length() > 1024U) || (length() % 256U))
- return image_init_result::FAIL;
+ {
+ return std::make_pair(
+ image_error::INVALIDLENGTH,
+ "Invalid PROM image size (must be a multiple of 256 bytes no larger than 1K)");
+ }
allocate();
if (fread(m_prom.get(), length()) != length())
- return image_init_result::FAIL;
+ return std::make_pair(image_error::UNSPECIFIED, "Error reading file");
map_prom();
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
void imm4_22_device::call_unload()
@@ -267,7 +271,7 @@ void imm4_22_device::device_reset()
}
-WRITE_LINE_MEMBER(imm4_22_device::reset_4002_in)
+void imm4_22_device::reset_4002_in(int state)
{
// FIXME: this takes several cycles to actually erase everything, and prevents writes while asserted
if (!state)
diff --git a/src/devices/bus/intellec4/intellec4.cpp b/src/devices/bus/intellec4/intellec4.cpp
index f1eb0934448..fb980a2efd5 100644
--- a/src/devices/bus/intellec4/intellec4.cpp
+++ b/src/devices/bus/intellec4/intellec4.cpp
@@ -69,7 +69,7 @@ univ_bus_device::univ_bus_device(machine_config const &mconfig, char const *tag,
input lines
----------------------------------*/
-WRITE_LINE_MEMBER(univ_bus_device::sync_in)
+void univ_bus_device::sync_in(int state)
{
for (device_univ_card_interface *card : m_cards)
{
@@ -80,7 +80,7 @@ WRITE_LINE_MEMBER(univ_bus_device::sync_in)
}
}
-WRITE_LINE_MEMBER(univ_bus_device::stop_acknowledge_in)
+void univ_bus_device::stop_acknowledge_in(int state)
{
for (device_univ_card_interface *card : m_cards)
{
@@ -91,7 +91,7 @@ WRITE_LINE_MEMBER(univ_bus_device::stop_acknowledge_in)
}
}
-WRITE_LINE_MEMBER(univ_bus_device::cpu_reset_in)
+void univ_bus_device::cpu_reset_in(int state)
{
for (device_univ_card_interface *card : m_cards)
{
@@ -109,11 +109,6 @@ WRITE_LINE_MEMBER(univ_bus_device::cpu_reset_in)
void univ_bus_device::device_start()
{
- m_test_out_cb.resolve_safe();
- m_stop_out_cb.resolve_safe();
- m_reset_4002_out_cb.resolve_safe();
- m_user_reset_out_cb.resolve_safe();
-
save_item(NAME(m_test));
save_item(NAME(m_stop));
save_item(NAME(m_reset_4002));
diff --git a/src/devices/bus/intellec4/intellec4.h b/src/devices/bus/intellec4/intellec4.h
index 287c23681bf..206134dadfb 100644
--- a/src/devices/bus/intellec4/intellec4.h
+++ b/src/devices/bus/intellec4/intellec4.h
@@ -167,18 +167,18 @@ public:
univ_bus_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock);
// input lines
- DECLARE_WRITE_LINE_MEMBER(sync_in);
- DECLARE_WRITE_LINE_MEMBER(test_in) {set_test(std::size(m_cards), state); }
- DECLARE_WRITE_LINE_MEMBER(stop_in) {set_stop(std::size(m_cards), state); }
- DECLARE_WRITE_LINE_MEMBER(stop_acknowledge_in);
- DECLARE_WRITE_LINE_MEMBER(cpu_reset_in);
- DECLARE_WRITE_LINE_MEMBER(reset_4002_in) { set_reset_4002(std::size(m_cards), state); }
+ void sync_in(int state);
+ void test_in(int state) {set_test(std::size(m_cards), state); }
+ void stop_in(int state) {set_stop(std::size(m_cards), state); }
+ void stop_acknowledge_in(int state);
+ void cpu_reset_in(int state);
+ void reset_4002_in(int state) { set_reset_4002(std::size(m_cards), state); }
// output lines
- DECLARE_READ_LINE_MEMBER(test_out) const { return (m_test & ~(u16(1U) << std::size(m_cards))) ? 0 : 1; }
- DECLARE_READ_LINE_MEMBER(stop_out) const { return (m_stop & ~(u16(1U) << std::size(m_cards))) ? 0 : 1; }
- DECLARE_READ_LINE_MEMBER(reset_4002_out) const { return (m_reset_4002 & ~(u16(1U) << std::size(m_cards))) ? 0 : 1; }
- DECLARE_READ_LINE_MEMBER(user_reset_out) const { return (m_user_reset & ~(u16(1U) << std::size(m_cards))) ? 0 : 1; }
+ int test_out() const { return (m_test & ~(u16(1U) << std::size(m_cards))) ? 0 : 1; }
+ int stop_out() const { return (m_stop & ~(u16(1U) << std::size(m_cards))) ? 0 : 1; }
+ int reset_4002_out() const { return (m_reset_4002 & ~(u16(1U) << std::size(m_cards))) ? 0 : 1; }
+ int user_reset_out() const { return (m_user_reset & ~(u16(1U) << std::size(m_cards))) ? 0 : 1; }
protected:
// device_t implementation
@@ -227,18 +227,18 @@ protected:
address_space &status_space() { return *m_bus->m_status_space; }
address_space &ram_ports_space() { return *m_bus->m_ram_ports_space; }
- DECLARE_WRITE_LINE_MEMBER(test_out) { m_bus->set_test(m_index, state); }
- DECLARE_WRITE_LINE_MEMBER(stop_out) { m_bus->set_stop(m_index, state); }
- DECLARE_WRITE_LINE_MEMBER(reset_4002_out) { m_bus->set_reset_4002(m_index, state); }
- DECLARE_WRITE_LINE_MEMBER(user_reset_out) { m_bus->set_user_reset(m_index, state); }
-
- virtual DECLARE_WRITE_LINE_MEMBER(sync_in) { }
- virtual DECLARE_WRITE_LINE_MEMBER(test_in) { }
- virtual DECLARE_WRITE_LINE_MEMBER(stop_in) { }
- virtual DECLARE_WRITE_LINE_MEMBER(stop_acknowledge_in) { }
- virtual DECLARE_WRITE_LINE_MEMBER(cpu_reset_in) { }
- virtual DECLARE_WRITE_LINE_MEMBER(reset_4002_in) { }
- virtual DECLARE_WRITE_LINE_MEMBER(user_reset_in) { }
+ void test_out(int state) { m_bus->set_test(m_index, state); }
+ void stop_out(int state) { m_bus->set_stop(m_index, state); }
+ void reset_4002_out(int state) { m_bus->set_reset_4002(m_index, state); }
+ void user_reset_out(int state) { m_bus->set_user_reset(m_index, state); }
+
+ virtual void sync_in(int state) { }
+ virtual void test_in(int state) { }
+ virtual void stop_in(int state) { }
+ virtual void stop_acknowledge_in(int state) { }
+ virtual void cpu_reset_in(int state) { }
+ virtual void reset_4002_in(int state) { }
+ virtual void user_reset_in(int state) { }
private:
void set_bus(univ_bus_device &bus);
diff --git a/src/devices/bus/intellec4/prommemory.cpp b/src/devices/bus/intellec4/prommemory.cpp
index 7af8a5757f2..87583d79cac 100644
--- a/src/devices/bus/intellec4/prommemory.cpp
+++ b/src/devices/bus/intellec4/prommemory.cpp
@@ -97,7 +97,7 @@ class imm6_26_device
public:
imm6_26_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
- virtual image_init_result call_load() override;
+ virtual std::pair<std::error_condition, std::string> call_load() override;
virtual void call_unload() override;
virtual bool is_readable() const noexcept override { return true; }
@@ -128,20 +128,24 @@ imm6_26_device::imm6_26_device(machine_config const &mconfig, char const *tag, d
}
-image_init_result imm6_26_device::call_load()
+std::pair<std::error_condition, std::string> imm6_26_device::call_load()
{
if ((length() > 4096U) || (length() % 256U))
- return image_init_result::FAIL;
+ {
+ return std::make_pair(
+ image_error::INVALIDLENGTH,
+ "Invalid PROM image size (must be a multiple of 256 bytes no larger than 4K)");
+ }
unmap();
allocate();
if (fread(m_data.get(), length()) != length())
- return image_init_result::FAIL;
+ return std::make_pair(image_error::UNSPECIFIED, "Error reading file");
// FIXME: gimme a cookie!
rom_space().install_rom(0x1000U, offs_t(0x1000U + length()), m_data.get());
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
void imm6_26_device::call_unload()
diff --git a/src/devices/bus/intellec4/tapereader.cpp b/src/devices/bus/intellec4/tapereader.cpp
index aa1acd9e963..ef42f617832 100644
--- a/src/devices/bus/intellec4/tapereader.cpp
+++ b/src/devices/bus/intellec4/tapereader.cpp
@@ -28,7 +28,7 @@ class imm4_90_device
public:
imm4_90_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
- virtual image_init_result call_load() override;
+ virtual std::pair<std::error_condition, std::string> call_load() override;
virtual void call_unload() override;
virtual char const *file_extensions() const noexcept override { return "bnpf,hex,lst,txt"; }
@@ -41,7 +41,7 @@ private:
u8 rom6_in() { return ~m_data & 0x0fU; }
u8 rom7_in() { return (~m_data >> 4) & 0x0fU; }
void rom4_out(u8 data) { advance(BIT(data, 3)); }
- DECLARE_WRITE_LINE_MEMBER(advance);
+ void advance(int state);
TIMER_CALLBACK_MEMBER(step);
emu_timer *m_step_timer;
@@ -65,13 +65,13 @@ imm4_90_device::imm4_90_device(machine_config const &mconfig, char const *tag, d
}
-image_init_result imm4_90_device::call_load()
+std::pair<std::error_condition, std::string> imm4_90_device::call_load()
{
m_step_timer->reset();
m_data = 0x00U;
m_ready = false;
m_stepping = false;
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
void imm4_90_device::call_unload()
@@ -99,7 +99,7 @@ void imm4_90_device::device_start()
}
-DECLARE_WRITE_LINE_MEMBER(imm4_90_device::advance)
+void imm4_90_device::advance(int state)
{
// this is edge-sensitive - CPU sends the narrowest pulse it can
if (!m_advance && !bool(state) && !m_stepping)
diff --git a/src/devices/bus/interpro/keyboard/hle.cpp b/src/devices/bus/interpro/keyboard/hle.cpp
index 8d773a9fa85..9f2ddacdc39 100644
--- a/src/devices/bus/interpro/keyboard/hle.cpp
+++ b/src/devices/bus/interpro/keyboard/hle.cpp
@@ -272,7 +272,7 @@ hle_device_base::~hle_device_base()
{
}
-WRITE_LINE_MEMBER(hle_device_base::input_txd)
+void hle_device_base::input_txd(int state)
{
device_buffered_serial_interface::rx_w(state);
}
diff --git a/src/devices/bus/interpro/keyboard/hle.h b/src/devices/bus/interpro/keyboard/hle.h
index 607b7b42087..ed50fafc956 100644
--- a/src/devices/bus/interpro/keyboard/hle.h
+++ b/src/devices/bus/interpro/keyboard/hle.h
@@ -21,7 +21,7 @@ class hle_device_base
public:
virtual ~hle_device_base() override;
- virtual DECLARE_WRITE_LINE_MEMBER(input_txd) override;
+ virtual void input_txd(int state) override;
protected:
// constructor/destructor
diff --git a/src/devices/bus/interpro/keyboard/keyboard.cpp b/src/devices/bus/interpro/keyboard/keyboard.cpp
index 2e31ee7e258..0c108497ecb 100644
--- a/src/devices/bus/interpro/keyboard/keyboard.cpp
+++ b/src/devices/bus/interpro/keyboard/keyboard.cpp
@@ -24,10 +24,9 @@ void interpro_keyboard_port_device::device_config_complete()
void interpro_keyboard_port_device::device_start()
{
- m_rxd_handler.resolve_safe();
}
-WRITE_LINE_MEMBER(interpro_keyboard_port_device::write_txd)
+void interpro_keyboard_port_device::write_txd(int state)
{
if (m_dev)
m_dev->input_txd(state);
diff --git a/src/devices/bus/interpro/keyboard/keyboard.h b/src/devices/bus/interpro/keyboard/keyboard.h
index a51c254d7f8..55ad0f95326 100644
--- a/src/devices/bus/interpro/keyboard/keyboard.h
+++ b/src/devices/bus/interpro/keyboard/keyboard.h
@@ -28,7 +28,7 @@ public:
auto rxd_handler_cb() { return m_rxd_handler.bind(); }
// input lines
- DECLARE_WRITE_LINE_MEMBER(write_txd);
+ void write_txd(int state);
protected:
virtual void device_start() override;
@@ -46,8 +46,8 @@ class device_interpro_keyboard_port_interface : public device_interface
public:
// input lines
- virtual DECLARE_WRITE_LINE_MEMBER(input_txd) = 0;
- DECLARE_WRITE_LINE_MEMBER(output_rxd) { m_port->m_rxd_handler(state); }
+ virtual void input_txd(int state) = 0;
+ void output_rxd(int state) { m_port->m_rxd_handler(state); }
protected:
device_interpro_keyboard_port_interface(machine_config const &mconfig, device_t &device);
diff --git a/src/devices/bus/interpro/keyboard/lle.cpp b/src/devices/bus/interpro/keyboard/lle.cpp
index 1556a3f4779..11deb78f137 100644
--- a/src/devices/bus/interpro/keyboard/lle.cpp
+++ b/src/devices/bus/interpro/keyboard/lle.cpp
@@ -148,7 +148,6 @@
#include "speaker.h"
#include "machine/keyboard.ipp"
-#define LOG_GENERAL (1U << 0)
#define LOG_RXTX (1U << 1)
#define LOG_PORT (1U << 2)
@@ -487,7 +486,7 @@ void lle_device_base::ext_map(address_map &map)
}, "write");
}
-READ_LINE_MEMBER(lle_device_base::t0_r)
+int lle_device_base::t0_r()
{
if ((VERBOSE & LOG_RXTX) && (m_mcu->pc() == 0x8e) && m_txd)
{
@@ -502,7 +501,7 @@ READ_LINE_MEMBER(lle_device_base::t0_r)
return !m_txd;
}
-READ_LINE_MEMBER(lle_device_base::t1_r)
+int lle_device_base::t1_r()
{
return BIT(m_lower[m_count >> 3]->read(), m_count & 0x7) ? ASSERT_LINE : CLEAR_LINE;
}
diff --git a/src/devices/bus/interpro/keyboard/lle.h b/src/devices/bus/interpro/keyboard/lle.h
index 385f2484fab..ac9d0bc45fb 100644
--- a/src/devices/bus/interpro/keyboard/lle.h
+++ b/src/devices/bus/interpro/keyboard/lle.h
@@ -30,10 +30,10 @@ protected:
virtual void io_map(address_map &map);
virtual void ext_map(address_map &map);
- DECLARE_WRITE_LINE_MEMBER(input_txd) override { m_txd = state; }
+ void input_txd(int state) override { m_txd = state; }
- DECLARE_READ_LINE_MEMBER(t0_r);
- DECLARE_READ_LINE_MEMBER(t1_r);
+ int t0_r();
+ int t1_r();
void p1_w(u8 data);
void p2_w(u8 data);
u8 bus_r();
diff --git a/src/devices/bus/interpro/mouse/mouse.cpp b/src/devices/bus/interpro/mouse/mouse.cpp
index 835bcd1f68d..c85eea90ed5 100644
--- a/src/devices/bus/interpro/mouse/mouse.cpp
+++ b/src/devices/bus/interpro/mouse/mouse.cpp
@@ -51,7 +51,6 @@ void interpro_mouse_port_device::device_config_complete()
void interpro_mouse_port_device::device_start()
{
- m_state_func.resolve_safe();
}
device_interpro_mouse_port_interface::device_interpro_mouse_port_interface(machine_config const &mconfig, device_t &device)
diff --git a/src/devices/bus/interpro/sr/edge.cpp b/src/devices/bus/interpro/sr/edge.cpp
index 7b5dc82d95f..45429a1e627 100644
--- a/src/devices/bus/interpro/sr/edge.cpp
+++ b/src/devices/bus/interpro/sr/edge.cpp
@@ -207,7 +207,6 @@
#include "emu.h"
#include "edge.h"
-#define LOG_GENERAL (1U << 0)
#define LOG_INTERRUPT (1U << 1)
#define VERBOSE (LOG_GENERAL)
@@ -720,7 +719,7 @@ u32 mpcba63_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, c
return 0;
}
-WRITE_LINE_MEMBER(edge1_device_base::vblank)
+void edge1_device_base::vblank(int state)
{
if (state)
{
@@ -780,7 +779,7 @@ void edge1_device_base::control_w(offs_t offset, u32 data, u32 mem_mask)
m_dsp->set_input_line(TMS3203X_HOLD, ASSERT_LINE);
}
-WRITE_LINE_MEMBER(edge1_device_base::holda)
+void edge1_device_base::holda(int state)
{
LOGMASKED(LOG_INTERRUPT, "hold acknowledge %d\n", state);
@@ -812,7 +811,7 @@ void edge2plus_processor_device_base::control_w(offs_t offset, u32 data, u32 mem
m_dsp1->set_input_line(TMS3203X_HOLD, ASSERT_LINE);
}
-WRITE_LINE_MEMBER(edge2plus_processor_device_base::holda)
+void edge2plus_processor_device_base::holda(int state)
{
LOGMASKED(LOG_INTERRUPT, "hold acknowledge %d\n", state);
@@ -855,7 +854,7 @@ void edge2plus_framebuffer_device_base::lut_select_w(u32 data)
// lookup table 3 enables address range 92030000-92030fff, written with zeroes
}
-WRITE_LINE_MEMBER(edge1_device_base::scc_irq)
+void edge1_device_base::scc_irq(int state)
{
if (state)
m_reg0 |= SCC_INT;
@@ -877,7 +876,7 @@ void edge1_device_base::kernel_w(offs_t offset, u32 data, u32 mem_mask)
m_status |= KREG_IN_FULL; // FIXME: what clears this?
}
-WRITE_LINE_MEMBER(edge2plus_processor_device_base::scc_irq)
+void edge2plus_processor_device_base::scc_irq(int state)
{
if (state)
m_reg0 |= SCC_INT;
diff --git a/src/devices/bus/interpro/sr/edge.h b/src/devices/bus/interpro/sr/edge.h
index d96896dd187..1ab789174e8 100644
--- a/src/devices/bus/interpro/sr/edge.h
+++ b/src/devices/bus/interpro/sr/edge.h
@@ -17,8 +17,8 @@
class edge1_device_base : public device_t, public device_srx_card_interface
{
public:
- DECLARE_WRITE_LINE_MEMBER(holda);
- DECLARE_WRITE_LINE_MEMBER(vblank);
+ void holda(int state);
+ void vblank(int state);
protected:
edge1_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
@@ -29,7 +29,7 @@ protected:
u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
- DECLARE_WRITE_LINE_MEMBER(scc_irq);
+ void scc_irq(int state);
u32 reg0_r();
void reg0_w(offs_t offset, u32 data, u32 mem_mask = ~0) { COMBINE_DATA(&m_reg0); }
@@ -109,8 +109,8 @@ protected:
virtual void device_start() override {}
- DECLARE_WRITE_LINE_MEMBER(holda);
- DECLARE_WRITE_LINE_MEMBER(scc_irq);
+ void holda(int state);
+ void scc_irq(int state);
u32 control_r() { return m_control; }
void control_w(offs_t offset, u32 data, u32 mem_mask = ~0);
diff --git a/src/devices/bus/interpro/sr/gt.cpp b/src/devices/bus/interpro/sr/gt.cpp
index 15158ede040..bae9a72f739 100644
--- a/src/devices/bus/interpro/sr/gt.cpp
+++ b/src/devices/bus/interpro/sr/gt.cpp
@@ -113,7 +113,6 @@
#include "bus/interpro/keyboard/keyboard.h"
#include "bus/interpro/mouse/mouse.h"
-#define LOG_GENERAL (1U << 0)
#define LOG_LINE (1U << 1)
#define LOG_BLIT (1U << 2)
@@ -1391,7 +1390,7 @@ void gtdb_device::srx_mapping_w(u32 data)
m_bus->install_map(*this, srx_base, srx_base | 0xffffff, &gtdb_device::map_dynamic);
}
-WRITE_LINE_MEMBER(gtdb_device::serial_irq)
+void gtdb_device::serial_irq(int state)
{
if (state)
m_mouse_int |= SERIAL;
diff --git a/src/devices/bus/interpro/sr/gt.h b/src/devices/bus/interpro/sr/gt.h
index aeeb70941ea..a48f3de698a 100644
--- a/src/devices/bus/interpro/sr/gt.h
+++ b/src/devices/bus/interpro/sr/gt.h
@@ -261,7 +261,7 @@ protected:
virtual void map(address_map &map) override;
virtual void map_dynamic(address_map &map);
- DECLARE_WRITE_LINE_MEMBER(serial_irq);
+ void serial_irq(int state);
void mouse_status_w(offs_t offset, u32 data, u32 mem_mask = ~0);
void srx_mapping_w(u32 data);
diff --git a/src/devices/bus/interpro/sr/sr.cpp b/src/devices/bus/interpro/sr/sr.cpp
index 82071af86d2..5ce5f8cc3b9 100644
--- a/src/devices/bus/interpro/sr/sr.cpp
+++ b/src/devices/bus/interpro/sr/sr.cpp
@@ -265,15 +265,6 @@ DEFINE_DEVICE_TYPE(CBUS_SLOT, cbus_slot_device, "cbus_slot", "InterPro CBUS slot
DEFINE_DEVICE_TYPE(SRX_BUS, srx_bus_device, "srx_bus", "InterPro SRX bus")
DEFINE_DEVICE_TYPE(SRX_SLOT, srx_slot_device, "srx_slot", "InterPro SRX slot")
-void interpro_bus_device::device_resolve_objects()
-{
- // resolve callbacks
- m_out_irq0_cb.resolve_safe();
- m_out_irq1_cb.resolve_safe();
- m_out_irq2_cb.resolve_safe();
- m_out_irq3_cb.resolve_safe();
-}
-
cbus_bus_device::cbus_bus_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: interpro_bus_device(mconfig, CBUS_BUS, tag, owner, clock)
, m_slot_count(0)
diff --git a/src/devices/bus/interpro/sr/sr.h b/src/devices/bus/interpro/sr/sr.h
index 0d30905943b..ee706178e5a 100644
--- a/src/devices/bus/interpro/sr/sr.h
+++ b/src/devices/bus/interpro/sr/sr.h
@@ -19,10 +19,10 @@ public:
auto out_irq2_cb() { return m_out_irq2_cb.bind(); }
auto out_irq3_cb() { return m_out_irq3_cb.bind(); }
- DECLARE_WRITE_LINE_MEMBER(irq0_w) { m_out_irq0_cb(state); }
- DECLARE_WRITE_LINE_MEMBER(irq1_w) { m_out_irq1_cb(state); }
- DECLARE_WRITE_LINE_MEMBER(irq2_w) { m_out_irq2_cb(state); }
- DECLARE_WRITE_LINE_MEMBER(irq3_w) { m_out_irq3_cb(state); }
+ void irq0_w(int state) { m_out_irq0_cb(state); }
+ void irq1_w(int state) { m_out_irq1_cb(state); }
+ void irq2_w(int state) { m_out_irq2_cb(state); }
+ void irq3_w(int state) { m_out_irq3_cb(state); }
protected:
// construction/destruction
@@ -37,9 +37,6 @@ protected:
{
}
- // device-level overrides
- virtual void device_resolve_objects() override;
-
// internal state
required_address_space m_main_space;
required_address_space m_io_space;
@@ -87,7 +84,7 @@ public:
}
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
private:
@@ -112,7 +109,7 @@ public:
cbus_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_resolve_objects() override;
virtual void device_start() override;
@@ -126,10 +123,10 @@ protected:
friend class cbus_slot_device;
public:
- DECLARE_WRITE_LINE_MEMBER(irq0) { m_bus->irq0_w(state); }
- DECLARE_WRITE_LINE_MEMBER(irq1) { m_bus->irq1_w(state); }
- DECLARE_WRITE_LINE_MEMBER(irq2) { m_bus->irq2_w(state); }
- DECLARE_WRITE_LINE_MEMBER(irq3) { m_bus->irq3_w(state); }
+ void irq0(int state) { m_bus->irq0_w(state); }
+ void irq1(int state) { m_bus->irq1_w(state); }
+ void irq2(int state) { m_bus->irq2_w(state); }
+ void irq3(int state) { m_bus->irq3_w(state); }
protected:
device_cbus_card_interface(const machine_config &mconfig, device_t &device, const char *idprom_region = "idprom")
@@ -199,7 +196,7 @@ public:
}
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
private:
@@ -224,7 +221,7 @@ public:
srx_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_resolve_objects() override;
virtual void device_start() override;
@@ -238,10 +235,10 @@ protected:
friend class srx_slot_device;
public:
- DECLARE_WRITE_LINE_MEMBER(irq0) { m_bus->irq0_w(state); }
- DECLARE_WRITE_LINE_MEMBER(irq1) { m_bus->irq1_w(state); }
- DECLARE_WRITE_LINE_MEMBER(irq2) { m_bus->irq2_w(state); }
- DECLARE_WRITE_LINE_MEMBER(irq3) { m_bus->irq3_w(state); }
+ void irq0(int state) { m_bus->irq0_w(state); }
+ void irq1(int state) { m_bus->irq1_w(state); }
+ void irq2(int state) { m_bus->irq2_w(state); }
+ void irq3(int state) { m_bus->irq3_w(state); }
protected:
device_srx_card_interface(const machine_config &mconfig, device_t &device, const char *idprom_region = "idprom")
diff --git a/src/devices/bus/intv/slot.cpp b/src/devices/bus/intv/slot.cpp
index f956f01c0fe..2d905d273ae 100644
--- a/src/devices/bus/intv/slot.cpp
+++ b/src/devices/bus/intv/slot.cpp
@@ -116,11 +116,11 @@ device_intv_cart_interface::~device_intv_cart_interface()
// rom_alloc - alloc the space for the cart
//-------------------------------------------------
-void device_intv_cart_interface::rom_alloc(uint32_t size, const char *tag)
+void device_intv_cart_interface::rom_alloc(uint32_t size)
{
if (m_rom == nullptr)
{
- m_rom = device().machine().memory().region_alloc(std::string(tag).append(INTVSLOT_ROM_REGION_TAG).c_str(), size, 1, ENDIANNESS_LITTLE)->base();
+ m_rom = device().machine().memory().region_alloc(device().subtag("^cart:rom"), size, 1, ENDIANNESS_LITTLE)->base();
memset(m_rom, 0xff, size);
m_rom_size = size;
}
@@ -222,7 +222,7 @@ static const char *intv_get_slot(int type)
call load
-------------------------------------------------*/
-image_init_result intv_cart_slot_device::load_fullpath()
+std::error_condition intv_cart_slot_device::load_fullpath()
{
uint8_t temp;
uint8_t num_segments;
@@ -243,15 +243,15 @@ image_init_result intv_cart_slot_device::load_fullpath()
// header
fread(&temp, 1);
if (temp != 0xa8)
- return image_init_result::FAIL;
+ return image_error::INVALIDIMAGE;
fread(&num_segments, 1);
fread(&temp, 1);
if (temp != (num_segments ^ 0xff))
- return image_init_result::FAIL;
+ return image_error::INVALIDIMAGE;
- m_cart->rom_alloc(0x20000, tag());
+ m_cart->rom_alloc(0x20000);
ROM = (uint8_t *)m_cart->get_rom_base();
for (int i = 0; i < num_segments; i++)
@@ -281,7 +281,7 @@ image_init_result intv_cart_slot_device::load_fullpath()
{
fread(&temp, 1);
}
- return image_init_result::PASS;
+ return std::error_condition();
}
/* otherwise, we load it as a .bin file, using extrainfo from intv.hsi in place of .cfg */
else
@@ -300,7 +300,7 @@ image_init_result intv_cart_slot_device::load_fullpath()
int mapper, rom[5], ram, extra;
std::string extrainfo;
- m_cart->rom_alloc(0x20000, tag());
+ m_cart->rom_alloc(0x20000);
ROM = (uint8_t *)m_cart->get_rom_base();
if (!hashfile_extrainfo(*this, extrainfo))
@@ -372,16 +372,16 @@ image_init_result intv_cart_slot_device::load_fullpath()
}
}
- return image_init_result::PASS;
+ return std::error_condition();
}
}
-image_init_result intv_cart_slot_device::call_load()
+std::pair<std::error_condition, std::string> intv_cart_slot_device::call_load()
{
if (m_cart)
{
if (!loaded_through_softlist())
- return load_fullpath();
+ return std::make_pair(load_fullpath(), std::string());
else
{
uint16_t offset[] = { 0x400, 0x2000, 0x4000, 0x4800, 0x5000, 0x6000, 0x7000, 0x8000, 0x8800, 0x9000, 0xa000, 0xb000, 0xc000, 0xd000, 0xe000, 0xf000};
@@ -401,7 +401,7 @@ image_init_result intv_cart_slot_device::call_load()
uint16_t address;
uint8_t *ROM, *region;
- m_cart->rom_alloc(extra_bank ? 0x22000 : 0x20000, tag());
+ m_cart->rom_alloc(extra_bank ? 0x22000 : 0x20000);
ROM = m_cart->get_rom_base();
for (int i = 0; i < 16; i++)
@@ -424,11 +424,11 @@ image_init_result intv_cart_slot_device::call_load()
m_cart->ram_alloc(get_software_region_length("ram"));
//printf("Type: %s\n", intv_get_slot(m_type));
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
}
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
@@ -444,8 +444,7 @@ std::string intv_cart_slot_device::get_default_card_software(get_default_card_so
hook.image_file()->length(len); // FIXME: check error return, guard against excessively large files
std::vector<uint8_t> rom(len);
- size_t actual;
- hook.image_file()->read(&rom[0], len, actual); // FIXME: check error return or read returning short
+ read(*hook.image_file(), &rom[0], len); // FIXME: check error return or read returning short
int type = INTV_STD;
if (rom[0] == 0xa8 && (rom[1] == (rom[2] ^ 0xff)))
diff --git a/src/devices/bus/intv/slot.h b/src/devices/bus/intv/slot.h
index 185f15128c9..fe497da4af4 100644
--- a/src/devices/bus/intv/slot.h
+++ b/src/devices/bus/intv/slot.h
@@ -70,7 +70,7 @@ public:
virtual void write_rome0(offs_t offset, uint16_t data) {}
virtual void write_romf0(offs_t offset, uint16_t data) {}
- void rom_alloc(uint32_t size, const char *tag);
+ void rom_alloc(uint32_t size);
void ram_alloc(uint32_t size);
uint8_t* get_rom_base() { return m_rom; }
uint8_t* get_ram_base() { return &m_ram[0]; }
@@ -111,19 +111,19 @@ public:
intv_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
virtual ~intv_cart_slot_device();
- // image-level overrides
- virtual image_init_result call_load() override;
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
virtual void call_unload() override {}
virtual bool is_reset_on_load() const noexcept override { return true; }
virtual const char *image_interface() const noexcept override { return "intv_cart"; }
virtual const char *file_extensions() const noexcept override { return "bin,int,rom,itv"; }
- // slot interface overrides
+ // device_slot_interface implementation
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
int get_type() { return m_type; }
- image_init_result load_fullpath();
+ std::error_condition load_fullpath();
void save_ram() { if (m_cart && m_cart->get_ram_size()) m_cart->save_ram(); }
@@ -181,8 +181,6 @@ DECLARE_DEVICE_TYPE(INTV_CART_SLOT, intv_cart_slot_device)
DEVICE CONFIGURATION MACROS
***************************************************************************/
-#define INTVSLOT_ROM_REGION_TAG ":cart:rom"
-
void intv_cart(device_slot_interface &device);
#endif // MAME_BUS_INTV_SLOT_H
diff --git a/src/devices/bus/iq151/iq151.cpp b/src/devices/bus/iq151/iq151.cpp
index d4ad9a8a865..aa729cefce3 100644
--- a/src/devices/bus/iq151/iq151.cpp
+++ b/src/devices/bus/iq151/iq151.cpp
@@ -86,15 +86,6 @@ void iq151cart_slot_device::device_start()
m_cart = get_card_device();
if (m_cart)
m_cart->set_screen_device(*m_screen);
-
- // resolve callbacks
- m_out_irq0_cb.resolve_safe();
- m_out_irq1_cb.resolve_safe();
- m_out_irq2_cb.resolve_safe();
- m_out_irq3_cb.resolve_safe();
- m_out_irq4_cb.resolve_safe();
- m_out_drq_cb.resolve_safe();
-
}
@@ -155,31 +146,28 @@ void iq151cart_slot_device::video_update(bitmap_ind16 &bitmap, const rectangle &
call load
-------------------------------------------------*/
-image_init_result iq151cart_slot_device::call_load()
+std::pair<std::error_condition, std::string> iq151cart_slot_device::call_load()
{
if (m_cart)
{
- offs_t read_length;
- uint8_t *cart_base = m_cart->get_cart_base();
+ uint8_t *const cart_base = m_cart->get_cart_base();
+ if (!cart_base)
+ return std::make_pair(image_error::INTERNAL, std::string());
- if (cart_base != nullptr)
+ offs_t read_length;
+ if (!loaded_through_softlist())
{
- if (!loaded_through_softlist())
- {
- read_length = length();
- fread(m_cart->get_cart_base(), read_length);
- }
- else
- {
- read_length = get_software_region_length("rom");
- memcpy(m_cart->get_cart_base(), get_software_region("rom"), read_length);
- }
+ read_length = length();
+ fread(m_cart->get_cart_base(), read_length);
}
else
- return image_init_result::FAIL;
+ {
+ read_length = get_software_region_length("rom");
+ memcpy(m_cart->get_cart_base(), get_software_region("rom"), read_length);
+ }
}
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
/*-------------------------------------------------
diff --git a/src/devices/bus/iq151/iq151.h b/src/devices/bus/iq151/iq151.h
index ff3992c7585..827dc404f37 100644
--- a/src/devices/bus/iq151/iq151.h
+++ b/src/devices/bus/iq151/iq151.h
@@ -108,14 +108,14 @@ public:
auto out_irq4_callback() { return m_out_irq4_cb.bind(); }
auto out_drq_callback() { return m_out_drq_cb.bind(); }
- // image-level overrides
- virtual image_init_result call_load() override;
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
virtual bool is_reset_on_load() const noexcept override { return true; }
virtual const char *image_interface() const noexcept override { return "iq151_cart"; }
virtual const char *file_extensions() const noexcept override { return "bin,rom"; }
- // slot interface overrides
+ // device_slot_interface implementation
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
// reading and writing
@@ -126,7 +126,7 @@ public:
virtual void video_update(bitmap_ind16 &bitmap, const rectangle &cliprect);
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
devcb_write_line m_out_irq0_cb;
diff --git a/src/devices/bus/isa/3c503.cpp b/src/devices/bus/isa/3c503.cpp
index 0bf96c34f53..34a9f970740 100644
--- a/src/devices/bus/isa/3c503.cpp
+++ b/src/devices/bus/isa/3c503.cpp
@@ -3,6 +3,8 @@
#include "emu.h"
#include "3c503.h"
+#include "multibyte.h"
+
#define SADDR 0xcc000
void el2_3c503_device::device_add_mconfig(machine_config &config)
@@ -24,10 +26,13 @@ el2_3c503_device::el2_3c503_device(const machine_config& mconfig, const char* ta
}
void el2_3c503_device::device_start() {
- char mac[7];
+ uint8_t mac[6];
uint32_t num = machine().rand();
memset(m_prom, 0x57, 16);
- sprintf(mac, "\x02\x60\x8c%c%c%c", (num >> 16) & 0xff, (num >> 8) & 0xff, num & 0xff);
+ mac[0] = 0x02;
+ mac[1] = 0x60;
+ mac[2] = 0x8c;
+ put_u24be(mac+3, num);
memcpy(m_prom, mac, 6);
memset(m_rom, 0, 8*1024); // empty
m_dp8390->set_mac(mac);
@@ -48,7 +53,7 @@ void el2_3c503_device::device_start() {
}
void el2_3c503_device::device_reset() {
- memcpy(m_prom, m_dp8390->get_mac(), 6);
+ memcpy(m_prom, &m_dp8390->get_mac()[0], 6);
memset(&m_regs, 0, sizeof(m_regs));
m_regs.bcfr = 0x80; // port 0x300
m_regs.pcfr = 0x20; // address 0xcc000
@@ -278,7 +283,7 @@ void el2_3c503_device::el2_3c503_hiport_w(offs_t offset, uint8_t data) {
}
}
-WRITE_LINE_MEMBER(el2_3c503_device::el2_3c503_irq_w) {
+void el2_3c503_device::el2_3c503_irq_w(int state) {
m_irq_state = state;
if(!(m_regs.gacfr & 0x80)) set_irq(state);
}
diff --git a/src/devices/bus/isa/3c505.cpp b/src/devices/bus/isa/3c505.cpp
index a50c28b2c1b..e56cfcd8d31 100644
--- a/src/devices/bus/isa/3c505.cpp
+++ b/src/devices/bus/isa/3c505.cpp
@@ -25,7 +25,6 @@
#include "emu.h"
#include "3c505.h"
-#define LOG_GENERAL (1U << 0)
#define LOG_REG (1U << 1)
#define LOG_DATA (1U << 2)
@@ -405,7 +404,8 @@ void isa16_3c505_device::acr_w(u8 data)
if ((data ^ m_acr) & ACR_LED2)
m_led[1] = bool(data & ACR_LED2);
- m_net->reset_w((data & ACR_R586) ? 1 : 0);
+ if ((data ^ m_acr) & ACR_R586)
+ m_net->reset_w((data & ACR_R586) ? 1 : 0);
if ((data ^ m_acr) & ACR_FLSH)
{
diff --git a/src/devices/bus/isa/aga.cpp b/src/devices/bus/isa/aga.cpp
index 81e6ba053fe..daf44fa9750 100644
--- a/src/devices/bus/isa/aga.cpp
+++ b/src/devices/bus/isa/aga.cpp
@@ -205,13 +205,13 @@ void isa8_aga_pc200_device::device_start()
gfx[i] = i;
}
-WRITE_LINE_MEMBER( isa8_aga_device::hsync_changed )
+void isa8_aga_device::hsync_changed(int state)
{
m_hsync = state ? 1 : 0;
}
-WRITE_LINE_MEMBER( isa8_aga_device::vsync_changed )
+void isa8_aga_device::vsync_changed(int state)
{
m_vsync = state ? 8 : 0;
if (state)
diff --git a/src/devices/bus/isa/aga.h b/src/devices/bus/isa/aga.h
index b5f986e9a34..aa6aa16f5d0 100644
--- a/src/devices/bus/isa/aga.h
+++ b/src/devices/bus/isa/aga.h
@@ -62,8 +62,8 @@ protected:
MC6845_UPDATE_ROW( cga_gfx_2bpp_update_row );
MC6845_UPDATE_ROW( cga_gfx_1bpp_update_row );
- DECLARE_WRITE_LINE_MEMBER( hsync_changed );
- DECLARE_WRITE_LINE_MEMBER( vsync_changed );
+ void hsync_changed(int state);
+ void vsync_changed(int state);
required_device<palette_device> m_palette;
required_device<mc6845_device> m_mc6845;
diff --git a/src/devices/bus/isa/aha1542b.cpp b/src/devices/bus/isa/aha1542b.cpp
index bba0bb76d41..b61b6e59228 100644
--- a/src/devices/bus/isa/aha1542b.cpp
+++ b/src/devices/bus/isa/aha1542b.cpp
@@ -79,12 +79,12 @@ void aha1542a_device::scsi_rstreq_clear_w(u8 data)
{
}
-READ_LINE_MEMBER(aha1542a_device::host_int_r)
+int aha1542a_device::host_int_r()
{
return 0;
}
-READ_LINE_MEMBER(aha1542a_device::scsi_rstreq_r)
+int aha1542a_device::scsi_rstreq_r()
{
return 0;
}
diff --git a/src/devices/bus/isa/aha1542b.h b/src/devices/bus/isa/aha1542b.h
index c46f456bfe9..36ab1cf2094 100644
--- a/src/devices/bus/isa/aha1542b.h
+++ b/src/devices/bus/isa/aha1542b.h
@@ -41,8 +41,8 @@ public:
static constexpr feature_type unemulated_features() { return feature::DISK; }
- DECLARE_READ_LINE_MEMBER(host_int_r);
- DECLARE_READ_LINE_MEMBER(scsi_rstreq_r);
+ int host_int_r();
+ int scsi_rstreq_r();
protected:
virtual ioport_constructor device_input_ports() const override;
diff --git a/src/devices/bus/isa/asc88.cpp b/src/devices/bus/isa/asc88.cpp
index 7bdb707f6a6..d809b4e4c8e 100644
--- a/src/devices/bus/isa/asc88.cpp
+++ b/src/devices/bus/isa/asc88.cpp
@@ -62,7 +62,7 @@ void asc88_device::device_reset()
control_w(0);
}
-WRITE_LINE_MEMBER(asc88_device::irq_w)
+void asc88_device::irq_w(int state)
{
if (m_irq != state)
{
@@ -76,7 +76,7 @@ WRITE_LINE_MEMBER(asc88_device::irq_w)
}
}
-WRITE_LINE_MEMBER(asc88_device::drq_w)
+void asc88_device::drq_w(int state)
{
if (m_drq != state)
{
diff --git a/src/devices/bus/isa/asc88.h b/src/devices/bus/isa/asc88.h
index 8cfdd784b98..6b8a99f4b97 100644
--- a/src/devices/bus/isa/asc88.h
+++ b/src/devices/bus/isa/asc88.h
@@ -32,8 +32,8 @@ protected:
virtual void dack_w(int line, u8 data) override;
private:
- DECLARE_WRITE_LINE_MEMBER(irq_w);
- DECLARE_WRITE_LINE_MEMBER(drq_w);
+ void irq_w(int state);
+ void drq_w(int state);
void control_w(u8 data);
u8 eeprom_r();
diff --git a/src/devices/bus/isa/bblue2.cpp b/src/devices/bus/isa/bblue2.cpp
index ad997664cc2..58ef846a897 100644
--- a/src/devices/bus/isa/bblue2.cpp
+++ b/src/devices/bus/isa/bblue2.cpp
@@ -244,7 +244,7 @@ void isa8_babyblue2_device::z80_control_w(offs_t offset, uint8_t data)
}
}
-WRITE_LINE_MEMBER(isa8_babyblue2_device::lpt_irq)
+void isa8_babyblue2_device::lpt_irq(int state)
{
if(m_h2->read() & 0x01)
m_isa->irq5_w(state);
diff --git a/src/devices/bus/isa/bblue2.h b/src/devices/bus/isa/bblue2.h
index cdce099d883..a18e0a802b5 100644
--- a/src/devices/bus/isa/bblue2.h
+++ b/src/devices/bus/isa/bblue2.h
@@ -30,9 +30,9 @@ public:
uint8_t z80_ram_r(offs_t offset) { return m_ram->read(offset); }
void z80_ram_w(offs_t offset, uint8_t data) { m_ram->write(offset,data); }
- DECLARE_WRITE_LINE_MEMBER(port1_irq) { m_isa->irq4_w(state); }
- DECLARE_WRITE_LINE_MEMBER(port2_irq) { m_isa->irq3_w(state); }
- DECLARE_WRITE_LINE_MEMBER(lpt_irq);
+ void port1_irq(int state) { m_isa->irq4_w(state); }
+ void port2_irq(int state) { m_isa->irq3_w(state); }
+ void lpt_irq(int state);
protected:
// device-level overrides
virtual void device_start() override;
diff --git a/src/devices/bus/isa/bt54x.cpp b/src/devices/bus/isa/bt54x.cpp
index 1c3c4bdf3f1..167dd415647 100644
--- a/src/devices/bus/isa/bt54x.cpp
+++ b/src/devices/bus/isa/bt54x.cpp
@@ -18,7 +18,7 @@
#include "bt54x.h"
#include "bus/nscsi/devices.h"
-#include "machine/ncr5390.h"
+#include "machine/ncr53c90.h"
//#include "machine/ncr86c05.h"
DEFINE_DEVICE_TYPE(BT542B, bt542b_device, "bt542b", "BusTek BT-542B SCSI Host Adapter") // Rev. G or earlier
diff --git a/src/devices/bus/isa/cga.cpp b/src/devices/bus/isa/cga.cpp
index 77595bbbfb0..c431772bcb9 100644
--- a/src/devices/bus/isa/cga.cpp
+++ b/src/devices/bus/isa/cga.cpp
@@ -692,7 +692,7 @@ MC6845_UPDATE_ROW( isa8_cga_device::cga_gfx_1bpp_update_row )
}
-WRITE_LINE_MEMBER( isa8_cga_device::hsync_changed )
+void isa8_cga_device::hsync_changed(int state)
{
m_hsync = state ? 1 : 0;
if(state && !m_vsync)
@@ -703,7 +703,7 @@ WRITE_LINE_MEMBER( isa8_cga_device::hsync_changed )
}
-WRITE_LINE_MEMBER( isa8_cga_device::vsync_changed )
+void isa8_cga_device::vsync_changed(int state)
{
if ( state )
{
diff --git a/src/devices/bus/isa/cga.h b/src/devices/bus/isa/cga.h
index 029dc35095f..a5307fb815e 100644
--- a/src/devices/bus/isa/cga.h
+++ b/src/devices/bus/isa/cga.h
@@ -55,8 +55,8 @@ protected:
virtual uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
- DECLARE_WRITE_LINE_MEMBER( hsync_changed );
- DECLARE_WRITE_LINE_MEMBER( vsync_changed );
+ void hsync_changed(int state);
+ void vsync_changed(int state);
public:
void mode_control_w(uint8_t data);
diff --git a/src/devices/bus/isa/com.h b/src/devices/bus/isa/com.h
index ff7b5e4eef8..0f77156f004 100644
--- a/src/devices/bus/isa/com.h
+++ b/src/devices/bus/isa/com.h
@@ -22,8 +22,8 @@ public:
// construction/destruction
isa8_com_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_WRITE_LINE_MEMBER(pc_com_interrupt_1) { m_isa->irq4_w(state); }
- DECLARE_WRITE_LINE_MEMBER(pc_com_interrupt_2) { m_isa->irq3_w(state); }
+ void pc_com_interrupt_1(int state) { m_isa->irq4_w(state); }
+ void pc_com_interrupt_2(int state) { m_isa->irq3_w(state); }
protected:
isa8_com_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
diff --git a/src/devices/bus/isa/dectalk.cpp b/src/devices/bus/isa/dectalk.cpp
index 9312d063158..a66896f51a4 100644
--- a/src/devices/bus/isa/dectalk.cpp
+++ b/src/devices/bus/isa/dectalk.cpp
@@ -98,7 +98,7 @@ void dectalk_isa_device::dsp_dma_w(uint16_t data)
m_dsp_dma = data;
}
-READ_LINE_MEMBER(dectalk_isa_device::bio_line_r)
+int dectalk_isa_device::bio_line_r()
{
// TODO: reading the bio line doesn't cause any direct external effects so this is wrong
if(m_bio == ASSERT_LINE)
@@ -111,7 +111,7 @@ void dectalk_isa_device::irq_line_w(uint16_t data)
m_cpu->int1_w(0);
}
-WRITE_LINE_MEMBER(dectalk_isa_device::clock_w)
+void dectalk_isa_device::clock_w(int state)
{
m_dsp->set_input_line(INPUT_LINE_IRQ0, (!(m_ctl & 0x20) || state) ? CLEAR_LINE : ASSERT_LINE);
}
diff --git a/src/devices/bus/isa/dectalk.h b/src/devices/bus/isa/dectalk.h
index 674efa91d5d..ac153d4b1e5 100644
--- a/src/devices/bus/isa/dectalk.h
+++ b/src/devices/bus/isa/dectalk.h
@@ -26,8 +26,8 @@ protected:
virtual void device_add_mconfig(machine_config &config) override;
private:
- DECLARE_READ_LINE_MEMBER(bio_line_r);
- DECLARE_WRITE_LINE_MEMBER(clock_w);
+ int bio_line_r();
+ void clock_w(int state);
void write(offs_t offset, uint8_t data);
uint8_t read(offs_t offset);
diff --git a/src/devices/bus/isa/ega.cpp b/src/devices/bus/isa/ega.cpp
index 1aca9ba7cb2..da9ea8550de 100644
--- a/src/devices/bus/isa/ega.cpp
+++ b/src/devices/bus/isa/ega.cpp
@@ -446,8 +446,6 @@ located at I/O port 0x3CE, and a data register located at I/O port 0x3CF.
#include "emu.h"
#include "ega.h"
-#include "screen.h"
-
#define LOG_READ (1U << 1)
#define LOG_SETUP (1U << 2)
#define LOG_MODE (1U << 3)
@@ -539,10 +537,10 @@ DEFINE_DEVICE_TYPE(ISA8_EGA, isa8_ega_device, "ega", "IBM Enhanced Graphics Adap
void isa8_ega_device::device_add_mconfig(machine_config &config)
{
- screen_device &screen(SCREEN(config, EGA_SCREEN_NAME, SCREEN_TYPE_RASTER));
- screen.set_raw(16.257_MHz_XTAL, 912, 0, 640, 262, 0, 200);
- screen.set_screen_update(EGA_CRTC_NAME, FUNC(crtc_ega_device::screen_update));
- screen.set_palette(m_palette);
+ SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
+ m_screen->set_raw(16.257_MHz_XTAL, 912, 0, 640, 262, 0, 200);
+ m_screen->set_screen_update(EGA_CRTC_NAME, FUNC(crtc_ega_device::screen_update));
+ m_screen->set_palette(m_palette);
PALETTE(config, m_palette).set_entries(64);
@@ -589,7 +587,7 @@ isa8_ega_device::isa8_ega_device(const machine_config &mconfig, device_type type
device_isa8_card_interface(mconfig, *this),
m_crtc_ega(*this, EGA_CRTC_NAME), m_videoram(nullptr), m_charA(nullptr), m_charB(nullptr),
m_misc_output(0), m_feature_control(0), m_frame_cnt(0), m_hsync(0), m_vsync(0), m_vblank(0), m_display_enable(0), m_irq(0), m_video_mode(0),
- m_palette(*this, "palette")
+ m_palette(*this, "palette"), m_screen(*this, EGA_SCREEN_NAME)
{
}
@@ -764,19 +762,19 @@ CRTC_EGA_PIXEL_UPDATE( isa8_ega_device::ega_update_row )
}
-WRITE_LINE_MEMBER( isa8_ega_device::de_changed )
+void isa8_ega_device::de_changed(int state)
{
m_display_enable = state ? 1 : 0;
}
-WRITE_LINE_MEMBER( isa8_ega_device::hsync_changed )
+void isa8_ega_device::hsync_changed(int state)
{
m_hsync = state ? 1 : 0;
}
-WRITE_LINE_MEMBER( isa8_ega_device::vsync_changed )
+void isa8_ega_device::vsync_changed(int state)
{
m_vsync = state ? 1 : 0;
if ( state )
@@ -786,7 +784,7 @@ WRITE_LINE_MEMBER( isa8_ega_device::vsync_changed )
}
-WRITE_LINE_MEMBER( isa8_ega_device::vblank_changed )
+void isa8_ega_device::vblank_changed(int state)
{
m_vblank = state ? 8 : 0;
}
@@ -863,21 +861,27 @@ CRTC_EGA_PIXEL_UPDATE( isa8_ega_device::pc_ega_text )
uint8_t chr = m_plane[0][ offset ];
uint8_t attr = m_plane[1][ offset ];
uint8_t data;
- uint16_t fg = m_attribute.data[ attr & 0x07 ];
- uint16_t bg = m_attribute.data[ ( attr >> 4 ) & 0x07 ];
+ uint8_t blink = m_attribute.data[0x10] & 0x08;
+ uint16_t fg = m_attribute.data[ attr & 0x0f ];
+ uint16_t bg = m_attribute.data[ ( attr >> 4 ) & (blink ? 0x07 : 0x0f) ];
- /* If character set A and B are equal attribute bit 3 is used as intensity */
if ( m_charA == m_charB )
- {
- /* intensity selector */
data = m_charB[ chr * 32 + ra ];
- if ( !( m_attribute.data[0x10] & 0x08 ) )
- fg = m_attribute.data[ attr & 0x0f ];
- }
else
{
/* character set selector */
data = ( attr & 0x08 ) ? m_charA[ chr * 32 + ra ] : m_charB[ chr * 32 + ra ];
+ fg &= 0x07;
+ }
+
+ if(m_screen->visible_area().height() == 200) // the ibm 5154 forces cga compatibility in 200 line modes
+ {
+ fg = fg | (BIT(fg, 4) ? 0x38 : 0);
+ if ( fg == 6 )
+ fg = 0x14;
+ bg = bg | (BIT(bg, 4) ? 0x38 : 0);
+ if ( bg == 6 )
+ bg = 0x14;
}
if ( x == cursor_x )
diff --git a/src/devices/bus/isa/ega.h b/src/devices/bus/isa/ega.h
index cea8667ba8e..8aa63fa04fe 100644
--- a/src/devices/bus/isa/ega.h
+++ b/src/devices/bus/isa/ega.h
@@ -7,6 +7,7 @@
#include "isa.h"
#include "video/crtc_ega.h"
+#include "screen.h"
#include "emupal.h"
//**************************************************************************
@@ -50,10 +51,10 @@ protected:
uint8_t alu_op( uint8_t data, uint8_t latch_data );
private:
- DECLARE_WRITE_LINE_MEMBER(de_changed);
- DECLARE_WRITE_LINE_MEMBER(hsync_changed);
- DECLARE_WRITE_LINE_MEMBER(vsync_changed);
- DECLARE_WRITE_LINE_MEMBER(vblank_changed);
+ void de_changed(int state);
+ void hsync_changed(int state);
+ void vsync_changed(int state);
+ void vblank_changed(int state);
CRTC_EGA_PIXEL_UPDATE(ega_update_row);
@@ -107,6 +108,7 @@ public:
uint8_t m_irq;
int m_video_mode;
required_device<palette_device> m_palette;
+ required_device<screen_device> m_screen;
};
diff --git a/src/devices/bus/isa/eis_hgb107x.cpp b/src/devices/bus/isa/eis_hgb107x.cpp
index ed3100c3e97..a42eb4aaddb 100644
--- a/src/devices/bus/isa/eis_hgb107x.cpp
+++ b/src/devices/bus/isa/eis_hgb107x.cpp
@@ -351,13 +351,13 @@ uint8_t isa8_epc_mda_device::io_read(offs_t offset)
return data;
}
-WRITE_LINE_MEMBER( isa8_epc_mda_device::hsync_changed )
+void isa8_epc_mda_device::hsync_changed(int state)
{
m_hsync = state ? 1 : 0;
}
-WRITE_LINE_MEMBER( isa8_epc_mda_device::vsync_changed )
+void isa8_epc_mda_device::vsync_changed(int state)
{
m_vsync = state ? 0x80 : 0;
if ( state )
diff --git a/src/devices/bus/isa/eis_hgb107x.h b/src/devices/bus/isa/eis_hgb107x.h
index 6689e7db0a8..4a2d3391ce3 100644
--- a/src/devices/bus/isa/eis_hgb107x.h
+++ b/src/devices/bus/isa/eis_hgb107x.h
@@ -24,8 +24,8 @@ public:
void io_write(offs_t offset, uint8_t data);
uint8_t status_r();
void mode_control_w(uint8_t data);
- DECLARE_WRITE_LINE_MEMBER(hsync_changed);
- DECLARE_WRITE_LINE_MEMBER(vsync_changed);
+ void hsync_changed(int state);
+ void vsync_changed(int state);
/* Monitor */
DECLARE_INPUT_CHANGED_MEMBER(monitor_changed);
diff --git a/src/devices/bus/isa/ex1280.cpp b/src/devices/bus/isa/ex1280.cpp
index 2d9153616e9..d96b9d74d53 100644
--- a/src/devices/bus/isa/ex1280.cpp
+++ b/src/devices/bus/isa/ex1280.cpp
@@ -193,7 +193,7 @@ TMS340X0_FROM_SHIFTREG_CB_MEMBER(isa16_ex1280_device::from_shiftreg)
// vblank_w - toggle vblank bit(?)
//-------------------------------------------------
-WRITE_LINE_MEMBER(isa16_ex1280_device::vblank_w)
+void isa16_ex1280_device::vblank_w(int state)
{
//m_flags &= ~(1 << 1);
//m_flags |= (state << 1);
diff --git a/src/devices/bus/isa/ex1280.h b/src/devices/bus/isa/ex1280.h
index a9637a1b1f6..d8c492a1908 100644
--- a/src/devices/bus/isa/ex1280.h
+++ b/src/devices/bus/isa/ex1280.h
@@ -39,7 +39,7 @@ protected:
void vram_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
uint16_t regs_r(offs_t offset, uint16_t mem_mask = ~0);
void regs_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
- DECLARE_WRITE_LINE_MEMBER(vblank_w);
+ void vblank_w(int state);
required_device<tms34010_device> m_cpu;
required_device<bt451_device> m_ramdac;
diff --git a/src/devices/bus/isa/fdc.cpp b/src/devices/bus/isa/fdc.cpp
index a08ec8b899a..1d41a496e75 100644
--- a/src/devices/bus/isa/fdc.cpp
+++ b/src/devices/bus/isa/fdc.cpp
@@ -9,7 +9,6 @@
#include "emu.h"
#include "fdc.h"
#include "machine/busmouse.h"
-#include "formats/pc_dsk.h"
#include "formats/naslite_dsk.h"
#include "formats/ibmxdf_dsk.h"
@@ -46,12 +45,12 @@ isa8_fdc_device::isa8_fdc_device(const machine_config &mconfig, device_type type
{
}
-WRITE_LINE_MEMBER( isa8_fdc_device::irq_w )
+void isa8_fdc_device::irq_w(int state)
{
m_isa->irq6_w(state ? ASSERT_LINE : CLEAR_LINE);
}
-WRITE_LINE_MEMBER( isa8_fdc_device::drq_w )
+void isa8_fdc_device::drq_w(int state)
{
m_isa->drq2_w(state ? ASSERT_LINE : CLEAR_LINE);
}
@@ -148,13 +147,13 @@ uint8_t isa8_upd765_fdc_device::dir_r()
return 0x00;
}
-WRITE_LINE_MEMBER(isa8_upd765_fdc_device::fdc_irq_w)
+void isa8_upd765_fdc_device::fdc_irq_w(int state)
{
fdc_irq = state;
check_irq();
}
-WRITE_LINE_MEMBER(isa8_upd765_fdc_device::fdc_drq_w)
+void isa8_upd765_fdc_device::fdc_drq_w(int state)
{
fdc_drq = state;
check_drq();
@@ -325,7 +324,7 @@ void isa8_ec1841_0003_device::device_start()
m_isa->install_device(0x023c, 0x023f, *m_bus_mouse, &bus_mouse_device::map);
}
-WRITE_LINE_MEMBER( isa8_ec1841_0003_device::aux_irq_w )
+void isa8_ec1841_0003_device::aux_irq_w(int state)
{
m_isa->irq4_w(state ? ASSERT_LINE : CLEAR_LINE);
}
diff --git a/src/devices/bus/isa/fdc.h b/src/devices/bus/isa/fdc.h
index 00431ef3e5c..5bf094b2dce 100644
--- a/src/devices/bus/isa/fdc.h
+++ b/src/devices/bus/isa/fdc.h
@@ -26,8 +26,8 @@ class isa8_fdc_device :
public device_isa8_card_interface
{
public:
- DECLARE_WRITE_LINE_MEMBER( irq_w );
- DECLARE_WRITE_LINE_MEMBER( drq_w );
+ void irq_w(int state);
+ void drq_w(int state);
static void floppy_formats(format_registration &fr);
protected:
@@ -57,8 +57,8 @@ protected:
uint8_t dir_r();
void ccr_w(uint8_t data);
- DECLARE_WRITE_LINE_MEMBER( fdc_irq_w );
- DECLARE_WRITE_LINE_MEMBER( fdc_drq_w );
+ void fdc_irq_w(int state);
+ void fdc_drq_w(int state);
private:
bool irq, drq, fdc_drq, fdc_irq;
@@ -135,7 +135,7 @@ protected:
virtual void device_start() override;
virtual void device_add_mconfig(machine_config &config) override;
- DECLARE_WRITE_LINE_MEMBER( aux_irq_w );
+ void aux_irq_w(int state);
required_device<bus_mouse_device> m_bus_mouse;
};
diff --git a/src/devices/bus/isa/gus.cpp b/src/devices/bus/isa/gus.cpp
index 7884ac37c8d..2017482fc96 100644
--- a/src/devices/bus/isa/gus.cpp
+++ b/src/devices/bus/isa/gus.cpp
@@ -380,21 +380,6 @@ void gf1_device::device_start()
{
acia6850_device::device_start();
- int i;
- double out = (double)(1 << 13);
-
- m_txirq_handler.resolve_safe();
- m_rxirq_handler.resolve_safe();
- m_wave_irq_handler.resolve_safe();
- m_ramp_irq_handler.resolve_safe();
- m_timer1_irq_handler.resolve_safe();
- m_timer2_irq_handler.resolve_safe();
- m_sb_irq_handler.resolve_safe();
- m_dma_irq_handler.resolve_safe();
- m_drq1_handler.resolve_safe();
- m_drq2_handler.resolve_safe();
- m_nmi_handler.resolve_safe();
-
// TODO: make DRAM size configurable. Can be 256k, 512k, 768k, or 1024k
m_wave_ram.resize(1024*1024);
memset(&m_wave_ram[0], 0, 1024*1024);
@@ -416,9 +401,10 @@ void gf1_device::device_start()
m_gf1_irq = 0;
m_midi_irq = 0;
- for (i=4095;i>=0;i--)
+ double out = double(1 << 13);
+ for (int i = 4095; i >= 0; i--)
{
- m_volume_table[i] = (int16_t)out;
+ m_volume_table[i] = int16_t(out);
out /= 1.002709201; /* 0.0235 dB Steps */
}
@@ -1467,7 +1453,7 @@ void isa16_gus_device::joy_w(offs_t offset, uint8_t data)
m_joy_time = machine().time();
}
-WRITE_LINE_MEMBER(isa16_gus_device::wavetable_irq)
+void isa16_gus_device::wavetable_irq(int state)
{
if(state)
set_irq(IRQ_WAVETABLE);
@@ -1475,7 +1461,7 @@ WRITE_LINE_MEMBER(isa16_gus_device::wavetable_irq)
reset_irq(IRQ_WAVETABLE);
}
-WRITE_LINE_MEMBER(isa16_gus_device::volumeramp_irq)
+void isa16_gus_device::volumeramp_irq(int state)
{
if(state)
set_irq(IRQ_VOLUME_RAMP);
@@ -1483,7 +1469,7 @@ WRITE_LINE_MEMBER(isa16_gus_device::volumeramp_irq)
reset_irq(IRQ_VOLUME_RAMP);
}
-WRITE_LINE_MEMBER(isa16_gus_device::timer1_irq)
+void isa16_gus_device::timer1_irq(int state)
{
if(state)
set_irq(IRQ_TIMER1);
@@ -1491,7 +1477,7 @@ WRITE_LINE_MEMBER(isa16_gus_device::timer1_irq)
reset_irq(IRQ_TIMER1);
}
-WRITE_LINE_MEMBER(isa16_gus_device::timer2_irq)
+void isa16_gus_device::timer2_irq(int state)
{
if(state)
set_irq(IRQ_TIMER2);
@@ -1499,7 +1485,7 @@ WRITE_LINE_MEMBER(isa16_gus_device::timer2_irq)
reset_irq(IRQ_TIMER2);
}
-WRITE_LINE_MEMBER(isa16_gus_device::dma_irq)
+void isa16_gus_device::dma_irq(int state)
{
if(state)
set_irq(IRQ_DRAM_TC_DMA);
@@ -1507,7 +1493,7 @@ WRITE_LINE_MEMBER(isa16_gus_device::dma_irq)
reset_irq(IRQ_DRAM_TC_DMA);
}
-WRITE_LINE_MEMBER(isa16_gus_device::sb_irq)
+void isa16_gus_device::sb_irq(int state)
{
if(state)
set_midi_irq(IRQ_SB);
@@ -1515,7 +1501,7 @@ WRITE_LINE_MEMBER(isa16_gus_device::sb_irq)
reset_midi_irq(IRQ_SB);
}
-WRITE_LINE_MEMBER(isa16_gus_device::drq1_w)
+void isa16_gus_device::drq1_w(int state)
{
m_isa->set_dma_channel(m_gf1->dma_channel1(), this, true);
switch(m_gf1->dma_channel1())
@@ -1540,7 +1526,7 @@ WRITE_LINE_MEMBER(isa16_gus_device::drq1_w)
}
}
-WRITE_LINE_MEMBER(isa16_gus_device::drq2_w)
+void isa16_gus_device::drq2_w(int state)
{
m_isa->set_dma_channel(m_gf1->dma_channel2(), this, true);
switch(m_gf1->dma_channel2())
@@ -1689,7 +1675,7 @@ void isa16_gus_device::reset_midi_irq(uint8_t source)
logerror("GUS: Reset MIDI IRQ %02x\n",source);
}
-WRITE_LINE_MEMBER( isa16_gus_device::midi_txirq )
+void isa16_gus_device::midi_txirq(int state)
{
if (state)
set_midi_irq(IRQ_MIDI_TRANSMIT);
@@ -1697,7 +1683,7 @@ WRITE_LINE_MEMBER( isa16_gus_device::midi_txirq )
reset_midi_irq(IRQ_MIDI_TRANSMIT | IRQ_MIDI_RECEIVE);
}
-WRITE_LINE_MEMBER( isa16_gus_device::midi_rxirq )
+void isa16_gus_device::midi_rxirq(int state)
{
if (state)
set_midi_irq(IRQ_MIDI_RECEIVE);
@@ -1705,13 +1691,13 @@ WRITE_LINE_MEMBER( isa16_gus_device::midi_rxirq )
reset_midi_irq(IRQ_MIDI_TRANSMIT | IRQ_MIDI_RECEIVE);
}
-WRITE_LINE_MEMBER( isa16_gus_device::write_acia_clock )
+void isa16_gus_device::write_acia_clock(int state)
{
m_gf1->write_txc(state);
m_gf1->write_rxc(state);
}
-WRITE_LINE_MEMBER( isa16_gus_device::nmi_w)
+void isa16_gus_device::nmi_w(int state)
{
m_irq_status |= IRQ_SB;
m_isa->nmi();
diff --git a/src/devices/bus/isa/gus.h b/src/devices/bus/isa/gus.h
index c39695997da..9f652fd8ccb 100644
--- a/src/devices/bus/isa/gus.h
+++ b/src/devices/bus/isa/gus.h
@@ -253,18 +253,18 @@ protected:
virtual ioport_constructor device_input_ports() const override;
private:
- DECLARE_WRITE_LINE_MEMBER(midi_txirq);
- DECLARE_WRITE_LINE_MEMBER(midi_rxirq);
- DECLARE_WRITE_LINE_MEMBER(wavetable_irq);
- DECLARE_WRITE_LINE_MEMBER(volumeramp_irq);
- DECLARE_WRITE_LINE_MEMBER(timer1_irq);
- DECLARE_WRITE_LINE_MEMBER(timer2_irq);
- DECLARE_WRITE_LINE_MEMBER(sb_irq);
- DECLARE_WRITE_LINE_MEMBER(dma_irq);
- DECLARE_WRITE_LINE_MEMBER(drq1_w);
- DECLARE_WRITE_LINE_MEMBER(drq2_w);
- DECLARE_WRITE_LINE_MEMBER(nmi_w);
- DECLARE_WRITE_LINE_MEMBER(write_acia_clock);
+ void midi_txirq(int state);
+ void midi_rxirq(int state);
+ void wavetable_irq(int state);
+ void volumeramp_irq(int state);
+ void timer1_irq(int state);
+ void timer2_irq(int state);
+ void sb_irq(int state);
+ void dma_irq(int state);
+ void drq1_w(int state);
+ void drq2_w(int state);
+ void nmi_w(int state);
+ void write_acia_clock(int state);
required_device<gf1_device> m_gf1;
diff --git a/src/devices/bus/isa/hdc.cpp b/src/devices/bus/isa/hdc.cpp
index 74d2a23d11b..a320f3f9ee5 100644
--- a/src/devices/bus/isa/hdc.cpp
+++ b/src/devices/bus/isa/hdc.cpp
@@ -117,7 +117,7 @@ const char *const s_hdc_command_names[] =
ROM_START( hdc )
ROM_REGION(0x02000,"hdc", 0)
- // Bios taken from WD1002A-WX1
+ // BIOS taken from WD1002A-WX1
ROM_LOAD("wdbios.rom", 0x00000, 0x02000, CRC(8e9e2bd4) SHA1(601d7ceab282394ebab50763c267e915a6a2166a)) /* WDC IDE Superbios 2.0 (06/28/89) Expansion Rom C8000-C9FFF */
ROM_END
@@ -196,8 +196,6 @@ void xt_hdc_device::device_start()
{
m_buffer = std::make_unique<uint8_t[]>(256*512); // maximum possible transfer
m_timer = timer_alloc(FUNC(xt_hdc_device::process_command), this);
- m_irq_handler.resolve_safe();
- m_drq_handler.resolve_safe();
}
void xt_hdc_device::device_reset()
@@ -227,7 +225,7 @@ void xt_hdc_device::device_reset()
m_error = 0;
}
-hard_disk_file *xt_hdc_device::pc_hdc_file(int id)
+harddisk_image_device *xt_hdc_device::pc_hdc_file(int id)
{
harddisk_image_device *img = nullptr;
switch (id)
@@ -245,7 +243,7 @@ hard_disk_file *xt_hdc_device::pc_hdc_file(int id)
if (!img->exists())
return nullptr;
- return img->get_hard_disk_file();
+ return img;
}
void xt_hdc_device::pc_hdc_result(bool set_error_info)
@@ -291,7 +289,7 @@ bool xt_hdc_device::no_dma()
int xt_hdc_device::get_lbasector()
{
- hard_disk_file *file = pc_hdc_file(m_drv);
+ harddisk_image_device *file = pc_hdc_file(m_drv);
const auto &info = file->get_info();
int lbasector = m_cylinder[m_drv];
@@ -314,7 +312,7 @@ int xt_hdc_device::get_lbasector()
int xt_hdc_device::dack_r()
{
- hard_disk_file *file = pc_hdc_file(m_drv);
+ harddisk_image_device *file = pc_hdc_file(m_drv);
if (!file)
return 0;
const auto &info = file->get_info();
@@ -387,7 +385,7 @@ int xt_hdc_device::dack_rs()
void xt_hdc_device::dack_w(int data)
{
- hard_disk_file *file = pc_hdc_file(m_drv);
+ harddisk_image_device *file = pc_hdc_file(m_drv);
if (!file)
return;
const auto &info = file->get_info();
@@ -455,7 +453,7 @@ void xt_hdc_device::execute_read()
if (m_sector_cnt[m_drv] == 0)
size = 256 * 512;
- hard_disk_file *disk = pc_hdc_file(m_drv);
+ harddisk_image_device *disk = pc_hdc_file(m_drv);
if (!disk)
return;
@@ -504,7 +502,7 @@ void xt_hdc_device::execute_write()
if (m_sector_cnt[m_drv] == 0)
size = 256 * 512;
- hard_disk_file *disk = pc_hdc_file(m_drv);
+ harddisk_image_device *disk = pc_hdc_file(m_drv);
if (!disk)
return;
@@ -1076,7 +1074,7 @@ uint8_t isa8_hdc_device::pc_hdc_dipswitch_r()
return m_dip;
}
-WRITE_LINE_MEMBER(isa8_hdc_device::irq_w)
+void isa8_hdc_device::irq_w(int state)
{
if (BIT(m_dip, 6))
m_isa->irq5_w(state);
@@ -1084,7 +1082,7 @@ WRITE_LINE_MEMBER(isa8_hdc_device::irq_w)
m_isa->irq2_w(state);
}
-WRITE_LINE_MEMBER(isa8_hdc_device::drq_w)
+void isa8_hdc_device::drq_w(int state)
{
m_isa->drq3_w(state);
}
diff --git a/src/devices/bus/isa/hdc.h b/src/devices/bus/isa/hdc.h
index 0f49d2118f9..059424fbb9e 100644
--- a/src/devices/bus/isa/hdc.h
+++ b/src/devices/bus/isa/hdc.h
@@ -52,7 +52,7 @@ protected:
virtual void device_start() override;
virtual void device_reset() override;
- hard_disk_file *pc_hdc_file(int id);
+ harddisk_image_device *pc_hdc_file(int id);
void pc_hdc_result(bool set_error_info);
bool no_dma();
int get_lbasector();
@@ -159,8 +159,8 @@ protected:
virtual const tiny_rom_entry *device_rom_region() const override;
virtual ioport_constructor device_input_ports() const override;
- DECLARE_WRITE_LINE_MEMBER(irq_w);
- DECLARE_WRITE_LINE_MEMBER(drq_w);
+ void irq_w(int state);
+ void drq_w(int state);
public:
virtual uint8_t dack_r(int line) override;
diff --git a/src/devices/bus/isa/hpblp.cpp b/src/devices/bus/isa/hpblp.cpp
new file mode 100644
index 00000000000..40c98d77a44
--- /dev/null
+++ b/src/devices/bus/isa/hpblp.cpp
@@ -0,0 +1,548 @@
+// license:BSD-3-Clause
+// copyright-holders:Sven Schnelle
+/***************************************************************************
+
+ HP Basic Language Coprocessor (82321A)
+
+***************************************************************************/
+
+#include "emu.h"
+#include "hpblp.h"
+
+//#define VERBOSE 1
+#include "logmacro.h"
+
+#define BLP_TAG "blpcpu"
+#define TMS_TAG "tms9914"
+
+DEFINE_DEVICE_TYPE(HPBLP, isa8_hpblp_device, "hpblp", "HP Basic Language Coprocessor")
+
+static INPUT_PORTS_START(hpblp)
+ PORT_START("BLPPORT")
+ PORT_DIPNAME(3, 0, "IO Address") PORT_DIPLOCATION("SW2:0,1")
+ PORT_DIPSETTING(0, "250h-257h")
+ PORT_DIPSETTING(1, "280h-287h")
+ PORT_DIPSETTING(2, "330h-337h")
+ PORT_DIPSETTING(3, "390h-397h")
+
+ PORT_START("BLPIRQ")
+ PORT_DIPNAME(7, 3, "Interrupt") PORT_DIPLOCATION("SW3:0,1,2")
+ PORT_DIPSETTING(0x0, "IRQ 3")
+ PORT_DIPSETTING(0x1, "IRQ 4")
+ PORT_DIPSETTING(0x2, "IRQ 5")
+ PORT_DIPSETTING(0x3, "IRQ 7")
+ PORT_DIPSETTING(0x4, "IRQ 9")
+INPUT_PORTS_END
+
+ioport_constructor isa8_hpblp_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(hpblp);
+}
+
+
+isa8_hpblp_device::isa8_hpblp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, HPBLP, tag, owner, clock),
+ device_isa8_card_interface(mconfig, *this),
+ m_maincpu(*this, BLP_TAG),
+ m_tms9914(*this, TMS_TAG),
+ m_ieee488(*this, IEEE488_TAG),
+ m_timer_10ms(nullptr),
+ m_reset(false)
+{
+}
+
+void isa8_hpblp_device::device_add_mconfig(machine_config &config)
+{
+ M68000(config, m_maincpu, 16_MHz_XTAL / 2);
+ m_maincpu->set_addrmap(AS_PROGRAM, &isa8_hpblp_device::m68map);
+
+ TMS9914(config, m_tms9914, XTAL(5'000'000));
+ m_tms9914->eoi_write_cb().set(IEEE488_TAG, FUNC(ieee488_device::host_eoi_w));
+ m_tms9914->dav_write_cb().set(IEEE488_TAG, FUNC(ieee488_device::host_dav_w));
+ m_tms9914->nrfd_write_cb().set(IEEE488_TAG, FUNC(ieee488_device::host_nrfd_w));
+ m_tms9914->ndac_write_cb().set(IEEE488_TAG, FUNC(ieee488_device::host_ndac_w));
+ m_tms9914->ifc_write_cb().set(IEEE488_TAG, FUNC(ieee488_device::host_ifc_w));
+ m_tms9914->srq_write_cb().set(IEEE488_TAG, FUNC(ieee488_device::host_srq_w));
+ m_tms9914->atn_write_cb().set(IEEE488_TAG, FUNC(ieee488_device::host_atn_w));
+ m_tms9914->ren_write_cb().set(IEEE488_TAG, FUNC(ieee488_device::host_ren_w));
+ m_tms9914->dio_write_cb().set(IEEE488_TAG, FUNC(ieee488_device::host_dio_w));
+ m_tms9914->dio_read_cb().set(IEEE488_TAG, FUNC(ieee488_device::dio_r));
+ m_tms9914->dio_read_cb().set(IEEE488_TAG, FUNC(ieee488_device::dio_r));
+ m_tms9914->dio_write_cb().set(IEEE488_TAG, FUNC(ieee488_device::host_dio_w));
+ m_tms9914->int_write_cb().set(FUNC(isa8_hpblp_device::gpib_irq));
+
+ IEEE488(config, m_ieee488, 0);
+ m_ieee488->eoi_callback().set(m_tms9914, FUNC(tms9914_device::eoi_w));
+ m_ieee488->dav_callback().set(m_tms9914, FUNC(tms9914_device::dav_w));
+ m_ieee488->nrfd_callback().set(m_tms9914, FUNC(tms9914_device::nrfd_w));
+ m_ieee488->ndac_callback().set(m_tms9914, FUNC(tms9914_device::ndac_w));
+ m_ieee488->ifc_callback().set(m_tms9914, FUNC(tms9914_device::ifc_w));
+ m_ieee488->srq_callback().set(m_tms9914, FUNC(tms9914_device::srq_w));
+ m_ieee488->atn_callback().set(m_tms9914, FUNC(tms9914_device::atn_w));
+ m_ieee488->ren_callback().set(m_tms9914, FUNC(tms9914_device::ren_w));
+
+ ieee488_slot_device &slot0(IEEE488_SLOT(config, "ieee0", 0));
+ hp_ieee488_devices(slot0);
+ slot0.set_default_option("hp9122c");
+
+ bus::hp_dio::dio16_device &dio16(DIO16(config, "diobus", 0));
+ dio16.set_program_space(m_maincpu, AS_PROGRAM);
+ m_maincpu->reset_cb().set(dio16, FUNC(bus::hp_dio::dio16_device::reset_in));
+
+ dio16.irq1_out_cb().set_inputline(m_maincpu, M68K_IRQ_1);
+ dio16.irq2_out_cb().set_inputline(m_maincpu, M68K_IRQ_2);
+ dio16.irq3_out_cb().set_inputline(m_maincpu, M68K_IRQ_3);
+ dio16.irq4_out_cb().set_inputline(m_maincpu, M68K_IRQ_4);
+ dio16.irq5_out_cb().set_inputline(m_maincpu, M68K_IRQ_5);
+ dio16.irq6_out_cb().set_inputline(m_maincpu, M68K_IRQ_6);
+ dio16.irq7_out_cb().set_inputline(m_maincpu, M68K_IRQ_7);
+
+ DIO32_SLOT(config, "sl0", 0, "diobus", dio16_cards, nullptr, false);
+ DIO32_SLOT(config, "sl1", 0, "diobus", dio16_cards, nullptr, false);
+}
+
+offs_t isa8_hpblp_device::get_bus_address(offs_t offset, uint16_t mem_mask)
+{
+ if (mem_mask == 0xff)
+ offset++;
+ return offset;
+}
+
+bool isa8_hpblp_device::forward_to_host(offs_t offset)
+{
+ if (offset >= 0x200000 && offset <= 0x2fffff)
+ return true;
+ if (offset >= 0x420000 && offset <= 0x42ffff)
+ return true;
+ if (offset >= 0x510000 && offset <= 0x51ffff)
+ return true;
+ if (offset >= 0x520000 && offset <= 0x52ffff)
+ return true;
+ if (offset >= 0x538000 && offset <= 0x53ffff)
+ return true;
+ if (offset >= 0x5f2000 && offset <= 0x5f3fff)
+ return true;
+ if (offset >= 0x690000 && offset <= 0x69ffff)
+ return true;
+ if (offset >= 0x6f0000 && offset <= 0x6fffff)
+ return true;
+ if (offset >= 0x730000 && offset <= 0x73ffff)
+ return true;
+ if (offset >= 0x7a0000 && offset <= 0x7affff)
+ return true;
+ return false;
+}
+
+uint8_t isa8_hpblp_device::status_val(offs_t offset)
+{
+ if (offset >= 0x200000 && offset <= 0x2fffff)
+ return 0x30;
+ if (offset >= 0x512000 && offset <= 0x517fff)
+ return 0x70;
+ if (offset >= 0x51ff00 && offset <= 0x51ffff)
+ return 0x50;
+ if (offset >= 0x538000 && offset <= 0x53ffff)
+ return 0xb0;
+ return 0xd0;
+}
+
+uint16_t isa8_hpblp_device::bus_r(offs_t offset, uint16_t mem_mask)
+{
+ offset <<= 1;
+
+ if (machine().side_effects_disabled())
+ return m_bus_data;
+
+ if (!forward_to_host(offset)) {
+ LOG("%s: %06x -> BERR\n", __func__, offset);
+ m_maincpu->trigger_bus_error();
+ return 0xffff;
+ }
+
+ if (m_ack_buscycle) {
+ m_ack_buscycle = false;
+ m_bus_read = false;
+ m_bus_address = 0;
+ LOG("%s: %06x %04x (%04x)\n", __func__, offset, m_bus_data, mem_mask);
+ return m_bus_data;
+ } else {
+ m_bus_address = get_bus_address(offset, mem_mask);
+ m_bus_mem_mask = mem_mask;
+ m_bus_read = true;
+ }
+ m_maincpu->defer_access();
+ return 0xffff;
+}
+
+void isa8_hpblp_device::bus_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ offset <<= 1;
+
+ if (!forward_to_host(offset)) {
+ LOG("%s: %06x -> BERR\n", __func__, offset);
+ m_maincpu->trigger_bus_error();
+ return;
+ }
+
+ if (m_ack_buscycle) {
+ m_ack_buscycle = false;
+ m_bus_write = false;
+ m_bus_address = 0;
+ return;
+ }
+
+ if (!m_bus_write) {
+ m_bus_address = get_bus_address(offset, mem_mask);
+ m_bus_mem_mask = mem_mask;
+ m_bus_write = true;
+ m_bus_data = data;
+ }
+ m_maincpu->defer_access();
+}
+
+void isa8_hpblp_device::gpib_w(offs_t offset, uint16_t data)
+{
+ if (offset & 0x08) {
+ m_tms9914->write(offset & 0x07, data);
+ return;
+ }
+
+ switch (offset) {
+ case 0:
+ m_tms9914->reset();
+ break;
+
+ case 1:
+ if (data >> 8 == 0)
+ m_gpib_reg1 = 0x84;
+ else if (data >> 8 == 1)
+ m_gpib_reg1 = 0xbf;
+ else
+ m_gpib_reg1 = 0xbe;
+ break;
+ default:
+ break;
+ }
+}
+
+uint16_t isa8_hpblp_device::gpib_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ if (offset & 0x8)
+ return m_tms9914->read(offset & 0x07);
+
+ switch(offset) {
+ case 0: /* ID */
+ data = 0x31;
+ break;
+ case 1:
+ /* Int control */
+ data = m_gpib_reg1;
+ break;
+ case 2:
+ /* Address */
+ data = 0xbe;
+ break;
+ default:
+ break;
+ }
+ return data;
+}
+
+void isa8_hpblp_device::update_gpib_irq()
+{
+ if ((m_gpib_reg1 & 0x40) && (m_gpib_reg1 & 0x80))
+ m_maincpu->set_input_line(M68K_IRQ_3, ASSERT_LINE);
+ else
+ m_maincpu->set_input_line(M68K_IRQ_3, CLEAR_LINE);
+}
+
+void isa8_hpblp_device::gpib_irq(int state)
+{
+ if (state) {
+ m_gpib_reg1 |= 0x40;
+ } else {
+ m_gpib_reg1 &= ~0x40;
+ }
+ update_gpib_irq();
+}
+
+void isa8_hpblp_device::m68map(address_map &map)
+{
+ map(0x000000, 0xffffff).rw(FUNC(isa8_hpblp_device::bus_r), FUNC(isa8_hpblp_device::bus_w));
+ map(0x000000, 0x00ffff).rom().nopw();
+ map(0x470000, 0x47001f).mirror(0x00ffe0).rw(FUNC(isa8_hpblp_device::gpib_r), FUNC(isa8_hpblp_device::gpib_w));
+ map(0xc00000, 0xffffff).ram();
+}
+
+void isa8_hpblp_device::hpblp_interrupt(int state)
+{
+ switch(m_irq) {
+ case 0:
+ m_isa->irq3_w(state);
+ break;
+ case 1:
+ m_isa->irq4_w(state);
+ break;
+ case 2:
+ m_isa->irq5_w(state);
+ break;
+ case 3:
+ m_isa->irq7_w(state);
+ break;
+ case 4:
+ m_isa->irq2_w(state);
+ break;
+ default:
+ break;
+ }
+}
+
+uint8_t isa8_hpblp_device::get_bus_address_partial(int shift)
+{
+ offs_t addr;
+
+ // The value read from the bus address registers (isa reg 2,3,4) is
+ // either the address during a waiting 68k bus cycle, or, if the
+ // processor is running the current bus address which might be a data
+ // read/write or program fetch. The DOS software checks whether these
+ // register changes during normal operation. Therefore just invert
+ // the address on every read if the CPU is not waiting for the host.
+
+ if (!m_bus_read && !m_bus_write)
+ m_bus_address ^= 0xffffff;
+
+ addr = m_bus_address;
+ return (addr >> shift) & 0xff;
+}
+
+uint8_t isa8_hpblp_device::addrl_r(offs_t offset)
+{
+ return get_bus_address_partial(0);
+}
+
+uint8_t isa8_hpblp_device::addrm_r(offs_t offset)
+{
+ return get_bus_address_partial(8);
+}
+
+uint8_t isa8_hpblp_device::addrh_r(offs_t offset)
+{
+ return get_bus_address_partial(16);
+}
+
+uint8_t isa8_hpblp_device::datal_r(offs_t offset)
+{
+ return m_bus_data & 0xff;
+}
+
+uint8_t isa8_hpblp_device::datah_r(offs_t offset)
+{
+ return m_bus_data >> 8;
+}
+
+void isa8_hpblp_device::datal_w(offs_t offset, uint8_t data)
+{
+ m_bus_data &= ~0xff;
+ m_bus_data |= data;
+}
+
+void isa8_hpblp_device::datah_w(offs_t offset, uint8_t data)
+{
+ m_bus_data &= ~0xff00;
+ m_bus_data |= (data << 8);
+}
+
+uint8_t isa8_hpblp_device::status_r(offs_t offset)
+{
+ uint8_t ret;
+
+ // bits:
+ // 7-5: type of buscycle (exact encoding unknown)
+ // 4 - INT status
+ // 2 - CPU RW#
+
+ if (m_bus_read || m_bus_write)
+ ret = status_val(m_bus_address);
+ else
+ ret = 0xe4;
+
+ if (m_bus_read)
+ ret |= 0x04;
+
+ if (!m_irq_state)
+ ret |= 0x10;
+ return ret;
+}
+
+void isa8_hpblp_device::irq_w(offs_t offset, uint8_t data)
+{
+ hpblp_interrupt(1);
+}
+
+uint8_t isa8_hpblp_device::reg5_r(offs_t offset)
+{
+ // state bits:
+ // 3-0: OS running
+ // 0: BOOTROM
+ // 1: HPBASIC
+ // 2: PASCAL
+ // 4: Is a 82324A card
+ return m_reg5;
+}
+
+uint8_t isa8_hpblp_device::reg6_r(offs_t offset)
+{
+ return m_reg6;
+}
+
+void isa8_hpblp_device::reg2_w(offs_t offset, uint8_t data)
+{
+ // bit 0 - CPU RESET# line
+ m_reset = data & 1;
+ if (m_reset)
+ device_reset();
+}
+
+// reg 3: force BERR# on current bus cycle
+void isa8_hpblp_device::reg3_w(offs_t offset, uint8_t data)
+{
+ m_ack_buscycle = false;
+ m_bus_read = false;
+ m_bus_write = false;
+ m_maincpu->trigger_bus_error();
+ machine().scheduler().synchronize();
+}
+
+// reg 4: clear pending 10ms timer interrupt to host
+void isa8_hpblp_device::reg4_w(offs_t offset, uint8_t data)
+{
+ hpblp_interrupt(0);
+}
+
+// reg 5: OS status
+void isa8_hpblp_device::reg5_w(offs_t offset, uint8_t data)
+{
+ m_reg5 = data;
+}
+
+// reg 6: seems to be used to trigger interrupts on the 68k.
+// Only seen with keyboard irqs so far.
+void isa8_hpblp_device::reg6_w(offs_t offset, uint8_t data)
+{
+ // bit 2-0: IPL?
+ if (data == 6) {
+ m_maincpu->set_input_line(M68K_IRQ_1, ASSERT_LINE);
+ } else {
+ m_maincpu->set_input_line(M68K_IRQ_1, CLEAR_LINE);
+ }
+ m_reg6 = data;
+}
+
+// reg 7: acknowledge current 68k bus cycle
+void isa8_hpblp_device::reg7_w(address_space &space, offs_t offset, uint8_t data)
+{
+ if (m_reset) {
+ // DOS software write to this reg during reset, so we need to ignore
+ // this write in order to not acknowledge the first bus cycle early
+ return;
+ }
+
+ m_bus_read = false;
+ m_bus_write = false;
+ m_ack_buscycle = true;
+ // It looks like the DOS software assumes that the m68k is always faster starting
+ // the next buscycle than the PC reading the data registers. So it seems they
+ // "optimized" the code to skip checking the bus status registers before accessing
+ // the data registers during a 32 bit instruction. (which will be split into 2x 16
+ // bit bus transactions by 68k. Eat all cycles to make the scheduler switch to 68k
+ // before the x86 CPU can read the registers again.
+ machine().scheduler().synchronize();
+}
+
+void isa8_hpblp_device::isamap(address_map &map)
+{
+ map(0, 0).rw(FUNC(isa8_hpblp_device::datal_r), FUNC(isa8_hpblp_device::datal_w));
+ map(1, 1).rw(FUNC(isa8_hpblp_device::datah_r), FUNC(isa8_hpblp_device::datah_w));
+ map(2, 2).rw(FUNC(isa8_hpblp_device::addrl_r), FUNC(isa8_hpblp_device::reg2_w));
+ map(3, 3).rw(FUNC(isa8_hpblp_device::addrm_r), FUNC(isa8_hpblp_device::reg3_w));
+ map(4, 4).rw(FUNC(isa8_hpblp_device::addrh_r), FUNC(isa8_hpblp_device::reg4_w));
+ map(5, 5).rw(FUNC(isa8_hpblp_device::reg5_r), FUNC(isa8_hpblp_device::reg5_w));
+ map(6, 6).rw(FUNC(isa8_hpblp_device::reg6_r), FUNC(isa8_hpblp_device::reg6_w));
+ map(7, 7).rw(FUNC(isa8_hpblp_device::status_r), FUNC(isa8_hpblp_device::reg7_w));
+}
+
+TIMER_CALLBACK_MEMBER(isa8_hpblp_device::timer10ms)
+{
+ if (m_reg6 & 2)
+ hpblp_interrupt(1);
+ m_timer_10ms->adjust(attotime::from_msec(10));
+}
+
+void isa8_hpblp_device::device_start()
+{
+ set_isa_device();
+ m_installed = false;
+ m_timer_10ms = timer_alloc(FUNC(isa8_hpblp_device::timer10ms), this);
+ m_timer_10ms->adjust(attotime::from_msec(10));
+
+ save_item(NAME(m_bus_address));
+ save_item(NAME(m_bus_mem_mask));
+ save_item(NAME(m_bus_data));
+ save_item(NAME(m_gpib_reg1));
+ save_item(NAME(m_reg5));
+ save_item(NAME(m_reg6));
+ save_item(NAME(m_ack_buscycle));
+ save_item(NAME(m_bus_read));
+ save_item(NAME(m_bus_write));
+ save_item(NAME(m_irq_state));
+ save_item(NAME(m_reset));
+}
+
+void isa8_hpblp_device::device_reset()
+{
+ uint16_t port;
+
+ if (!m_installed) {
+ // MAME doesn't allow reading ioport at device_start
+ m_irq = ioport("BLPIRQ")->read();
+ switch(ioport("BLPPORT")->read()) {
+ case 1:
+ port = 0x280;
+ break;
+ case 2:
+ port = 0x330;
+ break;
+ case 3:
+ port = 0x390;
+ break;
+ default:
+ port = 0x250;
+ break;
+ }
+ m_isa->install_device(port, port + 7, *this, &isa8_hpblp_device::isamap);
+ m_installed = true;
+ }
+
+ m_ack_buscycle = false;
+ m_bus_read = false;
+ m_bus_write = false;
+ m_bus_address = 0;
+ m_reg5 = 0;
+ m_reg6 = 0;
+ m_maincpu->reset();
+ m_gpib_reg1 = 0xbe;
+ m_tms9914->reset();
+}
+
+ROM_START(hpblp)
+ ROM_REGION(0x20000, BLP_TAG, 0)
+ ROM_LOAD16_BYTE( "1818-4576.bin", 0x000000, 0x008000, CRC(8beb6bdb) SHA1(9b620c577aea54841608d0d46f7e8077eef607c6))
+ ROM_LOAD16_BYTE( "1818-4577.bin", 0x000001, 0x008000, CRC(e8a5c071) SHA1(9e13c0ef2aed6565c33795780b7102f2647cf2a0))
+ROM_END
+
+const tiny_rom_entry *isa8_hpblp_device::device_rom_region() const
+{
+ return ROM_NAME(hpblp);
+}
diff --git a/src/devices/bus/isa/hpblp.h b/src/devices/bus/isa/hpblp.h
new file mode 100644
index 00000000000..10f9c2ea0cf
--- /dev/null
+++ b/src/devices/bus/isa/hpblp.h
@@ -0,0 +1,97 @@
+// license:BSD-3-Clause
+// copyright-holders:Sven Schnelle
+#ifndef MAME_BUS_ISA_HPBLP_H
+#define MAME_BUS_ISA_HPBLP_H
+
+#pragma once
+
+#include "isa.h"
+
+#include "bus/hp_dio/hp_dio.h"
+#include "bus/ieee488/ieee488.h"
+#include "cpu/m68000/m68000.h"
+#include "machine/tms9914.h"
+
+class isa8_hpblp_device :
+ public device_t,
+ public device_isa8_card_interface
+{
+public:
+ isa8_hpblp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual ioport_constructor device_input_ports() const override;
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+private:
+ // ISA part
+ void isamap(address_map &map);
+
+ uint8_t datal_r(offs_t offset);
+ uint8_t datah_r(offs_t offset);
+ uint8_t status_r(offs_t offset);
+ uint8_t addrh_r(offs_t offset);
+ uint8_t addrm_r(offs_t offset);
+ uint8_t addrl_r(offs_t offset);
+ uint8_t reg5_r(offs_t offset);
+ uint8_t reg6_r(offs_t offset);
+
+ void datal_w(offs_t offset, uint8_t data);
+ void datah_w(offs_t offset, uint8_t data);
+ void irq_w(offs_t offset, uint8_t data);
+ void reg2_w(offs_t offset, uint8_t data);
+ void reg3_w(offs_t offset, uint8_t data);
+ void reg4_w(offs_t offset, uint8_t data);
+ void reg5_w(offs_t offset, uint8_t data);
+ void reg6_w(offs_t offset, uint8_t data);
+ void reg7_w(address_space &space, offs_t offset, uint8_t data);
+
+ static uint8_t status_val(offs_t offset);
+
+ void hpblp_interrupt(int state);
+ TIMER_CALLBACK_MEMBER(timer10ms);
+
+ // M68000 part
+ void gpib_irq(int state);
+ void m68map(address_map &map);
+
+ uint16_t bus_r(offs_t offset, uint16_t mem_mask);
+ void bus_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint16_t gpib_r(offs_t offset);
+ void gpib_w(offs_t offset, uint16_t data);
+
+ static offs_t get_bus_address(offs_t offset, uint16_t mem_mask);
+ uint8_t get_bus_address_partial(int shift);
+
+ static bool forward_to_host(offs_t offset);
+ void update_gpib_irq();
+
+ required_device<m68000_device> m_maincpu;
+ required_device<tms9914_device> m_tms9914;
+ required_device<ieee488_device> m_ieee488;
+ emu_timer *m_timer_10ms;
+
+ uint32_t m_bus_address;
+ uint16_t m_bus_mem_mask;
+ uint16_t m_bus_data;
+ uint8_t m_gpib_reg1;
+ uint8_t m_reg5;
+ uint8_t m_reg6;
+ uint8_t m_irq;
+
+ bool m_installed;
+ bool m_ack_buscycle;
+ bool m_bus_read;
+ bool m_bus_write;
+ bool m_irq_state;
+ bool m_reset;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(HPBLP, isa8_hpblp_device)
+
+#endif // MAME_BUS_ISA_HPBLP_H
diff --git a/src/devices/bus/isa/ibm_mfc.cpp b/src/devices/bus/isa/ibm_mfc.cpp
index 21e388318ac..9f57836fd3e 100644
--- a/src/devices/bus/isa/ibm_mfc.cpp
+++ b/src/devices/bus/isa/ibm_mfc.cpp
@@ -235,13 +235,13 @@ void isa8_ibm_mfc_device::ppi1_o_c(uint8_t data)
// D8253 PIT
//-------------------------------------------------
-WRITE_LINE_MEMBER( isa8_ibm_mfc_device::d8253_out0 )
+void isa8_ibm_mfc_device::d8253_out0(int state)
{
if (m_tcr & TCR_TAE)
set_pc_interrupt(PC_IRQ_TIMERA, 1);
}
-WRITE_LINE_MEMBER( isa8_ibm_mfc_device::d8253_out1 )
+void isa8_ibm_mfc_device::d8253_out1(int state)
{
if (m_tcr & TCR_TBE)
set_pc_interrupt(PC_IRQ_TIMERB, 1);
@@ -252,7 +252,7 @@ WRITE_LINE_MEMBER( isa8_ibm_mfc_device::d8253_out1 )
// uPD71051 USART
//-------------------------------------------------
-WRITE_LINE_MEMBER( isa8_ibm_mfc_device::write_usart_clock )
+void isa8_ibm_mfc_device::write_usart_clock(int state)
{
m_d71051->write_txc(state);
m_d71051->write_rxc(state);
@@ -263,7 +263,7 @@ WRITE_LINE_MEMBER( isa8_ibm_mfc_device::write_usart_clock )
//-------------------------------------------------
-WRITE_LINE_MEMBER(isa8_ibm_mfc_device::ibm_mfc_ym_irq)
+void isa8_ibm_mfc_device::ibm_mfc_ym_irq(int state)
{
set_z80_interrupt(Z80_IRQ_YM, state);
}
@@ -315,7 +315,7 @@ void isa8_ibm_mfc_device::ibm_mfc_w(offs_t offset, uint8_t data)
case 0x2:
case 0x3:
{
- machine().scheduler().boost_interleave(attotime::zero, attotime::from_usec(1000));
+ machine().scheduler().perfect_quantum(attotime::from_usec(1000));
m_d71055c_0->write(offset, data);
break;
}
diff --git a/src/devices/bus/isa/ibm_mfc.h b/src/devices/bus/isa/ibm_mfc.h
index c6efe79d0da..4af1acdfe1e 100644
--- a/src/devices/bus/isa/ibm_mfc.h
+++ b/src/devices/bus/isa/ibm_mfc.h
@@ -52,12 +52,12 @@ private:
void ppi1_o_c(uint8_t data);
- DECLARE_WRITE_LINE_MEMBER( d8253_out0 );
- DECLARE_WRITE_LINE_MEMBER( d8253_out1 );
+ void d8253_out0(int state);
+ void d8253_out1(int state);
- DECLARE_WRITE_LINE_MEMBER( write_usart_clock );
+ void write_usart_clock(int state);
- DECLARE_WRITE_LINE_MEMBER( ibm_mfc_ym_irq );
+ void ibm_mfc_ym_irq(int state);
uint8_t ibm_mfc_r(offs_t offset);
void ibm_mfc_w(offs_t offset, uint8_t data);
diff --git a/src/devices/bus/isa/ibm_speech.cpp b/src/devices/bus/isa/ibm_speech.cpp
new file mode 100644
index 00000000000..59c45fcaa19
--- /dev/null
+++ b/src/devices/bus/isa/ibm_speech.cpp
@@ -0,0 +1,466 @@
+// license:BSD-3-Clause
+// copyright-holders:Katherine Rohl
+/*
+ IBM PS/2 Speech Adapter
+
+ The ROM listing calls this card the "TALKER II".
+
+ The ISA version of the card uses a different timing mechanism
+ than the PCjr version to account for a 4MHz operating speed
+ rather than the 4.77 bus clock. The ISA version also uses
+ IRQ7 rather than IRQ1.
+
+ Lots of TTL, all off-the-shelf parts except the mask ROM.
+
+ Y1 - 4MHz oscillator
+ ZM5 - MC14529CP
+ ZM8 - TMS5220CNL
+ ZM9 - 8254 PIT
+ ZM10 - 32Kx8 mask ROM
+ ZM22 - 8255A PIC
+*/
+
+#include "emu.h"
+#include "ibm_speech.h"
+
+#define LOG_ROM (1U << 1)
+#define LOG_MUX (1U << 2)
+#define LOG_CVSD (1U << 3)
+#define LOG_PIT (1U << 4)
+#define LOG_IRQ (1U << 5)
+#define LOG_PORTS (1U << 6)
+#define LOG_ALL (LOG_ROM|LOG_MUX|LOG_CVSD|LOG_PIT|LOG_IRQ|LOG_PORTS)
+
+//#define VERBOSE (LOG_PORTS)
+#include "logmacro.h"
+
+#ifdef _MSC_VER
+#define FUNCNAME __func__
+#else
+#define FUNCNAME __PRETTY_FUNCTION__
+#endif
+
+DEFINE_DEVICE_TYPE(ISA8_IBM_SPEECH, isa8_ibm_speech_device, "isa_ibm_speech", "IBM PS/2 Speech Adapter")
+
+//-------------------------------------------------
+// constructor
+//-------------------------------------------------
+
+isa8_ibm_speech_device::isa8_ibm_speech_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, ISA8_IBM_SPEECH, tag, owner, clock),
+ device_isa8_card_interface(mconfig, *this),
+ m_lpc(*this, "lpc"),
+ m_cvsd(*this, "cvsd"),
+ m_dac1bit(*this, "8254_audio"),
+ m_pit(*this, "timers"),
+ m_ppi(*this, "ppi"),
+ m_speaker(*this, "speaker"),
+ m_rom(*this, "option")
+{ }
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void isa8_ibm_speech_device::device_start()
+{
+ set_isa_device();
+
+ // Not configurable.
+ m_isa->install_device(0xfb98, 0xfb9b,
+ emu::rw_delegate(m_ppi, FUNC(i8255_device::read)),
+ emu::rw_delegate(m_ppi, FUNC(i8255_device::write)));
+ m_isa->install_device(0xfb9c, 0xfb9f,
+ emu::rw_delegate(m_pit, FUNC(pit8254_device::read)),
+ emu::rw_delegate(m_pit, FUNC(pit8254_device::write)));
+ m_isa->install_device(0xff98, 0xff98,
+ emu::rw_delegate(*this, FUNC(isa8_ibm_speech_device::shift_register_r)),
+ emu::rw_delegate(*this, FUNC(isa8_ibm_speech_device::shift_register_w)));
+ m_isa->install_device(0xff9f, 0xff9f,
+ emu::rw_delegate(*this, FUNC(isa8_ibm_speech_device::audio_control_latch_r)),
+ emu::rw_delegate(*this, FUNC(isa8_ibm_speech_device::audio_control_latch_w)));
+
+ m_channel_mux = 0;
+ m_acl_int_ena = false;
+ m_acl_chan_ena = false;
+ m_sr_clk = false;
+ m_cvsd_ed = false;
+ m_beeper_gate = false;
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void isa8_ibm_speech_device::device_reset()
+{
+ // Not configurable.
+ rom_page_w(0);
+ m_cvsd_sr_bits_remaining = 0;
+}
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+ROM_START( ibm_speech )
+ ROM_REGION( 0x8000, "option", 0 )
+ ROM_LOAD( "68x2838.zm10", 0x0000, 0x8000, CRC(98ddf27f) SHA1(0cb41d490db2ed59989d2eae14a002ad0382e7ad) )
+ROM_END
+
+const tiny_rom_entry *isa8_ibm_speech_device::device_rom_region() const
+{
+ return ROM_NAME( ibm_speech );
+}
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void isa8_ibm_speech_device::device_add_mconfig(machine_config &config)
+{
+ constexpr XTAL XTAL_Y1 = XTAL(4'000'000);
+
+ // breakout box
+ SPEAKER(config, m_speaker);
+
+ PIT8254(config, m_pit, 0);
+ // Channel 0: CVSD CLOCK.
+ // Rising edge goes to the MC3418's clock pin.
+ // Rising edge inverted goes to the shift register clock.
+ m_pit->set_clk<0>(XTAL_Y1); // CVSD clock is the 4MHz crystal.
+ m_pit->out_handler<0>().set(FUNC(isa8_ibm_speech_device::cvsd_clock_w));
+ // Channel 1: CVSD FRAME.
+ // PCjr: CVSD_CLOCK / 8, but seems to be just CVSD_CLOCK here.
+ m_pit->set_clk<1>(XTAL_Y1);
+ m_pit->out_handler<1>().set(FUNC(isa8_ibm_speech_device::cvsd_frame_w));
+ // Channel 2: INT CLOCK.
+ // Channel 2 can be configured either for interrupt mode or audio mode via the Audio Control Latch.
+ // In interrupt mode, IRQ1 is signalled by the 5220.
+ // The gate opens when the 5220 IRQ is signalled.
+ // In audio mode, the timer output is multiplexed into audio output.
+ // The gate is held open.
+ m_pit->set_clk<2>(XTAL_Y1);
+ m_pit->out_handler<2>().set(FUNC(isa8_ibm_speech_device::int_clock_w));
+
+ // TMS5220 LPC
+ // The 5220 has no direct-access speech ROM.
+ // All data is transferred from the host PC via the 8255.
+ // The preset vocabulary is in the option ROM.
+ TMS5220(config, m_lpc, 640000); // TODO: Confirm TMS clock
+ m_lpc->add_route(ALL_OUTPUTS, m_speaker, 1.0);
+ m_lpc->irq_cb().set(FUNC(isa8_ibm_speech_device::lpc_interrupt_w));
+
+ // MC3418 CVSD
+ MC3418(config, m_cvsd, 0);
+ m_cvsd->add_route(ALL_OUTPUTS, m_speaker, 1.0);
+
+ // PIT CH2
+ SPEAKER_SOUND(config, m_dac1bit);
+ m_dac1bit->add_route(ALL_OUTPUTS, m_speaker, 1.0);
+
+ I8255(config, m_ppi);
+ m_ppi->in_pa_callback().set(FUNC(isa8_ibm_speech_device::porta_r));
+ m_ppi->in_pb_callback().set(m_lpc, FUNC(tms5220_device::status_r)); // direct hookup
+ m_ppi->in_pc_callback().set(FUNC(isa8_ibm_speech_device::portc_r));
+
+ m_ppi->out_pa_callback().set(FUNC(isa8_ibm_speech_device::porta_w));
+ m_ppi->out_pb_callback().set(m_lpc, FUNC(tms5220_device::data_w)); // direct hookup
+ m_ppi->out_pc_callback().set(FUNC(isa8_ibm_speech_device::portc_w));
+}
+
+void isa8_ibm_speech_device::device_reset_after_children()
+{
+ m_pit->write_gate0(ASSERT_LINE); // pulled high
+ m_pit->write_gate1(ASSERT_LINE); // pulled high
+}
+
+/******************************************************************************
+ ROM bankswitching
+
+ The option ROM is 32Kx8 and divided into four 8K pages at CE00: to CFFF:.
+ Bits 2-3 of PPI PORT.A control which page is visible.
+ All pages contain the option ROM boot signature.
+******************************************************************************/
+void isa8_ibm_speech_device::rom_page_w(uint8_t data)
+{
+ m_isa->install_bank(0xce000, 0xcffff, m_rom + (0x2000*data));
+}
+
+/******************************************************************************
+ Audio Control Latch
+
+ This is for multiplexing interrupt and audio sources.
+******************************************************************************/
+uint8_t isa8_ibm_speech_device::audio_control_latch_r()
+{
+ uint8_t data = 0;
+
+ // The bits are inverted when reading.
+ data |= (m_acl_int_ena ? 0 : 2); // -INT_ENA
+ data |= (m_acl_chan_ena ? 0 : 1); // -CHAN_ENA
+
+ return data;
+}
+
+void isa8_ibm_speech_device::audio_control_latch_w(uint8_t data)
+{
+ m_acl_int_ena = BIT(data, 1); // INT_ENA
+ m_acl_chan_ena = BIT(data, 0); // CHAN_ENA
+
+ if(m_acl_int_ena)
+ {
+ // IRQ7 enabled, close PIT CH2 gate.
+ // CH2 will be set up for one-shot mode.
+ m_pit->write_gate2(CLEAR_LINE);
+ }
+ else
+ {
+ // IRQ7 disabled, PIT CH2 is in audio output mode. Gate is held open.
+ m_pit->write_gate2(ASSERT_LINE);
+ }
+}
+
+
+/******************************************************************************
+ PPI Port A
+
+ PA.0: CHANNEL MUX (O)
+ PA.1: CHANNEL MUX (O)
+ PA.2: ROM PAGE (O)
+ PA.3: ROM PAGE (O)
+ PA.4: n/c
+ PA.5: n/c
+ PA.6: n/c
+ PA.7: LPC IN PROGRESS (I/O)
+******************************************************************************/
+uint8_t isa8_ibm_speech_device::porta_r()
+{
+ uint8_t data = 0;
+
+ data |= (m_lpc_running << 7);
+
+ return data;
+}
+
+void isa8_ibm_speech_device::porta_w(uint8_t data)
+{
+ channel_mux_w(data & 3);
+ rom_page_w((data >> 2) & 3);
+ m_lpc_running = BIT(data, 7);
+}
+
+/******************************************************************************
+ PPI Port C
+
+ PC.0: -LPC READY (I)
+ PC.1: -LPC INT (I)
+ PC.2: CVSD FRAME (I)
+ PC.3: -CVSD CLOCK (I)
+ PC.4: LPC RS (O) (5220 RS#, inverted)
+ PC.5: LPC WS (O) (5220 WS#, inverted)
+ PC.6: CVSD E/D (I) (PC.6 | PIT.OUT1 triggers ZM12 SLOAD#)
+ PC.7: n/c
+******************************************************************************/
+uint8_t isa8_ibm_speech_device::portc_r()
+{
+ uint8_t data = 0;
+
+ data |= (m_lpc->readyq_r() << 0);
+ data |= (m_lpc->intq_r() << 1);
+ data |= (m_cvsd_frame << 2);
+
+ // PCjr
+ //data |= (!m_cvsd_clock ? (1 << 3) : 0);
+
+ if(m_cvsd_sr_bits_remaining > 0)
+ {
+ // ISA: Clock is held until the shift register needs a new frame.
+ }
+ else
+ {
+ data |= (!m_cvsd_clock << 3);
+ }
+
+ data |= (m_cvsd_ed << 6); // 0: CVSD playback, 1: CVSD record
+
+ return data;
+}
+
+void isa8_ibm_speech_device::portc_w(uint8_t data)
+{
+ m_lpc->rsq_w(!BIT(data, 4));
+ m_lpc->wsq_w(!BIT(data, 5));
+}
+
+/******************************************************************************
+ Channel Mux
+
+ Selects the audio source from the four possible sources. Only one source
+ can be used at a time.
+******************************************************************************/
+void isa8_ibm_speech_device::channel_mux_w(uint8_t data)
+{
+ switch(data & 3)
+ {
+ case 0:
+ LOGMASKED(LOG_MUX, "Channel MUX: source now LPC\n");
+ m_lpc->set_output_gain(0, 1.0);
+ m_cvsd->set_output_gain(0, 0.0);
+ m_beeper_gate = 0;
+ break;
+ case 1:
+ LOGMASKED(LOG_MUX, "Channel MUX: source now CVSD\n");
+ m_lpc->set_output_gain(0, 0.0);
+ m_cvsd->set_output_gain(0, 1.0);
+ m_beeper_gate = 0;
+ break;
+ case 2:
+ LOGMASKED(LOG_MUX, "Channel MUX: source now 8254\n");
+ m_lpc->set_output_gain(0, 0.0);
+ m_cvsd->set_output_gain(0, 0.0);
+ m_beeper_gate = 1;
+ break;
+ case 3:
+ LOGMASKED(LOG_MUX, "Channel MUX: source now Test Signal\n");
+ // TODO: How is this generated?
+ break;
+ }
+}
+
+void isa8_ibm_speech_device::lpc_interrupt_w(int state)
+{
+ // Active low.
+
+ // Pulse IRQ7 on falling edge.
+ if(m_lpc_interrupt && !state)
+ {
+ LOGMASKED(LOG_IRQ, "pulsing IRQ7\n");
+ m_isa->irq7_w(ASSERT_LINE); // Raise IRQ...
+ m_pit->write_gate2(ASSERT_LINE); // ...CH2 gate open, triggering CH2 one-shot.
+ }
+ else if(!m_lpc_interrupt && !state)
+ {
+ LOGMASKED(LOG_IRQ, "IRQ7 already raised, go away\n");
+ }
+ else if(state)
+ {
+ LOGMASKED(LOG_IRQ, "LPC INT pin going high, CH2 gate closed\n");
+ m_isa->irq7_w(CLEAR_LINE);
+ m_pit->write_gate2(CLEAR_LINE);
+ }
+
+ m_lpc_interrupt = state;
+}
+
+/******************************************************************************
+ CVSD Clock - PIT CH0
+
+ Sets the speed of the CVSD bitstream.
+
+ Non-inverted to:
+ - MC3418 CLK
+ Inverted to:
+ - PIT CLK1
+ - ZM12 serial clock
+ - PPI PORTC.3
+******************************************************************************/
+void isa8_ibm_speech_device::cvsd_clock_w(int state)
+{
+ m_cvsd_clock = state;
+
+ LOGMASKED(LOG_CVSD, "cvsd_clock_w %d\n", state);
+
+ // PIT CH0 is the CVSD CLOCK signal.
+ m_cvsd->clock_w(state); // Straight through to the CVSD CLK pin.
+
+ // Through an inverter and to:
+ //m_pit->write_clk1(state ? 0 : 1); // PCjr: PIT CLK1
+ cvsd_shiftreg_clk_w(state ? 0 : 1); // 74859 clock pin
+ // PPI PC.3 (handled over there)
+}
+
+/******************************************************************************
+ CVSD Frame - PIT CH1
+
+ Defined as (CVSD Clock / 8).
+ This signal goes low for one clock every 8 CVSD bit clocks, which specifies
+ how often a new byte gets latched into the CVSD shift register.
+******************************************************************************/
+void isa8_ibm_speech_device::cvsd_frame_w(int state)
+{
+ // PIT CH1 is the CVSD FRAME signal.
+ LOGMASKED(LOG_CVSD, "*** CVSD frame going %s\n", (state ? "high" : "low"));
+
+ if(state && (m_cvsd_sr_bits_remaining == 0))
+ {
+ m_cvsd_sr_serial = m_cvsd_sr_parallel;
+ }
+
+ m_cvsd_frame = state;
+}
+
+/******************************************************************************
+ INT CLOCK - PIT CH2
+
+ Clocked by the 4MHz crystal.
+
+ When INT_ENA is asserted, pulses IRQ7 when the 5220 raises an IRQ.
+ When INT_ENA is cleared, the timer acts as a PC speaker-style beeper.
+******************************************************************************/
+void isa8_ibm_speech_device::int_clock_w(int state)
+{
+ if(!m_acl_int_ena)
+ {
+ // CH2 is now a beeper.
+ //LOGMASKED(LOG_IRQ, "%s: INT CLOCK: beeper mode\n", FUNCNAME);
+ m_dac1bit->level_w(state);
+ }
+}
+
+/******************************************************************************
+ CVSD Shift Register
+******************************************************************************/
+void isa8_ibm_speech_device::cvsd_shiftreg_clk_w(int state)
+{
+ // If rising edge of the inverted signal...
+ if(!m_sr_clk && state)
+ {
+ // Shift one bit out of the shift register and into the CVSD.
+ if(m_cvsd_sr_bits_remaining > 0)
+ {
+ LOGMASKED(LOG_CVSD, "bit going SR -> CVSD, %d left\n", m_cvsd_sr_bits_remaining);
+ m_cvsd->digin_w(BIT(m_cvsd_sr_serial, 0));
+ m_cvsd_sr_serial >>= 1;
+
+ m_cvsd_sr_bits_remaining--;
+ }
+ }
+
+ m_sr_clk = state;
+}
+
+/******************************************************************************
+ CVSD Shift Register read and write logic.
+******************************************************************************/
+
+// The host sees the parallel side, the CVSD sees the serial side.
+uint8_t isa8_ibm_speech_device::shift_register_r()
+{
+ return m_cvsd_sr_parallel;
+}
+
+void isa8_ibm_speech_device::shift_register_w(uint8_t data)
+{
+ if(m_cvsd_sr_bits_remaining == 0)
+ {
+ LOGMASKED(LOG_CVSD, "incoming to CVSD shift register %02X\n", data);
+ m_cvsd_sr_parallel = data;
+ m_cvsd_sr_bits_remaining = 8;
+ cvsd_frame_w(1);
+ }
+ else
+ {
+ LOGMASKED(LOG_CVSD, "incoming to CVSD shift register %02X but not out of bits\n", data);
+ }
+}
diff --git a/src/devices/bus/isa/ibm_speech.h b/src/devices/bus/isa/ibm_speech.h
new file mode 100644
index 00000000000..7e33fdb1c04
--- /dev/null
+++ b/src/devices/bus/isa/ibm_speech.h
@@ -0,0 +1,83 @@
+// license:BSD-3-Clause
+// copyright-holders:Katherine Rohl
+
+#ifndef MAME_BUS_ISA_IBM_SPEECH_H
+#define MAME_BUS_ISA_IBM_SPEECH_H
+
+#pragma once
+
+#include "isa.h"
+#include "machine/i8255.h"
+#include "machine/pit8253.h"
+#include "sound/tms5220.h"
+#include "sound/hc55516.h"
+#include "sound/spkrdev.h"
+#include "speaker.h"
+
+class isa8_ibm_speech_device :
+ public device_t,
+ public device_isa8_card_interface
+{
+public:
+ isa8_ibm_speech_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ uint8_t audio_control_latch_r();
+ void audio_control_latch_w(uint8_t data);
+
+ uint8_t shift_register_r();
+ void shift_register_w(uint8_t data);
+
+protected:
+ // device_t implementation
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void device_reset_after_children() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+private:
+ required_device<tms5220_device> m_lpc;
+ required_device<mc3418_device> m_cvsd;
+ required_device<speaker_sound_device> m_dac1bit;
+ required_device<pit8254_device> m_pit;
+ required_device<i8255_device> m_ppi;
+ required_device<speaker_device> m_speaker;
+ required_region_ptr<uint8_t> m_rom;
+
+ void cvsd_clock_w(int state); // PIT CH0
+ void cvsd_frame_w(int state); // PIT CH1
+ void int_clock_w(int state); // PIT CH2
+ void lpc_interrupt_w(int state); // 5220 INT#
+ void cvsd_shiftreg_clk_w(int state); // SRCLK
+
+ uint8_t porta_r();
+ uint8_t portc_r();
+
+ void porta_w(uint8_t data);
+ void portc_w(uint8_t data);
+
+ void rom_page_w(uint8_t data);
+ void channel_mux_w(uint8_t data);
+
+ bool m_lpc_interrupt;
+ bool m_lpc_running;
+
+ bool m_cvsd_clock;
+ bool m_cvsd_frame;
+ bool m_cvsd_ed;
+
+ bool m_sr_clk;
+ bool m_beeper_gate;
+
+ bool m_acl_int_ena;
+ bool m_acl_chan_ena;
+
+ uint8_t m_channel_mux;
+ uint8_t m_cvsd_sr_bits_remaining;
+ uint8_t m_cvsd_sr_parallel;
+ uint8_t m_cvsd_sr_serial;
+};
+
+DECLARE_DEVICE_TYPE(ISA8_IBM_SPEECH, isa8_ibm_speech_device)
+
+#endif // MAME_BUS_ISA_IBM_SPEECH_H
diff --git a/src/devices/bus/isa/ide.cpp b/src/devices/bus/isa/ide.cpp
index 656995add4e..9565851fafc 100644
--- a/src/devices/bus/isa/ide.cpp
+++ b/src/devices/bus/isa/ide.cpp
@@ -35,7 +35,7 @@ void isa16_ide_device::alt_map(address_map &map)
map(0x6, 0x6).rw(FUNC(isa16_ide_device::ide16_alt_r), FUNC(isa16_ide_device::ide16_alt_w));
}
-WRITE_LINE_MEMBER(isa16_ide_device::ide_interrupt)
+void isa16_ide_device::ide_interrupt(int state)
{
if (is_primary())
{
diff --git a/src/devices/bus/isa/ide.h b/src/devices/bus/isa/ide.h
index 5cdccca6d90..326b4c396cd 100644
--- a/src/devices/bus/isa/ide.h
+++ b/src/devices/bus/isa/ide.h
@@ -33,7 +33,7 @@ protected:
virtual ioport_constructor device_input_ports() const override;
private:
- DECLARE_WRITE_LINE_MEMBER(ide_interrupt);
+ void ide_interrupt(int state);
uint8_t ide16_alt_r();
void ide16_alt_w(uint8_t data);
bool is_primary() { return m_is_primary; }
diff --git a/src/devices/bus/isa/isa.cpp b/src/devices/bus/isa/isa.cpp
index d8ac97b547f..f212f61d3d7 100644
--- a/src/devices/bus/isa/isa.cpp
+++ b/src/devices/bus/isa/isa.cpp
@@ -223,20 +223,6 @@ void isa8_device::device_config_complete()
void isa8_device::device_resolve_objects()
{
- // resolve callbacks
- m_write_iochrdy.resolve_safe();
- m_write_iochck.resolve_safe();
-
- m_out_irq2_cb.resolve_safe();
- m_out_irq3_cb.resolve_safe();
- m_out_irq4_cb.resolve_safe();
- m_out_irq5_cb.resolve_safe();
- m_out_irq6_cb.resolve_safe();
- m_out_irq7_cb.resolve_safe();
- m_out_drq1_cb.resolve_safe();
- m_out_drq2_cb.resolve_safe();
- m_out_drq3_cb.resolve_safe();
-
m_iowidth = m_iospace->data_width();
m_memwidth = m_memspace->data_width();
}
@@ -401,17 +387,17 @@ void isa8_device::unmap_readwrite(offs_t start, offs_t end)
}
// interrupt request from isa card
-WRITE_LINE_MEMBER( isa8_device::irq2_w ) { m_out_irq2_cb(state); }
-WRITE_LINE_MEMBER( isa8_device::irq3_w ) { m_out_irq3_cb(state); }
-WRITE_LINE_MEMBER( isa8_device::irq4_w ) { m_out_irq4_cb(state); }
-WRITE_LINE_MEMBER( isa8_device::irq5_w ) { m_out_irq5_cb(state); }
-WRITE_LINE_MEMBER( isa8_device::irq6_w ) { m_out_irq6_cb(state); }
-WRITE_LINE_MEMBER( isa8_device::irq7_w ) { m_out_irq7_cb(state); }
+void isa8_device::irq2_w(int state) { m_out_irq2_cb(state); }
+void isa8_device::irq3_w(int state) { m_out_irq3_cb(state); }
+void isa8_device::irq4_w(int state) { m_out_irq4_cb(state); }
+void isa8_device::irq5_w(int state) { m_out_irq5_cb(state); }
+void isa8_device::irq6_w(int state) { m_out_irq6_cb(state); }
+void isa8_device::irq7_w(int state) { m_out_irq7_cb(state); }
// dma request from isa card
-WRITE_LINE_MEMBER( isa8_device::drq1_w ) { m_out_drq1_cb(state); }
-WRITE_LINE_MEMBER( isa8_device::drq2_w ) { m_out_drq2_cb(state); }
-WRITE_LINE_MEMBER( isa8_device::drq3_w ) { m_out_drq3_cb(state); }
+void isa8_device::drq1_w(int state) { m_out_drq1_cb(state); }
+void isa8_device::drq2_w(int state) { m_out_drq2_cb(state); }
+void isa8_device::drq3_w(int state) { m_out_drq3_cb(state); }
uint8_t isa8_device::dack_r(int line)
{
@@ -465,7 +451,7 @@ void isa8_device::nmi()
device_isa8_card_interface::device_isa8_card_interface(const machine_config &mconfig, device_t &device)
: device_interface(device, "isa"),
- m_isa(nullptr), m_isa_dev(nullptr), m_next(nullptr)
+ m_isa(nullptr), m_isa_dev(nullptr)
{
}
@@ -521,27 +507,6 @@ isa16_device::isa16_device(const machine_config &mconfig, const char *tag, devic
{
}
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-
-void isa16_device::device_start()
-{
- isa8_device::device_start();
-
- // resolve callbacks
- m_out_irq10_cb.resolve_safe();
- m_out_irq11_cb.resolve_safe();
- m_out_irq12_cb.resolve_safe();
- m_out_irq14_cb.resolve_safe();
- m_out_irq15_cb.resolve_safe();
-
- m_out_drq0_cb.resolve_safe();
- m_out_drq5_cb.resolve_safe();
- m_out_drq6_cb.resolve_safe();
- m_out_drq7_cb.resolve_safe();
-}
-
template<typename R, typename W> void isa16_device::install16_device(offs_t start, offs_t end, R rhandler, W whandler)
{
int buswidth = m_iowidth;
@@ -596,50 +561,48 @@ void isa16_device::io16_w(offs_t offset, uint16_t data, uint16_t mem_mask)
uint16_t isa16_device::mem16_swap_r(offs_t offset, uint16_t mem_mask)
{
- uint16_t rv;
- mem_mask = (mem_mask<<8) | (mem_mask>>8);
+ mem_mask = swapendian_int16(mem_mask);
- rv = m_memspace->read_word(offset<<1, mem_mask);
+ uint16_t rv = m_memspace->read_word(offset<<1, mem_mask);
- return (rv<<8) | (rv>>8);
+ return swapendian_int16(rv);
}
void isa16_device::mem16_swap_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
- mem_mask = (mem_mask<<8) | (mem_mask>>8);
- data = (data<<8) | (data>>8);
+ mem_mask = swapendian_int16(mem_mask);
+ data = swapendian_int16(data);
m_memspace->write_word(offset<<1, data, mem_mask);
}
uint16_t isa16_device::io16_swap_r(offs_t offset, uint16_t mem_mask)
{
- uint16_t rv;
- mem_mask = (mem_mask<<8) | (mem_mask>>8);
+ mem_mask = swapendian_int16(mem_mask);
- rv = m_iospace->read_word(offset<<1, mem_mask);
+ uint16_t rv = m_iospace->read_word(offset<<1, mem_mask);
- return (rv<<8) | (rv>>8);
+ return swapendian_int16(rv);
}
void isa16_device::io16_swap_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
- mem_mask = (mem_mask<<8) | (mem_mask>>8);
- data = (data<<8) | (data>>8);
+ mem_mask = swapendian_int16(mem_mask);
+ data = swapendian_int16(data);
m_iospace->write_word(offset<<1, data, mem_mask);
}
// interrupt request from isa card
-WRITE_LINE_MEMBER( isa16_device::irq10_w ) { m_out_irq10_cb(state); }
-WRITE_LINE_MEMBER( isa16_device::irq11_w ) { m_out_irq11_cb(state); }
-WRITE_LINE_MEMBER( isa16_device::irq12_w ) { m_out_irq12_cb(state); }
-WRITE_LINE_MEMBER( isa16_device::irq14_w ) { m_out_irq14_cb(state); }
-WRITE_LINE_MEMBER( isa16_device::irq15_w ) { m_out_irq15_cb(state); }
+void isa16_device::irq10_w(int state) { m_out_irq10_cb(state); }
+void isa16_device::irq11_w(int state) { m_out_irq11_cb(state); }
+void isa16_device::irq12_w(int state) { m_out_irq12_cb(state); }
+void isa16_device::irq14_w(int state) { m_out_irq14_cb(state); }
+void isa16_device::irq15_w(int state) { m_out_irq15_cb(state); }
// dma request from isa card
-WRITE_LINE_MEMBER( isa16_device::drq0_w ) { m_out_drq0_cb(state); }
-WRITE_LINE_MEMBER( isa16_device::drq5_w ) { m_out_drq5_cb(state); }
-WRITE_LINE_MEMBER( isa16_device::drq6_w ) { m_out_drq6_cb(state); }
-WRITE_LINE_MEMBER( isa16_device::drq7_w ) { m_out_drq7_cb(state); }
+void isa16_device::drq0_w(int state) { m_out_drq0_cb(state); }
+void isa16_device::drq5_w(int state) { m_out_drq5_cb(state); }
+void isa16_device::drq6_w(int state) { m_out_drq6_cb(state); }
+void isa16_device::drq7_w(int state) { m_out_drq7_cb(state); }
uint16_t isa16_device::dack16_r(int line)
{
diff --git a/src/devices/bus/isa/isa.h b/src/devices/bus/isa/isa.h
index 939f8d88a26..4b02d0bf946 100644
--- a/src/devices/bus/isa/isa.h
+++ b/src/devices/bus/isa/isa.h
@@ -95,7 +95,7 @@ public:
protected:
isa8_slot_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
// configuration
@@ -172,16 +172,16 @@ public:
// FIXME: shouldn't need to expose this
address_space &memspace() const { return *m_memspace; }
- DECLARE_WRITE_LINE_MEMBER( irq2_w );
- DECLARE_WRITE_LINE_MEMBER( irq3_w );
- DECLARE_WRITE_LINE_MEMBER( irq4_w );
- DECLARE_WRITE_LINE_MEMBER( irq5_w );
- DECLARE_WRITE_LINE_MEMBER( irq6_w );
- DECLARE_WRITE_LINE_MEMBER( irq7_w );
+ void irq2_w(int state);
+ void irq3_w(int state);
+ void irq4_w(int state);
+ void irq5_w(int state);
+ void irq6_w(int state);
+ void irq7_w(int state);
- DECLARE_WRITE_LINE_MEMBER( drq1_w );
- DECLARE_WRITE_LINE_MEMBER( drq2_w );
- DECLARE_WRITE_LINE_MEMBER( drq3_w );
+ void drq1_w(int state);
+ void drq2_w(int state);
+ void drq3_w(int state);
// 8 bit accessors for ISA-defined address spaces
uint8_t mem_r(offs_t offset);
@@ -210,7 +210,7 @@ protected:
template<typename R, typename W> void install_space(int spacenum, offs_t start, offs_t end, R rhandler, W whandler);
- // device-level overrides
+ // device_t implementation
virtual void device_config_complete() override;
virtual void device_resolve_objects() override;
virtual void device_start() override;
@@ -250,13 +250,10 @@ DECLARE_DEVICE_TYPE(ISA8, isa8_device)
class device_isa8_card_interface : public device_interface
{
friend class isa8_device;
- template <class ElementType> friend class simple_list;
public:
// construction/destruction
virtual ~device_isa8_card_interface();
- device_isa8_card_interface *next() const { return m_next; }
-
void set_isa_device();
// configuration access
virtual uint8_t dack_r(int line);
@@ -274,9 +271,6 @@ public:
isa8_device *m_isa;
device_t *m_isa_dev;
-
-private:
- device_isa8_card_interface *m_next;
};
class isa16_device;
@@ -298,7 +292,7 @@ public:
isa16_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
};
@@ -328,16 +322,16 @@ public:
// for ISA16, put the 16-bit configs in the primary slots and the 8-bit configs in the secondary
virtual space_config_vector memory_space_config() const override;
- DECLARE_WRITE_LINE_MEMBER( irq10_w );
- DECLARE_WRITE_LINE_MEMBER( irq11_w );
- DECLARE_WRITE_LINE_MEMBER( irq12_w );
- DECLARE_WRITE_LINE_MEMBER( irq14_w );
- DECLARE_WRITE_LINE_MEMBER( irq15_w );
+ void irq10_w(int state);
+ void irq11_w(int state);
+ void irq12_w(int state);
+ void irq14_w(int state);
+ void irq15_w(int state);
- DECLARE_WRITE_LINE_MEMBER( drq0_w );
- DECLARE_WRITE_LINE_MEMBER( drq5_w );
- DECLARE_WRITE_LINE_MEMBER( drq6_w );
- DECLARE_WRITE_LINE_MEMBER( drq7_w );
+ void drq0_w(int state);
+ void drq5_w(int state);
+ void drq6_w(int state);
+ void drq7_w(int state);
uint16_t dack16_r(int line);
void dack16_w(int line, uint16_t data);
@@ -354,10 +348,6 @@ public:
uint16_t io16_swap_r(offs_t offset, uint16_t mem_mask = 0xffff);
void io16_swap_w(offs_t offset, uint16_t data, uint16_t mem_mask = 0xffff);
-protected:
- // device-level overrides
- virtual void device_start() override;
-
private:
// internal state
devcb_write_line m_out_irq10_cb;
diff --git a/src/devices/bus/isa/isa_cards.cpp b/src/devices/bus/isa/isa_cards.cpp
index 0b01c16d501..8ad01bcef63 100644
--- a/src/devices/bus/isa/isa_cards.cpp
+++ b/src/devices/bus/isa/isa_cards.cpp
@@ -18,6 +18,7 @@
#include "vga.h"
#include "vga_ati.h"
#include "svga_cirrus.h"
+#include "svga_paradise.h"
#include "svga_s3.h"
#include "svga_tseng.h"
#include "svga_trident.h"
@@ -57,6 +58,7 @@
#include "gblaster.h"
#include "gus.h"
#include "ibm_mfc.h"
+#include "ibm_speech.h"
#include "mpu401.h"
#include "pcmidi.h"
#include "sblaster.h"
@@ -81,6 +83,7 @@
#include "pds.h"
// other
+#include "hpblp.h"
#include "chessmdr.h"
#include "chessmsr.h"
#include "finalchs.h"
@@ -103,6 +106,8 @@ void pc_isa8_cards(device_slot_interface &device)
device.option_add("pgc", ISA8_PGC);
device.option_add("vga", ISA8_VGA);
device.option_add("svga_et4k", ISA8_SVGA_ET4K);
+ device.option_add("svga_et4k_kasan16", ISA8_SVGA_ET4K_KASAN16);
+ device.option_add("wd90c90_jk", ISA8_WD90C90_JK);
device.option_add("num9rev",ISA8_NUM_9_REV);
device.option_add("com", ISA8_COM);
device.option_add("fdc", ISA8_FDC_SUPERIO);
@@ -156,6 +161,8 @@ void pc_isa16_cards(device_slot_interface &device)
device.option_add("pgc", ISA8_PGC);
device.option_add("vga", ISA8_VGA);
device.option_add("svga_et4k", ISA8_SVGA_ET4K);
+ device.option_add("svga_et4k_kasan16", ISA8_SVGA_ET4K_KASAN16);
+ device.option_add("wd90c90_jk", ISA8_WD90C90_JK);
device.option_add("num9rev",ISA8_NUM_9_REV);
device.option_add("com", ISA8_COM);
device.option_add("comat", ISA8_COM_AT);
@@ -190,6 +197,7 @@ void pc_isa16_cards(device_slot_interface &device)
device.option_add("acb2072", ACB2072);
device.option_add("3xtwin", ISA8_3XTWIN);
device.option_add("opus108pm", ISA8_OPUS108PM);
+ device.option_add("ibm_speech", ISA8_IBM_SPEECH);
// 16-bit
device.option_add("ide", ISA16_IDE);
device.option_add("ne2000", NE2000);
@@ -203,14 +211,21 @@ void pc_isa16_cards(device_slot_interface &device)
device.option_add("gus",ISA16_GUS);
device.option_add("sblaster_16", ISA16_SOUND_BLASTER_16);
device.option_add("svga_s3", ISA16_SVGA_S3);
- device.option_add("s3virge", ISA16_S3VIRGE);
- device.option_add("s3virgedx", ISA16_S3VIRGEDX);
- device.option_add("dms3d2kp", ISA16_DMS3D2KPRO);
device.option_add("svga_dm",ISA16_SVGA_CIRRUS);
device.option_add("clgd542x",ISA16_SVGA_CIRRUS_GD542X);
device.option_add("gfxultra", ISA16_VGA_GFXULTRA);
device.option_add("gfxultrap", ISA16_SVGA_GFXULTRAPRO);
- device.option_add("tgui9680",ISA16_SVGA_TGUI9680);
+ device.option_add("tvga9000", ISA16_SVGA_TVGA9000);
+// device.option_add("tgui9680",ISA16_SVGA_TGUI9680);
+ device.option_add("pvga1a", ISA16_PVGA1A);
+ device.option_add("pvga1a_jk", ISA16_PVGA1A_JK);
+ device.option_add("wd90c00_jk", ISA16_WD90C00_JK);
+ device.option_add("wd90c11_lr", ISA16_WD90C11_LR);
+ device.option_add("wd90c30_lr", ISA16_WD90C30_LR);
+ device.option_add("wd90c31_lr", ISA16_WD90C31_LR);
+ device.option_add("wd90c31a_lr", ISA16_WD90C31A_LR);
+ device.option_add("wd90c31a_zs", ISA16_WD90C31A_ZS);
+ device.option_add("wd90c33_zz", ISA16_WD90C33_ZZ);
device.option_add("3c505", ISA16_3C505);
device.option_add("mach64", ISA16_SVGA_MACH64);
device.option_add("sb16_lle", ISA16_SB16);
@@ -235,4 +250,5 @@ void pc_isa16_cards(device_slot_interface &device)
device.option_add("dc820b", TEKRAM_DC820B); // actually an EISA card
device.option_add("omti8621", ISA16_OMTI8621);
device.option_add("lrk331", LRK331);
+ device.option_add("hpblp", HPBLP);
}
diff --git a/src/devices/bus/isa/lbaenhancer.cpp b/src/devices/bus/isa/lbaenhancer.cpp
index 242f1f47afe..df5d7cdb4a1 100644
--- a/src/devices/bus/isa/lbaenhancer.cpp
+++ b/src/devices/bus/isa/lbaenhancer.cpp
@@ -9,7 +9,7 @@
Generic BIOS extension card. Adds 28 bit LBA mode to any pre-1994
board with an empty ISA slot.
- Supports 1 to 4 large hard disks. Bios boot remains possible.
+ Supports 1 to 4 large hard disks. BIOS boot remains possible.
Check date code of Ami BIOS (at bottom of boot screen):
40-0100-001139-00101111-111192-486ABC-F (111192 will not support LBA)
diff --git a/src/devices/bus/isa/lpt.cpp b/src/devices/bus/isa/lpt.cpp
index 268ff2c9caf..548e3a57989 100644
--- a/src/devices/bus/isa/lpt.cpp
+++ b/src/devices/bus/isa/lpt.cpp
@@ -52,7 +52,7 @@ void isa8_lpt_device::device_reset()
m_isa->install_device(0x0278, 0x027b, read8sm_delegate(lpt, FUNC(pc_lpt_device::read)), write8sm_delegate(lpt, FUNC(pc_lpt_device::write)));
}
-WRITE_LINE_MEMBER(isa8_lpt_device::pc_cpu_line)
+void isa8_lpt_device::pc_cpu_line(int state)
{
if (is_primary())
m_isa->irq7_w(state);
diff --git a/src/devices/bus/isa/lpt.h b/src/devices/bus/isa/lpt.h
index 1aa2731bfaf..15f3259db52 100644
--- a/src/devices/bus/isa/lpt.h
+++ b/src/devices/bus/isa/lpt.h
@@ -39,7 +39,7 @@ protected:
virtual ioport_constructor device_input_ports() const override;
private:
- WRITE_LINE_MEMBER(pc_cpu_line);
+ void pc_cpu_line(int state);
// internal state
bool m_is_primary;
diff --git a/src/devices/bus/isa/mach32.cpp b/src/devices/bus/isa/mach32.cpp
deleted file mode 100644
index 064947d5c7c..00000000000
--- a/src/devices/bus/isa/mach32.cpp
+++ /dev/null
@@ -1,358 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Barry Rodewald
-/*
- * mach32.c
- *
- * Implementation of the ATi mach32 and mach64 video chips
- * Based on ati_vga and mach8
- *
- * Created on: 16/05/2014
- */
-
-#include "emu.h"
-#include "mach32.h"
-
-#include "screen.h"
-
-DEFINE_DEVICE_TYPE(ATIMACH32, mach32_device, "mach32", "ATi mach32")
-DEFINE_DEVICE_TYPE(ATIMACH32_8514A, mach32_8514a_device, "mach32_8514a", "ATi mach32 (2D acceleration module)")
-DEFINE_DEVICE_TYPE(ATIMACH64, mach64_device, "mach64", "ATi mach64")
-DEFINE_DEVICE_TYPE(ATIMACH64_8514A, mach64_8514a_device, "mach64_8514a", "ATi mach64 (2D acceleration module)")
-
-
-/*
- * mach32
- */
-
-// 8514/A device
-mach32_8514a_device::mach32_8514a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : mach32_8514a_device(mconfig, ATIMACH32_8514A, tag, owner, clock)
-{
-}
-
-mach32_8514a_device::mach32_8514a_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
- : mach8_device(mconfig, type, tag, owner, clock), m_chip_ID(0), m_membounds(0)
-{
-}
-
-
-// SVGA device
-mach32_device::mach32_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : mach32_device(mconfig, ATIMACH32, tag, owner, clock)
-{
-}
-
-mach32_device::mach32_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
- : ati_vga_device(mconfig, type, tag, owner, clock), m_8514a(*this,"8514a")
-{
-}
-
-void mach32_device::device_add_mconfig(machine_config &config)
-{
- ATIMACH32_8514A(config, "8514a", 0).set_vga(DEVICE_SELF);
- EEPROM_93C56_16BIT(config, "ati_eeprom");
-}
-
-void mach32_8514a_device::device_start()
-{
- mach8_device::device_start();
- // 017h 68800-AX
- // 177h 68800-LX
- // 2F7h 68800-6
- // The 68800-3 appears to return 0 for this field (undocumented)
- m_chip_ID = 0x17;
- m_membounds = 0;
-}
-
-// Configuration Status Register 1 (read only)
-// bit 0: Disable VGA: 0=VGA+8514/A, 1=8514/A only
-// bits 1-3: Bus Type: 0=16-bit ISA. 1=EISA, 2=16-bit MCA, 3=32-bit MCA, 4=LBus 386SX
-// 5=LBus 386DX, 6=LBus 486. 7=PCI
-// bits 4-6: RAM Type: 3=256Kx16 DRAM
-// bit 7: Chip Disable
-// bit 8: TST_VCTR_ENA: 1=delay memory write by 1/2 MCLK to test vector generation
-// bits 9-11: DAC Type: 0=ATI68830, 1=SC11483, 2=ATI68875, 3=Bt476, 4=Bt481, 5=ATI68860 (68800AX or higher)
-// The Graphics Ultra Pro has an ATI68875
-// bit 12: Enable internal uC address decode
-// bit 13-15: Card ID: ID when using multiple controllers
-uint16_t mach32_8514a_device::mach32_config1_r()
-{
- return 0x0430; // enable VGA, 16-bit ISA, 256Kx16 DRAM, ATI68875
-}
-
-
-/* 7AEE (W) Mach 32
- * bits 0-2 Monitor Alias - Monitor ID
- * bit 3 Enable reporting of Monitor Alias
- * bits 4-5 Pixel Width (0=4bpp, 1=8bpp, 2=16bpp, 3=24bpp)
- * bits 6-7 16bpp colour mode (0=555, 1=565, 2=655, 3=664)
- * bit 8 Multiplex pixels - processes 4 pixels in parallel by the DAC
- * bit 9 24bpp config (0=3Bytes/pixel, 1=4Bytes/pixel)
- * bit 10 24bpp colour order (0=RGB, LSB reserved in 4Bpp, 1=BGR, MSB reserved in 4Bpp)
- * bit 11 Display pixel size to be written
- * bits 12-13 DAC extended address inputs RS2,RS3
- * bit 14 Enabled 8-bit DAC (0=6-bit)
- * bit 15 Draw pixel size to be written
- * If bits 11 and 15 are both 0, then for compatibility, both will be written
- */
-void mach32_8514a_device::mach32_ge_ext_config_w(offs_t offset, uint16_t data, uint16_t mem_mask)
-{
- if(offset == 1)
- {
- COMBINE_DATA(&mach8.ge_ext_config);
- if(data & 0x0800)
- display_mode_change = true;
- if(!(data & 0x8000) && (!(data & 0x0800)))
- display_mode_change = true;
- }
-}
-
-void mach32_8514a_device::device_reset()
-{
-}
-
-void mach32_device::device_start()
-{
- ati_vga_device::device_start();
- ati.vga_chip_id = 0x00; // correct?
-}
-
-void mach32_device::device_reset()
-{
- ati_vga_device::device_reset();
-}
-
-void mach32_device::ati_define_video_mode()
-{
- uint16_t config = m_8514a->get_ext_config();
-
- if(ati.ext_reg[0x30] & 0x20)
- {
- if(m_8514a->has_display_mode_changed())
- {
- svga.rgb8_en = 0;
- svga.rgb15_en = 0;
- svga.rgb16_en = 0;
- svga.rgb32_en = 0;
-
- switch(config & 0x0030) // pixel depth
- {
- case 0x0000:
- break;
- case 0x0010:
- svga.rgb8_en = 1;
- break;
- case 0x0020:
- svga.rgb15_en = 1;
- break;
- case 0x0030:
- svga.rgb32_en = 1;
- break;
- }
- }
- }
- else
- {
- ati_vga_device::ati_define_video_mode();
- return;
- }
-
- set_dot_clock();
-}
-
-uint16_t mach32_device::offset()
-{
- if(get_video_depth() >= 15)
- return ati_vga_device::offset() << 1;
- return ati_vga_device::offset();
-}
-
-uint32_t mach32_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
-{
- ati_vga_device::screen_update(screen,bitmap,cliprect);
- uint8_t depth = get_video_depth();
-
- if(!m_cursor_enable)
- return 0;
-
- uint32_t src = (m_cursor_address & 0x000fffff) << 2;
-
- uint32_t colour0, colour1;
- if(depth == 8)
- {
- colour0 = pen(m_cursor_colour0_b);
- colour1 = pen(m_cursor_colour1_b);
- }
- else // 16/24/32bpp
- {
- colour0 = (m_cursor_colour0_r << 16) | (m_cursor_colour0_g << 8) | (m_cursor_colour0_b);
- colour1 = (m_cursor_colour1_r << 16) | (m_cursor_colour1_g << 8) | (m_cursor_colour1_b);
- }
-
- // draw hardware pointer (64x64 max)
- for(uint8_t y=0;y<64;y++)
- {
- uint32_t *dst = &bitmap.pix(m_cursor_vertical + y, m_cursor_horizontal);
- for(uint8_t x=0;x<64;x+=8)
- {
- uint16_t const bits = (vga.memory[(src+0) % vga.svga_intf.vram_size] | ((vga.memory[(src+1) % vga.svga_intf.vram_size]) << 8));
-
- for(uint8_t z=0;z<8;z++)
- {
- if(((z + x) > (m_cursor_offset_horizontal-1)) && (y < (63 - m_cursor_offset_vertical)))
- {
- uint8_t const val = (bits >> (z*2)) & 0x03;
- switch(val)
- {
- case 0: // cursor colour 0
- *dst = colour0;
- break;
- case 1: // cursor colour 1
- *dst = colour1;
- break;
- case 2: // transparent
- break;
- case 3: // complement
- *dst = ~(*dst);
- break;
- }
- dst++;
- }
- }
- src+=2;
- }
- }
-
- return 0;
-}
-
-// mach32 Hardware Pointer
-void mach32_device::mach32_cursor_l_w(offs_t offset, uint16_t data)
-{
- if(offset == 1)
- m_cursor_address = (m_cursor_address & 0xf0000) | data;
- if(LOG_MACH32) logerror("mach32 HW pointer data address: %05x",m_cursor_address);
-}
-
-void mach32_device::mach32_cursor_h_w(offs_t offset, uint16_t data)
-{
- if(offset == 1)
- {
- m_cursor_address = (m_cursor_address & 0x0ffff) | ((data & 0x000f) << 16);
- m_cursor_enable = data & 0x8000;
- if(LOG_MACH32) logerror("mach32 HW pointer data address: %05x",m_cursor_address);
- }
-}
-
-void mach32_device::mach32_cursor_pos_h(offs_t offset, uint16_t data)
-{
- if(offset == 1)
- m_cursor_horizontal = data & 0x07ff;
-}
-
-void mach32_device::mach32_cursor_pos_v(offs_t offset, uint16_t data)
-{
- if(offset == 1)
- m_cursor_vertical = data & 0x0fff;
-}
-
-void mach32_device::mach32_cursor_colour_b_w(offs_t offset, uint16_t data)
-{
- if(offset == 1)
- {
- m_cursor_colour0_b = data & 0xff;
- m_cursor_colour1_b = data >> 8;
- if(LOG_MACH32) logerror("Mach32: HW Cursor Colour Blue write RGB: 0: %02x %02x %02x 1: %02x %02x %02x\n"
- ,m_cursor_colour0_r,m_cursor_colour0_g,m_cursor_colour0_b,m_cursor_colour1_r,m_cursor_colour1_g,m_cursor_colour1_b);
- }
-}
-
-void mach32_device::mach32_cursor_colour_0_w(offs_t offset, uint16_t data)
-{
- if(offset == 1)
- {
- m_cursor_colour0_g = data & 0xff;
- m_cursor_colour0_r = data >> 8;
- if(LOG_MACH32) logerror("Mach32: HW Cursor Colour 0 write RGB: %02x %02x %02x\n",m_cursor_colour0_r,m_cursor_colour0_g,m_cursor_colour0_b);
- }
-}
-
-void mach32_device::mach32_cursor_colour_1_w(offs_t offset, uint16_t data)
-{
- if(offset == 1)
- {
- m_cursor_colour1_g = data & 0xff;
- m_cursor_colour1_r = data >> 8;
- if(LOG_MACH32) logerror("Mach32: HW Cursor Colour 1 write RGB: %02x %02x %02x\n",m_cursor_colour1_r,m_cursor_colour1_g,m_cursor_colour1_b);
- }
-}
-
-void mach32_device::mach32_cursor_offset_w(offs_t offset, uint16_t data, uint16_t mem_mask)
-{
- if(offset == 1)
- {
- if(ACCESSING_BITS_0_7)
- m_cursor_offset_horizontal = data & 0x00ff;
- if(ACCESSING_BITS_8_15)
- m_cursor_offset_vertical = data >> 8;
- if(LOG_MACH32) logerror("Mach32: HW Cursor Offset write H:%i V:%i\n",m_cursor_offset_horizontal,m_cursor_offset_vertical);
- }
-}
-
-/*
- * mach64
- */
-
-// 8514/A device
-mach64_8514a_device::mach64_8514a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : mach64_8514a_device(mconfig, ATIMACH64_8514A, tag, owner, clock)
-{
-}
-
-mach64_8514a_device::mach64_8514a_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
- : mach32_8514a_device(mconfig, type, tag, owner, clock)
-{
-}
-
-
-// SVGA device
-mach64_device::mach64_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : mach64_device(mconfig, ATIMACH64, tag, owner, clock)
-{
-}
-
-mach64_device::mach64_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
- : mach32_device(mconfig, type, tag, owner, clock), m_8514a(*this, "8514a")
-{
-}
-
-void mach64_device::device_add_mconfig(machine_config &config)
-{
- ATIMACH64_8514A(config, "8514a", 0).set_vga(DEVICE_SELF);
- EEPROM_93C56_16BIT(config, "ati_eeprom");
-}
-
-void mach64_8514a_device::device_start()
-{
- mach32_8514a_device::device_start();
- // 017h 68800-AX
- // 177h 68800-LX
- // 2F7h 68800-6
- // The 68800-3 appears to return 0 for this field (undocumented)
- m_chip_ID = 0x0000; // value is unknown for mach64
- m_membounds = 0;
-}
-
-void mach64_8514a_device::device_reset()
-{
-}
-
-void mach64_device::device_start()
-{
- mach32_device::device_start();
-}
-
-void mach64_device::device_reset()
-{
- mach32_device::device_reset();
-}
diff --git a/src/devices/bus/isa/mach32.h b/src/devices/bus/isa/mach32.h
deleted file mode 100644
index 38b4f673530..00000000000
--- a/src/devices/bus/isa/mach32.h
+++ /dev/null
@@ -1,233 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Barry Rodewald
-/*
- * mach32.h
- *
- * Created on: 16/05/2014
- */
-
-#ifndef MAME_BUS_ISA_MACH32_H
-#define MAME_BUS_ISA_MACH32_H
-
-#pragma once
-
-#include "video/pc_vga.h"
-#include "machine/eepromser.h"
-
-#define LOG_MACH32 1
-
-// 8514/A module of the Mach32
-class mach32_8514a_device : public mach8_device
-{
-public:
- // construction/destruction
- mach32_8514a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- uint16_t mach32_chipid_r() { return m_chip_ID; }
- uint16_t mach32_mem_boundary_r() { return m_membounds; }
- void mach32_mem_boundary_w(uint16_t data) { m_membounds = data; if(data & 0x10) logerror("ATI: Unimplemented memory boundary activated."); }
- void mach32_ge_ext_config_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
-
- uint16_t mach32_config1_r();
- void mach32_horz_overscan_w(uint16_t data) {} // TODO
- uint16_t mach32_ext_ge_r() { return 0x0000; } // TODO
-
- bool has_display_mode_changed() { if(display_mode_change) { display_mode_change = false; return true; } else return false; }
-
-protected:
- mach32_8514a_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void device_start() override;
- virtual void device_reset() override;
-
- uint16_t m_chip_ID;
- uint16_t m_membounds;
- bool display_mode_change;
-
-};
-
-// main SVGA device
-class mach32_device : public ati_vga_device
-{
-public:
- // construction/destruction
- mach32_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) override;
-
- required_device<mach32_8514a_device> m_8514a; // provides accelerated 2D drawing, derived from the Mach8 device
-
- // map 8514/A functions to 8514/A module
- uint16_t mach8_ec0_r() { return m_8514a->mach8_ec0_r(); }
- void mach8_ec0_w(uint16_t data) { m_8514a->mach8_ec0_w(data); }
- uint16_t mach8_ec1_r() { return m_8514a->mach8_ec1_r(); }
- void mach8_ec1_w(uint16_t data) { m_8514a->mach8_ec1_w(data); }
- uint16_t mach8_ec2_r() { return m_8514a->mach8_ec2_r(); }
- void mach8_ec2_w(uint16_t data) { m_8514a->mach8_ec2_w(data); }
- uint16_t mach8_ec3_r() { return m_8514a->mach8_ec3_r(); }
- void mach8_ec3_w(uint16_t data) { m_8514a->mach8_ec3_w(data); }
- uint16_t mach8_ext_fifo_r() { return m_8514a->mach8_ext_fifo_r(); }
- void mach8_linedraw_index_w(uint16_t data) { m_8514a->mach8_linedraw_index_w(data); }
- uint16_t mach8_bresenham_count_r() { return m_8514a->mach8_bresenham_count_r(); }
- void mach8_bresenham_count_w(uint16_t data) { m_8514a->mach8_bresenham_count_w(data); }
- void mach8_linedraw_w(uint16_t data) { m_8514a->mach8_linedraw_w(data); }
- uint16_t mach8_linedraw_r() { return m_8514a->mach8_linedraw_r(); }
- uint16_t mach8_scratch0_r() { return m_8514a->mach8_scratch0_r(); }
- void mach8_scratch0_w(uint16_t data) { m_8514a->mach8_scratch0_w(data); }
- uint16_t mach8_scratch1_r() { return m_8514a->mach8_scratch1_r(); }
- void mach8_scratch1_w(uint16_t data) { m_8514a->mach8_scratch1_w(data); }
- void mach8_crt_pitch_w(uint16_t data) { m_8514a->mach8_crt_pitch_w(data); }
- uint16_t mach8_config1_r() { return m_8514a->mach8_config1_r(); }
- uint16_t mach8_config2_smo_r() { return m_8514a->mach8_config2_r(); }
- uint16_t mach8_config2_sm_r(offs_t offset) { return m_8514a->mach8_config2_r(); }
- uint16_t mach8_sourcex_r() { return m_8514a->mach8_sourcex_r(); }
- uint16_t mach8_sourcey_r() { return m_8514a->mach8_sourcey_r(); }
- void mach8_ext_leftscissor_w(uint16_t data) { m_8514a->mach8_ext_leftscissor_w(data); }
- void mach8_ext_topscissor_w(uint16_t data) { m_8514a->mach8_ext_topscissor_w(data); }
- void mach8_ge_offset_l_w(uint16_t data) { m_8514a->mach8_ge_offset_l_w(data); }
- void mach8_ge_offset_h_w(uint16_t data) { m_8514a->mach8_ge_offset_h_w(data); }
- void mach8_scan_x_w(uint16_t data) { m_8514a->mach8_scan_x_w(data); }
- void mach8_dp_config_w(uint16_t data) { m_8514a->mach8_dp_config_w(data); }
- void mach8_ge_pitch_w(uint16_t data) { m_8514a->mach8_ge_pitch_w(data); }
- uint16_t mach8_ge_ext_config_r() { return m_8514a->mach8_ge_ext_config_r(); }
- void mach8_patt_data_w(uint16_t data) { m_8514a->mach8_patt_data_w(data); }
-
- uint16_t ibm8514_vtotal_r() { return m_8514a->ibm8514_vtotal_r(); }
- void ibm8514_vtotal_w(uint16_t data) { m_8514a->ibm8514_vtotal_w(data); }
- uint16_t ibm8514_htotal_r() { return m_8514a->ibm8514_htotal_r(); }
- void ibm8514_htotal_w(offs_t offset, uint8_t data) { m_8514a->ibm8514_htotal_w(offset,data); }
- uint16_t ibm8514_vdisp_r() { return m_8514a->ibm8514_vdisp_r(); }
- void ibm8514_vdisp_w(uint16_t data) { m_8514a->ibm8514_vdisp_w(data); }
- uint16_t ibm8514_vsync_r() { return m_8514a->ibm8514_vsync_r(); }
- void ibm8514_vsync_w(uint16_t data) { m_8514a->ibm8514_vsync_w(data); }
- uint16_t ibm8514_substatus_r() { return m_8514a->ibm8514_substatus_r(); }
- void ibm8514_subcontrol_w(uint16_t data) { m_8514a->ibm8514_subcontrol_w(data); }
- uint16_t ibm8514_subcontrol_r() { return m_8514a->ibm8514_subcontrol_r(); }
- uint16_t ibm8514_currentx_r() { return m_8514a->ibm8514_currentx_r(); }
- void ibm8514_currentx_w(uint16_t data) { m_8514a->ibm8514_currentx_w(data); }
- uint16_t ibm8514_currenty_r() { return m_8514a->ibm8514_currenty_r(); }
- void ibm8514_currenty_w(uint16_t data) { m_8514a->ibm8514_currenty_w(data); }
- uint16_t ibm8514_desty_r() { return m_8514a->ibm8514_desty_r(); }
- void ibm8514_desty_w(uint16_t data) { m_8514a->ibm8514_desty_w(data); }
- uint16_t ibm8514_destx_r() { return m_8514a->ibm8514_destx_r(); }
- void ibm8514_destx_w(uint16_t data) { m_8514a->ibm8514_destx_w(data); }
- uint16_t ibm8514_line_error_r() { return m_8514a->ibm8514_line_error_r(); }
- void ibm8514_line_error_w(uint16_t data) { m_8514a->ibm8514_line_error_w(data); }
- uint16_t ibm8514_width_r() { return m_8514a->ibm8514_width_r(); }
- void ibm8514_width_w(uint16_t data) { m_8514a->ibm8514_width_w(data); }
- uint16_t ibm8514_gpstatus_r() { return m_8514a->ibm8514_gpstatus_r(); }
- void ibm8514_cmd_w(uint16_t data) { m_8514a->ibm8514_cmd_w(data); }
- uint16_t ibm8514_ssv_r() { return m_8514a->ibm8514_ssv_r(); }
- void ibm8514_ssv_w(uint16_t data) { m_8514a->ibm8514_ssv_w(data); }
- uint16_t ibm8514_fgcolour_r() { return m_8514a->ibm8514_fgcolour_r(); }
- void ibm8514_fgcolour_w(uint16_t data) { m_8514a->ibm8514_fgcolour_w(data); }
- uint16_t ibm8514_bgcolour_r() { return m_8514a->ibm8514_bgcolour_r(); }
- void ibm8514_bgcolour_w(uint16_t data) { m_8514a->ibm8514_bgcolour_w(data); }
- uint16_t ibm8514_read_mask_r() { return m_8514a->ibm8514_read_mask_r(); }
- void ibm8514_read_mask_w(uint16_t data) { m_8514a->ibm8514_read_mask_w(data); }
- uint16_t ibm8514_write_mask_r() { return m_8514a->ibm8514_write_mask_r(); }
- void ibm8514_write_mask_w(uint16_t data) { m_8514a->ibm8514_write_mask_w(data); }
- uint16_t ibm8514_backmix_r() { return m_8514a->ibm8514_backmix_r(); }
- void ibm8514_backmix_w(uint16_t data) { m_8514a->ibm8514_backmix_w(data); }
- uint16_t ibm8514_foremix_r() { return m_8514a->ibm8514_foremix_r(); }
- void ibm8514_foremix_w(uint16_t data) { m_8514a->ibm8514_foremix_w(data); }
- uint16_t ibm8514_multifunc_r() { return m_8514a->ibm8514_multifunc_r(); }
- void ibm8514_multifunc_w(uint16_t data) { m_8514a->ibm8514_multifunc_w(data); }
- uint16_t ibm8514_pixel_xfer_r(offs_t offset) { return m_8514a->ibm8514_pixel_xfer_r(offset); }
- void mach8_pixel_xfer_w(offs_t offset, uint16_t data) { m_8514a->mach8_pixel_xfer_w(offset, data); }
- void mach8_advfunc_w(uint16_t data) { m_8514a->mach8_advfunc_w(data); }
-
- uint16_t mach32_chipid_r() { return m_8514a->mach32_chipid_r(); }
- uint16_t mach8_clksel_r() { return m_8514a->mach8_clksel_r(); }
- void mach8_clksel_w(uint16_t data) { m_8514a->mach8_clksel_w(data); } // read only on the mach8
- uint16_t mach32_mem_boundary_r() { return m_8514a->mach32_mem_boundary_r(); }
- void mach32_mem_boundary_w(uint16_t data) { m_8514a->mach32_mem_boundary_w(data); } // read only on the mach8
- uint8_t mach32_status_r(offs_t offset) { return m_8514a->ibm8514_status_r(offset); }
- uint16_t mach32_config1_smo_r() { return m_8514a->mach32_config1_r(); }
- uint16_t mach32_config1_sm_r(offs_t offset) { return m_8514a->mach32_config1_r(); }
- void mach32_horz_overscan_w(uint16_t data) { m_8514a->mach32_horz_overscan_w(data); }
- void mach32_ge_ext_config_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) { m_8514a->mach32_ge_ext_config_w(offset, data, mem_mask); ati_define_video_mode(); }
- uint16_t mach32_ext_ge_r() { return m_8514a->mach32_ext_ge_r(); }
- uint16_t mach32_readonly_s_r(offs_t offset, uint16_t mem_mask) { return 0; }
- uint16_t mach32_readonly_sm_r(offs_t offset) { return 0; }
- uint16_t mach32_readonly_smo_r() { return 0; }
- void mach32_cursor_pos_h(offs_t offset, uint16_t data);
- void mach32_cursor_pos_v(offs_t offset, uint16_t data);
- void mach32_cursor_colour_b_w(offs_t offset, uint16_t data);
- void mach32_cursor_colour_0_w(offs_t offset, uint16_t data);
- void mach32_cursor_colour_1_w(offs_t offset, uint16_t data);
- void mach32_cursor_l_w(offs_t offset, uint16_t data);
- void mach32_cursor_h_w(offs_t offset, uint16_t data);
- void mach32_cursor_offset_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
-
-protected:
- mach32_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
-
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_add_mconfig(machine_config &config) override;
- virtual void ati_define_video_mode() override;
- virtual uint16_t offset() override;
-
- // hardware pointer
- bool m_cursor_enable;
- uint32_t m_cursor_address;
- uint16_t m_cursor_horizontal;
- uint16_t m_cursor_vertical;
- uint8_t m_cursor_colour0_b;
- uint8_t m_cursor_colour0_r;
- uint8_t m_cursor_colour0_g;
- uint8_t m_cursor_colour1_b;
- uint8_t m_cursor_colour1_r;
- uint8_t m_cursor_colour1_g;
- uint8_t m_cursor_offset_horizontal;
- uint8_t m_cursor_offset_vertical;
-
-};
-
-/*
- * ATi mach64
- */
-
-// 8514/A module of the Mach64
-class mach64_8514a_device : public mach32_8514a_device
-{
-public:
- // construction/destruction
- mach64_8514a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- mach64_8514a_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void device_start() override;
- virtual void device_reset() override;
-};
-
-// main SVGA device
-class mach64_device : public mach32_device
-{
-public:
- // construction/destruction
- mach64_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- void mach64_config1_w(uint16_t data) { } // why does the mach64 BIOS write to these, they are read only on the mach32 and earlier
- void mach64_config2_w(uint16_t data) { }
-
-protected:
- mach64_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
-
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_add_mconfig(machine_config &config) override;
-
- required_device<mach64_8514a_device> m_8514a; // provides accelerated 2D drawing, derived from the Mach8 device
-};
-
-// device type definition
-DECLARE_DEVICE_TYPE(ATIMACH32, mach32_device)
-DECLARE_DEVICE_TYPE(ATIMACH32_8514A, mach32_8514a_device)
-DECLARE_DEVICE_TYPE(ATIMACH64, mach64_device)
-DECLARE_DEVICE_TYPE(ATIMACH64_8514A, mach64_8514a_device)
-
-#endif // MAME_BUS_ISA_MACH32_H
diff --git a/src/devices/bus/isa/mc1502_fdc.cpp b/src/devices/bus/isa/mc1502_fdc.cpp
index ad1c1bd8b8c..b2629e97946 100644
--- a/src/devices/bus/isa/mc1502_fdc.cpp
+++ b/src/devices/bus/isa/mc1502_fdc.cpp
@@ -10,7 +10,6 @@
#include "mc1502_fdc.h"
#include "cpu/i86/i86.h"
-#include "formats/pc_dsk.h"
//**************************************************************************
@@ -130,7 +129,7 @@ uint8_t mc1502_fdc_device::mc1502_wd17xx_motor_r()
return motor_on;
}
-WRITE_LINE_MEMBER(mc1502_fdc_device::mc1502_fdc_irq_drq)
+void mc1502_fdc_device::mc1502_fdc_irq_drq(int state)
{
if (state)
m_isa->set_ready(CLEAR_LINE); // deassert I/O CH RDY
diff --git a/src/devices/bus/isa/mc1502_fdc.h b/src/devices/bus/isa/mc1502_fdc.h
index 45fde02945d..a589ca0c810 100644
--- a/src/devices/bus/isa/mc1502_fdc.h
+++ b/src/devices/bus/isa/mc1502_fdc.h
@@ -45,7 +45,7 @@ protected:
virtual const tiny_rom_entry *device_rom_region() const override;
private:
- DECLARE_WRITE_LINE_MEMBER(mc1502_fdc_irq_drq);
+ void mc1502_fdc_irq_drq(int state);
required_device<fd1793_device> m_fdc;
int motor_on;
diff --git a/src/devices/bus/isa/mcd.cpp b/src/devices/bus/isa/mcd.cpp
index 9bb8b82a5da..085ab3676b9 100644
--- a/src/devices/bus/isa/mcd.cpp
+++ b/src/devices/bus/isa/mcd.cpp
@@ -3,9 +3,11 @@
#include "emu.h"
#include "mcd.h"
-#include "coreutil.h"
#include "speaker.h"
+#include "coreutil.h"
+#include "multibyte.h"
+
void mcd_isa_device::map(address_map &map)
{
map(0x0, 0x0).rw(FUNC(mcd_isa_device::data_r), FUNC(mcd_isa_device::cmd_w));
@@ -29,6 +31,7 @@ void mcd_isa_device::device_add_mconfig(machine_config &config)
CDDA(config, m_cdda);
m_cdda->add_route(0, "lheadphone", 1.0);
m_cdda->add_route(1, "rheadphone", 1.0);
+ m_cdda->set_cdrom_tag(*this);
}
//-------------------------------------------------
@@ -84,7 +87,6 @@ bool mcd_isa_device::read_sector(bool first)
if(m_cdrom_handle->get_track_type(m_cdrom_handle->get_track(lba)) == cdrom_file::CD_TRACK_AUDIO)
{
m_cdda->stop_audio();
- m_cdda->set_cdrom(m_cdrom_handle);
m_cdda->start_audio(lba, m_readcount);
return true;
}
@@ -165,8 +167,8 @@ uint16_t mcd_isa_device::dack16_r(int line)
uint16_t ret = 0;
if(m_buf_idx < 2351)
{
- ret = m_buf[m_buf_idx++];
- ret |= (m_buf[m_buf_idx++] << 8);
+ ret = get_u16le(&m_buf[m_buf_idx]);
+ m_buf_idx += 2;
}
m_buf_count -= 2;
if(!m_buf_count)
@@ -275,12 +277,8 @@ void mcd_isa_device::cmd_w(uint8_t data)
uint32_t first = cdrom_file::lba_to_msf(150), last = cdrom_file::lba_to_msf(m_cdrom_handle->get_track_start(0xaa));
m_cmdbuf[1] = 1;
m_cmdbuf[2] = dec_2_bcd(m_cdrom_handle->get_last_track());
- m_cmdbuf[3] = (last >> 16) & 0xff;
- m_cmdbuf[4] = (last >> 8) & 0xff;
- m_cmdbuf[5] = last & 0xff;
- m_cmdbuf[6] = (first >> 16) & 0xff;
- m_cmdbuf[7] = (first >> 8) & 0xff;
- m_cmdbuf[8] = first & 0xff;
+ put_u24be(&m_cmdbuf[3], last);
+ put_u24be(&m_cmdbuf[6], first);
m_cmdbuf[9] = 0;
m_cmdbuf_count = 10;
m_readcount = 0;
@@ -301,13 +299,9 @@ void mcd_isa_device::cmd_w(uint8_t data)
m_cmdbuf[1] = (m_cdrom_handle->get_adr_control(m_curtoctrk) << 4) & 0xf0;
m_cmdbuf[2] = 0; // track num except when reading toc
m_cmdbuf[3] = dec_2_bcd(m_curtoctrk + 1); // index
- m_cmdbuf[4] = (len >> 16) & 0xff;
- m_cmdbuf[5] = (len >> 8) & 0xff;
- m_cmdbuf[6] = len & 0xff;
+ put_u24be(&m_cmdbuf[4], len);
m_cmdbuf[7] = 0;
- m_cmdbuf[8] = (start >> 16) & 0xff;
- m_cmdbuf[9] = (start >> 8) & 0xff;
- m_cmdbuf[10] = start & 0xff;
+ put_u24be(&m_cmdbuf[8], start);
if(m_curtoctrk >= tracks)
m_curtoctrk = 0;
else if(m_mode & MODE_GET_TOC)
diff --git a/src/devices/bus/isa/mcd.h b/src/devices/bus/isa/mcd.h
index 4c2b7a0e636..b6a2fce564d 100644
--- a/src/devices/bus/isa/mcd.h
+++ b/src/devices/bus/isa/mcd.h
@@ -6,7 +6,7 @@
#pragma once
#include "isa.h"
-#include "imagedev/chd_cd.h"
+#include "imagedev/cdromimg.h"
#include "sound/cdda.h"
//**************************************************************************
diff --git a/src/devices/bus/isa/mda.cpp b/src/devices/bus/isa/mda.cpp
index e3ff8e90f99..77ac7d6028e 100644
--- a/src/devices/bus/isa/mda.cpp
+++ b/src/devices/bus/isa/mda.cpp
@@ -96,7 +96,7 @@ static GFXDECODE_START( gfx_pcmda )
GFXDECODE_END
-WRITE_LINE_MEMBER( isa8_mda_device::pc_cpu_line )
+void isa8_mda_device::pc_cpu_line(int state)
{
m_isa->irq7_w(state);
}
@@ -403,13 +403,13 @@ MC6845_UPDATE_ROW( isa8_hercules_device::crtc_update_row )
}
-WRITE_LINE_MEMBER( isa8_mda_device::hsync_changed )
+void isa8_mda_device::hsync_changed(int state)
{
m_hsync = state ? 1 : 0;
}
-WRITE_LINE_MEMBER( isa8_mda_device::vsync_changed )
+void isa8_mda_device::vsync_changed(int state)
{
m_vsync = state ? 0x80 : 0;
if ( state )
diff --git a/src/devices/bus/isa/mda.h b/src/devices/bus/isa/mda.h
index e16c80e8ce1..97e08dfcf1b 100644
--- a/src/devices/bus/isa/mda.h
+++ b/src/devices/bus/isa/mda.h
@@ -31,8 +31,8 @@ public:
virtual uint8_t status_r();
virtual void mode_control_w(uint8_t data);
- DECLARE_WRITE_LINE_MEMBER(hsync_changed);
- DECLARE_WRITE_LINE_MEMBER(vsync_changed);
+ void hsync_changed(int state);
+ void vsync_changed(int state);
virtual MC6845_UPDATE_ROW( crtc_update_row );
@@ -51,7 +51,7 @@ protected:
optional_device<pc_lpt_device> m_lpt;
private:
- WRITE_LINE_MEMBER(pc_cpu_line);
+ void pc_cpu_line(int state);
MC6845_UPDATE_ROW( mda_text_inten_update_row );
MC6845_UPDATE_ROW( mda_text_blink_update_row );
diff --git a/src/devices/bus/isa/mpu401.cpp b/src/devices/bus/isa/mpu401.cpp
index 7f6a28b87b4..db482947789 100644
--- a/src/devices/bus/isa/mpu401.cpp
+++ b/src/devices/bus/isa/mpu401.cpp
@@ -34,7 +34,7 @@ DIP-SWs
1 irq7
*/
-WRITE_LINE_MEMBER( isa8_mpu401_device::mpu_irq_out )
+void isa8_mpu401_device::mpu_irq_out(int state)
{
}
diff --git a/src/devices/bus/isa/mpu401.h b/src/devices/bus/isa/mpu401.h
index 89974be7b84..74054aad765 100644
--- a/src/devices/bus/isa/mpu401.h
+++ b/src/devices/bus/isa/mpu401.h
@@ -32,7 +32,7 @@ protected:
private:
// called back by the MPU401 core to set the IRQ line state
- DECLARE_WRITE_LINE_MEMBER(mpu_irq_out);
+ void mpu_irq_out(int state);
required_device<mpu401_device> m_mpu401;
};
diff --git a/src/devices/bus/isa/mufdc.cpp b/src/devices/bus/isa/mufdc.cpp
index 2a078f812f9..5c9ebd84923 100644
--- a/src/devices/bus/isa/mufdc.cpp
+++ b/src/devices/bus/isa/mufdc.cpp
@@ -18,7 +18,6 @@
#include "mufdc.h"
#include "formats/naslite_dsk.h"
-#include "formats/pc_dsk.h"
//**************************************************************************
@@ -176,12 +175,12 @@ uint8_t mufdc_device::fdc_input_r()
return ~m_config->read();
}
-WRITE_LINE_MEMBER( mufdc_device::fdc_irq_w )
+void mufdc_device::fdc_irq_w(int state)
{
m_isa->irq6_w(state ? ASSERT_LINE : CLEAR_LINE);
}
-WRITE_LINE_MEMBER( mufdc_device::fdc_drq_w )
+void mufdc_device::fdc_drq_w(int state)
{
m_isa->drq2_w(state ? ASSERT_LINE : CLEAR_LINE);
}
diff --git a/src/devices/bus/isa/mufdc.h b/src/devices/bus/isa/mufdc.h
index b746d135003..80b3ae786fb 100644
--- a/src/devices/bus/isa/mufdc.h
+++ b/src/devices/bus/isa/mufdc.h
@@ -54,8 +54,8 @@ private:
static void floppy_formats(format_registration &fr);
uint8_t fdc_input_r();
- DECLARE_WRITE_LINE_MEMBER( fdc_irq_w );
- DECLARE_WRITE_LINE_MEMBER( fdc_drq_w );
+ void fdc_irq_w(int state);
+ void fdc_drq_w(int state);
required_device<mcs3201_device> m_fdc;
required_ioport m_config;
diff --git a/src/devices/bus/isa/myb3k_com.cpp b/src/devices/bus/isa/myb3k_com.cpp
index b500d95b993..e4a8ce30ca8 100644
--- a/src/devices/bus/isa/myb3k_com.cpp
+++ b/src/devices/bus/isa/myb3k_com.cpp
@@ -123,7 +123,7 @@ void isa8_myb3k_com_device::device_reset()
// pit_rxc - write receive clock if pit is selected source
//-----------------------------------------------------------
#define CLK_SEL 0x80
-WRITE_LINE_MEMBER(isa8_myb3k_com_device::pit_rxc)
+void isa8_myb3k_com_device::pit_rxc(int state)
{
if ((m_control & CLK_SEL) != 0)
{
@@ -134,7 +134,7 @@ WRITE_LINE_MEMBER(isa8_myb3k_com_device::pit_rxc)
//------------------------------------------------------------
// pit_txc - write transmit clock if pit is selected source
//------------------------------------------------------------
-WRITE_LINE_MEMBER(isa8_myb3k_com_device::pit_txc)
+void isa8_myb3k_com_device::pit_txc(int state)
{
if ((m_control & CLK_SEL) != 0)
{
@@ -146,7 +146,7 @@ WRITE_LINE_MEMBER(isa8_myb3k_com_device::pit_txc)
// rem_rxc - write receive clock if remote clock is selected
// source, eg for synchronous modes
//-----------------------------------------------------------
-WRITE_LINE_MEMBER(isa8_myb3k_com_device::rem_rxc)
+void isa8_myb3k_com_device::rem_rxc(int state)
{
if ((m_control & CLK_SEL) == 0)
{
@@ -158,7 +158,7 @@ WRITE_LINE_MEMBER(isa8_myb3k_com_device::rem_rxc)
// rem_txc - write transmit clock if remote cloc is selected
// source, eg for synchronous modes
//------------------------------------------------------------
-WRITE_LINE_MEMBER(isa8_myb3k_com_device::rem_txc)
+void isa8_myb3k_com_device::rem_txc(int state)
{
if ((m_control & CLK_SEL) == 0)
{
@@ -169,7 +169,7 @@ WRITE_LINE_MEMBER(isa8_myb3k_com_device::rem_txc)
//------------------------------------------------
// com_int_rx - signal selected interrup on ISA bus
//------------------------------------------------
-WRITE_LINE_MEMBER(isa8_myb3k_com_device::com_int_rx)
+void isa8_myb3k_com_device::com_int_rx(int state)
{
m_irq_rx = state;
com_int();
@@ -178,7 +178,7 @@ WRITE_LINE_MEMBER(isa8_myb3k_com_device::com_int_rx)
//------------------------------------------------
// com_int_tx - signal selected interrup on ISA bus
//------------------------------------------------
-WRITE_LINE_MEMBER(isa8_myb3k_com_device::com_int_tx)
+void isa8_myb3k_com_device::com_int_tx(int state)
{
m_irq_tx = state;
com_int();
@@ -202,7 +202,7 @@ void isa8_myb3k_com_device::com_int()
// dcd_w - DCD line value gated by a LS368
//------------------------------------------------
#define DCD_BIT 0x02
-WRITE_LINE_MEMBER(isa8_myb3k_com_device::dcd_w)
+void isa8_myb3k_com_device::dcd_w(int state)
{
if (state == ASSERT_LINE)
{
@@ -218,7 +218,7 @@ WRITE_LINE_MEMBER(isa8_myb3k_com_device::dcd_w)
// ri_w - RI line value gated by a LS368
//------------------------------------------------
#define RI_BIT 0x01
-WRITE_LINE_MEMBER(isa8_myb3k_com_device::ri_w)
+void isa8_myb3k_com_device::ri_w(int state)
{
if (state == ASSERT_LINE)
{
diff --git a/src/devices/bus/isa/myb3k_com.h b/src/devices/bus/isa/myb3k_com.h
index bdd591b5291..0dd75f0ec60 100644
--- a/src/devices/bus/isa/myb3k_com.h
+++ b/src/devices/bus/isa/myb3k_com.h
@@ -39,14 +39,14 @@ public:
// construction/destruction
isa8_myb3k_com_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_WRITE_LINE_MEMBER(pit_txc);
- DECLARE_WRITE_LINE_MEMBER(pit_rxc);
- DECLARE_WRITE_LINE_MEMBER(rem_txc);
- DECLARE_WRITE_LINE_MEMBER(rem_rxc);
- DECLARE_WRITE_LINE_MEMBER(com_int_rx);
- DECLARE_WRITE_LINE_MEMBER(com_int_tx);
- DECLARE_WRITE_LINE_MEMBER(dcd_w);
- DECLARE_WRITE_LINE_MEMBER(ri_w);
+ void pit_txc(int state);
+ void pit_rxc(int state);
+ void rem_txc(int state);
+ void rem_rxc(int state);
+ void com_int_rx(int state);
+ void com_int_tx(int state);
+ void dcd_w(int state);
+ void ri_w(int state);
void dce_control(uint8_t data);
uint8_t dce_status();
diff --git a/src/devices/bus/isa/myb3k_fdc.cpp b/src/devices/bus/isa/myb3k_fdc.cpp
index 1ca69a19be5..49b142d66bc 100644
--- a/src/devices/bus/isa/myb3k_fdc.cpp
+++ b/src/devices/bus/isa/myb3k_fdc.cpp
@@ -24,10 +24,7 @@
#include "emu.h"
#include "myb3k_fdc.h"
-#include "formats/pc_dsk.h"
-#include "formats/imd_dsk.h"
-//#define LOG_GENERAL (1U << 0) //defined in logmacro.h already
#define LOG_READ (1U << 1)
#define LOG_CMD (1U << 2)
@@ -164,7 +161,7 @@ void isa8_myb3k_fdc471x_device_base::device_start()
//-------------------------------------------------
// irq_w - signal interrupt request to ISA bus
//-------------------------------------------------
-WRITE_LINE_MEMBER( isa8_myb3k_fdc471x_device_base::irq_w )
+void isa8_myb3k_fdc471x_device_base::irq_w(int state)
{
LOG("%s: %d\n", FUNCNAME, state);
m_isa->irq6_w(state ? ASSERT_LINE : CLEAR_LINE);
@@ -173,7 +170,7 @@ WRITE_LINE_MEMBER( isa8_myb3k_fdc471x_device_base::irq_w )
//-------------------------------------------------
// drq_w - signal dma request to ISA bus
//-------------------------------------------------
-WRITE_LINE_MEMBER( isa8_myb3k_fdc471x_device_base::drq_w )
+void isa8_myb3k_fdc471x_device_base::drq_w(int state)
{
LOG("%s: %d\n", FUNCNAME, state);
diff --git a/src/devices/bus/isa/myb3k_fdc.h b/src/devices/bus/isa/myb3k_fdc.h
index b2a645423d6..c3d77fd0929 100644
--- a/src/devices/bus/isa/myb3k_fdc.h
+++ b/src/devices/bus/isa/myb3k_fdc.h
@@ -13,7 +13,6 @@
#include "isa.h"
#include "imagedev/floppy.h"
#include "machine/wd_fdc.h"
-#include "formats/imd_dsk.h"
class isa8_myb3k_fdc471x_device_base :
public device_t,
@@ -38,8 +37,8 @@ protected:
virtual uint8_t myb3k_fdc_status();
virtual void myb3k_fdc_command(uint8_t data);
- DECLARE_WRITE_LINE_MEMBER( irq_w );
- DECLARE_WRITE_LINE_MEMBER( drq_w );
+ void irq_w(int state);
+ void drq_w(int state);
required_device<wd_fdc_device_base> m_fdc;
optional_device_array<floppy_connector, 4> m_floppy_connectors;
diff --git a/src/devices/bus/isa/ne1000.cpp b/src/devices/bus/isa/ne1000.cpp
index d2234098c34..7cf08d11beb 100644
--- a/src/devices/bus/isa/ne1000.cpp
+++ b/src/devices/bus/isa/ne1000.cpp
@@ -3,6 +3,8 @@
#include "emu.h"
#include "ne1000.h"
+#include "multibyte.h"
+
DEFINE_DEVICE_TYPE(NE1000, ne1000_device, "ne1000", "NE1000 Network Adapter")
@@ -14,8 +16,8 @@ void ne1000_device::device_add_mconfig(machine_config &config)
m_dp8390->mem_write_callback().set(FUNC(ne1000_device::ne1000_mem_write));
}
-ne1000_device::ne1000_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, NE1000, tag, owner, clock),
+ne1000_device::ne1000_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, NE1000, tag, owner, clock),
device_isa8_card_interface(mconfig, *this),
m_dp8390(*this, "dp8390d"),
m_irq(0)
@@ -23,10 +25,11 @@ ne1000_device::ne1000_device(const machine_config &mconfig, const char *tag, dev
}
void ne1000_device::device_start() {
- char mac[7];
+ uint8_t mac[6];
uint32_t num = machine().rand();
memset(m_prom, 0x57, 16);
- sprintf(mac+2, "\x1b%c%c%c", (num >> 16) & 0xff, (num >> 8) & 0xff, num & 0xff);
+ mac[2] = 0x1b;
+ put_u24be(mac+3, num);
mac[0] = 0; mac[1] = 0; // avoid gcc warning
memcpy(m_prom, mac, 6);
m_dp8390->set_mac(mac);
@@ -35,7 +38,7 @@ void ne1000_device::device_start() {
}
void ne1000_device::device_reset() {
- memcpy(m_prom, m_dp8390->get_mac(), 6);
+ memcpy(m_prom, &m_dp8390->get_mac()[0], 6);
m_irq = ioport("CONFIG")->read() & 3;
}
@@ -73,7 +76,7 @@ void ne1000_device::ne1000_port_w(offs_t offset, uint8_t data) {
return;
}
-WRITE_LINE_MEMBER(ne1000_device::ne1000_irq_w) {
+void ne1000_device::ne1000_irq_w(int state) {
switch(m_irq) {
case 0:
m_isa->irq2_w(state);
diff --git a/src/devices/bus/isa/ne2000.cpp b/src/devices/bus/isa/ne2000.cpp
index 08c73b96dac..1473c043f2a 100644
--- a/src/devices/bus/isa/ne2000.cpp
+++ b/src/devices/bus/isa/ne2000.cpp
@@ -3,6 +3,8 @@
#include "emu.h"
#include "ne2000.h"
+#include "multibyte.h"
+
DEFINE_DEVICE_TYPE(NE2000, ne2000_device, "ne2000", "NE2000 Network Adapter")
@@ -14,8 +16,8 @@ void ne2000_device::device_add_mconfig(machine_config &config)
m_dp8390->mem_write_callback().set(FUNC(ne2000_device::ne2000_mem_write));
}
-ne2000_device::ne2000_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock)
- : device_t(mconfig, NE2000, tag, owner, clock),
+ne2000_device::ne2000_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock) :
+ device_t(mconfig, NE2000, tag, owner, clock),
device_isa16_card_interface(mconfig, *this),
m_dp8390(*this, "dp8390d"),
m_irq(0)
@@ -23,10 +25,11 @@ ne2000_device::ne2000_device(const machine_config& mconfig, const char* tag, dev
}
void ne2000_device::device_start() {
- char mac[7];
+ uint8_t mac[6];
uint32_t num = machine().rand();
memset(m_prom, 0x57, 16);
- sprintf(mac+2, "\x1b%c%c%c", (num >> 16) & 0xff, (num >> 8) & 0xff, num & 0xff);
+ mac[2] = 0x1b;
+ put_u24be(mac+3, num);
mac[0] = 0; mac[1] = 0; // avoid gcc warning
memcpy(m_prom, mac, 6);
m_dp8390->set_mac(mac);
@@ -35,7 +38,7 @@ void ne2000_device::device_start() {
}
void ne2000_device::device_reset() {
- memcpy(m_prom, m_dp8390->get_mac(), 6);
+ memcpy(m_prom, &m_dp8390->get_mac()[0], 6);
m_irq = ioport("CONFIG")->read() & 3;
}
@@ -83,7 +86,7 @@ void ne2000_device::ne2000_port_w(offs_t offset, uint16_t data, uint16_t mem_mas
return;
}
-WRITE_LINE_MEMBER(ne2000_device::ne2000_irq_w) {
+void ne2000_device::ne2000_irq_w(int state) {
switch(m_irq) {
case 0:
m_isa->irq2_w(state);
diff --git a/src/devices/bus/isa/np600.cpp b/src/devices/bus/isa/np600.cpp
index 5fca3ff1910..b69b6a24327 100644
--- a/src/devices/bus/isa/np600.cpp
+++ b/src/devices/bus/isa/np600.cpp
@@ -20,6 +20,7 @@ np600a3_device::np600a3_device(const machine_config &mconfig, const char *tag, d
, device_isa16_card_interface(mconfig, *this)
, m_npcpu(*this, "npcpu")
, m_lcc(*this, "lcc")
+ , m_enetaddr(*this, "enetaddr")
{
}
@@ -33,7 +34,11 @@ void np600a3_device::lcc_ca_w(u16 data)
m_lcc->ca(1);
}
-WRITE_LINE_MEMBER(np600a3_device::host_int_w)
+void np600a3_device::int1_ack_w(u8 data)
+{
+}
+
+void np600a3_device::host_int_w(int state)
{
logerror("%s: Host interrupt %s\n", machine().describe_context(), state ? "asserted" : "cleared");
}
@@ -43,6 +48,11 @@ u16 np600a3_device::status_r()
return 0;
}
+u8 np600a3_device::enetaddr_r(offs_t offset)
+{
+ return m_enetaddr[offset];
+}
+
void np600a3_device::mem_map(address_map &map)
{
map(0x00000, 0x7ffff).ram().share("netram"); // GM71256-12 x16
@@ -54,8 +64,11 @@ void np600a3_device::mem_map(address_map &map)
void np600a3_device::io_map(address_map &map)
{
map(0x0000, 0x0001).w(FUNC(np600a3_device::lcc_ca_w));
+ map(0x0010, 0x0010).w("fromhost", FUNC(generic_latch_16_device::acknowledge_w));
+ map(0x0020, 0x0020).w(FUNC(np600a3_device::int1_ack_w));
map(0x0070, 0x007f).w("bitlatch", FUNC(ls259_device::write_a0));
map(0x0080, 0x0081).r(FUNC(np600a3_device::status_r));
+ map(0x0300, 0x033f).r(FUNC(np600a3_device::enetaddr_r)).umask16(0x00ff);
}
void np600a3_device::lcc_map(address_map &map)
@@ -66,15 +79,19 @@ void np600a3_device::lcc_map(address_map &map)
void np600a3_device::device_add_mconfig(machine_config &config)
{
- I80186(config, m_npcpu, 16_MHz_XTAL);
- m_npcpu->set_addrmap(AS_PROGRAM, &np600a3_device::mem_map);
- m_npcpu->set_addrmap(AS_IO, &np600a3_device::io_map);
+ i80186_cpu_device &npcpu(I80186(config, m_npcpu, 16_MHz_XTAL));
+ npcpu.set_addrmap(AS_PROGRAM, &np600a3_device::mem_map);
+ npcpu.set_addrmap(AS_IO, &np600a3_device::io_map);
+ npcpu.tmrout0_handler().set_inputline(m_npcpu, INPUT_LINE_NMI);
ls259_device &bitlatch(LS259(config, "bitlatch")); // U28
bitlatch.q_out_cb<1>().set(FUNC(np600a3_device::host_int_w));
bitlatch.q_out_cb<4>().set(m_lcc, FUNC(i82586_device::reset_w)).invert();
- GENERIC_LATCH_16(config, "fromhost");
+ generic_latch_16_device &fromhost(GENERIC_LATCH_16(config, "fromhost"));
+ fromhost.data_pending_callback().set(m_npcpu, FUNC(i80186_cpu_device::int0_w));
+ fromhost.set_separate_acknowledge(true);
+
GENERIC_LATCH_16(config, "tohost");
I82586(config, m_lcc, 16_MHz_XTAL / 2); // clock presumed (20 MHz XTAL also present for SEEQ DQ8023A transceiver)
@@ -87,10 +104,12 @@ ROM_START(np600a3)
ROM_LOAD16_BYTE("258-0032-00_rev_ba.u38", 0x0000, 0x2000, CRC(84ccb317) SHA1(3ecc8e265336f5d3b0f276f18dd1b7001778f2c3))
ROM_LOAD16_BYTE("258-0033-00_rev_ba.u39", 0x0001, 0x2000, CRC(0e0f726c) SHA1(520773e235a826438b025381cd3861df86d4965d))
- // Undumped small devices (mostly or all PLDs):
+ ROM_REGION(0x20, "enetaddr", 0)
+ ROM_LOAD("020701079bfa.u29", 0x00, 0x20, NO_DUMP) // MMI 63S081N (or equivalent PROM, probably having different label and contents for each PCB)
+
+ // Other undumped small devices (mostly or all PLDs):
// 258-0037-00 REV AA (U17, 20 pins)
// 258-0027-01 REV AB (U20, 20 pins)
- // 020701079BFA (U29, 16 pins)
// 258-0031-00 REV AC (U34, PAL20xx, 24 pins)
// 258-0030-00 REV AA (U36, 20 pins)
// 258-0028-01 REV AA (U44, 20 pins)
diff --git a/src/devices/bus/isa/np600.h b/src/devices/bus/isa/np600.h
index 51bdf8813c1..889d77ef485 100644
--- a/src/devices/bus/isa/np600.h
+++ b/src/devices/bus/isa/np600.h
@@ -28,8 +28,10 @@ protected:
private:
void lcc_ca_w(u16 data);
- DECLARE_WRITE_LINE_MEMBER(host_int_w);
+ void int1_ack_w(u8 data);
+ void host_int_w(int state);
u16 status_r();
+ u8 enetaddr_r(offs_t offset);
void mem_map(address_map &map);
void io_map(address_map &map);
@@ -37,6 +39,7 @@ private:
required_device<cpu_device> m_npcpu;
required_device<i82586_device> m_lcc;
+ required_region_ptr<u8> m_enetaddr;
};
DECLARE_DEVICE_TYPE(NP600A3, np600a3_device)
diff --git a/src/devices/bus/isa/omti8621.cpp b/src/devices/bus/isa/omti8621.cpp
index 186e398c411..149638160c3 100644
--- a/src/devices/bus/isa/omti8621.cpp
+++ b/src/devices/bus/isa/omti8621.cpp
@@ -16,7 +16,6 @@
#include "omti8621.h"
#include "image.h"
#include "imagedev/harddriv.h"
-#include "formats/pc_dsk.h"
#include "formats/naslite_dsk.h"
#include "formats/apollo_dsk.h"
@@ -53,16 +52,16 @@ public:
// construction/destruction
omti_disk_image_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- // image-level overrides
+ // device_image_interface implementation
virtual bool support_command_line_image_creation() const noexcept override { return true; }
virtual const char *file_extensions() const noexcept override { return "awd"; }
virtual const char *image_type_name() const noexcept override { return "winchester"; }
virtual const char *image_brief_type_name() const noexcept override { return "disk"; }
- virtual image_init_result call_create(int format_type, util::option_resolution *format_options) override;
+ virtual std::pair<std::error_condition, std::string> call_create(int format_type, util::option_resolution *format_options) override;
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
virtual void device_reset() override;
@@ -1276,13 +1275,13 @@ void omti8621_device::set_jumper(uint16_t disk_type)
}
// FDC uses the standard IRQ 6 / DMA 2, doesn't appear to be configurable
-WRITE_LINE_MEMBER( omti8621_device::fdc_irq_w )
+void omti8621_device::fdc_irq_w(int state)
{
if (BIT(m_moten, 3))
m_isa->irq6_w(state ? ASSERT_LINE : CLEAR_LINE);
}
-WRITE_LINE_MEMBER( omti8621_device::fdc_drq_w )
+void omti8621_device::fdc_drq_w(int state)
{
if (BIT(m_moten, 3))
m_isa->drq2_w(state ? ASSERT_LINE : CLEAR_LINE);
@@ -1469,7 +1468,7 @@ void omti_disk_image_device::device_reset()
disk image create callback
-------------------------------------------------*/
-image_init_result omti_disk_image_device::call_create(int format_type, util::option_resolution *format_options)
+std::pair<std::error_condition, std::string> omti_disk_image_device::call_create(int format_type, util::option_resolution *format_options)
{
logerror("device_create_omti_disk: creating OMTI Disk with %d blocks\n", m_sector_count);
@@ -1478,12 +1477,9 @@ image_init_result omti_disk_image_device::call_create(int format_type, util::opt
for (int x = 0; x < m_sector_count; x++)
{
- if (fwrite(sectordata, OMTI_DISK_SECTOR_SIZE)
- < OMTI_DISK_SECTOR_SIZE)
- {
- return image_init_result::FAIL;
- }
+ if (fwrite(sectordata, OMTI_DISK_SECTOR_SIZE) < OMTI_DISK_SECTOR_SIZE)
+ return std::make_pair(image_error::UNSPECIFIED, std::string());
}
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
diff --git a/src/devices/bus/isa/omti8621.h b/src/devices/bus/isa/omti8621.h
index 3e5cce1c59a..0893dec9352 100644
--- a/src/devices/bus/isa/omti8621.h
+++ b/src/devices/bus/isa/omti8621.h
@@ -16,8 +16,10 @@
#pragma once
#include "isa.h"
-#include "machine/upd765.h"
+
#include "imagedev/floppy.h"
+#include "machine/upd765.h"
+
/***************************************************************************
FUNCTION PROTOTYPES
@@ -44,7 +46,7 @@ protected:
device_t *owner,
uint32_t clock);
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
virtual void device_reset() override;
virtual const tiny_rom_entry *device_rom_region() const override;
@@ -70,8 +72,8 @@ protected:
std::string cpu_context() const;
private:
- DECLARE_WRITE_LINE_MEMBER( fdc_irq_w );
- DECLARE_WRITE_LINE_MEMBER( fdc_drq_w );
+ void fdc_irq_w(int state);
+ void fdc_drq_w(int state);
static void floppy_formats(format_registration &fr);
void fd_moten_w(uint8_t data);
diff --git a/src/devices/bus/isa/opus100pm.cpp b/src/devices/bus/isa/opus100pm.cpp
index 86803a390a3..cfa070eacf3 100644
--- a/src/devices/bus/isa/opus100pm.cpp
+++ b/src/devices/bus/isa/opus100pm.cpp
@@ -31,7 +31,6 @@
#include "emu.h"
#include "opus100pm.h"
-#define LOG_GENERAL (1U << 0)
#define LOG_STAT (1U << 1)
#define LOG_REG (1U << 2)
diff --git a/src/devices/bus/isa/p1_fdc.cpp b/src/devices/bus/isa/p1_fdc.cpp
index 390f98727b0..651262b4110 100644
--- a/src/devices/bus/isa/p1_fdc.cpp
+++ b/src/devices/bus/isa/p1_fdc.cpp
@@ -10,7 +10,6 @@
#include "p1_fdc.h"
#include "cpu/i86/i86.h"
-#include "formats/pc_dsk.h"
//**************************************************************************
@@ -115,7 +114,7 @@ void p1_fdc_device::p1_wd17xx_aux_w(int data)
floppy1->mon_w(!(data & 8));
}
-WRITE_LINE_MEMBER(p1_fdc_device::p1_fdc_irq_drq)
+void p1_fdc_device::p1_fdc_irq_drq(int state)
{
if (state)
m_isa->set_ready(CLEAR_LINE); // deassert I/O CH RDY
diff --git a/src/devices/bus/isa/p1_fdc.h b/src/devices/bus/isa/p1_fdc.h
index ceeb278f5c7..0c1ae3a492a 100644
--- a/src/devices/bus/isa/p1_fdc.h
+++ b/src/devices/bus/isa/p1_fdc.h
@@ -43,7 +43,7 @@ protected:
virtual const tiny_rom_entry *device_rom_region() const override;
private:
- DECLARE_WRITE_LINE_MEMBER(p1_fdc_irq_drq);
+ void p1_fdc_irq_drq(int state);
required_device<fd1793_device> m_fdc;
required_device<cpu_device> m_cpu;
diff --git a/src/devices/bus/isa/p1_hdc.cpp b/src/devices/bus/isa/p1_hdc.cpp
index 9ee84ece875..0b4b54b49ec 100644
--- a/src/devices/bus/isa/p1_hdc.cpp
+++ b/src/devices/bus/isa/p1_hdc.cpp
@@ -14,8 +14,7 @@
// MACROS / CONSTANTS
//**************************************************************************
-//#define LOG_GENERAL (1U << 0) //defined in logmacro.h already
-#define LOG_DEBUG (1U << 1)
+#define LOG_DEBUG (1U << 1)
//#define VERBOSE (LOG_DEBUG)
//#define LOG_OUTPUT_FUNC printf
diff --git a/src/devices/bus/isa/p1_sound.cpp b/src/devices/bus/isa/p1_sound.cpp
index f2e69debf95..11fe4c53c43 100644
--- a/src/devices/bus/isa/p1_sound.cpp
+++ b/src/devices/bus/isa/p1_sound.cpp
@@ -128,7 +128,7 @@ void p1_sound_device::dac_w(offs_t offset, uint8_t data)
m_isa->irq7_w(CLEAR_LINE);
}
-WRITE_LINE_MEMBER(p1_sound_device::sampler_sync)
+void p1_sound_device::sampler_sync(int state)
{
if (state)
{
diff --git a/src/devices/bus/isa/p1_sound.h b/src/devices/bus/isa/p1_sound.h
index 3b7f1c40af9..519c58bfd6b 100644
--- a/src/devices/bus/isa/p1_sound.h
+++ b/src/devices/bus/isa/p1_sound.h
@@ -49,7 +49,7 @@ protected:
virtual void device_add_mconfig(machine_config &config) override;
private:
- DECLARE_WRITE_LINE_MEMBER(sampler_sync);
+ void sampler_sync(int state);
uint8_t m_dac_data[16];
int m_dac_ptr;
diff --git a/src/devices/bus/isa/pgc.cpp b/src/devices/bus/isa/pgc.cpp
index b8329e0ee53..1a67e545378 100644
--- a/src/devices/bus/isa/pgc.cpp
+++ b/src/devices/bus/isa/pgc.cpp
@@ -32,7 +32,6 @@
#include "screen.h"
-//#define LOG_GENERAL (1U << 0) //defined in logmacro.h already
#define LOG_VRAM (1U << 1)
#define LOG_CMD (1U << 2)
@@ -253,7 +252,7 @@ void isa8_pgc_device::device_reset()
//
-WRITE_LINE_MEMBER(isa8_pgc_device::vblank_irq)
+void isa8_pgc_device::vblank_irq(int state)
{
if (state)
{
diff --git a/src/devices/bus/isa/pgc.h b/src/devices/bus/isa/pgc.h
index d560dbdda09..43bc42e2b85 100644
--- a/src/devices/bus/isa/pgc.h
+++ b/src/devices/bus/isa/pgc.h
@@ -41,7 +41,7 @@ protected:
private:
uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
- DECLARE_WRITE_LINE_MEMBER(vblank_irq);
+ void vblank_irq(int state);
IRQ_CALLBACK_MEMBER(irq_callback);
void vram_w(offs_t offset, uint8_t data);
diff --git a/src/devices/bus/isa/s3virge.cpp b/src/devices/bus/isa/s3virge.cpp
deleted file mode 100644
index 9fb6f98d204..00000000000
--- a/src/devices/bus/isa/s3virge.cpp
+++ /dev/null
@@ -1,1624 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Barry Rodewald
-/*
- * s3virge.cpp
- *
- * Implementation of the S3 Virge series of video card
- *
- * Current status:
- * - Working on getting VESA video modes working better - 800x600 and higher skip every other line at
- * 8-bit depth, but are fine at 15/16-bit depth.
- * - S3D is not implemented at all, so no 2D/3D acceleration yet.
- */
-
-#include "emu.h"
-#include "s3virge.h"
-
-#include "screen.h"
-
-#define VERBOSE (LOG_REG | LOG_CMD | LOG_MMIO)
-
-#include "logmacro.h"
-
-#define LOG_REG (1U << 1)
-#define LOG_CMD (1U << 2)
-#define LOG_MMIO (1U << 3)
-
-#define LOGREG(...) LOGMASKED(LOG_REG, __VA_ARGS__)
-#define LOGCMD(...) LOGMASKED(LOG_CMD, __VA_ARGS__)
-#define LOGMMIO(...) LOGMASKED(LOG_MMIO, __VA_ARGS__)
-
-
-#define CRTC_PORT_ADDR ((vga.miscellaneous_output & 1) ? 0x3d0 : 0x3b0)
-
-DEFINE_DEVICE_TYPE(S3VIRGE, s3virge_vga_device, "virge_vga", "S3 86C325")
-DEFINE_DEVICE_TYPE(S3VIRGEDX, s3virgedx_vga_device, "virgedx_vga", "S3 86C375")
-DEFINE_DEVICE_TYPE(S3VIRGEDX1, s3virgedx_rev1_vga_device, "virgedx_vga_r1", "S3 86C375 (rev 1)")
-
-s3virge_vga_device::s3virge_vga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : s3virge_vga_device(mconfig, S3VIRGE, tag, owner, clock)
-{
-}
-
-s3virge_vga_device::s3virge_vga_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
- : s3_vga_device(mconfig, type, tag, owner, clock)
- , m_linear_config_changed_cb(*this)
-{
-}
-
-s3virgedx_vga_device::s3virgedx_vga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : s3virgedx_vga_device(mconfig, S3VIRGEDX, tag, owner, clock)
-{
-}
-
-s3virgedx_vga_device::s3virgedx_vga_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
- : s3virge_vga_device(mconfig, type, tag, owner, clock)
-{
-}
-
-s3virgedx_rev1_vga_device::s3virgedx_rev1_vga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : s3virgedx_vga_device(mconfig, S3VIRGEDX1, tag, owner, clock)
-{
-}
-
-void s3virge_vga_device::device_start()
-{
- zero();
-
- for (int i = 0; i < 0x100; i++)
- set_pen_color(i, 0, 0, 0);
-
- // Avoid an infinite loop when displaying. 0 is not possible anyway.
- vga.crtc.maximum_scan_line = 1;
-
- // copy over interfaces
- vga.read_dipswitch.set(nullptr); //read_dipswitch;
- vga.svga_intf.seq_regcount = 0x1c;
- vga.svga_intf.crtc_regcount = 0x19;
- vga.memory = std::make_unique<uint8_t []>(vga.svga_intf.vram_size);
- memset(&vga.memory[0], 0, vga.svga_intf.vram_size);
-
- save_pointer(vga.memory, "Video RAM", vga.svga_intf.vram_size);
- save_item(vga.crtc.data,"CRTC Registers");
- save_item(vga.sequencer.data,"Sequencer Registers");
- save_item(vga.attribute.data,"Attribute Registers");
-
- m_vblank_timer = timer_alloc(FUNC(vga_device::vblank_timer_cb), this);
- m_draw_timer = timer_alloc(FUNC(s3virge_vga_device::draw_step_tick), this);
-
- memset(&s3, 0, sizeof(s3));
- memset(&s3virge, 0, sizeof(s3virge));
- s3virge.linear_address = 0x70000000;
- s3virge.linear_address_size_full = 0x10000;
- s3virge.s3d.cmd_fifo_slots_free = 16;
- save_item(s3virge.s3d.pattern,"S3D Pattern Data");
- save_item(s3virge.s3d.reg[0],"S3D Registers: BitBLT");
- save_item(s3virge.s3d.reg[1],"S3D Registers: 2D Line");
- save_item(s3virge.s3d.reg[2],"S3D Registers: 2D Polygon");
- save_item(s3virge.s3d.reg[3],"S3D Registers: 3D Line");
- save_item(s3virge.s3d.reg[4],"S3D Registers: 3D Triangle");
-
- m_linear_config_changed_cb.resolve_safe();
-
- // Initialise hardware graphics cursor colours, Windows 95 doesn't touch the registers for some reason
- for (int x = 0; x < 4; x++)
- {
- s3.cursor_fg[x] = 0xff;
- s3.cursor_bg[x] = 0x00;
- }
- // set device ID
- s3.id_high = 0x56; // CR2D
- s3.id_low = 0x31; // CR2E
- s3.revision = 0x00; // CR2F (value unknown)
- s3.id_cr30 = 0xe1; // CR30
-}
-
-void s3virgedx_vga_device::device_start()
-{
- s3virge_vga_device::device_start();
-
- // set device ID
- s3.id_high = 0x8a; // CR2D
- s3.id_low = 0x01; // CR2E
- s3.revision = 0x00; // CR2F (value unknown)
- s3.id_cr30 = 0xe1; // CR30
-}
-
-void s3virgedx_rev1_vga_device::device_start()
-{
- s3virge_vga_device::device_start();
-
- // set device ID
- s3.id_high = 0x8a; // CR2D
- s3.id_low = 0x01; // CR2E
- s3.revision = 0x01; // CR2F
- s3.id_cr30 = 0xe1; // CR30
-}
-
-void s3virge_vga_device::device_reset()
-{
- vga_device::device_reset();
- // Power-on strapping bits. Sampled at reset, but can be modified later.
- // These are just assumed defaults.
- s3.strapping = 0x000f0912;
-}
-
-void s3virgedx_vga_device::device_reset()
-{
- vga_device::device_reset();
- // Power-on strapping bits. Sampled at reset, but can be modified later.
- // These are just assumed defaults.
- s3.strapping = 0x000f0912;
-}
-
-void s3virgedx_rev1_vga_device::device_reset()
-{
- vga_device::device_reset();
- // Power-on strapping bits. Sampled at reset, but can be modified later.
- // These are based on results from a Diamond Stealth 3D 2000 Pro (Virge/DX based)
- // bits 8-15 are still unknown, S3ID doesn't show config register 2 (CR37)
- s3.strapping = 0x0aff0912;
-}
-
-uint16_t s3virge_vga_device::offset()
-{
- if(svga.rgb24_en)
- return vga.crtc.offset * 6; // special handling for 24bpp packed mode
- return s3_vga_device::offset();
-}
-
-uint8_t s3virge_vga_device::s3_crtc_reg_read(uint8_t index)
-{
- uint8_t res;
-
- if(index <= 0x18)
- res = crtc_reg_read(index);
- else
- {
- switch(index)
- {
- case 0x2d:
- res = s3.id_high;
- break;
- case 0x2e:
- res = s3.id_low;
- break;
- case 0x2f:
- res = s3.revision;
- break;
- case 0x30: // CR30 Chip ID/REV register
- res = s3.id_cr30;
- break;
- case 0x31:
- res = s3.memory_config;
- break;
- case 0x35:
- res = s3.crt_reg_lock;
- break;
- case 0x36: // Configuration register 1
- res = s3.strapping & 0x000000ff;
- break;
- case 0x37: // Configuration register 2
- res = (s3.strapping & 0x0000ff00) >> 8;
- break;
- case 0x38:
- res = s3.reg_lock1;
- break;
- case 0x39:
- res = s3.reg_lock2;
- break;
- case 0x42: // CR42 Mode Control
- res = s3.cr42 & 0x0f; // bit 5 set if interlaced, leave it unset for now.
- break;
- case 0x43:
- res = s3.cr43;
- break;
- case 0x45:
- res = s3.cursor_mode;
- break;
- case 0x46:
- res = (s3.cursor_x & 0xff00) >> 8;
- break;
- case 0x47:
- res = s3.cursor_x & 0x00ff;
- break;
- case 0x48:
- res = (s3.cursor_y & 0xff00) >> 8;
- break;
- case 0x49:
- res = s3.cursor_y & 0x00ff;
- break;
- case 0x4a:
- res = s3.cursor_fg[s3.cursor_fg_ptr];
- s3.cursor_fg_ptr = 0;
- break;
- case 0x4b:
- res = s3.cursor_bg[s3.cursor_bg_ptr];
- s3.cursor_bg_ptr = 0;
- break;
- case 0x4c:
- res = (s3.cursor_start_addr & 0xff00) >> 8;
- break;
- case 0x4d:
- res = s3.cursor_start_addr & 0x00ff;
- break;
- case 0x4e:
- res = s3.cursor_pattern_x;
- break;
- case 0x4f:
- res = s3.cursor_pattern_y;
- break;
- case 0x51:
- res = (vga.crtc.start_addr_latch & 0x0c0000) >> 18;
- res |= ((svga.bank_w & 0x30) >> 2);
- break;
- case 0x55:
- res = s3.extended_dac_ctrl;
- break;
- case 0x58:
- res = s3virge.linear_address_size & 0x03;
- res |= s3virge.linear_address_enable ? 0x10 : 0x00;
- break;
- case 0x59:
- res = (s3virge.linear_address & 0xff000000) >> 24;
- break;
- case 0x5a:
- switch(s3virge.linear_address_size & 0x03)
- {
- case 0: // 64kB
- default:
- res = (s3virge.linear_address & 0x00ff0000) >> 16;
- break;
- case 1: // 1MB
- res = (s3virge.linear_address & 0x00f00000) >> 16;
- break;
- case 2: // 2MB
- res = (s3virge.linear_address & 0x00e00000) >> 16;
- break;
- case 3: // 4MB
- res = (s3virge.linear_address & 0x00c00000) >> 16;
- break;
- }
- break;
- case 0x5c:
- // if VGA dot clock is set to 3 (misc reg bits 2-3), then selected dot clock is read, otherwise read VGA clock select
- if((vga.miscellaneous_output & 0xc) == 0x0c)
- res = s3.cr42 & 0x0f;
- else
- res = (vga.miscellaneous_output & 0xc) >> 2;
- break;
- case 0x67:
- res = s3.ext_misc_ctrl_2;
- break;
- case 0x68: // Configuration register 3
- res = (s3.strapping & 0x00ff0000) >> 16;
- break;
- case 0x69:
- res = vga.crtc.start_addr_latch >> 16;
- break;
- case 0x6a:
- res = svga.bank_r & 0x7f;
- break;
- case 0x6f: // Configuration register 4
- res = (s3.strapping & 0xff000000) >> 24;
- break;
- default:
- res = vga.crtc.data[index];
- //machine.debug_break();
- //printf("%02x\n",index);
- break;
- }
- }
-
- return res;
-}
-
-void s3virge_vga_device::s3_define_video_mode()
-{
- int divisor = 1;
- const XTAL base_xtal = XTAL(14'318'181);
- XTAL xtal = (vga.miscellaneous_output & 0xc) ? base_xtal*2 : base_xtal*1.75;
-
- if((vga.miscellaneous_output & 0xc) == 0x0c)
- {
- // Dot clock is set via SR12 and SR13
- // DCLK calculation
- double ratio = (double)(s3.clk_pll_m+2) / (double)((s3.clk_pll_n+2)*(pow(2.0,s3.clk_pll_r))); // clock between XIN and XOUT
- xtal = base_xtal * ratio;
- //printf("DCLK set to %dHz M=%i N=%i R=%i\n",xtal,s3.clk_pll_m,s3.clk_pll_n,s3.clk_pll_r);
- }
-
- if((s3.ext_misc_ctrl_2) >> 4)
- {
- svga.rgb8_en = 0;
- svga.rgb15_en = 0;
- svga.rgb16_en = 0;
- svga.rgb24_en = 0;
- switch((s3.ext_misc_ctrl_2) >> 4)
- {
- case 0x01: svga.rgb8_en = 1; break;
- case 0x03: svga.rgb15_en = 1; divisor = 2; break;
- case 0x05: svga.rgb16_en = 1; divisor = 2; break;
- case 0x0d: svga.rgb24_en = 1; divisor = 1; break;
- default: fatalerror("TODO: s3 video mode not implemented %02x\n",((s3.ext_misc_ctrl_2) >> 4));
- }
- }
- else
- {
- svga.rgb8_en = (s3.cr3a & 0x10) >> 4;
- svga.rgb15_en = 0;
- svga.rgb16_en = 0;
- svga.rgb24_en = 0;
- }
- if(s3.cr43 & 0x80) // Horizontal clock doubling (technically, doubles horizontal CRT parameters)
- divisor *= 2;
- recompute_params_clock(divisor, xtal.value());
-}
-
-void s3virge_vga_device::s3_crtc_reg_write(uint8_t index, uint8_t data)
-{
- if(index <= 0x18)
- {
- crtc_reg_write(index,data);
- s3_define_video_mode();
- }
- else
- {
- switch(index)
- {
- case 0x31: // CR31 Memory Configuration Register
- s3.memory_config = data;
- vga.crtc.start_addr_latch &= ~0x30000;
- vga.crtc.start_addr_latch |= ((data & 0x30) << 12);
- s3_define_video_mode();
- break;
- case 0x35:
- if((s3.reg_lock1 & 0xc) != 8 || ((s3.reg_lock1 & 0xc0) == 0)) // lock register
- return;
- s3.crt_reg_lock = data;
- svga.bank_w = data & 0xf;
- svga.bank_r = svga.bank_w;
- break;
- case 0x36:
- if(s3.reg_lock2 == 0xa5)
- {
- s3.strapping = (s3.strapping & 0xffffff00) | data;
- LOGREG("CR36: Strapping data = %08x\n",s3.strapping);
- }
- break;
- case 0x37:
- if(s3.reg_lock2 == 0xa5)
- {
- s3.strapping = (s3.strapping & 0xffff00ff) | (data << 8);
- LOGREG("CR37: Strapping data = %08x\n",s3.strapping);
- }
- break;
- case 0x38:
- s3.reg_lock1 = data;
- break;
- case 0x39:
- /* TODO: reg lock mechanism */
- s3.reg_lock2 = data;
- break;
- case 0x3a:
- s3.cr3a = data;
- break;
- case 0x40:
- s3.enable_s3d = data & 0x01; // enable S3D registers
- break;
- case 0x42:
- s3.cr42 = data; // bit 5 = interlace, bits 0-3 = dot clock (seems to be undocumented)
- break;
- case 0x43:
- s3.cr43 = data; // bit 2 = bit 8 of offset register, but only if bits 4-5 of CR51 are 00h.
- if((s3.cr51 & 0x30) == 0)
- vga.crtc.offset = (vga.crtc.offset & 0x00ff) | ((data & 0x04) << 6);
- else
- vga.crtc.offset = (vga.crtc.offset & 0x00ff) | ((s3.cr51 & 0x30) << 4);
- s3_define_video_mode();
- break;
-/*
-3d4h index 45h (R/W): CR45 Hardware Graphics Cursor Mode
-bit 0 HWGC ENB. Hardware Graphics Cursor Enable. Set to enable the
- HardWare Cursor in VGA and enhanced modes.
- 1 (911/24) Delay Timing for Pattern Data Fetch
- 2 (801/5,928) Hardware Cursor Horizontal Stretch 2. If set the cursor
- pixels are stretched horizontally to two bytes and items 0 and 1 of
- the fore/background stacks in 3d4h index 4Ah/4Bh are used.
- 3 (801/5,928) Hardware Cursor Horizontal Stretch 3. If set the cursor
- pixels are stretched horizontally to three bytes and items 0,1 and
- 2 of the fore/background stacks in 3d4h index 4Ah/4Bh are used.
- 2-3 (805i,864/964) HWC-CSEL. Hardware Cursor Color Select.
- 0: 4/8bit, 1: 15/16bt, 2: 24bit, 3: 32bit
- Note: So far I've had better luck with: 0: 8/15/16bit, 1: 32bit??
- 4 (80x +) Hardware Cursor Right Storage. If set the cursor data is
- stored in the last 256 bytes of 4 1Kyte lines (4bits/pixel) or the
- last 512 bytes of 2 2Kbyte lines (8bits/pixel). Intended for
- 1280x1024 modes where there are no free lines at the bottom.
- 5 (928) Cursor Control Enable for Brooktree Bt485 DAC. If set and 3d4h
- index 55h bit 5 is set the HC1 output becomes the ODF and the HC0
- output becomes the CDE
- (964) BT485 ODF Selection for Bt485A RAMDAC. If set pin 185 (RS3
- /ODF) is the ODF output to a Bt485A compatible RamDAC (low for even
- fields and high for odd fields), if clear pin185 is the RS3 output.
- */
- case 0x45:
- s3.cursor_mode = data;
- break;
-/*
-3d4h index 46h M(R/W): CR46/7 Hardware Graphics Cursor Origin-X
-bit 0-10 The HardWare Cursor X position. For 64k modes this value should be
- twice the actual X co-ordinate.
- */
- case 0x46:
- s3.cursor_x = (s3.cursor_x & 0x00ff) | (data << 8);
- break;
- case 0x47:
- s3.cursor_x = (s3.cursor_x & 0xff00) | data;
- break;
-/*
-3d4h index 48h M(R/W): CR48/9 Hardware Graphics Cursor Origin-Y
-bit 0-9 (911/24) The HardWare Cursor Y position.
- 0-10 (80x +) The HardWare Cursor Y position.
-Note: The position is activated when the high byte of the Y coordinate (index
- 48h) is written, so this byte should be written last (not 911/924 ?)
- */
- case 0x48:
- s3.cursor_y = (s3.cursor_y & 0x00ff) | (data << 8);
- break;
- case 0x49:
- s3.cursor_y = (s3.cursor_y & 0xff00) | data;
- break;
-
-/*
-3d4h index 4Ah (R/W): Hardware Graphics Cursor Foreground Stack (80x +)
-bit 0-7 The Foreground Cursor color. Three bytes (4 for the 864/964) are
- stacked here. When the Cursor Mode register (3d4h index 45h) is read
- the stackpointer is reset. When a byte is written the byte is
- written into the current top of stack and the stackpointer is
- increased. The first byte written (item 0) is allways used, the
- other two(3) only when Hardware Cursor Horizontal Stretch (3d4h
- index 45h bit 2-3) is enabled.
- */
- case 0x4a:
- s3.cursor_fg[s3.cursor_fg_ptr++] = data;
- s3.cursor_fg_ptr %= 4;
- break;
-/*
-3d4h index 4Bh (R/W): Hardware Graphics Cursor Background Stack (80x +)
-bit 0-7 The Background Cursor color. Three bytes (4 for the 864/964) are
- stacked here. When the Cursor Mode register (3d4h index 45h) is read
- the stackpointer is reset. When a byte is written the byte is
- written into the current top of stack and the stackpointer is
- increased. The first byte written (item 0) is allways used, the
- other two(3) only when Hardware Cursor Horizontal Stretch (3d4h
- index 45h bit 2-3) is enabled.
- */
- case 0x4b:
- s3.cursor_bg[s3.cursor_bg_ptr++] = data;
- s3.cursor_bg_ptr %= 4;
- break;
-/*
-3d4h index 4Ch M(R/W): CR4C/D Hardware Graphics Cursor Storage Start Address
-bit 0-9 (911,924) HCS_STADR. Hardware Graphics Cursor Storage Start Address
- 0-11 (80x,928) HWGC_STA. Hardware Graphics Cursor Storage Start Address
- 0-12 (864,964) HWGC_STA. Hardware Graphics Cursor Storage Start Address
- Address of the HardWare Cursor Map in units of 1024 bytes (256 bytes
- for planar modes). The cursor map is a 64x64 bitmap with 2 bits (A
- and B) per pixel. The map is stored as one word (16 bits) of bit A,
- followed by one word with the corresponding 16 B bits.
- The bits are interpreted as:
- A B MS-Windows: X-11:
- 0 0 Background Screen data
- 0 1 Foreground Screen data
- 1 0 Screen data Background
- 1 1 Inverted screen Foreground
- The Windows/X11 switch is only available for the 80x +.
- (911/24) For 64k color modes the cursor is stored as one byte (8
- bits) of A bits, followed by the 8 B-bits, and each bit in the
- cursor should be doubled to provide a consistent cursor image.
- (801/5,928) For Hi/True color modes use the Horizontal Stretch bits
- (3d4h index 45h bits 2 and 3).
- */
- case 0x4c:
- s3.cursor_start_addr = (s3.cursor_start_addr & 0x00ff) | (data << 8);
- LOGREG("HW Cursor Address: %08x\n",s3.cursor_start_addr);
- break;
- case 0x4d:
- s3.cursor_start_addr = (s3.cursor_start_addr & 0xff00) | data;
- LOGREG("HW Cursor Address: %08x\n",s3.cursor_start_addr);
- break;
-/*
-3d4h index 4Eh (R/W): CR4E HGC Pattern Disp Start X-Pixel Position
-bit 0-5 Pattern Display Start X-Pixel Position.
- */
- case 0x4e:
- s3.cursor_pattern_x = data;
- break;
-/*
-3d4h index 4Fh (R/W): CR4F HGC Pattern Disp Start Y-Pixel Position
-bit 0-5 Pattern Display Start Y-Pixel Position.
- */
- case 0x4f:
- s3.cursor_pattern_y = data;
- break;
- case 0x51:
- s3.cr51 = data;
- vga.crtc.start_addr_latch &= ~0xc0000;
- vga.crtc.start_addr_latch |= ((data & 0x3) << 18);
- svga.bank_w = (svga.bank_w & 0xcf) | ((data & 0x0c) << 2);
- svga.bank_r = svga.bank_w;
- if((data & 0x30) != 0x00)
- vga.crtc.offset = (vga.crtc.offset & 0x00ff) | ((data & 0x30) << 4);
- else
- vga.crtc.offset = (vga.crtc.offset & 0x00ff) | ((s3.cr43 & 0x04) << 6);
- s3_define_video_mode();
- break;
- case 0x53:
- s3.cr53 = data;
- break;
-/*
-3d4h index 55h (R/W): Extended Video DAC Control Register (80x +)
-bit 0-1 DAC Register Select Bits. Passed to the RS2 and RS3 pins on the
- RAMDAC, allowing access to all 8 or 16 registers on advanced RAMDACs.
- If this field is 0, 3d4h index 43h bit 1 is active.
- 2 Enable General Input Port Read. If set DAC reads are disabled and the
- STRD strobe for reading the General Input Port is enabled for reading
- while DACRD is active, if clear DAC reads are enabled.
- 3 (928) Enable External SID Operation if set. If set video data is
- passed directly from the VRAMs to the DAC rather than through the
- VGA chip
- 4 Hardware Cursor MS/X11 Mode. If set the Hardware Cursor is in X11
- mode, if clear in MS-Windows mode
- 5 (80x,928) Hardware Cursor External Operation Mode. If set the two
- bits of cursor data ,is output on the HC[0-1] pins for the video DAC
- The SENS pin becomes HC1 and the MID2 pin becomes HC0.
- 6 ??
- 7 (80x,928) Disable PA Output. If set PA[0-7] and VCLK are tristated.
- (864/964) TOFF VCLK. Tri-State Off VCLK Output. VCLK output tri
- -stated if set
- */
- case 0x55:
- s3.extended_dac_ctrl = data;
- break;
-
- case 0x58:
- {
- const uint8_t old_size = s3virge.linear_address_size;
- const bool old_enable = s3virge.linear_address_enable;
- const bool size_changed = old_size != s3virge.linear_address_size;
-
- s3virge.linear_address_size = data & 0x03;
- s3virge.linear_address_enable = data & 0x10;
-
- switch(data & 0x03)
- {
- case LAW_64K:
- s3virge.linear_address_size_full = 0x10000;
- break;
- case LAW_1MB:
- s3virge.linear_address_size_full = 0x100000;
- break;
- case LAW_2MB:
- s3virge.linear_address_size_full = 0x200000;
- break;
- case LAW_4MB:
- s3virge.linear_address_size_full = 0x400000;
- break;
- }
-
- if ((s3virge.linear_address_enable != old_enable) || size_changed)
- {
- m_linear_config_changed_cb(s3virge.linear_address_enable);
- }
-
- LOGREG("CR58: write %02x\n", data);
- break;
- }
- case 0x59:
- {
- const uint32_t old_address = s3virge.linear_address;
- s3virge.linear_address = (s3virge.linear_address & 0x00ff0000) | (data << 24);
- LOGREG("Linear framebuffer address = %08x\n",s3virge.linear_address);
-
- if (old_address != s3virge.linear_address && s3virge.linear_address_enable)
- {
- m_linear_config_changed_cb(1);
- }
- break;
- }
- case 0x5a:
- {
- const uint32_t old_address = s3virge.linear_address;
- s3virge.linear_address = (s3virge.linear_address & 0xff000000) | (data << 16);
- LOGREG("Linear framebuffer address = %08x\n",s3virge.linear_address);
-
- if (old_address != s3virge.linear_address && s3virge.linear_address_enable)
- {
- m_linear_config_changed_cb(1);
- }
- break;
- }
-
-/*
-3d4h index 5Dh (R/W): Extended Horizontal Overflow Register (80x +)
-bit 0 Horizontal Total bit 8. Bit 8 of the Horizontal Total register (3d4h
- index 0)
- 1 Horizontal Display End bit 8. Bit 8 of the Horizontal Display End
- register (3d4h index 1)
- 2 Start Horizontal Blank bit 8. Bit 8 of the Horizontal Start Blanking
- register (3d4h index 2).
- 3 (864,964) EHB+64. End Horizontal Blank +64. If set the /BLANK pulse
- is extended by 64 DCLKs. Note: Is this bit 6 of 3d4h index 3 or
- does it really extend by 64 ?
- 4 Start Horizontal Sync Position bit 8. Bit 8 of the Horizontal Start
- Retrace register (3d4h index 4).
- 5 (864,964) EHS+32. End Horizontal Sync +32. If set the HSYNC pulse
- is extended by 32 DCLKs. Note: Is this bit 5 of 3d4h index 5 or
- does it really extend by 32 ?
- 6 (928,964) Data Transfer Position bit 8. Bit 8 of the Data Transfer
- Position register (3d4h index 3Bh)
- 7 (928,964) Bus-Grant Terminate Position bit 8. Bit 8 of the Bus Grant
- Termination register (3d4h index 5Fh).
-*/
- case 0x5d:
- vga.crtc.horz_total = (vga.crtc.horz_total & 0xfeff) | ((data & 0x01) << 8);
- vga.crtc.horz_disp_end = (vga.crtc.horz_disp_end & 0xfeff) | ((data & 0x02) << 7);
- vga.crtc.horz_blank_start = (vga.crtc.horz_blank_start & 0xfeff) | ((data & 0x04) << 6);
- vga.crtc.horz_blank_end = (vga.crtc.horz_blank_end & 0xffbf) | ((data & 0x08) << 3);
- vga.crtc.horz_retrace_start = (vga.crtc.horz_retrace_start & 0xfeff) | ((data & 0x10) << 4);
- vga.crtc.horz_retrace_end = (vga.crtc.horz_retrace_end & 0xffdf) | (data & 0x20);
- s3_define_video_mode();
- break;
-/*
-3d4h index 5Eh (R/W): Extended Vertical Overflow Register (80x +)
-bit 0 Vertical Total bit 10. Bit 10 of the Vertical Total register (3d4h
- index 6). Bits 8 and 9 are in 3d4h index 7 bit 0 and 5.
- 1 Vertical Display End bit 10. Bit 10 of the Vertical Display End
- register (3d4h index 12h). Bits 8 and 9 are in 3d4h index 7 bit 1
- and 6
- 2 Start Vertical Blank bit 10. Bit 10 of the Vertical Start Blanking
- register (3d4h index 15h). Bit 8 is in 3d4h index 7 bit 3 and bit 9
- in 3d4h index 9 bit 5
- 4 Vertical Retrace Start bit 10. Bit 10 of the Vertical Start Retrace
- register (3d4h index 10h). Bits 8 and 9 are in 3d4h index 7 bit 2
- and 7.
- 6 Line Compare Position bit 10. Bit 10 of the Line Compare register
- (3d4h index 18h). Bit 8 is in 3d4h index 7 bit 4 and bit 9 in 3d4h
- index 9 bit 6.
- */
- case 0x5e:
- vga.crtc.vert_total = (vga.crtc.vert_total & 0xfbff) | ((data & 0x01) << 10);
- vga.crtc.vert_disp_end = (vga.crtc.vert_disp_end & 0xfbff) | ((data & 0x02) << 9);
- vga.crtc.vert_blank_start = (vga.crtc.vert_blank_start & 0xfbff) | ((data & 0x04) << 8);
- vga.crtc.vert_retrace_start = (vga.crtc.vert_retrace_start & 0xfbff) | ((data & 0x10) << 6);
- vga.crtc.line_compare = (vga.crtc.line_compare & 0xfbff) | ((data & 0x40) << 4);
- s3_define_video_mode();
- break;
- case 0x67:
- s3.ext_misc_ctrl_2 = data;
- s3_define_video_mode();
- //printf("%02x X\n",data);
- break;
- case 0x68:
- if(s3.reg_lock2 == 0xa5)
- {
- s3.strapping = (s3.strapping & 0xff00ffff) | (data << 16);
- LOGREG("CR68: Strapping data = %08x\n",s3.strapping);
- }
- break;
- case 0x69:
- vga.crtc.start_addr_latch &= ~0x1f0000;
- vga.crtc.start_addr_latch |= ((data & 0x1f) << 16);
- s3_define_video_mode();
- break;
- case 0x6a:
- svga.bank_w = data & 0x3f;
- svga.bank_r = svga.bank_w;
- break;
- case 0x6f:
- if(s3.reg_lock2 == 0xa5)
- {
- s3.strapping = (s3.strapping & 0x00ffffff) | (data << 24);
- LOGREG("CR6F: Strapping data = %08x\n",s3.strapping);
- }
- break;
- default:
- LOGREG("S3: CR%02X write %02x\n",index,data);
- break;
- }
- }
-}
-
-
-uint8_t s3virge_vga_device::port_03b0_r(offs_t offset)
-{
- uint8_t res = 0xff;
-
- if (CRTC_PORT_ADDR == 0x3b0)
- {
- switch(offset)
- {
- case 5:
- res = s3_crtc_reg_read(vga.crtc.index);
- break;
- default:
- res = vga_device::port_03b0_r(offset);
- break;
- }
- }
-
- return res;
-}
-
-void s3virge_vga_device::port_03b0_w(offs_t offset, uint8_t data)
-{
- if (CRTC_PORT_ADDR == 0x3b0)
- {
- switch(offset)
- {
- case 5:
- vga.crtc.data[vga.crtc.index] = data;
- s3_crtc_reg_write(vga.crtc.index,data);
- break;
- default:
- vga_device::port_03b0_w(offset,data);
- break;
- }
- }
-}
-
-uint8_t s3virge_vga_device::port_03c0_r(offs_t offset)
-{
- uint8_t res;
-
- switch(offset)
- {
- default:
- res = s3_vga_device::port_03c0_r(offset);
- break;
- }
-
- return res;
-}
-
-void s3virge_vga_device::port_03c0_w(offs_t offset, uint8_t data)
-{
- switch(offset)
- {
- default:
- s3_vga_device::port_03c0_w(offset,data);
- break;
- }
-}
-
-uint8_t s3virge_vga_device::port_03d0_r(offs_t offset)
-{
- uint8_t res = 0xff;
-
- if (CRTC_PORT_ADDR == 0x3d0)
- {
- switch(offset)
- {
- case 5:
- res = s3_crtc_reg_read(vga.crtc.index);
- break;
- default:
- res = vga_device::port_03d0_r(offset);
- break;
- }
- }
-
- return res;
-}
-
-void s3virge_vga_device::port_03d0_w(offs_t offset, uint8_t data)
-{
- if (CRTC_PORT_ADDR == 0x3d0)
- {
- switch(offset)
- {
- case 5:
- vga.crtc.data[vga.crtc.index] = data;
- s3_crtc_reg_write(vga.crtc.index,data);
- break;
- default:
- vga_device::port_03d0_w(offset,data);
- break;
- }
- }
-}
-
-uint8_t s3virge_vga_device::mem_r(offs_t offset)
-{
- if (svga.rgb8_en || svga.rgb15_en || svga.rgb16_en || svga.rgb24_en || svga.rgb32_en)
- {
- uint8_t data;
- if(offset & 0x10000)
- return 0;
- data = 0xff;
- if(vga.sequencer.data[4] & 0x8)
- {
- if(offset + (svga.bank_r*0x10000) < vga.svga_intf.vram_size)
- data = vga.memory[offset + (svga.bank_r*0x10000)];
- }
- else
- {
- int i;
-
- for(i=0;i<4;i++)
- {
- if(vga.sequencer.map_mask & 1 << i)
- {
- if(offset*4+i+(svga.bank_r*0x10000) < vga.svga_intf.vram_size)
- data |= vga.memory[offset*4+i+(svga.bank_r*0x10000)];
- }
- }
- }
- return data;
- }
- if((offset + (svga.bank_r*0x10000)) < vga.svga_intf.vram_size)
- return vga_device::mem_r(offset);
- else
- return 0xff;
-}
-
-void s3virge_vga_device::mem_w(offs_t offset, uint8_t data)
-{
- // bit 4 of CR53 enables memory-mapped I/O
- if(s3.cr53 & 0x10)
- {
- // TODO
- }
-
- if (svga.rgb8_en || svga.rgb15_en || svga.rgb16_en || svga.rgb32_en)
- {
- // printf("%08x %02x (%02x %02x) %02X\n",offset,data,vga.sequencer.map_mask,svga.bank_w,(vga.sequencer.data[4] & 0x08));
- if(offset & 0x10000)
- return;
- if(vga.sequencer.data[4] & 0x8)
- {
- if((offset + (svga.bank_w*0x10000)) < vga.svga_intf.vram_size)
- vga.memory[(offset + (svga.bank_w*0x10000))] = data;
- }
- else
- {
- int i;
- for(i=0;i<4;i++)
- {
- if(vga.sequencer.map_mask & 1 << i)
- {
- if((offset*4+i+(svga.bank_w*0x10000)) < vga.svga_intf.vram_size)
- vga.memory[(offset*4+i+(svga.bank_w*0x10000))] = data;
- }
- }
- }
- return;
- }
-
- if((offset + (svga.bank_w*0x10000)) < vga.svga_intf.vram_size)
- vga_device::mem_w(offset,data);
-}
-
-uint8_t s3virge_vga_device::fb_r(offs_t offset)
-{
- if(offset < s3virge.linear_address_size_full)
- return vga.memory[offset % vga.svga_intf.vram_size];
- return 0xff;
-}
-
-void s3virge_vga_device::fb_w(offs_t offset, uint8_t data)
-{
- if(offset < s3virge.linear_address_size_full)
- vga.memory[offset % vga.svga_intf.vram_size] = data;
-}
-
-void s3virge_vga_device::add_command(int cmd_type)
-{
- // add command to S3D FIFO
- if(s3virge.s3d.cmd_fifo_slots_free == 0)
- {
- LOGCMD("Attempt to add command when all command slots are full\n");
- return;
- }
- memcpy(s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_next_ptr].reg,s3virge.s3d.reg[cmd_type],256*4);
- s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_next_ptr].op_type = cmd_type;
- LOGCMD("Added command type %i cmd %08x ptr %u\n",s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_next_ptr].op_type,s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_next_ptr].reg[S3D_REG_COMMAND],s3virge.s3d.cmd_fifo_next_ptr);
- s3virge.s3d.cmd_fifo_next_ptr++;
- if(s3virge.s3d.cmd_fifo_next_ptr >= 16)
- s3virge.s3d.cmd_fifo_next_ptr = 0;
- if(s3virge.s3d.cmd_fifo_slots_free == 16) // if all slots are free, start command now
- command_start();
- s3virge.s3d.cmd_fifo_slots_free--;
- // TODO: handle full FIFO
-}
-
-void s3virge_vga_device::command_start()
-{
- // start next command in FIFO
- int cmd_type = s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].op_type;
-
- switch(cmd_type)
- {
- case OP_2DLINE:
- LOGCMD("2D Line command (unsupported) [%u]\n", s3virge.s3d.cmd_fifo_current_ptr);
- break;
- case OP_2DPOLY:
- LOGCMD("2D Poly command (unsupported) [%u]\n", s3virge.s3d.cmd_fifo_current_ptr);
- break;
- case OP_3DLINE:
- LOGCMD("3D Line command (unsupported) [%u]\n", s3virge.s3d.cmd_fifo_current_ptr);
- break;
- case OP_3DTRI:
- LOGCMD("3D Tri command (unsupported) [%u]\n", s3virge.s3d.cmd_fifo_current_ptr);
- break;
- case OP_BITBLT:
- s3virge.s3d.state = S3D_STATE_BITBLT;
- s3virge.s3d.busy = true;
- s3virge.s3d.bitblt_x_src = (s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_RSRC_XY] & 0x07ff0000) >> 16;
- s3virge.s3d.bitblt_y_src = (s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_RSRC_XY] & 0x000007ff);
- s3virge.s3d.bitblt_x_dst = (s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_RDEST_XY] & 0x07ff0000) >> 16;
- s3virge.s3d.bitblt_y_dst = (s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_RDEST_XY] & 0x000007ff);
- s3virge.s3d.bitblt_width = (s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_RWIDTH_HEIGHT] & 0xffff0000) >> 16;
- s3virge.s3d.bitblt_height = (s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_RWIDTH_HEIGHT] & 0x0000ffff);
- s3virge.s3d.bitblt_x_current = s3virge.s3d.bitblt_x_dst;
- s3virge.s3d.bitblt_x_src_current = s3virge.s3d.bitblt_x_src;
- s3virge.s3d.bitblt_y_current = s3virge.s3d.bitblt_y_dst;
- s3virge.s3d.bitblt_y_src_current = s3virge.s3d.bitblt_y_src;
- s3virge.s3d.bitblt_pat_x = s3virge.s3d.bitblt_x_current % 8;
- s3virge.s3d.bitblt_pat_y = s3virge.s3d.bitblt_y_current % 8;
- s3virge.s3d.clip_r = s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_CLIP_L_R] & 0x000007ff;
- s3virge.s3d.clip_l = (s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_CLIP_L_R] & 0x07ff0000) >> 16;
- s3virge.s3d.clip_b = s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_CLIP_T_B] & 0x000007ff;
- s3virge.s3d.clip_t = (s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_CLIP_T_B] & 0x07ff0000) >> 16;
- if(!(s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x00000080))
- m_draw_timer->adjust(attotime::from_nsec(250),0,attotime::from_nsec(250));
- s3virge.s3d.bitblt_step_count = 0;
- s3virge.s3d.bitblt_mono_pattern =
- s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_MONO_PAT_0] | (uint64_t)(s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_MONO_PAT_1]) << 32;
- s3virge.s3d.bitblt_current_pixel = 0;
- s3virge.s3d.bitblt_pixel_pos = 0;
- s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_PAT_BG_CLR] = 0xffffffff; // win31 never sets this?
- LOGCMD("Started BitBLT command [%u]\n", s3virge.s3d.cmd_fifo_current_ptr);
- //if(((s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x01fe0000) >> 17) == 0xf0) machine().debug_break();
- break;
- }
-}
-
-void s3virge_vga_device::command_finish()
-{
- s3virge.s3d.state = S3D_STATE_IDLE;
- s3virge.s3d.cmd_fifo_current_ptr++;
- if(s3virge.s3d.cmd_fifo_current_ptr >= 16)
- s3virge.s3d.cmd_fifo_current_ptr = 0;
- s3virge.s3d.cmd_fifo_slots_free++;
- if(s3virge.s3d.cmd_fifo_slots_free > 16)
- s3virge.s3d.cmd_fifo_slots_free = 16;
- m_draw_timer->adjust(attotime::never);
-
- // check if there is another command in the FIFO
- if(s3virge.s3d.cmd_fifo_slots_free < 16)
- command_start();
- else
- s3virge.s3d.busy = false;
-
- LOGMMIO("Command finished [%u] (%u slots free)\n",s3virge.s3d.cmd_fifo_current_ptr,s3virge.s3d.cmd_fifo_slots_free);
-}
-
-void s3virge_vga_device::line2d_step()
-{
- command_finish();
-}
-
-void s3virge_vga_device::poly2d_step()
-{
- command_finish();
-}
-
-void s3virge_vga_device::line3d_step()
-{
- command_finish();
-}
-
-void s3virge_vga_device::poly3d_step()
-{
- command_finish();
-}
-
-
-uint32_t s3virge_vga_device::GetROP(uint8_t rop, uint32_t src, uint32_t dst, uint32_t pat)
-{
- uint32_t ret = 0;
-
- switch(rop)
- {
- case 0x00: // 0
- ret = 0;
- break;
- case 0x55: // Dn
- ret = ~dst;
- break;
- case 0x5a: // DPx
- ret = dst ^ pat;
- break;
- case 0x66: // DSx
- ret = dst ^ src;
- break;
- case 0x88: // DSa
- ret = dst & src;
- break;
- case 0xb8: // PSDPxax
- ret = ((dst ^ pat) & src) ^ pat;
-// machine().debug_break();
- break;
- case 0xcc:
- ret = src;
- break;
- case 0xf0:
- ret = pat;
- break;
- case 0xff: // 1
- ret = 0xffffffff;
- break;
- default:
- popmessage("Unimplemented ROP 0x%02x",rop);
- }
-
- return ret;
-}
-
-bool s3virge_vga_device::advance_pixel()
-{
- bool xpos, ypos;
- int16_t top, left, right, bottom;
- // advance src/dst and pattern location
- xpos = s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x02000000; // X Positive
- ypos = s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x04000000; // Y Positive
- if(xpos)
- {
- left = s3virge.s3d.bitblt_x_dst;
- right = s3virge.s3d.bitblt_x_dst + s3virge.s3d.bitblt_width + 1;
- s3virge.s3d.bitblt_x_current++;
- s3virge.s3d.bitblt_x_src_current++;
- s3virge.s3d.bitblt_pat_x++;
- }
- else
- {
- left = s3virge.s3d.bitblt_x_dst - s3virge.s3d.bitblt_width - 1;
- right = s3virge.s3d.bitblt_x_dst;
- s3virge.s3d.bitblt_x_current--;
- s3virge.s3d.bitblt_x_src_current--;
- s3virge.s3d.bitblt_pat_x--;
-// machine().debug_break();
- }
- if(ypos)
- {
- top = s3virge.s3d.bitblt_y_dst;
- bottom = s3virge.s3d.bitblt_y_dst + s3virge.s3d.bitblt_height;
- }
- else
- {
- top = s3virge.s3d.bitblt_y_dst - s3virge.s3d.bitblt_height;
- bottom = s3virge.s3d.bitblt_y_dst;
- }
- if(s3virge.s3d.bitblt_pat_x < 0 || s3virge.s3d.bitblt_pat_x >= 8)
- s3virge.s3d.bitblt_pat_x = s3virge.s3d.bitblt_x_current % 8;
- if((s3virge.s3d.bitblt_x_current >= right) || (s3virge.s3d.bitblt_x_current <= left))
- {
- s3virge.s3d.bitblt_x_current = s3virge.s3d.bitblt_x_dst;
- s3virge.s3d.bitblt_x_src_current = s3virge.s3d.bitblt_x_src;
- if(ypos)
- {
- s3virge.s3d.bitblt_y_current++;
- s3virge.s3d.bitblt_y_src_current++;
- s3virge.s3d.bitblt_pat_y++;
- }
- else
- {
- s3virge.s3d.bitblt_y_current--;
- s3virge.s3d.bitblt_y_src_current--;
- s3virge.s3d.bitblt_pat_y--;
- }
- s3virge.s3d.bitblt_pat_x = s3virge.s3d.bitblt_x_current % 8;
- if(s3virge.s3d.bitblt_pat_y >= 8 || s3virge.s3d.bitblt_pat_y < 0)
- s3virge.s3d.bitblt_pat_y = s3virge.s3d.bitblt_y_current % 8;
- logerror("SRC: %i,%i DST: %i,%i PAT: %i,%i Bounds: %i,%i,%i,%i\n",
- s3virge.s3d.bitblt_x_src_current,s3virge.s3d.bitblt_y_src_current,
- s3virge.s3d.bitblt_x_current,s3virge.s3d.bitblt_y_current,
- s3virge.s3d.bitblt_pat_x,s3virge.s3d.bitblt_pat_y,
- left,right,top,bottom);
- if((s3virge.s3d.bitblt_y_current >= bottom) || (s3virge.s3d.bitblt_y_current <= top))
- return true;
- }
- return false;
-}
-
-void s3virge_vga_device::bitblt_step()
-{
- if((s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x40))
- bitblt_monosrc_step();
- else
- bitblt_colour_step();
-}
-
-void s3virge_vga_device::bitblt_colour_step()
-{
- // progress current BitBLT operation
- // get source and destination addresses
- uint32_t src_base = s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_SRC_BASE] & 0x003ffff8;
- uint32_t dst_base = s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_DEST_BASE] & 0x003ffff8;
- uint8_t pixel_size = (s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x0000001c) >> 2;
- uint8_t rop = (s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x01fe0000) >> 17;
- uint32_t src = 0;
- uint32_t dst = 0;
- uint32_t pat = 0;
- int align = (s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x000000c00) >> 10;
- int x;
- bool done = false;
-
- switch(pixel_size)
- {
- case 0: // 8bpp
- for(x=0;x<4;x++)
- {
- if(s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x80)
- src = s3virge.s3d.image_xfer >> (x*8);
- else
- src = read_pixel8(src_base,s3virge.s3d.bitblt_x_src_current,s3virge.s3d.bitblt_y_src_current);
- if(s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x100)
- {
- pat = (s3virge.s3d.bitblt_mono_pattern & (1 << ((s3virge.s3d.bitblt_pat_y*8) + (7-s3virge.s3d.bitblt_pat_x)))
- ? s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_PAT_FG_CLR] : s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_PAT_BG_CLR]);
- }
- else
- pat = (s3virge.s3d.pattern[(s3virge.s3d.bitblt_pat_y*8) + s3virge.s3d.bitblt_pat_x]) << 8;
- dst = read_pixel8(dst_base,s3virge.s3d.bitblt_x_current,s3virge.s3d.bitblt_y_current);
- write_pixel8(dst_base,s3virge.s3d.bitblt_x_current,s3virge.s3d.bitblt_y_current,GetROP(rop, src, dst, pat) & 0xff);
- done = advance_pixel();
- if(done)
- {
- command_finish();
- break;
- }
- if((s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x80) && s3virge.s3d.bitblt_x_current == s3virge.s3d.bitblt_x_dst)
- {
- if(align == 2) // doubleword aligned, end here
- break;
- if(align == 1) // word aligned, move to next word
- {
- if(x < 2)
- x = 2;
- else
- break;
- }
- }
- }
- break;
- case 1: // 16bpp
- if(s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x80)
- src = s3virge.s3d.image_xfer;
- else
- src = read_pixel16(src_base,s3virge.s3d.bitblt_x_src_current,s3virge.s3d.bitblt_y_src_current);
- dst = read_pixel16(dst_base,s3virge.s3d.bitblt_x_current,s3virge.s3d.bitblt_y_current);
- if(s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x100)
- {
- pat = (s3virge.s3d.bitblt_mono_pattern & (1 << ((s3virge.s3d.bitblt_pat_y*8) + (7-s3virge.s3d.bitblt_pat_x)))
- ? s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_PAT_FG_CLR] : s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_PAT_BG_CLR]);
- }
- else
- pat = s3virge.s3d.pattern[(s3virge.s3d.bitblt_pat_y*16) + (s3virge.s3d.bitblt_pat_x*2)] | (s3virge.s3d.pattern[(s3virge.s3d.bitblt_pat_y*16) + (s3virge.s3d.bitblt_pat_x*2) + 1]) << 8;
- write_pixel16(dst_base,s3virge.s3d.bitblt_x_current,s3virge.s3d.bitblt_y_current,GetROP(rop, src, dst, pat) & 0xffff);
- done = advance_pixel();
- if(done)
- {
- command_finish();
- break;
- }
- if((s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x80) && s3virge.s3d.bitblt_x_current == s3virge.s3d.bitblt_x_dst && align == 2)
- break; // if a new line of an image transfer, and is dword aligned, stop here
- if(s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x80)
- src = s3virge.s3d.image_xfer >> 16;
- else
- src = read_pixel16(src_base,s3virge.s3d.bitblt_x_src_current,s3virge.s3d.bitblt_y_src_current);
- dst = read_pixel16(dst_base,s3virge.s3d.bitblt_x_current,s3virge.s3d.bitblt_y_current);
- if(s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x100)
- {
- pat = (s3virge.s3d.bitblt_mono_pattern & (1 << ((s3virge.s3d.bitblt_pat_y*8) + (7-s3virge.s3d.bitblt_pat_x)))
- ? s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_PAT_FG_CLR] : s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_PAT_BG_CLR]);
- }
- else
- pat = s3virge.s3d.pattern[(s3virge.s3d.bitblt_pat_y*16) + (s3virge.s3d.bitblt_pat_x*2)] | (s3virge.s3d.pattern[(s3virge.s3d.bitblt_pat_y*16) + (s3virge.s3d.bitblt_pat_x*2) + 1]) << 8;
- write_pixel16(dst_base,s3virge.s3d.bitblt_x_current,s3virge.s3d.bitblt_y_current,GetROP(rop, src, dst, pat) & 0xffff);
- if(advance_pixel())
- command_finish();
- break;
- case 2: // 24bpp
- if(s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x80)
- {
- src = s3virge.s3d.image_xfer;
- for(x=0;x<4;x++)
- {
- s3virge.s3d.bitblt_current_pixel |= ((s3virge.s3d.image_xfer >> (x*8)) & 0xff) << s3virge.s3d.bitblt_pixel_pos*8;
- s3virge.s3d.bitblt_pixel_pos++;
- if(s3virge.s3d.bitblt_pixel_pos > 2)
- {
- s3virge.s3d.bitblt_pixel_pos = 0;
- dst = read_pixel24(dst_base,s3virge.s3d.bitblt_x_current,s3virge.s3d.bitblt_y_current);
- if(s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x100)
- {
- pat = (s3virge.s3d.bitblt_mono_pattern & (1 << ((s3virge.s3d.bitblt_pat_y*8) + (7-s3virge.s3d.bitblt_pat_x)))
- ? s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_PAT_FG_CLR] : s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_PAT_BG_CLR]);
- }
- else
- pat = s3virge.s3d.pattern[(s3virge.s3d.bitblt_pat_y*24) + (s3virge.s3d.bitblt_pat_x*3)] | (s3virge.s3d.pattern[(s3virge.s3d.bitblt_pat_y*24) + (s3virge.s3d.bitblt_pat_x*3) + 1]) << 8
- | (s3virge.s3d.pattern[(s3virge.s3d.bitblt_pat_y*24) + (s3virge.s3d.bitblt_pat_x*3) + 2]) << 16;
- write_pixel24(dst_base,s3virge.s3d.bitblt_x_current,s3virge.s3d.bitblt_y_current,GetROP(rop, s3virge.s3d.bitblt_current_pixel, dst, pat));
- s3virge.s3d.bitblt_current_pixel = 0;
- done = advance_pixel();
- if((s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x80) && s3virge.s3d.bitblt_x_current == s3virge.s3d.bitblt_x_dst)
- {
- if(align == 2) // doubleword aligned, end here
- x = 4;
- if(align == 1) // word aligned, move to next word
- {
- if(x < 2)
- x = 2;
- else
- x = 4;
- }
- }
- if(done)
- command_finish();
- }
- }
- break;
- }
- else
- {
- src = read_pixel24(src_base,s3virge.s3d.bitblt_x_src_current,s3virge.s3d.bitblt_y_src_current);
- dst = read_pixel24(dst_base,s3virge.s3d.bitblt_x_current,s3virge.s3d.bitblt_y_current);
- if(s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x100)
- {
- pat = (s3virge.s3d.bitblt_mono_pattern & (1 << ((s3virge.s3d.bitblt_pat_y*8) + (7-s3virge.s3d.bitblt_pat_x)))
- ? s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_PAT_FG_CLR] : s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_PAT_BG_CLR]);
- }
- else
- pat = s3virge.s3d.pattern[(s3virge.s3d.bitblt_pat_y*24) + (s3virge.s3d.bitblt_pat_x*3)] | (s3virge.s3d.pattern[(s3virge.s3d.bitblt_pat_y*24) + (s3virge.s3d.bitblt_pat_x*3) + 1]) << 8
- | (s3virge.s3d.pattern[(s3virge.s3d.bitblt_pat_y*24) + (s3virge.s3d.bitblt_pat_x*3) + 2]) << 16;
- }
- write_pixel24(dst_base,s3virge.s3d.bitblt_x_current,s3virge.s3d.bitblt_y_current,GetROP(rop, src, dst, pat));
- if(advance_pixel())
- command_finish();
- break;
- }
-
- s3virge.s3d.bitblt_step_count++;
-}
-
-void s3virge_vga_device::bitblt_monosrc_step()
-{
- // progress current monochrome source BitBLT operation
- uint32_t src_base = s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_SRC_BASE] & 0x003ffff8;
- uint32_t dst_base = s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_DEST_BASE] & 0x003ffff8;
- uint8_t pixel_size = (s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x0000001c) >> 2;
- uint8_t rop = (s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x01fe0000) >> 17;
- uint32_t src = 0;
- uint32_t dst = 0;
- uint32_t pat = 0;
- int align = (s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x000000c00) >> 10;
- int x;
- bool done = false;
-
- switch(pixel_size)
- {
- case 0: // 8bpp
- for(x=31;x>=0;x--)
- {
- if(s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x80)
- src = bitswap<32>(s3virge.s3d.image_xfer,7,6,5,4,3,2,1,0,15,14,13,12,11,10,9,8,23,22,21,20,19,18,17,16,31,30,29,28,27,26,25,24);
- else
- src = read_pixel8(src_base,s3virge.s3d.bitblt_x_src_current,s3virge.s3d.bitblt_y_src_current);
- dst = read_pixel8(dst_base,s3virge.s3d.bitblt_x_current,s3virge.s3d.bitblt_y_current);
-
- if(src & (1 << x))
- write_pixel8(dst_base,s3virge.s3d.bitblt_x_current,s3virge.s3d.bitblt_y_current,GetROP(rop, s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_SRC_FG_CLR], dst, pat) & 0xff);
- else if(!(s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x200)) // only draw background colour if transparency is not set
- write_pixel8(dst_base,s3virge.s3d.bitblt_x_current,s3virge.s3d.bitblt_y_current,GetROP(rop, s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_SRC_BG_CLR], dst, pat) & 0xff);
- //printf("Pixel write(%i): X: %i Y: %i SRC: %04x DST: %04x PAT: %04x ROP: %02x\n",x,s3virge.s3d.bitblt_x_current, s3virge.s3d.bitblt_y_current, src, dst, pat, rop);
- done = advance_pixel();
- if((s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x80) && s3virge.s3d.bitblt_x_current == s3virge.s3d.bitblt_x_dst)
- {
- switch(align)
- {
- case 0:
- x &= ~7;
- break;
- case 1:
- x &= ~15;
- break;
- case 2:
- x = -1;
- break;
- }
- if(done)
- {
- command_finish();
- break;
- }
- }
- }
- break;
- case 1: // 16bpp
- for(x=31;x>=0;x--)
- {
- if(s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x80)
- src = bitswap<32>(s3virge.s3d.image_xfer,7,6,5,4,3,2,1,0,15,14,13,12,11,10,9,8,23,22,21,20,19,18,17,16,31,30,29,28,27,26,25,24);
- else
- src = read_pixel16(src_base,s3virge.s3d.bitblt_x_src_current,s3virge.s3d.bitblt_y_src_current);
- dst = read_pixel16(dst_base,s3virge.s3d.bitblt_x_current,s3virge.s3d.bitblt_y_current);
-
- if(src & (1 << x))
- write_pixel16(dst_base,s3virge.s3d.bitblt_x_current,s3virge.s3d.bitblt_y_current,GetROP(rop, s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_SRC_FG_CLR], dst, pat) & 0xffff);
- else if(!(s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x200)) // only draw background colour if transparency is not set
- write_pixel16(dst_base,s3virge.s3d.bitblt_x_current,s3virge.s3d.bitblt_y_current,GetROP(rop, s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_SRC_BG_CLR], dst, pat) & 0xffff);
- //printf("Pixel write(%i): X: %i Y: %i SRC: %04x DST: %04x PAT: %04x ROP: %02x\n",x,s3virge.s3d.bitblt_x_current, s3virge.s3d.bitblt_y_current, src, dst, pat, rop);
- done = advance_pixel();
- if((s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x80) && s3virge.s3d.bitblt_x_current == s3virge.s3d.bitblt_x_dst)
- {
- switch(align)
- {
- case 0:
- x &= ~7;
- break;
- case 1:
- x &= ~15;
- break;
- case 2:
- x = -1;
- break;
- }
- if(done)
- {
- command_finish();
- break;
- }
- }
- }
- break;
- case 2: // 24bpp
- for(x=31;x>=0;x--)
- {
- if(s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x80)
- src = bitswap<32>(s3virge.s3d.image_xfer,7,6,5,4,3,2,1,0,15,14,13,12,11,10,9,8,23,22,21,20,19,18,17,16,31,30,29,28,27,26,25,24);
- else
- src = read_pixel24(src_base,s3virge.s3d.bitblt_x_src_current,s3virge.s3d.bitblt_y_src_current);
- dst = read_pixel24(dst_base,s3virge.s3d.bitblt_x_current,s3virge.s3d.bitblt_y_current);
-
- if(src & (1 << x))
- write_pixel24(dst_base,s3virge.s3d.bitblt_x_current,s3virge.s3d.bitblt_y_current,GetROP(rop, s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_SRC_FG_CLR], dst, pat));
- else if(!(s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x200)) // only draw background colour if transparency is not set
- write_pixel24(dst_base,s3virge.s3d.bitblt_x_current,s3virge.s3d.bitblt_y_current,GetROP(rop, s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_SRC_BG_CLR], dst, pat));
- //printf("Pixel write(%i): X: %i Y: %i SRC: %04x DST: %04x PAT: %04x ROP: %02x\n",x,s3virge.s3d.bitblt_x_current, s3virge.s3d.bitblt_y_current, src, dst, pat, rop);
- done = advance_pixel();
- if((s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x80) && s3virge.s3d.bitblt_x_current == s3virge.s3d.bitblt_x_dst)
- {
- switch(align)
- {
- case 0:
- x &= ~7;
- break;
- case 1:
- x &= ~15;
- break;
- case 2:
- x = -1;
- break;
- }
- if(done)
- {
- command_finish();
- break;
- }
- }
- }
- break;
- }
-
- s3virge.s3d.bitblt_step_count++;
-}
-
-TIMER_CALLBACK_MEMBER(s3virge_vga_device::draw_step_tick)
-{
- // TODO: S3D state timing
- switch(s3virge.s3d.state)
- {
- case S3D_STATE_IDLE:
- m_draw_timer->adjust(attotime::zero);
- break;
- case S3D_STATE_2DLINE:
- line2d_step();
- break;
- case S3D_STATE_2DPOLY:
- poly2d_step();
- break;
- case S3D_STATE_3DLINE:
- line3d_step();
- break;
- case S3D_STATE_3DPOLY:
- poly3d_step();
- break;
- case S3D_STATE_BITBLT:
- bitblt_step();
- break;
- }
-}
-
-inline void s3virge_vga_device::write_pixel32(uint32_t base, uint16_t x, uint16_t y, uint32_t val)
-{
- if(s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x00000002)
- if(x < s3virge.s3d.clip_l || x > s3virge.s3d.clip_r || y < s3virge.s3d.clip_t || y > s3virge.s3d.clip_b)
- return;
- vga.memory[(base + (x*4) + (y*dest_stride())) % vga.svga_intf.vram_size] = val & 0xff;
- vga.memory[(base + 1 + (x*4) + (y*dest_stride())) % vga.svga_intf.vram_size] = (val >> 8) & 0xff;
- vga.memory[(base + 2 + (x*4) + (y*dest_stride())) % vga.svga_intf.vram_size] = (val >> 16) & 0xff;
- vga.memory[(base + 3 + (x*4) + (y*dest_stride())) % vga.svga_intf.vram_size] = (val >> 24) & 0xff;
-}
-
-inline void s3virge_vga_device::write_pixel24(uint32_t base, uint16_t x, uint16_t y, uint32_t val)
-{
- if(s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x00000002)
- if(x < s3virge.s3d.clip_l || x > s3virge.s3d.clip_r || y < s3virge.s3d.clip_t || y > s3virge.s3d.clip_b)
- return;
- vga.memory[(base + (x*3) + (y*dest_stride())) % vga.svga_intf.vram_size] = val & 0xff;
- vga.memory[(base + 1 + (x*3) + (y*dest_stride())) % vga.svga_intf.vram_size] = (val >> 8) & 0xff;
- vga.memory[(base + 2 + (x*3) + (y*dest_stride())) % vga.svga_intf.vram_size] = (val >> 16) & 0xff;
-}
-
-inline void s3virge_vga_device::write_pixel16(uint32_t base, uint16_t x, uint16_t y, uint16_t val)
-{
- if(s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x00000002)
- if(x < s3virge.s3d.clip_l || x > s3virge.s3d.clip_r || y < s3virge.s3d.clip_t || y > s3virge.s3d.clip_b)
- return;
- vga.memory[(base + (x*2) + (y*dest_stride())) % vga.svga_intf.vram_size] = val & 0xff;
- vga.memory[(base + 1 + (x*2) + (y*dest_stride())) % vga.svga_intf.vram_size] = (val >> 8) & 0xff;
-}
-
-inline void s3virge_vga_device::write_pixel8(uint32_t base, uint16_t x, uint16_t y, uint8_t val)
-{
- if(s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x00000002)
- if(x < s3virge.s3d.clip_l || x > s3virge.s3d.clip_r || y < s3virge.s3d.clip_t || y > s3virge.s3d.clip_b)
- return;
- vga.memory[(base + x + (y*dest_stride())) % vga.svga_intf.vram_size] = val;
-}
-
-inline uint32_t s3virge_vga_device::read_pixel32(uint32_t base, uint16_t x, uint16_t y)
-{
- return (vga.memory[(base + (x*4) + (y*dest_stride())) % vga.svga_intf.vram_size] << 24) |
- (vga.memory[(base + 1 + (x*4) + (y*dest_stride())) % vga.svga_intf.vram_size] << 16) |
- (vga.memory[(base + 2 + (x*4) + (y*dest_stride())) % vga.svga_intf.vram_size] << 8) |
- vga.memory[(base + 3 + (x*4) + (y*dest_stride())) % vga.svga_intf.vram_size];
-}
-
-inline uint32_t s3virge_vga_device::read_pixel24(uint32_t base, uint16_t x, uint16_t y)
-{
- return (vga.memory[(base + (x*3) + (y*dest_stride())) % vga.svga_intf.vram_size]) |
- (vga.memory[(base + 1 + (x*3) + (y*dest_stride())) % vga.svga_intf.vram_size] << 8) |
- (vga.memory[(base + 2 + (x*3) + (y*dest_stride())) % vga.svga_intf.vram_size] << 16);
-}
-
-inline uint16_t s3virge_vga_device::read_pixel16(uint32_t base, uint16_t x, uint16_t y)
-{
- return (vga.memory[(base + (x*2) + (y*dest_stride()) % vga.svga_intf.vram_size)]) |
- (vga.memory[(base + 1 + (x*2) + (y*dest_stride())) % vga.svga_intf.vram_size] << 8);
-}
-
-inline uint8_t s3virge_vga_device::read_pixel8(uint32_t base, uint16_t x, uint16_t y)
-{
- return vga.memory[(base + x + (y*dest_stride())) % vga.svga_intf.vram_size];
-}
-
-// 2D command register format - A500 (BitBLT), A900 (2D line), AD00 (2D Polygon)
-// bit 0 - Autoexecute, if set command is executed when the highest relevant register is written to (A50C / A97C / AD7C)
-// bit 1 - Enable hardware clipping
-// bits 2-4 - Destination colour format - (0 = 8bpp palettised, 1 = 16bpp RGB1555 or RGB565, 2 = 24bpp RGB888
-// bit 5 - Draw enable - if reset, doesn't draw anything, but is still executed
-// bit 6 - Image source Mono transfer, if set source is mono, otherwise source is the same pixel depth as the destination
-// bit 7 - Image data source - 0 = source is in video memory, 1 = source is from the image transfer port (CPU / system memory)
-// bit 8 - Mono pattern - if set, pattern data is mono, otherwise pattern data is the same pixel depth as the destination
-// Cleared to 0 if using an ROP with a colour source Must be set to 1 if doing a rectangle fill operation
-// bit 9 - Transparency - if set, does not update if a background colour is selected. Effectively only if bit 7 is set, Typically used for text display.
-// bits 10-11 - Image transfer alignment - Data for an image transfer is byte (0), word (1), or doubleword (2) aligned. All image transfers are doubleword in size.
-// bits 12-13 - First doubleword offset - (Image transfers) - start with the given byte (+1) in a doubleword for an image transfer
-// bits 17-24 - MS Windows Raster Operation
-// bit 25 - X Positive - if set, BitBLT is performed from left to right, otherwise, from right to left
-// bit 26 - Y Positive - if set, BitBLT is performed from top to bottom, otherwise from bottom to top
-// bits 27-30 - 2D Command - 0000 = BitBLT, 0010 = Rectangle Fill, 0011 = Line Draw, 0101 = Polygon Fill, 1111 = NOP (Turns off autoexecute without executing a command)
-// bit 31 - 2D / 3D Select
-
-
-uint32_t s3virge_vga_device::s3d_sub_status_r()
-{
- uint32_t res = 0x00000000;
-
- if(!s3virge.s3d.busy)
- res |= 0x00002000; // S3d engine is idle
-
- //res |= (s3virge.s3d.cmd_fifo_slots_free << 8);
- if(s3virge.s3d.cmd_fifo_slots_free == 16)
- res |= 0x1f00;
-
- return res;
-}
-
-void s3virge_vga_device::s3d_sub_control_w(uint32_t data)
-{
- s3virge.interrupt_enable = data & 0x00003f80;
- // TODO: bits 14-15==10 - reset engine
- LOGMMIO("Sub control = %08x\n", data);
-}
-
-uint32_t s3virge_vga_device::s3d_func_ctrl_r()
-{
- uint32_t ret = 0;
-
- ret |= (s3virge.s3d.cmd_fifo_slots_free << 6);
- return ret;
-}
-
-uint32_t s3virge_vga_device::s3d_register_r(offs_t offset)
-{
- uint32_t res = 0;
- int op_type = (((offset*4) & 0x1c00) >> 10) - 1;
-
- // unused registers
- if(offset < 0x100/4)
- return 0;
- if(offset >= 0x1c0/4 && offset < 0x400/4)
- return 0;
-
- // handle BitBLT pattern registers
- if((offset >= 0x100/4) && (offset < 0x1c0/4))
- return s3virge.s3d.pattern[offset - (0x100/4)];
-
- res = s3virge.s3d.reg[op_type][((offset*4) & 0x03ff) / 4];
- LOGMMIO("MM%04X returning %08x\n", (offset*4)+0xa000, res);
-
- return res;
-}
-
-void s3virge_vga_device::s3d_register_w(offs_t offset, uint32_t data)
-{
- int op_type = (((offset*4) & 0x1c00) >> 10) - 1;
-
- // unused registers
- if(offset < 0x100/4)
- return;
- if(offset >= 0x1c0/4 && offset < 0x400/4)
- return;
-
- // handle BitBLT pattern registers
- if((offset >= 0x100/4) && (offset < 0x1c0/4))
- {
- //COMBINE_DATA(&s3virge.s3d.pattern[(offset*4) - (0x100/4)]);
- s3virge.s3d.pattern[((offset - 0x100/4)*4)+3] = (data & 0xff000000) >> 24;
- s3virge.s3d.pattern[((offset - 0x100/4)*4)+2] = (data & 0x00ff0000) >> 16;
- s3virge.s3d.pattern[((offset - 0x100/4)*4)+1] = (data & 0x0000ff00) >> 8;
- s3virge.s3d.pattern[((offset - 0x100/4)*4)] = (data & 0x000000ff);
- return;
- }
-
- s3virge.s3d.reg[op_type][((offset*4) & 0x03ff) / 4] = data;
- LOGMMIO("MM%04X = %08x\n", (offset*4)+0xa000, data);
- switch(offset)
- {
- case 0x500/4:
- if(!(data & 0x00000001))
- add_command(op_type);
- break;
- case 0x50c/4:
- if(s3virge.s3d.reg[op_type][S3D_REG_COMMAND] & 0x00000001) // autoexecute enabled
- add_command(op_type);
- break;
- }
-}
-
diff --git a/src/devices/bus/isa/s3virge.h b/src/devices/bus/isa/s3virge.h
deleted file mode 100644
index aec31340d7b..00000000000
--- a/src/devices/bus/isa/s3virge.h
+++ /dev/null
@@ -1,252 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Barry Rodewald
-/*
- * s3virge.h
- *
- * S3 ViRGE 2D/3D video card
- *
- */
-
-#ifndef MAME_BUS_ISA_S3VIRGE_H
-#define MAME_BUS_ISA_S3VIRGE_H
-
-#pragma once
-
-#include "video/pc_vga.h"
-
-// ======================> s3virge_vga_device
-
-class s3virge_vga_device : public s3_vga_device
-{
-public:
- // construction/destruction
- s3virge_vga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- auto linear_config_changed() { return m_linear_config_changed_cb.bind(); }
-
- virtual uint8_t port_03b0_r(offs_t offset) override;
- virtual void port_03b0_w(offs_t offset, uint8_t data) override;
- virtual uint8_t port_03c0_r(offs_t offset) override;
- virtual void port_03c0_w(offs_t offset, uint8_t data) override;
- virtual uint8_t port_03d0_r(offs_t offset) override;
- virtual void port_03d0_w(offs_t offset, uint8_t data) override;
- virtual uint8_t mem_r(offs_t offset) override;
- virtual void mem_w(offs_t offset, uint8_t data) override;
-
- uint8_t fb_r(offs_t offset);
- void fb_w(offs_t offset, uint8_t data);
- uint32_t s3d_sub_status_r();
- void s3d_sub_control_w(uint32_t data);
- uint32_t s3d_func_ctrl_r();
-
- uint32_t s3d_register_r(offs_t offset);
- void s3d_register_w(offs_t offset, uint32_t data);
-
- void image_xfer(uint32_t data)
- {
-// if(s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x00000080)
- {
-// logerror("IMG Xfer:(%u):%08x X:%u(%u) Y:%u(%u)\n",s3virge.s3d.bitblt_step_count,data,s3virge.s3d.bitblt_x_current,s3virge.s3d.bitblt_width,s3virge.s3d.bitblt_y_current,s3virge.s3d.bitblt_height);
- s3virge.s3d.image_xfer = data;
- bitblt_step();
- }
- }
-
- uint16_t get_crtc_port() { return (vga.miscellaneous_output&1)?0x3d0:0x3b0; }
- uint32_t get_linear_address() { return s3virge.linear_address; }
- void set_linear_address(uint32_t addr) { s3virge.linear_address = addr; }
- uint8_t get_linear_address_size() { return s3virge.linear_address_size; }
- uint32_t get_linear_address_size_full() { return s3virge.linear_address_size_full; }
- bool is_linear_address_active() { return s3virge.linear_address_enable; }
- bool is_new_mmio_active() { return s3.cr53 & 0x08; }
- uint16_t dest_stride()
- {
-// if((s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_COMMAND] & 0x0000001c) == 0x08)
-// {
-// popmessage("Stride=%08x",(((s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_DEST_SRC_STR] >> 16) & 0xfff8) / 3)
-// + ((s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_DEST_SRC_STR] >> 16) & 0xfff8));
-// return (((s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_DEST_SRC_STR] >> 16) & 0xfff8) / 3)
-// + ((s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_DEST_SRC_STR] >> 16) & 0xfff8);
-// }
-// else
- return (s3virge.s3d.cmd_fifo[s3virge.s3d.cmd_fifo_current_ptr].reg[S3D_REG_DEST_SRC_STR] >> 16) & 0xfff8;
- }
-
- ibm8514a_device* get_8514() { fatalerror("s3virge requested non-existent 8514/A device\n"); return nullptr; }
-
-protected:
- s3virge_vga_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
-
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual uint16_t offset() override;
-
- enum
- {
- LAW_64K = 0,
- LAW_1MB,
- LAW_2MB,
- LAW_4MB
- };
-
- // register groups
- enum
- {
- OP_BITBLT = 0,
- OP_2DLINE,
- OP_2DPOLY,
- OP_3DLINE,
- OP_3DTRI
- };
-
- enum
- {
- S3D_STATE_IDLE = 0,
- S3D_STATE_BITBLT,
- S3D_STATE_2DLINE,
- S3D_STATE_2DPOLY,
- S3D_STATE_3DLINE,
- S3D_STATE_3DPOLY
- };
-
- enum
- {
- S3D_REG_SRC_BASE = 0xd4/4,
- S3D_REG_DEST_BASE = 0xd8/4,
- S3D_REG_CLIP_L_R = 0xdc/4,
- S3D_REG_CLIP_T_B = 0xe0/4,
- S3D_REG_DEST_SRC_STR = 0xe4/4,
- S3D_REG_MONO_PAT_0 = 0xe8/4,
- S3D_REG_MONO_PAT_1 = 0xec/4,
- S3D_REG_PAT_BG_CLR = 0xf0/4,
- S3D_REG_PAT_FG_CLR = 0xf4/4,
- S3D_REG_SRC_BG_CLR = 0xf8/4,
- S3D_REG_SRC_FG_CLR = 0xfc/4,
- S3D_REG_COMMAND = 0x100/4,
- S3D_REG_RWIDTH_HEIGHT = 0x104/4,
- S3D_REG_RSRC_XY = 0x108/4,
- S3D_REG_RDEST_XY = 0x10c/4
- };
-
- struct
- {
- uint32_t linear_address;
- uint8_t linear_address_size;
- uint32_t linear_address_size_full;
- bool linear_address_enable;
- uint32_t interrupt_enable;
-
- struct
- {
- int state;
- bool busy;
- struct
- {
- uint32_t reg[256];
- int op_type;
- } cmd_fifo[16];
- int cmd_fifo_next_ptr; // command added here in FIFO
- int cmd_fifo_current_ptr; // command currently being processed in FIFO
- int cmd_fifo_slots_free;
-
- uint8_t pattern[0xc0];
- uint32_t reg[5][256];
-
- // BitBLT command state
- uint16_t bitblt_x_src;
- uint16_t bitblt_y_src;
- uint16_t bitblt_x_dst;
- uint16_t bitblt_y_dst;
- int16_t bitblt_x_current;
- int16_t bitblt_y_current;
- int16_t bitblt_x_src_current;
- int16_t bitblt_y_src_current;
- int8_t bitblt_pat_x;
- int8_t bitblt_pat_y;
- uint16_t bitblt_height;
- uint16_t bitblt_width;
- uint32_t bitblt_step_count;
- uint64_t bitblt_mono_pattern;
- uint32_t bitblt_current_pixel;
- uint32_t bitblt_pixel_pos; // current position in a pixel (for packed 24bpp colour image transfers)
- uint32_t image_xfer; // source data via image transfer ports
- uint16_t clip_l;
- uint16_t clip_r;
- uint16_t clip_t;
- uint16_t clip_b;
- } s3d;
- } s3virge;
-
- TIMER_CALLBACK_MEMBER(draw_step_tick);
-
- inline void write_pixel32(uint32_t base, uint16_t x, uint16_t y, uint32_t val);
- inline void write_pixel24(uint32_t base, uint16_t x, uint16_t y, uint32_t val);
- inline void write_pixel16(uint32_t base, uint16_t x, uint16_t y, uint16_t val);
- inline void write_pixel8(uint32_t base, uint16_t x, uint16_t y, uint8_t val);
- inline uint32_t read_pixel32(uint32_t base, uint16_t x, uint16_t y);
- inline uint32_t read_pixel24(uint32_t base, uint16_t x, uint16_t y);
- inline uint16_t read_pixel16(uint32_t base, uint16_t x, uint16_t y);
- inline uint8_t read_pixel8(uint32_t base, uint16_t x, uint16_t y);
-
- uint32_t GetROP(uint8_t rop, uint32_t src, uint32_t dst, uint32_t pat);
- bool advance_pixel();
-
- devcb_write_line m_linear_config_changed_cb;
-
-private:
- emu_timer* m_draw_timer;
- void bitblt_step();
- void bitblt_colour_step();
- void bitblt_monosrc_step();
- void line2d_step();
- void poly2d_step();
- void line3d_step();
- void poly3d_step();
- void add_command(int cmd_type);
- void command_start();
- void command_finish();
-
- virtual uint8_t s3_crtc_reg_read(uint8_t index);
- virtual void s3_define_video_mode(void);
- virtual void s3_crtc_reg_write(uint8_t index, uint8_t data);
- // has no 8514/A device
-};
-
-
-// ======================> s3virgedx_vga_device
-
-class s3virgedx_vga_device : public s3virge_vga_device
-{
-public:
- // construction/destruction
- s3virgedx_vga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- s3virgedx_vga_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
-
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
-};
-
-// ======================> s3virgedx_vga_device
-
-class s3virgedx_rev1_vga_device : public s3virgedx_vga_device
-{
-public:
- // construction/destruction
- s3virgedx_rev1_vga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
-};
-
-// device type definition
-DECLARE_DEVICE_TYPE(S3VIRGE, s3virge_vga_device)
-DECLARE_DEVICE_TYPE(S3VIRGEDX, s3virgedx_vga_device)
-DECLARE_DEVICE_TYPE(S3VIRGEDX1, s3virgedx_rev1_vga_device)
-
-#endif // MAME_BUS_ISA_S3VIRGE_H
diff --git a/src/devices/bus/isa/sblaster.cpp b/src/devices/bus/isa/sblaster.cpp
index 33905e05da3..c073dd6fe07 100644
--- a/src/devices/bus/isa/sblaster.cpp
+++ b/src/devices/bus/isa/sblaster.cpp
@@ -69,7 +69,7 @@ static const int m_cmd_fifo_length[256] =
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* Ax */
4, -1, 4, -1, 4, -1, 4, -1, 4, -1, -1, -1, -1, -1, 4, -1, /* Bx */
4, -1, 4, -1, 4, -1, 4, -1, 4, -1, -1, -1, -1, -1, 4, -1, /* Cx */
- 1, 1, -1, 1, -1, 1, 1, -1, 1, 1, 1, -1, -1, -1, -1, -1, /* Dx */
+ 1, 1, -1, 1, 1, 1, 1, -1, 1, 1, 1, -1, -1, -1, -1, -1, /* Dx */
2, 1, 2, 1, 2, -1, -1, -1, 1, -1, -1, -1, -1, -1, -1, -1, /* Ex */
-1, -1, 1, -1, -1, -1, -1, -1, 1, -1, -1, -1, 1, -1, -1, -1 /* Fx */
};
@@ -569,13 +569,16 @@ void sb_device::process_fifo(uint8_t cmd)
case 0x42: // set input sample rate
m_dsp.adc_freq = m_dsp.fifo[2] + (m_dsp.fifo[1] << 8);
break;
+ case 0xd4: // continue 8-bit dma
+ drq_w(1);
+ break;
case 0xd5: // pause 16-bit dma
m_timer->adjust(attotime::never, 0);
drq16_w(0); // drop DRQ
m_dsp.dma_throttled = false;
m_dsp.dma_timer_started = false;
break;
- case 0xd6: // resume 16-bit dma
+ case 0xd6: // continue 16-bit dma
logerror("SB: 16-bit dma resume\n");
break;
case 0xd9: // stop 16-bit autoinit
@@ -1818,3 +1821,21 @@ void sb_device::xmit_char(uint8_t data)
m_tx_waiting++;
}
}
+
+void isa16_sblaster16_device::remap(int space_id, offs_t start, offs_t end)
+{
+ if (space_id == AS_IO)
+ {
+ ymf262_device &ymf262 = *subdevice<ymf262_device>("ymf262");
+ m_isa->install_device(0x0200, 0x0207, read8smo_delegate(*subdevice<pc_joy_device>("pc_joy"), FUNC(pc_joy_device::joy_port_r)), write8smo_delegate(*subdevice<pc_joy_device>("pc_joy"), FUNC(pc_joy_device::joy_port_w)));
+ m_isa->install_device(0x0226, 0x0227, read8sm_delegate(*this, FUNC(sb_device::dsp_reset_r)), write8sm_delegate(*this, FUNC(sb_device::dsp_reset_w)));
+ m_isa->install_device(0x022a, 0x022b, read8sm_delegate(*this, FUNC(sb_device::dsp_data_r)), write8sm_delegate(*this, FUNC(sb_device::dsp_data_w)));
+ m_isa->install_device(0x022c, 0x022d, read8sm_delegate(*this, FUNC(sb_device::dsp_wbuf_status_r)), write8sm_delegate(*this, FUNC(sb_device::dsp_cmd_w)));
+ m_isa->install_device(0x022e, 0x022f, read8sm_delegate(*this, FUNC(sb_device::dsp_rbuf_status_r)), write8sm_delegate(*this, FUNC(sb_device::dsp_rbuf_status_w)));
+ m_isa->install_device(0x0224, 0x0225, read8sm_delegate(*this, FUNC(sb16_device::mixer_r)), write8sm_delegate(*this, FUNC(sb16_device::mixer_w)));
+ m_isa->install_device(0x0330, 0x0331, read8sm_delegate(*this, FUNC(sb16_device::mpu401_r)), write8sm_delegate(*this, FUNC(sb16_device::mpu401_w)));
+ m_isa->install_device(0x0388, 0x038b, read8sm_delegate(ymf262, FUNC(ymf262_device::read)), write8sm_delegate(ymf262, FUNC(ymf262_device::write)));
+ m_isa->install_device(0x0220, 0x0223, read8sm_delegate(ymf262, FUNC(ymf262_device::read)), write8sm_delegate(ymf262, FUNC(ymf262_device::write)));
+ m_isa->install_device(0x0228, 0x0229, read8sm_delegate(ymf262, FUNC(ymf262_device::read)), write8sm_delegate(ymf262, FUNC(ymf262_device::write)));
+ }
+}
diff --git a/src/devices/bus/isa/sblaster.h b/src/devices/bus/isa/sblaster.h
index f09f05957be..1443f2fa09c 100644
--- a/src/devices/bus/isa/sblaster.h
+++ b/src/devices/bus/isa/sblaster.h
@@ -37,7 +37,7 @@ public:
void dsp_rbuf_status_w(offs_t offset, uint8_t data);
void dsp_cmd_w(offs_t offset, uint8_t data);
- DECLARE_WRITE_LINE_MEMBER( midi_rx_w ) { device_serial_interface::rx_w((uint8_t)state); }
+ void midi_rx_w(int state) { device_serial_interface::rx_w((uint8_t)state); }
protected:
void common(machine_config &config);
@@ -244,6 +244,7 @@ protected:
// optional information overrides
virtual void device_add_mconfig(machine_config &config) override;
+ virtual void remap(int space_id, offs_t start, offs_t end) override;
};
// device type definition
diff --git a/src/devices/bus/isa/sc499.cpp b/src/devices/bus/isa/sc499.cpp
index a670bb38aa4..f7775f83a75 100644
--- a/src/devices/bus/isa/sc499.cpp
+++ b/src/devices/bus/isa/sc499.cpp
@@ -1295,19 +1295,19 @@ void sc499_ctape_image_device::write_block(int block_num, uint8_t *ptr)
memcpy(&m_ctape_data[block_num * SC499_CTAPE_BLOCK_SIZE], ptr, SC499_CTAPE_BLOCK_SIZE);
}
-image_init_result sc499_ctape_image_device::call_load()
+std::pair<std::error_condition, std::string> sc499_ctape_image_device::call_load()
{
try
{
auto const size = length();
m_ctape_data.resize(size);
if (!fseek(0, SEEK_SET) && (fread(m_ctape_data.data(), size) == size))
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
catch (...)
{
}
- return image_init_result::FAIL;
+ return std::make_pair(image_error::UNSPECIFIED, std::string());
}
void sc499_ctape_image_device::call_unload()
@@ -1320,3 +1320,7 @@ void sc499_ctape_image_device::call_unload()
// fwrite(m_ctape_data, m_ctape_data.size);
//}
}
+
+void sc499_ctape_image_device::device_start()
+{
+}
diff --git a/src/devices/bus/isa/sc499.h b/src/devices/bus/isa/sc499.h
index ffcd8c37a85..8bb94221b41 100644
--- a/src/devices/bus/isa/sc499.h
+++ b/src/devices/bus/isa/sc499.h
@@ -13,7 +13,8 @@
#pragma once
-#include "bus/isa/isa.h"
+#include "isa.h"
+
#include "imagedev/magtape.h"
@@ -29,8 +30,8 @@ public:
// construction/destruction
sc499_ctape_image_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- // image-level overrides
- virtual image_init_result call_load() override;
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
virtual void call_unload() override;
virtual bool support_command_line_image_creation() const noexcept override { return true; }
@@ -44,8 +45,8 @@ public:
uint64_t tapelen() { return m_ctape_data.size(); }
protected:
- // device-level overrides
- virtual void device_start() override { }
+ // device_t implementation
+ virtual void device_start() override;
std::vector<uint8_t> m_ctape_data;
};
diff --git a/src/devices/bus/isa/side116.cpp b/src/devices/bus/isa/side116.cpp
index bad6645bf5a..de47081b9fd 100644
--- a/src/devices/bus/isa/side116.cpp
+++ b/src/devices/bus/isa/side116.cpp
@@ -176,7 +176,7 @@ void side116_device::write(offs_t offset, uint8_t data)
}
}
-WRITE_LINE_MEMBER( side116_device::ide_interrupt )
+void side116_device::ide_interrupt(int state)
{
uint8_t level = m_config->read() & 0x18;
diff --git a/src/devices/bus/isa/side116.h b/src/devices/bus/isa/side116.h
index 380e6206222..919785d86b7 100644
--- a/src/devices/bus/isa/side116.h
+++ b/src/devices/bus/isa/side116.h
@@ -43,7 +43,7 @@ protected:
virtual const tiny_rom_entry *device_rom_region() const override;
private:
- DECLARE_WRITE_LINE_MEMBER( ide_interrupt );
+ void ide_interrupt(int state);
required_device<ata_interface_device> m_ata;
required_ioport m_config;
diff --git a/src/devices/bus/isa/svga_cirrus.cpp b/src/devices/bus/isa/svga_cirrus.cpp
index 750d0f41142..9cf220bbcf1 100644
--- a/src/devices/bus/isa/svga_cirrus.cpp
+++ b/src/devices/bus/isa/svga_cirrus.cpp
@@ -11,13 +11,56 @@
#include "screen.h"
+// no ROMs were found for the Cirrus Logic CL-GD410/420, CL-GD6410, CL-GD6420, CL-GD6235, CL-GD6440, CL-GD7543, CL-GD7548, CL-GD5480
+// *.vbi dumps were done with the NSSI utility
ROM_START( dm_clgd5430 )
+ // Diamond Speedstar Pro SE V1.00 - 8bit VL card - Chip: CL-GD5430-446AM - OSC: 14.31818MHz - RAM: 1MB - Connector: DB15 - VESA feature connector
ROM_REGION(0x8000,"dm_clgd5430", 0)
ROM_LOAD("speedstar_pro_se_v1.00.u2", 0x00000, 0x8000, CRC(ed79572c) SHA1(15131e2b2db7a34971083a250e4a21ab7bd64a9d) )
ROM_IGNORE( 0x8000 )
ROM_END
+// unemulated Chipsets from the CL-GD5430 onwards
+
+/*
+ Cirrus Logic CL-GD543x - ISA cards
+
+// Diamond Speedstar 64 ISA Rev. A3A - Chip: CL-GD5434-J-QC-F - RAM: 2MB - ROM: 32KB V2.02 - OSC: 14.31818MHz - Connector: DB15 - VESA feature connector
+// a v2.01 exists as well
+ROM_START( diass64 )
+ ROM_REGION(0x08000, "clgd543x_isa", 0)
+ ROM_LOAD("diamond_multimedia_speedstar64_v2.02.bin", 0x00000, 0x08000, CRC(7423bca7) SHA1(20bf727218688f8ecd4e7a1607ee5c6260ee01eb) )
+ROM_END
+
+// STB Nitro 64 ISA - ROM: CL-GD543x VGA BIOS Version 1.22 (a 1.1 exists) - RAM: 1MB, 2MB - Chip: Cirrus Logic CL-GD5434 - Connector: DB15 - VESA feature connector - OSC: 14.31818 MHz
+ROM_START( nitro64 )
+ ROM_REGION(0x08000, "clgd543x_isa", 0)
+ ROM_LOAD("nitro64.vbi", "0x00000, 0x8000, CRC(269704bb), SHA1(8a7f5c3c107c3300a82a8cb42e19f9411d8ca0c1) )
+ROM_END
+
+*/
+
+/*
+ Cirrus Logic CL-GD543x - VLB cards
+
+Source: ROM dump - MVA-CL5434 8bit VLB VGA card - Chips: CL-GD5434-HC-D - ROM: VL R1.10B, CKS: 6400H - OSC: 14.31818 - Connector: DB15 - VESA feature connector
+ROM_START( clgd543x_vlb )
+ ROM_REGION(0x10000, "clgd543x_vlb", 0)
+ ROM_SYSTEM_BIOS(0, "mvacl5434", "MVA-CL5434 8bit VLB VGA card")
+ ROMX_LOAD("mva_clgd5434_27c512.bin", 0x00000, 0x10000, CRC(811aecef) SHA1(0a65d2d3640936492d2f2a4ac8d07897343b15ef), ROM_BIOS(0) )
+ Kelvin 64 / EZ - Source: EPROM dump, Pulled from a non-working card - ROM: CL-GD543x VGA BIOS Version 1.00a - OSC: 14.31818 MHz
+ ROM_SYSTEM_BIOS(1, "kel64ez", "Orchid Kelvin 64 EZ VLB")
+ ROMX_LOAD("ogvlb.bin", 0x08000, 0x8000, CRC(16af65bb) SHA1(16db72ebc67f5dea81418cf25e562eb6da00218c), ROM_BIOS(1) )
+ // Orchid Kelvin 64 MPEG - 16bit VLB - Chips: Cirrus Logic CL-GD5434, Alliance ProMotion-6410, Analog Devices ADSP-2105 KP-40 ED/AA0888-1.1, MUSIC MU9C4870-80DC
+ // ROM: Kelvin 64-VLB BIOS Ver 1.10B - OSC: 14.318180 Mhz, 55.000 MHz, unreadable - Connectors: DB15, 2x3.5mm jacks - Potentiometer on rear bracket
+ ROM_SYSTEM_BIOS(2, "kelmpeg", "Orchid Kelvin MPEG Version 1.10B")
+ ROMX_LOAD("kelvin64_mpeg.bin", 0x00000, 0x10000, CRC(403020a4) SHA1(1ee70f6cc3c7b9a9afb402a1bc939f9f2e0cc739), ROM_BIOS(2) )
+ROM_END
+
+*/
+
+
//**************************************************************************
// GLOBAL VARIABLES
//**************************************************************************
@@ -34,9 +77,9 @@ void isa16_svga_cirrus_device::device_add_mconfig(machine_config &config)
{
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
screen.set_raw(25.175_MHz_XTAL, 800, 0, 640, 524, 0, 480);
- screen.set_screen_update("vga", FUNC(cirrus_gd5430_device::screen_update));
+ screen.set_screen_update("vga", FUNC(cirrus_gd5430_vga_device::screen_update));
- CIRRUS_GD5430(config, m_vga, 0);
+ CIRRUS_GD5430_VGA(config, m_vga, 0);
m_vga->set_screen("screen");
m_vga->set_vram_size(0x200000);
}
@@ -65,6 +108,11 @@ isa16_svga_cirrus_device::isa16_svga_cirrus_device(const machine_config &mconfig
{
}
+void isa16_svga_cirrus_device::io_isa_map(address_map &map)
+{
+ map(0x00, 0x2f).m(m_vga, FUNC(cirrus_gd5430_vga_device::io_map));
+}
+
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
@@ -76,11 +124,8 @@ void isa16_svga_cirrus_device::device_start()
m_isa->install_rom(this, 0xc0000, 0xc7fff, "dm_clgd5430");
- m_isa->install_device(0x03b0, 0x03bf, read8sm_delegate(*m_vga, FUNC(cirrus_gd5430_device::port_03b0_r)), write8sm_delegate(*m_vga, FUNC(cirrus_gd5430_device::port_03b0_w)));
- m_isa->install_device(0x03c0, 0x03cf, read8sm_delegate(*m_vga, FUNC(cirrus_gd5430_device::port_03c0_r)), write8sm_delegate(*m_vga, FUNC(cirrus_gd5430_device::port_03c0_w)));
- m_isa->install_device(0x03d0, 0x03df, read8sm_delegate(*m_vga, FUNC(cirrus_gd5430_device::port_03d0_r)), write8sm_delegate(*m_vga, FUNC(cirrus_gd5430_device::port_03d0_w)));
-
- m_isa->install_memory(0xa0000, 0xbffff, read8sm_delegate(*m_vga, FUNC(cirrus_gd5430_device::mem_r)), write8sm_delegate(*m_vga, FUNC(cirrus_gd5430_device::mem_w)));
+ m_isa->install_memory(0xa0000, 0xbffff, read8sm_delegate(*m_vga, FUNC(cirrus_gd5430_vga_device::mem_r)), write8sm_delegate(*m_vga, FUNC(cirrus_gd5430_vga_device::mem_w)));
+ m_isa->install_device(0x03b0, 0x03df, *this, &isa16_svga_cirrus_device::io_isa_map);
}
//-------------------------------------------------
@@ -91,6 +136,97 @@ void isa16_svga_cirrus_device::device_reset()
{
}
+// unemulated chipsets up to the CL-GD542x
+
+/*
+ Cirrus Logic CL-GD510/520
+
+
+ROM_START( clgd510 )
+ // Source: ROM dump - 8bit ISA card - Chips: Cirrus Logic CL-GD520A-40PC-A, GL-GD510A-32PC-A, UMBC82C11 - OSC: 32.514MhZ, 25.175MHz, 28.322MHz
+ // ROM: VGA/P-II 27256 U24 VER 2.00 - GAL: VGA/P(I.II) R0 U32 16L8A, VGA/P(I.II) R0 U6 16L8A - Connectors: DB15, DB9 - DIP: 8-way
+ ROM_REGION(0x08000, "clgd510", 0)
+ ROM_SYSTEM_BIOS(0, "eaglevgapii_v2.00", "Eagle VGA-PII V2.00")
+ ROMX_LOAD("eagle_ii_vga_bios_vga_p-ii_27256_u24_ver2.00.bin", 0x00000, 0x08000, CRC(90b7e179) SHA1(d22988c3d31ba457c24ef9b798baf41dd3017b61), ROM_BIOS(0) )
+ ROM_SYSTEM_BIOS(1, "eaglevgapii_v2.12", "Eagle VGA-PII V2.12")
+ ROMX_LOAD("gd510520.vbi", 0x00000, 0x08000, CRC(750b13db) SHA1(4c8bbf5e5d88988d48ad708fe794d5bb2aa6d8a1), ROM_BIOS(1) )
+ ROM_SYSTEM_BIOS(2, "morse_v.220", "Morse KP 800/16 V2.20")
+ ROMX_LOAD("kp800-16.vbi", 0x00000, 0x08000, CRC(7ec61c15) SHA1(1deeba9dcfa920952c92b0e44752dd169f4a145c), ROM_BIOS(2) )
+ // Morse KP 800 VGA - 8bit ISA VGA card - Source: EPROM dump - Chips: CL-GD520A-32PC-B, CL-GD510, PAL18L8ACN, Inmos A B171S-35C - ROM: Eagle II VGA BIOS Version 2.12
+ // RAM: 256KB - OSC: 28.322000 MHz, 32.514000 MHz, 25.175000MHz - Connectors: DB15, DB9 - DIP: 8-way
+ ROM_SYSTEM_BIOS(3, "morse_v212", "Morse KP 800 V2.12")
+ ROMX_LOAD("morse_kp800_vga_cl-gd520a-32pc-b.bin", 0x00000, 0x08000, CRC(9a12e070) SHA1(536046c6c2549d8cc16a546d5ec1739d647486d7), ROM_BIOS(3) )
+ // Videoseven VEGA VGA 8bit ISA graphics card - RAM: 256KB - Chips: Cirrus Logic CL-GD540A-32PC-C, AM81C178-50PC, CL-GD510A-32PC-B -
+ // Connectors: DB9, DB15, 32pin, 6pin - DIP: 6 way
+ ROM_SYSTEM_BIOS(4, "v7vegavga147", "Videoseven VEGA VGA Version 1.47")
+ ROMX_LOAD("v7_vega_vga_62L1989V5_435-0016-47.bin", 0x00000, 0x08000, CRC(79daa514) SHA1(cc3fc6bf54ba2668ae0083f917e91beb78894e30), ROM_BIOS(4) )
+ ROM_SYSTEM_BIOS(5, "v7vegavga178", "Videoseven VEGA VGA Version 1.78")
+ ROMX_LOAD("vegavga.vbi", 0x00000, 0x08000, CRC(438c6790) SHA1(16abdc1bc3cd38f13ce16dc11fa4e99f169b9807), ROM_BIOS(5) )
+ROM_END
+
+*/
+
+/*
+ Cirrus Logic CL-GD610/620 flat panel controller
+
+// KS-750V/3100V 16bit ISA LCD display card Ver:A3 - Chips: Inmos 99113-D IMSG171P-50G, CL-GD620-32QC-C, CL-GD610-320C-C - OSC: 25.175000 MHz, 32.514 MHz, 28.322MHz, 24.000MHz
+// Connectors: internal, DB9, DB15 - RAM: 256KB - DIP: 8 way
+ROM_START( clgd610 )
+ ROM_REGION(0x08000, "clgd610", 0)
+ ROM_LOAD("ks-750v.vbi", 0x00000, 0x08000, CRC(1bc7cd1d) SHA1(fdc29cc261b0efbfeec21b0c0f68d79323cf8604) )
+ROM_END
+
+*/
+
+/*
+ Cirrus Logic CL-GD5320
+
+// CVGA-V3-256 16bit ISA Cirrus Logic CL-GD5320 card - Chips: CL-GD5320-36QC-B, RAMDAC JT82C176-66 - Connector: DB15 - OSC: 25.175 MHz, 28.322 MHz, 36.000 MHz, 40.000 MHz, RAM: 256KB
+ROM_START( clgd5320 )
+ ROM_REGION(0x08000, "clgd532", 0)
+ ROM_LOAD("5320.vbi", 0x00000, 0x08000, CRC(633ad9c6) SHA1(bc66f77b819ea00065216dbf94d4bf1f142f95c9) )
+ROM_END
+
+*/
+
+/*
+ Cirrus Logic CL-GD5401 - Acumos AVGA1
+
+ROM_START( clgd5401 )
+ ROM_REGION(0x08000, "clgd5401", 0)
+ // ROM: originally even/odd ROMs marked VA30 Ver 1.00 (c) 1991 EIZO Corp - RAM: 256KB - Connector: DB15 - VESA feature connector - Chip: AVGA1
+ ROM_SYSTEM_BIOS(0, "eizova30", "Eizo VA30 V1.00")
+ ROMX_LOAD("eizova30.vbi", 0x02000, 0x06000, CRC(17c2c190) SHA1(081ec7dea9aff0e4577892909802d6e9a620dcf7), ROM_BIOS(0) )
+ //Acumos AVGA1 16bit ISA card - ROM: VGA1 BIOS Ver B 1.00 07 321-01 9210S - RAM: 256KB - Chip: acumos AVGA1 320-01 PC2561TK 9210 - Connector: DB15 - 26pin Edge connector
+ ROM_SYSTEM_BIOS(1, "version_b", "Version B")
+ ROMX_LOAD("32001withlogo.vbi", 0x02000, 0x06000, CRC(5619d4a9) SHA1(4f1b1f78c363e004124715c980b996bd1dcc54af), ROM_BIOS(1) )
+ ROM_SYSTEM_BIOS(2, "version_d", "Version D")
+ ROMX_LOAD("nousa.bin", 0x00000, 0x08000, CRC(797f0767) SHA1(a318367d385d7185cdd3d73838677f52c4a8cefb), ROM_BIOS(2) )
+ ROM_SYSTEM_BIOS(3, "vga1_v1.00_07_d", "VGA1 BIOS v1.00 07 D"
+ ROMX_LOAD("avga1.bin", 0x00000, 0x08000, CRC(6722ee8b) SHA1(1c90327888e803705e61a4d49629720f4ee9b7a5), ROM_SKIP(1) | ROM_BIOS(3) )
+ ROM_CONTINUE( 0x00001, 0x04000 )
+ ROM_SYSTEM_BIOS(4, "nover", "No revision shown"
+ ROMX_LOAD("avga1.rom", 0x00000, 0x08000 CRC(0f562e1f) SHA1(8a0808fe0bc31ecd51ffa1a0a31902da0e9541d4), ROM_BIOS(4) )
+ // ISA16 - Chip: CL-GD5401-42QC-B - RAM: 256KB - MicroMax M5401 V321-01 REV. 3 MADE IN U.S.A. - FCC ID: IWLVGAADAPTER 1V1
+ ROM_SYSTEM_BIOS(5, "micromax", "MicroMax M5401 V321-01 rev.3")
+ ROMX_LOAD("cl5401.bin", 0x00000, 0x08000, CRC(a40551d6) SHA1(db38190f06e4af2c2d59ae310e65883bb16cd3d6), ROM_SKIP(1) | ROM_BIOS(5) )
+ ROM_CONTINUE( 0x00001, 0x04000 )
+ROM_END
+
+*/
+
+/*
+ Cirrus Logic CL-GD5402 / Acumos AVGA2
+
+// 16bit ISA graphics card - Chips: acumos AVGA2 340-01 10908 9228 - RAM: 512KB - Connector: DB15 - VESA feature connector
+
+ROM_START( clgd5402 )
+ ROM_REGION(0x10000, "clgd5402", 0)
+ ROM_LOAD16_BYTE("avga2vram.vbi", 0x08000, 0x10000, CRC(ef4fc687) SHA1(8be0fe065c652d6a39d742df8f217c914574b701) )
+ROM_END
+
+*/
+
/*
Generic CL-GD542x video card
@@ -98,8 +234,62 @@ void isa16_svga_cirrus_device::device_reset()
ROM_START( clgd542x )
ROM_REGION(0x08000, "clgd542x", 0)
- ROM_LOAD16_BYTE("techyosd-isa-bios-v1.2.u8", 0x00000, 0x04000, CRC(6adf7e71) SHA1(2b07d964cc7c2c0aa560625b7c12f38d4537d652) )
- ROM_CONTINUE( 0x00001, 0x04000 )
+ ROM_SYSTEM_BIOS(0, "techyosd_v1.2", "techyosd-isa-bios-v1.2")
+ ROMX_LOAD("techyosd-isa-bios-v1.2.u8", 0x00000, 0x04000, CRC(6adf7e71) SHA1(2b07d964cc7c2c0aa560625b7c12f38d4537d652), ROM_SKIP(1) | ROM_BIOS(0) )
+ ROM_CONTINUE( 0x00001, 0x04000 )
+ // Source: ROM Dump, the chip is marked TECHYOSD VL-BIOS V1.2 9323
+ // From an 8-Bit VL-Bus VGA Card GT M 94V-0 using the Cirrus Logic CL-GD5426-800C-A chip - 1 MB RAM - OSC 14.31818 - VESA feature connector, DB15 connector
+ ROM_SYSTEM_BIOS(1, "techyosd_v1.2_a", "techyosd-isa-bios-v1.2 alt. dump")
+ ROMX_LOAD("cl_gt_m_94v-0.bin", 0x00000, 0x04000, CRC(9eea184a) SHA1(b70ff57405830110c3ccc5313bcd736c8dcd9b81), ROM_SKIP(1) | ROM_BIOS(1) )
+ ROM_CONTINUE( 0x00001, 0x04000 )
+ // Boca Research BRI4610 - ISA16 VGA card, Chips: CL-GD5428-800C-A, RAM: 1MB, Bios Version 1.30B, VESA feature connector, DB15 connector
+ ROM_SYSTEM_BIOS(2, "boca_v1.3", "Boca Research BRI4610 v1.3")
+ ROMX_LOAD("boca_gd5428_1.30b.bin", 0x00000, 0x04000, CRC(6cc8f318) SHA1(2cac4bf2537626cff41aa81ad4627ec6c40dcf99), ROM_SKIP(1) | ROM_BIOS(2) )
+ ROM_CONTINUE( 0x00001, 0x04000 )
+ ROM_SYSTEM_BIOS(3, "bri4610_v141a", "Boca Research BRI4610 V1.41a")
+ ROMX_LOAD("isamalaysia.bin" , 0x00000, 0x8000, CRC(b15804d0) SHA1(9778320ec1560e78aa978a4ef21e098535cb0fcf), ROM_BIOS(3) )
+ // Boca Research BRI4611 - ISA16 VGA card - Chip: CL-GD5422-80QC-C - ROM: CL-GD540X/542X VGA BIOS Version 1.00d - RAM: 1MB - Connector: DB15 - VESA feature connector
+ ROM_SYSTEM_BIOS(4, "bri4611", "Boca Research BRI4611")
+ ROMX_LOAD("gd5422_boca.vbi", 0x00000, 0x08000, CRC(dd1de1c2) SHA1(548e84e412563e4dc1c12736a8d355bf91aaa3b9), ROM_BIOS(4) )
+ ROM_SYSTEM_BIOS(5, "ver_1.00d", "Ver. 1.00d")
+ ROMX_LOAD("cl-gd5422_bios_rom_ver_1.00d.bin", 0x00000, 0x04000, CRC(c63b1eb8) SHA1(01782fdef5c22fa6418bc881ee9781bf273c389b), ROM_SKIP(1) | ROM_BIOS(5) )
+ ROM_CONTINUE( 0x00001, 0x04000 )
+ // Diamond Speedstar PRO - Chipset: CL-GD5426-80QC-B - ROM: Ver 2.04 - RAM: 1MB - Connector: DB15 - VESA feature connectorVL card
+ ROM_SYSTEM_BIOS(6, "speedstar_pro", "Diamond Speedstar PRO")
+ ROMX_LOAD("diamond5426_v204.vbi", 0x00000, 0x08000, CRC(c98491b0) SHA1(19ae9d2bf39e5b2726d6d556ef2cfa84b06d4da9), ROM_BIOS(6) )
+ // ISA16 - Chip: CL-GD5424-80QC-GW - RAM: 512KB
+ ROM_SYSTEM_BIOS(7, "5424_ver_1.41", "5424 Ver 1.41")
+ ROMX_LOAD("cl5424.bin", 0x0000, 0x04000, CRC(c3b0239a) SHA1(6327b98b26f481f993ebbd0dc18410e4fb5b3aad), ROM_SKIP(1) | ROM_BIOS(7) )
+ ROM_CONTINUE( 0x00001, 0x04000 )
+ ROM_IGNORE(0x8000)
+ // UTD-01D CL542X - VLB - Chip: Cirrus Logic CL-GD5428-80QC-A - RAM: 1MB
+ ROM_SYSTEM_BIOS(8, "5428_ver_1.41", "5428 Ver 1.41")
+ ROMX_LOAD("cl5428.bin", 0x00000, 0x04000, CRC(baba9c04) SHA1(2b7a426e060f656c401586a1a6c1183edbf464a5), ROM_SKIP(1) | ROM_BIOS(8) )
+ ROM_CONTINUE( 0x00001, 0x04000 )
+ ROM_SYSTEM_BIOS(9, "cl5429_v1.00a", "CL-GD5429 Ver.1.00a")
+ ROMX_LOAD("5429.vbi", 0x00000, 0x08000, CRC(a2d81c5b) SHA1(8060cd4b49052572bb5ec929f8ad21e2addce237), ROM_BIOS(9) )
+ // VLB - CL5429 SOJ/SMT/4L/V1 - ROM: CL-GD5906-20DC-1.00 - Chipset: Cirrus Logic CL-GD5429-86QC-B - RAM: 1MB, max. 2MB
+ ROM_SYSTEM_BIOS(10, "20dc-1.00", "CL-GD5906-20DC-1.00")
+ ROMX_LOAD("cl5429.bin", 0x00000, 0x8000, CRC(c4af3673) SHA1(a987c6047141b3d478aeccccd07936210ddb374b), ROM_BIOS(10) )
+ // Source: ROM dump - NCR 8bit VLB VGA card S17-0000248 - Chip: CL-GD5428-80QC-A - ROM: CL-GD5422/5424/5426/5428 VGA BIOS Version 1.3 - RAM: 1MB - Connector: DB15 - VESA feature connector
+ ROM_SYSTEM_BIOS(11, "ncr_5428_v130", "NCR 5428 VLB V1.30")
+ ROMX_LOAD("ncr_vlb_vga_cl-gd5428-80qc-a.bin", 0x00000, 0x08000, CRC(2d68bfb7) SHA1(f0e385e4d2c4a417ed21f10bf340ad6338b768bd), ROM_BIOS(11) )
+ // Machspeed VGA GUI 2100 - 16bit VLB Cirrus Logic CL-GD5428 based VGA card - ROM: CL-GD542X VGA BIOS Version 1.41 - Chips: MACHSPEED GTK6189 9408 CL-GD5428-80QC-A
+ // RAM: 1MB max. 2MB - Connectors: DB15 - VESA feature connector
+ ROM_SYSTEM_BIOS(12, "machspeed2100", "Machspeed VGA GUI 2100 V1.41a")
+ ROMX_LOAD("machspeed_vga_gui_2100_vlb.vbi", 0x00000, 0x08000, CRC(da3b3261) SHA1(a09ceea0d8036e13ec501dd6cc32bca16f2f9204), ROM_BIOS(12) )
+ // Octek VL-Combo rev.3.2 - This is a Cirrus Logic CL-GD5426 based VGA card that includes 2 serial ports, a parallel port, a floppy controller and an IDE HDD controller.
+ // Chips: CL-GD5426, SMC FDC37C652QF, PROMISE PDC20230C
+ // The 64KB original dump includes two identical 32KB halves with 16KB "quarters" interleaved in each.
+ // The rev.3.3 card uses the same BIOS but a CL-GD5428
+ ROM_SYSTEM_BIOS(13, "octec_vlcombo3.2", "Octek VL-Combo rev.3.2")
+ ROMX_LOAD("octek_vl-combo_rev3_2_27256.bin", 0x00000, 0x04000, CRC(0dbabb0a) SHA1(693c384abf42420276a2727ec4a4c1792704eb30), ROM_SKIP(1) | ROM_BIOS(13) )
+ ROM_CONTINUE( 0x00001, 0x04000 )
+ // Octek VL-Combo rev.2.1 - PDC20230-B IDE-controller
+ // Software dump using the MESS method, the Promise HDD-controller part is dumped from D800, the 32K from C800 are FF
+ ROM_SYSTEM_BIOS(14, "octec_vlcombo2.1", "Octek VL-Combo rev.2.1")
+ ROMX_LOAD("octek_vl_combo_v2.1_myc000.bin", 0x00000, 0x08000, CRC(1a97b6d5) SHA1(fde41c45347b66ed4b1f99c3f7057e7411cdf4da), ROM_BIOS(14) )
+ // ROM_LOAD("octek_vl_combo_v2.1_myd800.bin", 0x00000, 0x02000, CRC(2c472bfe) SHA1(ab4879924f5826c38f6066ac769106584ac2d2e8) ) // HDD
ROM_END
//**************************************************************************
@@ -114,9 +304,9 @@ void isa16_svga_cirrus_gd542x_device::device_add_mconfig(machine_config &config)
{
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
screen.set_raw(25.175_MHz_XTAL, 800, 0, 640, 524, 0, 480);
- screen.set_screen_update("vga", FUNC(cirrus_gd5428_device::screen_update));
+ screen.set_screen_update("vga", FUNC(cirrus_gd5428_vga_device::screen_update));
- CIRRUS_GD5428(config, m_vga, 0);
+ CIRRUS_GD5428_VGA(config, m_vga, 0);
m_vga->set_screen("screen");
m_vga->set_vram_size(0x200000);
}
@@ -145,6 +335,11 @@ isa16_svga_cirrus_gd542x_device::isa16_svga_cirrus_gd542x_device(const machine_c
{
}
+void isa16_svga_cirrus_gd542x_device::io_isa_map(address_map &map)
+{
+ map(0x00, 0x2f).m(m_vga, FUNC(cirrus_gd5428_vga_device::io_map));
+}
+
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
@@ -156,11 +351,19 @@ void isa16_svga_cirrus_gd542x_device::device_start()
m_isa->install_rom(this, 0xc0000, 0xc7fff, "clgd542x");
- m_isa->install_device(0x03b0, 0x03bf, read8sm_delegate(*m_vga, FUNC(cirrus_gd5428_device::port_03b0_r)), write8sm_delegate(*m_vga, FUNC(cirrus_gd5428_device::port_03b0_w)));
- m_isa->install_device(0x03c0, 0x03cf, read8sm_delegate(*m_vga, FUNC(cirrus_gd5428_device::port_03c0_r)), write8sm_delegate(*m_vga, FUNC(cirrus_gd5428_device::port_03c0_w)));
- m_isa->install_device(0x03d0, 0x03df, read8sm_delegate(*m_vga, FUNC(cirrus_gd5428_device::port_03d0_r)), write8sm_delegate(*m_vga, FUNC(cirrus_gd5428_device::port_03d0_w)));
+ m_isa->install_memory(0xa0000, 0xbffff, read8sm_delegate(*m_vga, FUNC(cirrus_gd5428_vga_device::mem_r)), write8sm_delegate(*m_vga, FUNC(cirrus_gd5428_vga_device::mem_w)));
+ m_isa->install_device(0x03b0, 0x03df, *this, &isa16_svga_cirrus_gd542x_device::io_isa_map);
+}
- m_isa->install_memory(0xa0000, 0xbffff, read8sm_delegate(*m_vga, FUNC(cirrus_gd5428_device::mem_r)), write8sm_delegate(*m_vga, FUNC(cirrus_gd5428_device::mem_w)));
+void isa16_svga_cirrus_gd542x_device::remap(int space_id, offs_t start, offs_t end)
+{
+ if (space_id == AS_PROGRAM)
+ {
+ m_isa->install_memory(0xa0000, 0xbffff, read8sm_delegate(*m_vga, FUNC(cirrus_gd5428_vga_device::mem_r)), write8sm_delegate(*m_vga, FUNC(cirrus_gd5428_vga_device::mem_w)));
+ m_isa->install_rom(this, 0xc0000, 0xc7fff, "clgd542x");
+ }
+ else if (space_id == AS_IO)
+ m_isa->install_device(0x03b0, 0x03df, *this, &isa16_svga_cirrus_gd542x_device::io_isa_map);
}
//-------------------------------------------------
diff --git a/src/devices/bus/isa/svga_cirrus.h b/src/devices/bus/isa/svga_cirrus.h
index d2e7d75595c..cfc4d495c1c 100644
--- a/src/devices/bus/isa/svga_cirrus.h
+++ b/src/devices/bus/isa/svga_cirrus.h
@@ -6,7 +6,7 @@
#pragma once
#include "isa.h"
-#include "video/clgd542x.h"
+#include "video/pc_vga_cirrus.h"
//**************************************************************************
// TYPE DEFINITIONS
@@ -31,8 +31,10 @@ protected:
virtual void device_add_mconfig(machine_config &config) override;
virtual const tiny_rom_entry *device_rom_region() const override;
+ void io_isa_map(address_map &map);
+
private:
- required_device<cirrus_gd5430_device> m_vga;
+ required_device<cirrus_gd5430_vga_device> m_vga;
};
class isa16_svga_cirrus_gd542x_device :
@@ -45,6 +47,7 @@ public:
uint8_t input_port_0_r();
+ virtual void remap(int space_id, offs_t start, offs_t end) override;
protected:
// device-level overrides
virtual void device_start() override;
@@ -54,8 +57,10 @@ protected:
virtual void device_add_mconfig(machine_config &config) override;
virtual const tiny_rom_entry *device_rom_region() const override;
+ void io_isa_map(address_map &map);
+
private:
- required_device<cirrus_gd5428_device> m_vga;
+ required_device<cirrus_gd5428_vga_device> m_vga;
};
diff --git a/src/devices/bus/isa/svga_paradise.cpp b/src/devices/bus/isa/svga_paradise.cpp
new file mode 100644
index 00000000000..955096ea3aa
--- /dev/null
+++ b/src/devices/bus/isa/svga_paradise.cpp
@@ -0,0 +1,649 @@
+// license:BSD-3-Clause
+// copyright-holders: Angelo Salese
+/***************************************************************************
+
+ISA SVGA Paradise / Western Digital wrapper
+
+TODO:
+- Add ISA8 and MCA variants for pvga1a_jk;
+- Nokia NVGA2, wd90c00_jk: they don't boot, accesses areas $c6000-$c7fff
+ that aren't covered in current dumps;
+ \- Specifically they do:
+ 000C03AB: cmp word ptr [10h],0h ; wd90c00 == 0x3000
+ 000C03B0: 75 09 jne 0C03BBh
+ 000C03B2: cmp byte ptr [12h],7Eh ; wd90c00 == 0x00
+ 000C03B7: jne 0C03BBh
+ 000C03B9: pop ds
+ 000C03BA: ret
+ 000C03BB: jmp 0FFFFh:0h ; reset machine
+
+
+***************************************************************************/
+
+#include "emu.h"
+#include "svga_paradise.h"
+
+#include "screen.h"
+
+// TODO: some of these are also ISA8
+DEFINE_DEVICE_TYPE(ISA16_PVGA1A, isa16_pvga1a_device, "pvga1a", "Paradise Systems PVGA1A Graphics Card")
+DEFINE_DEVICE_TYPE(ISA16_PVGA1A_JK, isa16_pvga1a_jk_device, "pvga1a_jk", "Paradise Systems PVGA1A-JK Graphics Card")
+DEFINE_DEVICE_TYPE(ISA8_WD90C90_JK, isa8_wd90c90_jk_device, "wd90c90_jk", "Western Digital WD90C90-JK Graphics Card")
+DEFINE_DEVICE_TYPE(ISA16_WD90C00_JK, isa16_wd90c00_jk_device, "wd90c00_jk", "Western Digital WD90C00-JK Graphics Card")
+DEFINE_DEVICE_TYPE(ISA16_WD90C11_LR, isa16_wd90c11_lr_device, "wd90c11_lr", "Western Digital WD90C11-LR Graphics Card \"1024 CX\"")
+DEFINE_DEVICE_TYPE(ISA16_WD90C30_LR, isa16_wd90c30_lr_device, "wd90c30_lr", "Western Digital WD90C30-LR Graphics Card \"1024 DX\"")
+DEFINE_DEVICE_TYPE(ISA16_WD90C31_LR, isa16_wd90c31_lr_device, "wd90c31_lr", "Western Digital WD90C31-LR Graphics Card")
+DEFINE_DEVICE_TYPE(ISA16_WD90C31A_LR, isa16_wd90c31a_lr_device, "wd90c31a_lr", "Western Digital WD90C31A-LR Graphics Card")
+//DEFINE_DEVICE_TYPE(ISA16_WD90C31_ZS, isa16_wd90c31_zs_device, "wd90c31_zs", "Western Digital WD90C31-ZS Graphics Card")
+DEFINE_DEVICE_TYPE(ISA16_WD90C31A_ZS, isa16_wd90c31a_zs_device, "wd90c31a_zs", "Western Digital WD90C31A-ZS Graphics Card")
+// TODO: Also VL-Bus
+DEFINE_DEVICE_TYPE(ISA16_WD90C33_ZZ, isa16_wd90c33_zz_device, "wd90c33_zz", "Western Digital WD90C33-ZZ Graphics Card")
+
+isa16_pvga1a_device::isa16_pvga1a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, ISA16_PVGA1A, tag, owner, clock),
+ device_isa16_card_interface(mconfig, *this),
+ m_vga(*this, "vga")
+{
+}
+
+ROM_START( pvga1a )
+ ROM_REGION(0x8000,"vga_rom", 0)
+ ROM_SYSTEM_BIOS(0, "pvga1a", "Paradise Systems PVGA1A")
+ // WD Copyright in the ROMs
+ // TODO: pinpoint what rom size are these
+ // BIOS.BIN 1xxxxxxxxxxxxxxx = 0xFF
+ ROMX_LOAD("bios.bin", 0x000000, 0x008000, CRC(2be5d405) SHA1(5e3b4ebae221b7ad02f3eaa052178cb39d1d9bbe), ROM_BIOS(0))
+ ROM_IGNORE( 0x8000 )
+ // Paradise Copyright in the ROMs
+ // 8bit Paradise Basic VGA
+ ROM_SYSTEM_BIOS(1, "basic01488", "Paradise Basic VGA 07/14/88") // Char SEL checker
+ ROMX_LOAD( "pvga1a.bin", 0x000000, 0x08000, CRC(ffb5aa30) SHA1(4f785702744ac7565e4ec659b9841e750948e8cb), ROM_BIOS(1) )
+ // WD Copyright in the ROMs
+ // 8bit Paradise Basic VGA
+ ROM_SYSTEM_BIOS(2, "basic092189", "Paradise Basic VGA 09/21/89")
+ ROMX_LOAD( "pvga1_89.bin", 0x000000, 0x08000, CRC(9521f5a0) SHA1(1ab06a897edeef1a8e119099897a1d7954d7b9d9), ROM_BIOS(2) )
+ // Paradise Copyright in the ROMs
+ // ISA16 graphics card - RAM: 256KB - 8-bit mode supported - FCC ID: DBM5UEVGAPROF - Connectors: DB15, 26pin EDGE - Chips: Paradise PVGA1A, AVASEM V3476-40
+ // DIP: 4way - OSC: 42 MHz, 36 MHz, 25.1750 MHz, 28.3220 MHz
+ ROM_SYSTEM_BIOS(3, "philips", "Philips PVGA1A") // Char SEL checker
+ ROMX_LOAD("par_u35.bin", 0x000000, 0x004000, CRC(afa802a4) SHA1(33ee89248d945869206aee3d9cb63bd375e51ed7), ROM_SKIP(1) | ROM_BIOS(3))
+ ROMX_LOAD("par_u36.bin", 0x000001, 0x004000, CRC(c51ab2e3) SHA1(d53d2a9aeffc7c41199fe91bc3d6d2e4d90173c8), ROM_SKIP(1) | ROM_BIOS(3))
+
+ // There's also a:
+ // ROMX_LOAD( "paradisepvga1a.bin", 0x000000, 0x008000, CRC(e7c6883a) SHA1(61ae199d3a9077844c8a1aa80c3f5804c29383e8), ROM_BIOS(N) )
+ // BIOS.BIN [1/4] paradisepvga1a.BIN [1/2] IDENTICAL
+ // Which doesn't boot with invalid REP opcode, assume bad.
+ROM_END
+
+const tiny_rom_entry *isa16_pvga1a_device::device_rom_region() const
+{
+ return ROM_NAME( pvga1a );
+}
+
+void isa16_pvga1a_device::device_add_mconfig(machine_config &config)
+{
+ screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
+ screen.set_raw(25.175_MHz_XTAL, 800, 0, 640, 524, 0, 480);
+ screen.set_screen_update("vga", FUNC(pvga1a_vga_device::screen_update));
+
+ PVGA1A(config, m_vga, 0);
+ m_vga->set_screen("screen");
+ m_vga->set_vram_size(0x100000);
+}
+
+void isa16_pvga1a_device::io_isa_map(address_map &map)
+{
+ map(0x00, 0x2f).m(m_vga, FUNC(pvga1a_vga_device::io_map));
+}
+
+void isa16_pvga1a_device::device_start()
+{
+ set_isa_device();
+
+ m_isa->install_rom(this, 0xc0000, 0xc7fff, "vga_rom");
+
+ m_isa->install_memory(0xa0000, 0xbffff, read8sm_delegate(*m_vga, FUNC(pvga1a_vga_device::mem_r)), write8sm_delegate(*m_vga, FUNC(pvga1a_vga_device::mem_w)));
+ m_isa->install_device(0x03b0, 0x03df, *this, &isa16_pvga1a_device::io_isa_map);
+}
+
+void isa16_pvga1a_device::remap(int space_id, offs_t start, offs_t end)
+{
+ if (space_id == AS_PROGRAM)
+ {
+ m_isa->install_memory(0xa0000, 0xbffff, read8sm_delegate(*m_vga, FUNC(pvga1a_vga_device::mem_r)), write8sm_delegate(*m_vga, FUNC(pvga1a_vga_device::mem_w)));
+ m_isa->install_rom(this, 0xc0000, 0xc7fff, "vga_rom");
+ }
+ else if (space_id == AS_IO)
+ m_isa->install_device(0x03b0, 0x03df, *this, &isa16_pvga1a_device::io_isa_map);
+}
+
+/******************
+ *
+ * PVGA1A-JK
+ *
+ *****************/
+
+isa16_pvga1a_jk_device::isa16_pvga1a_jk_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, ISA16_PVGA1A_JK, tag, owner, clock),
+ device_isa16_card_interface(mconfig, *this),
+ m_vga(*this, "vga")
+{
+}
+
+ROM_START( pvga1a_jk )
+ ROM_REGION(0x8000,"vga_rom", ROMREGION_ERASEFF)
+ // WD Copyright in the ROMs
+ // "Paradise Basic VGA"?
+ ROM_SYSTEM_BIOS(0, "pvga1a_jk", "Paradise Systems PVGA1A-JK")
+ // BIOS.BIN 1xxxxxxxxxxxxxxx = 0xFF
+ ROMX_LOAD( "bios.bin", 0x000000, 0x08000, CRC(2bfe8adb) SHA1(afd8c33f24e28b025e43ae68d95fd6811659013b), ROM_BIOS(0) )
+ ROM_IGNORE( 0x8000 )
+ // TODO: consider splitting if a good dump surfaces
+ ROM_SYSTEM_BIOS(1, "nvga2", "Nokia NVGA2") // Char SEL checker
+ ROMX_LOAD( "nokia.vbi", 0x000000, 0x06000, BAD_DUMP CRC(9f430ae7) SHA1(3d37b86853347d43ebc85a7e92e4a609b13406bb), ROM_BIOS(1) )
+ // WD Copyright in the ROMs - on startup there is a coloured pattern in the top third of the screen
+ // Epson Parts No. Y19120100100 - 16bit ISA graphics card - ROM: Western Digtal CVGA-A02/B02, 27C128 EPROMs - RAM: 256KB - Chips: Paradise PVGA1A-JK, IMSGI76P-40
+ // OSC: 42.000 MHz, 36.000 MHz, 25.175 MHz, 28.322 MHz - Connectors: DB15, 26 pin EDGE - DIP: 4way
+ ROM_SYSTEM_BIOS(2, "epson", "Epson PVGA1A") // Char SEL checker
+ ROMX_LOAD( "epson_pvga1a_cvga_a02.bin", 0x000000, 0x004000, CRC(5b94c843) SHA1(c2c70c03097a36bf1c6de687d228bcfec5bd4b2d), ROM_SKIP(1) | ROM_BIOS(2) )
+ ROMX_LOAD( "epson_pvga1a_cvga_b02.bin", 0x000001, 0x004000, CRC(e7c297c3) SHA1(f60802a8271c437df26eca57ed61cab75e5c0618), ROM_SKIP(1) |ROM_BIOS(2) )
+ // GO481 as used in the Olivetti M290
+ ROM_SYSTEM_BIOS(3, "go481m290", "GO481 for M290")
+ ROMX_LOAD("pvga_pdp5_1.06.bin", 0x000000, 0x004000, CRC(034490d6) SHA1(4729f000d04308f6fdcbcad48ac697755a884749), ROM_SKIP(1) | ROM_BIOS(3) )
+ ROMX_LOAD("pvga_pdp7_1.06.bin", 0x000001, 0x004000, CRC(c105c829) SHA1(310b9d361d077d2eece9659c0613169897fb597a), ROM_SKIP(1) | ROM_BIOS(3) )
+ // Used in: Olivetti M290, M300, M380XP and was a popular upgrade to the M24 (16bit card works in a 8bit slot)
+ // 16bit ISA graphics adapter - Chip: Paradise PVGA1A-JK - ROM: 2x27128, WD copyright - RAM: 256KB - OSC: 36MHz, 25.175MHz, 28.322 MHz - Connector: DB15
+ // V1.06 ROMs have the labels "PDP5" and "PDP7"
+ ROM_SYSTEM_BIOS(4, "go481", "Olivetti GO481")
+ ROMX_LOAD( "oli_go481_lo_trunc.bin", 0x000000, 0x004000, CRC(10daae11) SHA1(63e45ce063e934763786f3d0ee9acba2dbda93a8), ROM_SKIP(1) | ROM_BIOS(4))
+ ROMX_LOAD( "oli_go481_hi_trunc.bin", 0x000001, 0x004000, CRC(cd09170f) SHA1(63f0427f81b31e7668a746f502dc7637dce1bfff), ROM_SKIP(1) | ROM_BIOS(4))
+ // Paradise Copyright in ROMs
+ // offered as replacement ROMs for an Olivetti GO481
+ ROM_SYSTEM_BIOS(5, "16bitjk", "16bit ISA PVGA1A-JK") // Char SEL checker
+ ROMX_LOAD( "vga_paradaise_pvga1a-jk_lo_27c128.bin", 0x000000, 0x004000, CRC(a00bd1e8) SHA1(545d0bacfa5bab9208685fc880509827ae527d84), ROM_SKIP(1) | ROM_BIOS(5) )
+ ROMX_LOAD( "vga_paradaise_pvga1a-jk_hi_27c128.bin", 0x000001, 0x004000, CRC(fb3dbc51) SHA1(218811ae3f58002eece74c4e444309d8a2a21836), ROM_SKIP(1) | ROM_BIOS(5) )
+ROM_END
+
+const tiny_rom_entry *isa16_pvga1a_jk_device::device_rom_region() const
+{
+ return ROM_NAME( pvga1a_jk );
+}
+
+void isa16_pvga1a_jk_device::device_add_mconfig(machine_config &config)
+{
+ screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
+ screen.set_raw(25.175_MHz_XTAL, 800, 0, 640, 524, 0, 480);
+ screen.set_screen_update("vga", FUNC(pvga1a_vga_device::screen_update));
+
+ // TODO: is there any real difference between PVGA1A and PVGA1A-JK VGA controller wise?
+ PVGA1A(config, m_vga, 0);
+ m_vga->set_screen("screen");
+ // 256kB to 1MB
+ m_vga->set_vram_size(0x100000);
+}
+
+void isa16_pvga1a_jk_device::io_isa_map(address_map &map)
+{
+ map(0x00, 0x2f).m(m_vga, FUNC(pvga1a_vga_device::io_map));
+}
+
+void isa16_pvga1a_jk_device::device_start()
+{
+ set_isa_device();
+
+ m_isa->install_rom(this, 0xc0000, 0xc7fff, "vga_rom");
+
+ m_isa->install_memory(0xa0000, 0xbffff, read8sm_delegate(*m_vga, FUNC(pvga1a_vga_device::mem_r)), write8sm_delegate(*m_vga, FUNC(pvga1a_vga_device::mem_w)));
+ m_isa->install_device(0x03b0, 0x03df, *this, &isa16_pvga1a_jk_device::io_isa_map);
+}
+
+/******************
+ *
+ * WD90C90-JK
+ *
+ *****************/
+
+isa8_wd90c90_jk_device::isa8_wd90c90_jk_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, ISA8_WD90C90_JK, tag, owner, clock),
+ device_isa8_card_interface(mconfig, *this),
+ m_vga(*this, "vga")
+{
+}
+
+ROM_START( wd90c90_jk )
+ ROM_REGION(0x8000,"vga_rom", ROMREGION_ERASEFF)
+ ROM_SYSTEM_BIOS(0, "wd90c90_jk", "ZTECH ZPVGA")
+ ROMX_LOAD( "bios.bin", 0x000000, 0x008000, CRC(a7f0e81c) SHA1(578ee0e8f9a5e56df6c05386978d0f41c638ddcf), ROM_BIOS(0) )
+ ROM_IGNORE( 0x8000 )
+ROM_END
+
+const tiny_rom_entry *isa8_wd90c90_jk_device::device_rom_region() const
+{
+ return ROM_NAME( wd90c90_jk );
+}
+
+void isa8_wd90c90_jk_device::device_add_mconfig(machine_config &config)
+{
+ screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
+ screen.set_raw(25.175_MHz_XTAL, 800, 0, 640, 524, 0, 480);
+ screen.set_screen_update("vga", FUNC(pvga1a_vga_device::screen_update));
+
+ PVGA1A(config, m_vga, 0);
+ m_vga->set_screen("screen");
+ // 256kB to 1MB
+ m_vga->set_vram_size(0x100000);
+}
+
+void isa8_wd90c90_jk_device::io_isa_map(address_map &map)
+{
+ map(0x00, 0x2f).m(m_vga, FUNC(pvga1a_vga_device::io_map));
+}
+
+void isa8_wd90c90_jk_device::device_start()
+{
+ set_isa_device();
+
+ m_isa->install_rom(this, 0xc0000, 0xc7fff, "vga_rom");
+
+ m_isa->install_memory(0xa0000, 0xbffff, read8sm_delegate(*m_vga, FUNC(pvga1a_vga_device::mem_r)), write8sm_delegate(*m_vga, FUNC(pvga1a_vga_device::mem_w)));
+ m_isa->install_device(0x03b0, 0x03df, *this, &isa8_wd90c90_jk_device::io_isa_map);
+}
+
+/******************
+ *
+ * WD90C00-JK
+ *
+ *****************/
+
+isa16_wd90c00_jk_device::isa16_wd90c00_jk_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, ISA16_WD90C00_JK, tag, owner, clock),
+ device_isa16_card_interface(mconfig, *this),
+ m_vga(*this, "vga")
+{
+}
+
+ROM_START( wd90c00_jk )
+ ROM_REGION(0x8000,"vga_rom", ROMREGION_ERASE00)
+ ROM_SYSTEM_BIOS(0, "wd90c00_jk", "Western Digital WD90C00-JK")
+ // "vga bios western digital wd90c00 1989 (part 1).bin"
+ ROMX_LOAD( "wdh.bin", 0x000001, 0x004000, CRC(0f4c7aed) SHA1(bdcc298b863ea7f37b1352164107264a12030cb5), ROM_SKIP(1) | ROM_BIOS(0) )
+ ROMX_LOAD( "wdl.bin", 0x000000, 0x004000, CRC(6916523e) SHA1(a4024e8a71b310fc95a37743bc255212c7dd73a5), ROM_SKIP(1) | ROM_BIOS(0) )
+ ROM_SYSTEM_BIOS(1, "wd90c00_jk_1", "Western Digital WD90C00-JK (alt)")
+ ROMX_LOAD( "wd90c00l.bin", 0x000000, 0x004000, CRC(a4fdc1db) SHA1(9680ab2049a0fd49bb23eb0a08487518cb9fa861), ROM_SKIP(1) | ROM_BIOS(1) )
+ ROMX_LOAD( "wd90c00h.bin", 0x000001, 0x004000, CRC(b3279a8d) SHA1(d531c5e3d2c083190477b8d799dc5205c9357181), ROM_SKIP(1) | ROM_BIOS(1) )
+ ROM_SYSTEM_BIOS(2, "wd90c00_jk_v", "Western Digital WD90C00-JK (alt .vbi)")
+ ROMX_LOAD( "90c00jk-lh6673.vbi", 0x000000, 0x006000, BAD_DUMP CRC(595eda15) SHA1(a3d4a978f30a0669bcb4a74ce196fd7a798d456f), ROM_BIOS(2) )
+ROM_END
+
+const tiny_rom_entry *isa16_wd90c00_jk_device::device_rom_region() const
+{
+ return ROM_NAME( wd90c00_jk );
+}
+
+void isa16_wd90c00_jk_device::device_add_mconfig(machine_config &config)
+{
+ screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
+ screen.set_raw(25.175_MHz_XTAL, 800, 0, 640, 524, 0, 480);
+ screen.set_screen_update("vga", FUNC(wd90c00_vga_device::screen_update));
+
+ WD90C00(config, m_vga, 0);
+ m_vga->set_screen("screen");
+ // 256kB, 512kB, 1MB
+ m_vga->set_vram_size(0x100000);
+}
+
+void isa16_wd90c00_jk_device::io_isa_map(address_map &map)
+{
+ map(0x00, 0x2f).m(m_vga, FUNC(wd90c00_vga_device::io_map));
+}
+
+void isa16_wd90c00_jk_device::device_start()
+{
+ set_isa_device();
+
+ m_isa->install_rom(this, 0xc0000, 0xc7fff, "vga_rom");
+
+ m_isa->install_memory(0xa0000, 0xbffff, read8sm_delegate(*m_vga, FUNC(wd90c00_vga_device::mem_r)), write8sm_delegate(*m_vga, FUNC(wd90c00_vga_device::mem_w)));
+ m_isa->install_device(0x03b0, 0x03df, *this, &isa16_wd90c00_jk_device::io_isa_map);
+}
+
+/******************
+ *
+ * WD90C11-LR
+ *
+ *****************/
+
+isa16_wd90c11_lr_device::isa16_wd90c11_lr_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, ISA16_WD90C11_LR, tag, owner, clock),
+ device_isa16_card_interface(mconfig, *this),
+ m_vga(*this, "vga")
+{
+}
+
+ROM_START( wd90c11_lr )
+ ROM_REGION(0x8000,"vga_rom", ROMREGION_ERASE00)
+ // Octek PVGA1C - Version LR - WDC Paradise 90C11A
+ ROM_SYSTEM_BIOS(0, "wd90c11_lr", "Western Digital WD90C11-LR")
+ ROMX_LOAD( "wd90c11.vbi", 0x000000, 0x008000, CRC(9c1296d7) SHA1(10fd263ab0187d8960d4cb2954254732ac29472f), ROM_BIOS(0) )
+ROM_END
+
+const tiny_rom_entry *isa16_wd90c11_lr_device::device_rom_region() const
+{
+ return ROM_NAME( wd90c11_lr );
+}
+
+void isa16_wd90c11_lr_device::device_add_mconfig(machine_config &config)
+{
+ screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
+ screen.set_raw(25.175_MHz_XTAL, 800, 0, 640, 524, 0, 480);
+ screen.set_screen_update("vga", FUNC(wd90c11a_vga_device::screen_update));
+
+ WD90C11A(config, m_vga, 0);
+ m_vga->set_screen("screen");
+ // 512KB (+ option for 1MB? Verify with interlace)
+ m_vga->set_vram_size(0x100000);
+}
+
+void isa16_wd90c11_lr_device::io_isa_map(address_map &map)
+{
+ map(0x00, 0x2f).m(m_vga, FUNC(wd90c11a_vga_device::io_map));
+}
+
+void isa16_wd90c11_lr_device::device_start()
+{
+ set_isa_device();
+
+ m_isa->install_rom(this, 0xc0000, 0xc7fff, "vga_rom");
+
+ m_isa->install_memory(0xa0000, 0xbffff, read8sm_delegate(*m_vga, FUNC(wd90c11a_vga_device::mem_r)), write8sm_delegate(*m_vga, FUNC(wd90c11a_vga_device::mem_w)));
+ m_isa->install_device(0x03b0, 0x03df, *this, &isa16_wd90c11_lr_device::io_isa_map);
+}
+
+/******************
+ *
+ * WD90C30-LR
+ *
+ *****************/
+
+isa16_wd90c30_lr_device::isa16_wd90c30_lr_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, ISA16_WD90C30_LR, tag, owner, clock),
+ device_isa16_card_interface(mconfig, *this),
+ m_vga(*this, "vga")
+{
+}
+
+ROM_START( wd90c30_lr )
+ ROM_REGION(0x8000,"vga_rom", ROMREGION_ERASE00)
+ ROM_SYSTEM_BIOS(0, "wd90c30_lr", "Western Digital WD90C30-LR")
+ ROMX_LOAD( "90c30-lr.vbi", 0x000000, 0x008000, CRC(3356ad43) SHA1(6cd56cf274b3c9262b7ca12d49bae63afc331c58), ROM_BIOS(0) )
+ // WDC 90C30 reference design - Chips: WDC WD90C30-LR, MUSIC TR9C1710-80DCA - ROMS: 62-003265-008 - RAM: 512KB, up to 1MB
+ // Connectors: DB15, 26pin EDGE - DIP: 5 way (SW1)
+ // Identical 27C256 ROMs are used on a VG-8000 WD90C30 VGA
+ ROM_SYSTEM_BIOS(1, "wdc30lr_hl", "WD90C30-LR Hi/Lo")
+ ROMX_LOAD("u25.bin", 0x000000, 0x4000, CRC(f3ba68ae) SHA1(a072c9f8bd465c18fc75b9f8890061587abda1f2), ROM_SKIP(1) | ROM_BIOS(1) )
+ ROM_IGNORE( 0x4000 )
+ ROMX_LOAD("u24.bin", 0x000001, 0x4000, CRC(797ec96d) SHA1(902418504a446f0a484fd3da6f65d3cff3987280), ROM_SKIP(1) | ROM_BIOS(1) )
+ ROM_IGNORE( 0x4000 )
+ROM_END
+
+const tiny_rom_entry *isa16_wd90c30_lr_device::device_rom_region() const
+{
+ return ROM_NAME( wd90c30_lr );
+}
+
+void isa16_wd90c30_lr_device::device_add_mconfig(machine_config &config)
+{
+ screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
+ screen.set_raw(25.175_MHz_XTAL, 800, 0, 640, 524, 0, 480);
+ screen.set_screen_update("vga", FUNC(wd90c30_vga_device::screen_update));
+
+ WD90C30(config, m_vga, 0);
+ m_vga->set_screen("screen");
+ // 512KB, 1MB
+ m_vga->set_vram_size(0x100000);
+}
+
+void isa16_wd90c30_lr_device::io_isa_map(address_map &map)
+{
+ map(0x00, 0x2f).m(m_vga, FUNC(wd90c30_vga_device::io_map));
+}
+
+void isa16_wd90c30_lr_device::device_start()
+{
+ set_isa_device();
+
+ m_isa->install_rom(this, 0xc0000, 0xc7fff, "vga_rom");
+
+ m_isa->install_memory(0xa0000, 0xbffff, read8sm_delegate(*m_vga, FUNC(wd90c30_vga_device::mem_r)), write8sm_delegate(*m_vga, FUNC(wd90c30_vga_device::mem_w)));
+ m_isa->install_device(0x03b0, 0x03df, *this, &isa16_wd90c30_lr_device::io_isa_map);
+}
+
+/******************
+ *
+ * WD90C31-LR
+ *
+ *****************/
+
+isa16_wd90c31_lr_device::isa16_wd90c31_lr_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, ISA16_WD90C31_LR, tag, owner, clock),
+ device_isa16_card_interface(mconfig, *this),
+ m_vga(*this, "vga")
+{
+}
+
+ROM_START( wd90c31_lr )
+ ROM_REGION(0x8000,"vga_rom", ROMREGION_ERASE00)
+ ROM_SYSTEM_BIOS(0, "wdxlr831", "Western Digital WD90C31-LR")
+ ROMX_LOAD( "62-003259-800.bin", 0x000001, 0x004000, CRC(e71090bd) SHA1(f784ebc14801a0944271aab9ba4746dd9d0e001d), ROM_SKIP(1) | ROM_BIOS(0) )
+ ROMX_LOAD( "62-003260-800.bin", 0x000000, 0x004000, CRC(1e66af70) SHA1(7f236d6acb34d07480584d51f6bb57836ff262c4), ROM_SKIP(1) | ROM_BIOS(0) )
+ROM_END
+
+const tiny_rom_entry *isa16_wd90c31_lr_device::device_rom_region() const
+{
+ return ROM_NAME( wd90c31_lr );
+}
+
+void isa16_wd90c31_lr_device::device_add_mconfig(machine_config &config)
+{
+ screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
+ screen.set_raw(25.175_MHz_XTAL, 800, 0, 640, 524, 0, 480);
+ screen.set_screen_update("vga", FUNC(wd90c30_vga_device::screen_update));
+
+ WD90C31(config, m_vga, 0);
+ m_vga->set_screen("screen");
+ // 512KB, 1MB
+ m_vga->set_vram_size(0x100000);
+}
+
+void isa16_wd90c31_lr_device::io_isa_map(address_map &map)
+{
+ map(0x00, 0x2f).m(m_vga, FUNC(wd90c31_vga_device::io_map));
+}
+
+void isa16_wd90c31_lr_device::device_start()
+{
+ set_isa_device();
+
+ m_isa->install_rom(this, 0xc0000, 0xc7fff, "vga_rom");
+
+ m_isa->install_memory(0xa0000, 0xbffff, read8sm_delegate(*m_vga, FUNC(wd90c31_vga_device::mem_r)), write8sm_delegate(*m_vga, FUNC(wd90c31_vga_device::mem_w)));
+ m_isa->install_device(0x03b0, 0x03df, *this, &isa16_wd90c31_lr_device::io_isa_map);
+ m_isa->install_device(0x23c0, 0x23c7, *m_vga, &wd90c31_vga_device::ext_io_map);
+}
+
+void isa16_wd90c31_lr_device::remap(int space_id, offs_t start, offs_t end)
+{
+ if (space_id == AS_PROGRAM)
+ {
+ m_isa->install_rom(this, 0xc0000, 0xc7fff, "vga_rom");
+
+ m_isa->install_memory(0xa0000, 0xbffff, read8sm_delegate(*m_vga, FUNC(wd90c31_vga_device::mem_r)), write8sm_delegate(*m_vga, FUNC(wd90c31_vga_device::mem_w)));
+ }
+ else if (space_id == AS_IO)
+ {
+ m_isa->install_device(0x03b0, 0x03df, *this, &isa16_wd90c31_lr_device::io_isa_map);
+ m_isa->install_device(0x23c0, 0x23c7, *m_vga, &wd90c31_vga_device::ext_io_map);
+ }
+}
+
+/******************
+ *
+ * WD90C31A-LR
+ *
+ *****************/
+
+isa16_wd90c31a_lr_device::isa16_wd90c31a_lr_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, ISA16_WD90C31A_LR, tag, owner, clock),
+ device_isa16_card_interface(mconfig, *this),
+ m_vga(*this, "vga")
+{
+}
+
+ROM_START( wd90c31a_lr )
+ ROM_REGION(0x8000,"vga_rom", ROMREGION_ERASE00)
+ ROM_SYSTEM_BIOS(0, "speed24x", "Diamond Speedstar 24x (Vers. 1.04)")
+ ROMX_LOAD( "wd90c31alrdiamondspeedstar24x2.bin", 0x000000, 0x008000, CRC(578cb3c3) SHA1(ca7d871f9589eb06ace8075dd2d87a59bd191744), ROM_BIOS(0) )
+// "wd90c31alrdiamondspeedstar24x1.bin" identical to above
+ ROM_SYSTEM_BIOS(1, "wd90c31a_lr", "Western Digital WD90C31A-LR")
+ ROMX_LOAD( "bios.bin", 0x000000, 0x008000, CRC(cdc4c32e) SHA1(52ed7b8301ec5ebab0d87bab8cddd9cc8612e2ab), ROM_BIOS(1) )
+ ROM_IGNORE( 0x8000 )
+ROM_END
+
+const tiny_rom_entry *isa16_wd90c31a_lr_device::device_rom_region() const
+{
+ return ROM_NAME( wd90c31a_lr );
+}
+
+void isa16_wd90c31a_lr_device::device_add_mconfig(machine_config &config)
+{
+ screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
+ screen.set_raw(25.175_MHz_XTAL, 800, 0, 640, 524, 0, 480);
+ screen.set_screen_update("vga", FUNC(wd90c00_vga_device::screen_update));
+
+ WD90C31(config, m_vga, 0); // WD90C31A
+ m_vga->set_screen("screen");
+ // 512KB, 1MB
+ m_vga->set_vram_size(0x100000);
+}
+
+void isa16_wd90c31a_lr_device::io_isa_map(address_map &map)
+{
+ map(0x00, 0x2f).m(m_vga, FUNC(wd90c31_vga_device::io_map));
+}
+
+void isa16_wd90c31a_lr_device::device_start()
+{
+ set_isa_device();
+
+ m_isa->install_rom(this, 0xc0000, 0xc7fff, "vga_rom");
+
+ m_isa->install_memory(0xa0000, 0xbffff, read8sm_delegate(*m_vga, FUNC(wd90c31_vga_device::mem_r)), write8sm_delegate(*m_vga, FUNC(wd90c31_vga_device::mem_w)));
+ m_isa->install_device(0x03b0, 0x03df, *this, &isa16_wd90c31a_lr_device::io_isa_map);
+ m_isa->install_device(0x23c0, 0x23c7, *m_vga, &wd90c31_vga_device::ext_io_map);
+}
+
+/******************
+ *
+ * WD90C31A-ZS
+ *
+ *****************/
+
+isa16_wd90c31a_zs_device::isa16_wd90c31a_zs_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, ISA16_WD90C31A_ZS, tag, owner, clock),
+ device_isa16_card_interface(mconfig, *this),
+ m_vga(*this, "vga")
+{
+}
+
+ROM_START( wd90c31a_zs )
+ ROM_REGION(0x8000,"vga_rom", ROMREGION_ERASE00)
+ ROM_SYSTEM_BIOS(0, "wd90c31a_zs", "Western Digital WD90C31A-ZS")
+ ROM_LOAD( "wd90c31azs.bin", 0x000000, 0x008000, CRC(521db1dd) SHA1(52cefcc9a1b7374c7414bb93a7805207ba5b7fe3) )
+ROM_END
+
+const tiny_rom_entry *isa16_wd90c31a_zs_device::device_rom_region() const
+{
+ return ROM_NAME( wd90c31a_zs );
+}
+
+void isa16_wd90c31a_zs_device::device_add_mconfig(machine_config &config)
+{
+ screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
+ screen.set_raw(25.175_MHz_XTAL, 800, 0, 640, 524, 0, 480);
+ screen.set_screen_update("vga", FUNC(wd90c00_vga_device::screen_update));
+
+ WD90C31(config, m_vga, 0); // WD90C31A
+ m_vga->set_screen("screen");
+ // 512KB, 1MB
+ m_vga->set_vram_size(0x100000);
+}
+
+void isa16_wd90c31a_zs_device::io_isa_map(address_map &map)
+{
+ map(0x00, 0x2f).m(m_vga, FUNC(wd90c31_vga_device::io_map));
+}
+
+void isa16_wd90c31a_zs_device::device_start()
+{
+ set_isa_device();
+
+ m_isa->install_rom(this, 0xc0000, 0xc7fff, "vga_rom");
+
+ m_isa->install_memory(0xa0000, 0xbffff, read8sm_delegate(*m_vga, FUNC(wd90c31_vga_device::mem_r)), write8sm_delegate(*m_vga, FUNC(wd90c31_vga_device::mem_w)));
+ m_isa->install_device(0x03b0, 0x03df, *this, &isa16_wd90c31a_zs_device::io_isa_map);
+ m_isa->install_device(0x23c0, 0x23c7, *m_vga, &wd90c31_vga_device::ext_io_map);
+}
+
+/******************
+ *
+ * WD90C33-ZZ
+ *
+ *****************/
+
+isa16_wd90c33_zz_device::isa16_wd90c33_zz_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, ISA16_WD90C33_ZZ, tag, owner, clock),
+ device_isa16_card_interface(mconfig, *this),
+ m_vga(*this, "vga")
+{
+}
+
+ROM_START( wd90c33_zz )
+ ROM_REGION(0x8000,"vga_rom", ROMREGION_ERASE00)
+ ROM_SYSTEM_BIOS(0, "wd90c33_zz", "Western Digital WD90C33-ZZ")
+ ROM_LOAD( "bios.bin", 0x000000, 0x008000, CRC(b719d557) SHA1(0f93213ed439059d23e0793478793ffd6188ce12) )
+ ROM_IGNORE( 0x8000 )
+ROM_END
+
+const tiny_rom_entry *isa16_wd90c33_zz_device::device_rom_region() const
+{
+ return ROM_NAME( wd90c33_zz );
+}
+
+void isa16_wd90c33_zz_device::device_add_mconfig(machine_config &config)
+{
+ screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
+ screen.set_raw(25.175_MHz_XTAL, 800, 0, 640, 524, 0, 480);
+ screen.set_screen_update("vga", FUNC(wd90c33_vga_device::screen_update));
+
+ WD90C33(config, m_vga, 0);
+ m_vga->set_screen("screen");
+ // 1MB, 2MB
+ m_vga->set_vram_size(0x100000);
+}
+
+void isa16_wd90c33_zz_device::io_isa_map(address_map &map)
+{
+ map(0x00, 0x2f).m(m_vga, FUNC(wd90c33_vga_device::io_map));
+}
+
+void isa16_wd90c33_zz_device::device_start()
+{
+ set_isa_device();
+
+ m_isa->install_rom(this, 0xc0000, 0xc7fff, "vga_rom");
+
+ m_isa->install_memory(0xa0000, 0xbffff, read8sm_delegate(*m_vga, FUNC(wd90c33_vga_device::mem_r)), write8sm_delegate(*m_vga, FUNC(wd90c33_vga_device::mem_w)));
+ m_isa->install_device(0x03b0, 0x03df, *this, &isa16_wd90c33_zz_device::io_isa_map);
+ m_isa->install_device(0x23c0, 0x23cf, *m_vga, &wd90c33_vga_device::ext_io_map);
+ m_isa->install_device(0x23d0, 0x23d3, *m_vga, &wd90c33_vga_device::localbus_if_map);
+}
diff --git a/src/devices/bus/isa/svga_paradise.h b/src/devices/bus/isa/svga_paradise.h
new file mode 100644
index 00000000000..8b9eeea6367
--- /dev/null
+++ b/src/devices/bus/isa/svga_paradise.h
@@ -0,0 +1,253 @@
+// license:BSD-3-Clause
+// copyright-holders: Angelo Salese
+
+#ifndef MAME_BUS_ISA_SVGA_PARADISE_H
+#define MAME_BUS_ISA_SVGA_PARADISE_H
+
+#pragma once
+
+#include "isa.h"
+#include "video/pc_vga_paradise.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class isa16_pvga1a_device :
+ public device_t,
+ public device_isa16_card_interface
+{
+public:
+ // construction/destruction
+ isa16_pvga1a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void remap(int space_id, offs_t start, offs_t end) override;
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+ void io_isa_map(address_map &map);
+
+private:
+ required_device<pvga1a_vga_device> m_vga;
+};
+
+class isa16_pvga1a_jk_device :
+ public device_t,
+ public device_isa16_card_interface
+{
+public:
+ // construction/destruction
+ isa16_pvga1a_jk_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+ void io_isa_map(address_map &map);
+
+private:
+ required_device<pvga1a_vga_device> m_vga;
+};
+
+class isa8_wd90c90_jk_device :
+ public device_t,
+ public device_isa8_card_interface
+{
+public:
+ // construction/destruction
+ isa8_wd90c90_jk_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+ void io_isa_map(address_map &map);
+
+private:
+ required_device<pvga1a_vga_device> m_vga;
+};
+
+class isa16_wd90c00_jk_device :
+ public device_t,
+ public device_isa16_card_interface
+{
+public:
+ // construction/destruction
+ isa16_wd90c00_jk_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+ void io_isa_map(address_map &map);
+
+private:
+ required_device<wd90c00_vga_device> m_vga;
+};
+
+class isa16_wd90c11_lr_device :
+ public device_t,
+ public device_isa16_card_interface
+{
+public:
+ // construction/destruction
+ isa16_wd90c11_lr_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+ void io_isa_map(address_map &map);
+
+private:
+ required_device<wd90c11a_vga_device> m_vga;
+};
+
+class isa16_wd90c30_lr_device :
+ public device_t,
+ public device_isa16_card_interface
+{
+public:
+ // construction/destruction
+ isa16_wd90c30_lr_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+ void io_isa_map(address_map &map);
+
+private:
+ required_device<wd90c30_vga_device> m_vga;
+};
+
+class isa16_wd90c31_lr_device :
+ public device_t,
+ public device_isa16_card_interface
+{
+public:
+ // construction/destruction
+ isa16_wd90c31_lr_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void remap(int space_id, offs_t start, offs_t end) override;
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+ void io_isa_map(address_map &map);
+
+private:
+ required_device<wd90c31_vga_device> m_vga;
+};
+
+class isa16_wd90c31a_lr_device :
+ public device_t,
+ public device_isa16_card_interface
+{
+public:
+ // construction/destruction
+ isa16_wd90c31a_lr_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+ void io_isa_map(address_map &map);
+
+private:
+ required_device<wd90c31_vga_device> m_vga;
+};
+
+class isa16_wd90c31a_zs_device :
+ public device_t,
+ public device_isa16_card_interface
+{
+public:
+ // construction/destruction
+ isa16_wd90c31a_zs_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+ void io_isa_map(address_map &map);
+
+private:
+ required_device<wd90c31_vga_device> m_vga;
+};
+
+class isa16_wd90c33_zz_device :
+ public device_t,
+ public device_isa16_card_interface
+{
+public:
+ // construction/destruction
+ isa16_wd90c33_zz_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+ void io_isa_map(address_map &map);
+
+private:
+ required_device<wd90c33_vga_device> m_vga;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(ISA16_PVGA1A, isa16_pvga1a_device)
+DECLARE_DEVICE_TYPE(ISA16_PVGA1A_JK, isa16_pvga1a_jk_device)
+DECLARE_DEVICE_TYPE(ISA8_WD90C90_JK, isa8_wd90c90_jk_device)
+DECLARE_DEVICE_TYPE(ISA16_WD90C00_JK, isa16_wd90c00_jk_device)
+DECLARE_DEVICE_TYPE(ISA16_WD90C11_LR, isa16_wd90c11_lr_device)
+DECLARE_DEVICE_TYPE(ISA16_WD90C30_LR, isa16_wd90c30_lr_device)
+DECLARE_DEVICE_TYPE(ISA16_WD90C31_LR, isa16_wd90c31_lr_device)
+DECLARE_DEVICE_TYPE(ISA16_WD90C31A_LR, isa16_wd90c31a_lr_device)
+DECLARE_DEVICE_TYPE(ISA16_WD90C31A_ZS, isa16_wd90c31a_zs_device)
+DECLARE_DEVICE_TYPE(ISA16_WD90C33_ZZ, isa16_wd90c33_zz_device)
+
+
+#endif // MAME_BUS_ISA_SVGA_PARADISE_H
diff --git a/src/devices/bus/isa/svga_s3.cpp b/src/devices/bus/isa/svga_s3.cpp
index 58984396d86..c935e3e0152 100644
--- a/src/devices/bus/isa/svga_s3.cpp
+++ b/src/devices/bus/isa/svga_s3.cpp
@@ -1,10 +1,30 @@
// license:BSD-3-Clause
// copyright-holders:Barry Rodewald
-/***************************************************************************
+/**************************************************************************************************
ISA SVGA S3 wrapper
-***************************************************************************/
+ ISA16
+ - P86C911
+ - P86C911A
+ - P86C924
+ - P86C801
+ - 86C801-R
+ ISA16 / VL-Bus
+ - P86C928
+ - P86C805 / 86C805-P / 86C805-Q
+ - 86C805i
+ VL-Bus / PCI
+ - Vision864
+ - Vision868
+ - Vision964
+ - Vision968
+ - Trio64 (Spea V7-MIRAGE P64, probably last card before full transition to PCI)
+
+ TODO:
+ - all s3_764 roms are really PCI and needs to be moved to video/virge_pci.cpp.
+
+**************************************************************************************************/
#include "emu.h"
#include "svga_s3.h"
@@ -55,9 +75,9 @@ void isa16_svga_s3_device::device_add_mconfig(machine_config &config)
{
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
screen.set_raw(25.175_MHz_XTAL, 800, 0, 640, 524, 0, 480);
- screen.set_screen_update(m_vga, FUNC(s3_vga_device::screen_update));
+ screen.set_screen_update(m_vga, FUNC(s3trio64_vga_device::screen_update));
- S3_VGA(config, m_vga, 0);
+ S3_TRIO64_VGA(config, m_vga, 0);
m_vga->set_screen("screen");
m_vga->set_vram_size(0x100000);
}
@@ -86,6 +106,11 @@ isa16_svga_s3_device::isa16_svga_s3_device(const machine_config &mconfig, const
{
}
+void isa16_svga_s3_device::io_isa_map(address_map &map)
+{
+ map(0x00, 0x2f).m(m_vga, FUNC(s3trio64_vga_device::io_map));
+}
+
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
@@ -97,9 +122,8 @@ void isa16_svga_s3_device::device_start()
m_isa->install_rom(this, 0xc0000, 0xc7fff, "s3_764");
- m_isa->install_device(0x03b0, 0x03bf, read8sm_delegate(*m_vga, FUNC(s3_vga_device::port_03b0_r)), write8sm_delegate(*m_vga, FUNC(s3_vga_device::port_03b0_w)));
- m_isa->install_device(0x03c0, 0x03cf, read8sm_delegate(*m_vga, FUNC(s3_vga_device::port_03c0_r)), write8sm_delegate(*m_vga, FUNC(s3_vga_device::port_03c0_w)));
- m_isa->install_device(0x03d0, 0x03df, read8sm_delegate(*m_vga, FUNC(s3_vga_device::port_03d0_r)), write8sm_delegate(*m_vga, FUNC(s3_vga_device::port_03d0_w)));
+ m_isa->install_device(0x03b0, 0x03df, *this, &isa16_svga_s3_device::io_isa_map);
+
m_isa->install16_device(0x82e8, 0x82eb, read16smo_delegate(*m_8514, FUNC(ibm8514a_device::ibm8514_currenty_r)), write16smo_delegate(*m_8514, FUNC(ibm8514a_device::ibm8514_currenty_w)));
m_isa->install16_device(0x86e8, 0x86eb, read16smo_delegate(*m_8514, FUNC(ibm8514a_device::ibm8514_currentx_r)), write16smo_delegate(*m_8514, FUNC(ibm8514a_device::ibm8514_currentx_w)));
m_isa->install16_device(0x8ae8, 0x8aeb, read16smo_delegate(*m_8514, FUNC(ibm8514a_device::ibm8514_desty_r)), write16smo_delegate(*m_8514, FUNC(ibm8514a_device::ibm8514_desty_w)));
@@ -117,7 +141,7 @@ void isa16_svga_s3_device::device_start()
m_isa->install16_device(0xbee8, 0xbeeb, read16smo_delegate(*m_8514, FUNC(ibm8514a_device::ibm8514_multifunc_r)), write16smo_delegate(*m_8514, FUNC(ibm8514a_device::ibm8514_multifunc_w)));
m_isa->install16_device(0xe2e8, 0xe2eb, read16sm_delegate(*m_8514, FUNC(ibm8514a_device::ibm8514_pixel_xfer_r)), write16sm_delegate(*m_8514, FUNC(ibm8514a_device::ibm8514_pixel_xfer_w)));
- m_isa->install_memory(0xa0000, 0xbffff, read8sm_delegate(*m_vga, FUNC(s3_vga_device::mem_r)), write8sm_delegate(*m_vga, FUNC(s3_vga_device::mem_w)));
+ m_isa->install_memory(0xa0000, 0xbffff, read8sm_delegate(*m_vga, FUNC(s3trio64_vga_device::mem_r)), write8sm_delegate(*m_vga, FUNC(s3trio64_vga_device::mem_w)));
}
//-------------------------------------------------
@@ -127,311 +151,3 @@ void isa16_svga_s3_device::device_start()
void isa16_svga_s3_device::device_reset()
{
}
-
-
-/*
- * S3 Virge 2D/3D accelerator
- */
-
-ROM_START( s3virge )
- ROM_REGION(0x8000,"s3virge", 0)
- ROM_DEFAULT_BIOS("virge")
-
- ROM_SYSTEM_BIOS( 0, "virge", "PCI S3 ViRGE v1.00-10" )
- ROMX_LOAD("pci_m-v_virge-4s3.bin", 0x00000, 0x8000, CRC(d0a0f1de) SHA1(b7b41081974762a199610219bdeab149b7c7143d), ROM_BIOS(0) )
-
- ROM_SYSTEM_BIOS( 1, "virgeo", "PCI S3 ViRGE v1.00-05" )
- ROMX_LOAD("s3virge.bin", 0x00000, 0x8000, CRC(a7983a85) SHA1(e885371816d3237f7badd57ccd602cd863c9c9f8), ROM_BIOS(1) )
- ROM_IGNORE( 0x8000 )
-ROM_END
-
-//**************************************************************************
-// GLOBAL VARIABLES
-//**************************************************************************
-
-DEFINE_DEVICE_TYPE(ISA16_S3VIRGE, isa16_s3virge_device, "s3virge", "S3 ViRGE Graphics Card")
-
-
-//-------------------------------------------------
-// device_add_mconfig - add device configuration
-//-------------------------------------------------
-
-void isa16_s3virge_device::device_add_mconfig(machine_config &config)
-{
- screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
- screen.set_raw(25.175_MHz_XTAL, 800, 0, 640, 524, 0, 480);
- screen.set_screen_update(m_vga, FUNC(s3virge_vga_device::screen_update));
-
- S3VIRGE(config, m_vga, 0);
- m_vga->set_screen("screen");
- m_vga->set_vram_size(0x400000);
- m_vga->linear_config_changed().set(FUNC(isa16_s3virge_device::linear_config_changed_w));
-}
-
-//-------------------------------------------------
-// linear_config_changed_w - callback to indicate
-// enabling, disabling, or changig of the linear
-// framebuffer configuration.
-//-------------------------------------------------
-
-WRITE_LINE_MEMBER(isa16_s3virge_device::linear_config_changed_w)
-{
-}
-
-//-------------------------------------------------
-// rom_region - device-specific ROM region
-//-------------------------------------------------
-
-const tiny_rom_entry *isa16_s3virge_device::device_rom_region() const
-{
- return ROM_NAME( s3virge );
-}
-
-//**************************************************************************
-// LIVE DEVICE
-//**************************************************************************
-
-//-------------------------------------------------
-// isa16_vga_device - constructor
-//-------------------------------------------------
-
-isa16_s3virge_device::isa16_s3virge_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, ISA16_S3VIRGE, tag, owner, clock),
- device_isa16_card_interface(mconfig, *this),
- m_vga(*this, "vga")
-{
-}
-
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-uint8_t isa16_s3virge_device::input_port_0_r() { return 0xff; } //return machine().root_device().ioport("IN0")->read(); }
-
-void isa16_s3virge_device::device_start()
-{
- set_isa_device();
-
- m_isa->install_rom(this, 0xc0000, 0xc7fff, "s3virge");
-
- m_isa->install_device(0x03b0, 0x03bf, read8sm_delegate(*m_vga, FUNC(s3virge_vga_device::port_03b0_r)), write8sm_delegate(*m_vga, FUNC(s3virge_vga_device::port_03b0_w)));
- m_isa->install_device(0x03c0, 0x03cf, read8sm_delegate(*m_vga, FUNC(s3virge_vga_device::port_03c0_r)), write8sm_delegate(*m_vga, FUNC(s3virge_vga_device::port_03c0_w)));
- m_isa->install_device(0x03d0, 0x03df, read8sm_delegate(*m_vga, FUNC(s3virge_vga_device::port_03d0_r)), write8sm_delegate(*m_vga, FUNC(s3virge_vga_device::port_03d0_w)));
-
- m_isa->install_memory(0xa0000, 0xbffff, read8sm_delegate(*m_vga, FUNC(s3virge_vga_device::mem_r)), write8sm_delegate(*m_vga, FUNC(s3virge_vga_device::mem_w)));
-}
-
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
-void isa16_s3virge_device::device_reset()
-{
-}
-
-/*
- * S3 ViRGE/DX
- */
-
-ROM_START( s3virgedx )
- ROM_REGION(0x8000,"s3virgedx", 0)
- ROM_LOAD("s3virgedx.bin", 0x00000, 0x8000, CRC(0da83bd3) SHA1(228a2d644e1732cb5a2eb1291608c7050cf39229) )
-ROM_END
-
-//**************************************************************************
-// GLOBAL VARIABLES
-//**************************************************************************
-
-DEFINE_DEVICE_TYPE(ISA16_S3VIRGEDX, isa16_s3virgedx_device, "s3virgedx", "S3 ViRGE/DX Graphics Card")
-
-
-//-------------------------------------------------
-// device_add_mconfig - add device configuration
-//-------------------------------------------------
-
-void isa16_s3virgedx_device::device_add_mconfig(machine_config &config)
-{
- screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
- screen.set_raw(25.175_MHz_XTAL, 800, 0, 640, 524, 0, 480);
- screen.set_screen_update(m_vga, FUNC(s3virgedx_vga_device::screen_update));
-
- S3VIRGEDX(config, m_vga, 0);
- m_vga->set_screen("screen");
- m_vga->set_vram_size(0x400000);
- m_vga->linear_config_changed().set(FUNC(isa16_s3virgedx_device::linear_config_changed_w));
-}
-
-//-------------------------------------------------
-// linear_config_changed_w - callback to indicate
-// enabling, disabling, or changig of the linear
-// framebuffer configuration.
-//-------------------------------------------------
-
-WRITE_LINE_MEMBER(isa16_s3virgedx_device::linear_config_changed_w)
-{
- const bool old = m_lfb_enable;
- m_lfb_enable = state;
- if (state)
- {
- if (old)
- {
- m_isa->unmap_readwrite(m_lfb_start, m_lfb_end);
- }
- m_lfb_start = m_vga->get_linear_address();
- m_lfb_end = m_lfb_start + m_vga->get_linear_address_size_full() - 1;
- m_isa->install_memory(m_lfb_start, m_lfb_end, read8sm_delegate(*m_vga, FUNC(s3virge_vga_device::fb_r)), write8sm_delegate(*m_vga, FUNC(s3virge_vga_device::fb_w)));
- }
- else
- {
- m_isa->unmap_readwrite(m_lfb_start, m_lfb_end);
- }
-}
-
-//-------------------------------------------------
-// rom_region - device-specific ROM region
-//-------------------------------------------------
-
-const tiny_rom_entry *isa16_s3virgedx_device::device_rom_region() const
-{
- return ROM_NAME( s3virgedx );
-}
-
-//**************************************************************************
-// LIVE DEVICE
-//**************************************************************************
-
-//-------------------------------------------------
-// isa16_vga_device - constructor
-//-------------------------------------------------
-
-isa16_s3virgedx_device::isa16_s3virgedx_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, ISA16_S3VIRGEDX, tag, owner, clock),
- device_isa16_card_interface(mconfig, *this),
- m_vga(*this, "vga")
-{
-}
-
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-uint8_t isa16_s3virgedx_device::input_port_0_r() { return 0xff; } //return machine().root_device().ioport("IN0")->read(); }
-
-void isa16_s3virgedx_device::device_start()
-{
- set_isa_device();
-
- m_isa->install_rom(this, 0xc0000, 0xc7fff, "s3virgedx");
-
- m_isa->install_device(0x03b0, 0x03bf, read8sm_delegate(*m_vga, FUNC(s3virge_vga_device::port_03b0_r)), write8sm_delegate(*m_vga, FUNC(s3virge_vga_device::port_03b0_w)));
- m_isa->install_device(0x03c0, 0x03cf, read8sm_delegate(*m_vga, FUNC(s3virge_vga_device::port_03c0_r)), write8sm_delegate(*m_vga, FUNC(s3virge_vga_device::port_03c0_w)));
- m_isa->install_device(0x03d0, 0x03df, read8sm_delegate(*m_vga, FUNC(s3virge_vga_device::port_03d0_r)), write8sm_delegate(*m_vga, FUNC(s3virge_vga_device::port_03d0_w)));
-
- m_isa->install_memory(0xa0000, 0xbffff, read8sm_delegate(*m_vga, FUNC(s3virge_vga_device::mem_r)), write8sm_delegate(*m_vga, FUNC(s3virge_vga_device::mem_w)));
-
- save_item(NAME(m_lfb_enable));
- save_item(NAME(m_lfb_start));
- save_item(NAME(m_lfb_end));
-}
-
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
-void isa16_s3virgedx_device::device_reset()
-{
- m_lfb_enable = m_vga->is_linear_address_active();
- m_lfb_start = m_vga->get_linear_address();
- m_lfb_end = m_lfb_start + m_vga->get_linear_address_size_full() - 1;
-}
-
-
-/*
- * Diamond Stealth 3D 2000 Pro
- */
-
-ROM_START( stealth3d2kpro )
- ROM_REGION(0x8000,"stealth3d", 0)
- ROM_LOAD("virgedxdiamond.bin", 0x00000, 0x8000, CRC(58b0dcda) SHA1(b13ae6b04db6fc05a76d924ddf2efe150b823029) )
-ROM_END
-
-//**************************************************************************
-// GLOBAL VARIABLES
-//**************************************************************************
-
-DEFINE_DEVICE_TYPE(ISA16_DMS3D2KPRO, isa16_stealth3d2kpro_device, "dms3d2kp", "Diamond Stealth 3D 2000 Pro")
-
-
-//-------------------------------------------------
-// device_add_mconfig - add device configuration
-//-------------------------------------------------
-
-void isa16_stealth3d2kpro_device::device_add_mconfig(machine_config &config)
-{
- screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
- screen.set_raw(25.175_MHz_XTAL, 800, 0, 640, 524, 0, 480);
- screen.set_screen_update(m_vga, FUNC(s3virgedx_rev1_vga_device::screen_update));
-
- S3VIRGEDX1(config, m_vga, 0);
- m_vga->set_screen("screen");
- m_vga->set_vram_size(0x400000);
- m_vga->linear_config_changed().set(FUNC(isa16_stealth3d2kpro_device::linear_config_changed_w));
-}
-
-//-------------------------------------------------
-// linear_config_changed_w - callback to indicate
-// enabling, disabling, or changig of the linear
-// framebuffer configuration.
-//-------------------------------------------------
-
-WRITE_LINE_MEMBER(isa16_stealth3d2kpro_device::linear_config_changed_w)
-{
-}
-
-//-------------------------------------------------
-// rom_region - device-specific ROM region
-//-------------------------------------------------
-
-const tiny_rom_entry *isa16_stealth3d2kpro_device::device_rom_region() const
-{
- return ROM_NAME( stealth3d2kpro );
-}
-
-//**************************************************************************
-// LIVE DEVICE
-//**************************************************************************
-
-//-------------------------------------------------
-// isa16_vga_device - constructor
-//-------------------------------------------------
-
-isa16_stealth3d2kpro_device::isa16_stealth3d2kpro_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, ISA16_DMS3D2KPRO, tag, owner, clock),
- device_isa16_card_interface(mconfig, *this),
- m_vga(*this, "vga")
-{
-}
-
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-uint8_t isa16_stealth3d2kpro_device::input_port_0_r() { return 0xff; } //return machine().root_device().ioport("IN0")->read(); }
-
-void isa16_stealth3d2kpro_device::device_start()
-{
- set_isa_device();
-
- m_isa->install_rom(this, 0xc0000, 0xc7fff, "stealth3d");
-
- m_isa->install_device(0x03b0, 0x03bf, read8sm_delegate(*m_vga, FUNC(s3virge_vga_device::port_03b0_r)), write8sm_delegate(*m_vga, FUNC(s3virge_vga_device::port_03b0_w)));
- m_isa->install_device(0x03c0, 0x03cf, read8sm_delegate(*m_vga, FUNC(s3virge_vga_device::port_03c0_r)), write8sm_delegate(*m_vga, FUNC(s3virge_vga_device::port_03c0_w)));
- m_isa->install_device(0x03d0, 0x03df, read8sm_delegate(*m_vga, FUNC(s3virge_vga_device::port_03d0_r)), write8sm_delegate(*m_vga, FUNC(s3virge_vga_device::port_03d0_w)));
-
- m_isa->install_memory(0xa0000, 0xbffff, read8sm_delegate(*m_vga, FUNC(s3virge_vga_device::mem_r)), write8sm_delegate(*m_vga, FUNC(s3virge_vga_device::mem_w)));
-}
-
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
-void isa16_stealth3d2kpro_device::device_reset()
-{
-}
diff --git a/src/devices/bus/isa/svga_s3.h b/src/devices/bus/isa/svga_s3.h
index a07b0e039c6..921eff6f440 100644
--- a/src/devices/bus/isa/svga_s3.h
+++ b/src/devices/bus/isa/svga_s3.h
@@ -6,8 +6,8 @@
#pragma once
#include "isa.h"
-#include "video/pc_vga.h"
-#include "s3virge.h"
+#include "video/pc_vga_s3.h"
+
//**************************************************************************
// TYPE DEFINITIONS
@@ -34,94 +34,14 @@ protected:
virtual void device_add_mconfig(machine_config &config) override;
virtual const tiny_rom_entry *device_rom_region() const override;
-private:
- required_device<s3_vga_device> m_vga;
- required_device<ibm8514a_device> m_8514;
-};
-
-class isa16_s3virge_device :
- public device_t,
- public device_isa16_card_interface
-{
-public:
- // construction/destruction
- isa16_s3virge_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- uint8_t input_port_0_r();
-
-protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
-
- // optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
-
- DECLARE_WRITE_LINE_MEMBER(linear_config_changed_w);
-
-private:
- required_device<s3virge_vga_device> m_vga;
-};
-
-class isa16_s3virgedx_device :
- public device_t,
- public device_isa16_card_interface
-{
-public:
- // construction/destruction
- isa16_s3virgedx_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- uint8_t input_port_0_r();
-
-protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
-
- // optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
-
- DECLARE_WRITE_LINE_MEMBER(linear_config_changed_w);
+ void io_isa_map(address_map &map);
private:
- required_device<s3virgedx_vga_device> m_vga;
- bool m_lfb_enable;
- uint32_t m_lfb_start;
- uint32_t m_lfb_end;
-};
-
-class isa16_stealth3d2kpro_device :
- public device_t,
- public device_isa16_card_interface
-{
-public:
- // construction/destruction
- isa16_stealth3d2kpro_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- uint8_t input_port_0_r();
-
-protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
-
- // optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
-
- DECLARE_WRITE_LINE_MEMBER(linear_config_changed_w);
-
-private:
- required_device<s3virgedx_vga_device> m_vga;
+ required_device<s3trio64_vga_device> m_vga;
+ required_device<ibm8514a_device> m_8514;
};
-
// device type definition
DECLARE_DEVICE_TYPE(ISA16_SVGA_S3, isa16_svga_s3_device)
-DECLARE_DEVICE_TYPE(ISA16_S3VIRGE, isa16_s3virge_device)
-DECLARE_DEVICE_TYPE(ISA16_S3VIRGEDX, isa16_s3virgedx_device)
-DECLARE_DEVICE_TYPE(ISA16_DMS3D2KPRO, isa16_stealth3d2kpro_device)
#endif // MAME_BUS_ISA_SVGA_S3_H
diff --git a/src/devices/bus/isa/svga_trident.cpp b/src/devices/bus/isa/svga_trident.cpp
index f3b4e0f9a6f..790a405770e 100644
--- a/src/devices/bus/isa/svga_trident.cpp
+++ b/src/devices/bus/isa/svga_trident.cpp
@@ -1,17 +1,81 @@
// license:BSD-3-Clause
// copyright-holders:Barry Rodewald
/*
- * svga_trident.c
+ * svga_trident.cpp
*
* Created on: 6/09/2014
+ *
+ * TODO:
+ * - tgui9680 is a PCI card, not ISA!
+ * \- the only client is pc/calchase.cpp, which at the time of this writing uses legacy PCI bus;
+ *
*/
#include "emu.h"
#include "svga_trident.h"
-#include "video/pc_vga.h"
+#include "video/pc_vga_trident.h"
#include "screen.h"
+ROM_START( tvga9000 )
+ ROM_REGION( 0x8000, "tvga9000", 0 )
+ ROM_SYSTEM_BIOS(0, "v350", "Version D3.50 12/02/92")
+ ROMX_LOAD( "trident_quadtel_tvga9000_isa16.bin", 0x0000, 0x8000, CRC(ad0e7351) SHA1(eb525460a80e1c1baa34642b93d54caf2607920d), ROM_BIOS(0) )
+ ROM_IGNORE ( 0x8000 )
+ ROM_SYSTEM_BIOS(1, "v300", "Version D3.00 11/12/91")
+ ROMX_LOAD( "quadtel_tvga_bios_software_1991_ver_d3_0_lh.bin", 0x0000, 0x8000, CRC(d35a8ce9) SHA1(9cff3cb86a85dcbd34234bc4fd1dd0011f3d48fd), ROM_BIOS(1) )
+ ROM_IGNORE ( 0x8000 )
+ROM_END
+
+DEFINE_DEVICE_TYPE(ISA16_SVGA_TVGA9000, isa16_svga_tvga9000_device, "tvga9000", "Trident/Quadtel TVGA9000B SVGA card")
+
+void isa16_svga_tvga9000_device::device_add_mconfig(machine_config &config)
+{
+ screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
+ screen.set_raw(25.175_MHz_XTAL, 800, 0, 640, 524, 0, 480);
+ screen.set_screen_update(m_vga, FUNC(trident_vga_device::screen_update));
+
+ TVGA9000_VGA(config, m_vga, 0);
+ m_vga->set_screen("screen");
+ m_vga->set_vram_size(512 * 1024); // 0x80000
+}
+
+const tiny_rom_entry *isa16_svga_tvga9000_device::device_rom_region() const
+{
+ return ROM_NAME( tvga9000 );
+}
+
+isa16_svga_tvga9000_device::isa16_svga_tvga9000_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, ISA16_SVGA_TVGA9000, tag, owner, clock)
+ , device_isa16_card_interface(mconfig, *this)
+ , m_vga(*this, "vga")
+{
+}
+
+void isa16_svga_tvga9000_device::io_isa_map(address_map &map)
+{
+ map(0x00, 0x2f).m(m_vga, FUNC(tvga9000_device::io_map));
+}
+
+uint8_t isa16_svga_tvga9000_device::input_port_0_r() { return 0xff; } //return machine().root_device().ioport("IN0")->read(); }
+
+void isa16_svga_tvga9000_device::device_start()
+{
+ set_isa_device();
+
+ m_isa->install_rom(this, 0xc0000, 0xc7fff, "tvga9000");
+
+ m_isa->install_device(0x03b0, 0x03df, *this, &isa16_svga_tvga9000_device::io_isa_map);
+
+ m_isa->install_device(0x43c4, 0x43cb, read8sm_delegate(*m_vga, FUNC(tvga9000_device::port_43c6_r)), write8sm_delegate(*m_vga, FUNC(tvga9000_device::port_43c6_w)));
+ m_isa->install_device(0x83c4, 0x83cb, read8sm_delegate(*m_vga, FUNC(tvga9000_device::port_83c6_r)), write8sm_delegate(*m_vga, FUNC(tvga9000_device::port_83c6_w)));
+
+ m_isa->install_memory(0xa0000, 0xbffff, read8sm_delegate(*m_vga, FUNC(tvga9000_device::mem_r)), write8sm_delegate(*m_vga, FUNC(tvga9000_device::mem_w)));
+}
+
+/*
+ * TGUI9680
+ */
ROM_START( tgui9680 )
ROM_REGION( 0x8000, "tgui9680", 0 )
@@ -19,9 +83,6 @@ ROM_START( tgui9680 )
ROM_CONTINUE( 0x0001, 0x4000 )
ROM_END
-//**************************************************************************
-// GLOBAL VARIABLES
-//**************************************************************************
DEFINE_DEVICE_TYPE(ISA16_SVGA_TGUI9680, isa16_svga_tgui9680_device, "tgui9680", "Trident TGUI9680 Graphics Card (BIOS X5.5 (02) 02/13/96)")
@@ -58,11 +119,16 @@ const tiny_rom_entry *isa16_svga_tgui9680_device::device_rom_region() const
// isa8_vga_device - constructor
//-------------------------------------------------
-isa16_svga_tgui9680_device::isa16_svga_tgui9680_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, ISA16_SVGA_TGUI9680, tag, owner, clock),
- device_isa16_card_interface(mconfig, *this),
- m_vga(*this, "vga")
+isa16_svga_tgui9680_device::isa16_svga_tgui9680_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, ISA16_SVGA_TGUI9680, tag, owner, clock)
+ , device_isa16_card_interface(mconfig, *this)
+ , m_vga(*this, "vga")
+{
+}
+
+void isa16_svga_tgui9680_device::io_isa_map(address_map &map)
{
+ map(0x00, 0x2f).m(m_vga, FUNC(trident_vga_device::io_map));
}
//-------------------------------------------------
@@ -76,9 +142,8 @@ void isa16_svga_tgui9680_device::device_start()
m_isa->install_rom(this, 0xc0000, 0xc7fff, "tgui9680");
- m_isa->install_device(0x3b0, 0x3bf, read8sm_delegate(*m_vga, FUNC(trident_vga_device::port_03b0_r)), write8sm_delegate(*m_vga, FUNC(trident_vga_device::port_03b0_w)));
- m_isa->install_device(0x3c0, 0x3cf, read8sm_delegate(*m_vga, FUNC(trident_vga_device::port_03c0_r)), write8sm_delegate(*m_vga, FUNC(trident_vga_device::port_03c0_w)));
- m_isa->install_device(0x3d0, 0x3df, read8sm_delegate(*m_vga, FUNC(trident_vga_device::port_03d0_r)), write8sm_delegate(*m_vga, FUNC(trident_vga_device::port_03d0_w)));
+ m_isa->install_device(0x03b0, 0x03df, *this, &isa16_svga_tgui9680_device::io_isa_map);
+
m_isa->install_device(0x43c4, 0x43cb, read8sm_delegate(*m_vga, FUNC(trident_vga_device::port_43c6_r)), write8sm_delegate(*m_vga, FUNC(trident_vga_device::port_43c6_w)));
m_isa->install_device(0x83c4, 0x83cb, read8sm_delegate(*m_vga, FUNC(trident_vga_device::port_83c6_r)), write8sm_delegate(*m_vga, FUNC(trident_vga_device::port_83c6_w)));
@@ -88,16 +153,8 @@ void isa16_svga_tgui9680_device::device_start()
// m_isa->install_memory(0x4400000, 0x45fffff, read8sm_delegate(*m_vga, FUNC(trident_vga_device::vram_r)), write8sm_delegate(*m_vga, FUNC(trident_vga_device::vram_w)));
// win95 drivers
-// m_isa->install_memory(0x4000000, 0x41fffff, read8sm_delegate(*m_vga, FUNC(trident_vga_device::vram_r)), write8sm_delegate(FUNC(*m_vga, trident_vga_device::vram_w)));
+// m_isa->install_memory(0x4000000, 0x41fffff, read8sm_delegate(*m_vga, FUNC(trident_vga_device::vram_r)), write8sm_delegate(*m_vga, FUNC(trident_vga_device::vram_w)));
// acceleration ports
m_isa->install_device(0x2120, 0x21ff, read8sm_delegate(*m_vga, FUNC(trident_vga_device::accel_r)), write8sm_delegate(*m_vga, FUNC(trident_vga_device::accel_w)));
}
-
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
-void isa16_svga_tgui9680_device::device_reset()
-{
-}
diff --git a/src/devices/bus/isa/svga_trident.h b/src/devices/bus/isa/svga_trident.h
index c5c7bfdcf1d..1ca7b622009 100644
--- a/src/devices/bus/isa/svga_trident.h
+++ b/src/devices/bus/isa/svga_trident.h
@@ -2,22 +2,43 @@
// copyright-holders:Barry Rodewald
/*
* svga_trident.h
- *
- * Created on: 6/09/2014
*/
#ifndef MAME_BUS_ISA_SVGA_TRIDENT_H
#define MAME_BUS_ISA_SVGA_TRIDENT_H
#include "isa.h"
-#include "video/pc_vga.h"
-#include "bus/isa/trident.h"
+
+#include "video/pc_vga_trident.h"
+
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
-// ======================> isa16_vga_device
+class isa16_svga_tvga9000_device :
+ public device_t,
+ public device_isa16_card_interface
+{
+public:
+ // construction/destruction
+ isa16_svga_tvga9000_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ uint8_t input_port_0_r();
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+ void io_isa_map(address_map &map);
+
+private:
+ required_device<tvga9000_device> m_vga;
+};
class isa16_svga_tgui9680_device :
public device_t,
@@ -32,18 +53,20 @@ public:
protected:
// device-level overrides
virtual void device_start() override;
- virtual void device_reset() override;
// optional information overrides
virtual void device_add_mconfig(machine_config &config) override;
virtual const tiny_rom_entry *device_rom_region() const override;
+ void io_isa_map(address_map &map);
+
private:
required_device<trident_vga_device> m_vga;
};
// device type definition
+DECLARE_DEVICE_TYPE(ISA16_SVGA_TVGA9000, isa16_svga_tvga9000_device)
DECLARE_DEVICE_TYPE(ISA16_SVGA_TGUI9680, isa16_svga_tgui9680_device)
diff --git a/src/devices/bus/isa/svga_tseng.cpp b/src/devices/bus/isa/svga_tseng.cpp
index 0d1485ad17d..39a6533f3c7 100644
--- a/src/devices/bus/isa/svga_tseng.cpp
+++ b/src/devices/bus/isa/svga_tseng.cpp
@@ -4,25 +4,36 @@
ISA SVGA Tseng wrapper
+ TODO:
+ - Implement Korean font ROM for Kasan 16
+
***************************************************************************/
#include "emu.h"
#include "svga_tseng.h"
-#include "video/pc_vga.h"
-
-#include "screen.h"
-
+/*
+ * (tseng labs famous et4000 isa vga card (oem))
+ * ROM_LOAD("et4000b.bin", 0xc0000, 0x8000, CRC(a903540d) SHA1(unknown) )
+ *
+ * Version "8.06X 04/15/92" (yay for semver)
+ * Tested, draws corrupted GFX, likely bad
+ * ROM_LOAD("et4000.bin.other", 0xc0000, 0x8000, CRC(f01e4be0) SHA1(95d75ff41bcb765e50bd87a8da01835fd0aa01d5) )
+ */
ROM_START( et4000 )
ROM_REGION(0x8000,"et4000", 0)
- ROM_LOAD("et4000.bin", 0x00000, 0x8000, CRC(f1e817a8) SHA1(945d405b0fb4b8f26830d495881f8587d90e5ef9) )
+ ROM_SYSTEM_BIOS(0, "v801x", "Tseng Version 8.01X 04/07/93")
+ ROMX_LOAD("et4000.bin", 0x00000, 0x8000, CRC(f1e817a8) SHA1(945d405b0fb4b8f26830d495881f8587d90e5ef9), ROM_BIOS(0) )
+ ROM_SYSTEM_BIOS(1, "v800x", "ColorImage Version 8.00X 09/18/90")
+ ROMX_LOAD("cvet4kax.bin", 0x00000, 0x8000, CRC(a3ab496c) SHA1(8644b4178cd0e841139bfa06c9da493dd74d22e8), ROM_BIOS(1) )
ROM_END
//**************************************************************************
// GLOBAL VARIABLES
//**************************************************************************
-DEFINE_DEVICE_TYPE(ISA8_SVGA_ET4K, isa8_svga_et4k_device, "et4000", "SVGA Tseng ET4000 Graphics Card")
+DEFINE_DEVICE_TYPE(ISA8_SVGA_ET4K, isa8_svga_et4k_device, "et4000", "SVGA Tseng ET4000AX Graphics Card")
+DEFINE_DEVICE_TYPE(ISA8_SVGA_ET4K_KASAN16, isa8_svga_et4k_kasan16_device, "et4000_kasan16", "SVGA Kasan Hangulmadang-16 ET4000AX Graphics Card")
//-------------------------------------------------
@@ -58,9 +69,14 @@ const tiny_rom_entry *isa8_svga_et4k_device::device_rom_region() const
//-------------------------------------------------
isa8_svga_et4k_device::isa8_svga_et4k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, ISA8_SVGA_ET4K, tag, owner, clock),
- device_isa8_card_interface(mconfig, *this),
- m_vga(*this, "vga")
+ isa8_svga_et4k_device(mconfig, ISA8_SVGA_ET4K, tag, owner, clock)
+{
+}
+
+isa8_svga_et4k_device::isa8_svga_et4k_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, type, tag, owner, clock)
+ , device_isa8_card_interface(mconfig, *this)
+ , m_vga(*this, "vga")
{
}
@@ -102,11 +118,14 @@ void isa8_svga_et4k_device::remap(int space_id, offs_t start, offs_t end)
map_io();
}
+void isa8_svga_et4k_device::io_isa_map(address_map &map)
+{
+ map(0x00, 0x2f).m(m_vga, FUNC(tseng_vga_device::io_map));
+}
+
void isa8_svga_et4k_device::map_io()
{
- m_isa->install_device(0x3b0, 0x3bf, read8sm_delegate(*m_vga, FUNC(tseng_vga_device::port_03b0_r)), write8sm_delegate(*m_vga, FUNC(tseng_vga_device::port_03b0_w)));
- m_isa->install_device(0x3c0, 0x3cf, read8sm_delegate(*m_vga, FUNC(tseng_vga_device::port_03c0_r)), write8sm_delegate(*m_vga, FUNC(tseng_vga_device::port_03c0_w)));
- m_isa->install_device(0x3d0, 0x3df, read8sm_delegate(*m_vga, FUNC(tseng_vga_device::port_03d0_r)), write8sm_delegate(*m_vga, FUNC(tseng_vga_device::port_03d0_w)));
+ m_isa->install_device(0x03b0, 0x03df, *this, &isa8_svga_et4k_device::io_isa_map);
}
void isa8_svga_et4k_device::map_ram()
@@ -118,3 +137,29 @@ void isa8_svga_et4k_device::map_rom()
{
m_isa->install_rom(this, 0xc0000, 0xc7fff, "et4000");
}
+
+/*
+ * Korean cards
+ *
+ * Same as regular ET4000AX with extra font I/Os
+ */
+
+isa8_svga_et4k_kasan16_device::isa8_svga_et4k_kasan16_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : isa8_svga_et4k_device(mconfig, ISA8_SVGA_ET4K_KASAN16, tag, owner, clock)
+ , m_hangul_rom(*this, "hangul")
+{
+}
+
+ROM_START( kasan16 )
+ ROM_REGION(0x8000,"et4000", 0)
+ ROM_SYSTEM_BIOS(0, "v802x", "Version 8.02X 06/13/90, Kasan BIOS Ver 1.0a 05/01/91")
+ ROMX_LOAD("et4000_kasan16.bin", 0x00000, 0x8000, CRC(57bcc3ad) SHA1(a55e7eb27ef2b4f118ea2028835e88988f07cf57), ROM_BIOS(0) )
+
+ ROM_REGION(0x80000, "hangul", 0)
+ ROM_LOAD("kasan_ksc5601.rom", 0x00000, 0x80000, CRC(a547c5ec) SHA1(1358feb2ccaca040a176bedc7c256ec481351b41) )
+ROM_END
+
+const tiny_rom_entry *isa8_svga_et4k_kasan16_device::device_rom_region() const
+{
+ return ROM_NAME( kasan16 );
+}
diff --git a/src/devices/bus/isa/svga_tseng.h b/src/devices/bus/isa/svga_tseng.h
index 690956741b5..f842889e027 100644
--- a/src/devices/bus/isa/svga_tseng.h
+++ b/src/devices/bus/isa/svga_tseng.h
@@ -6,7 +6,11 @@
#pragma once
#include "isa.h"
-#include "video/pc_vga.h"
+
+#include "video/pc_vga_tseng.h"
+
+#include "screen.h"
+
//**************************************************************************
// TYPE DEFINITIONS
@@ -27,6 +31,8 @@ public:
virtual void remap(int space_id, offs_t start, offs_t end) override;
protected:
+ isa8_svga_et4k_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
// device-level overrides
virtual void device_start() override;
virtual void device_reset() override;
@@ -35,6 +41,8 @@ protected:
virtual void device_add_mconfig(machine_config &config) override;
virtual const tiny_rom_entry *device_rom_region() const override;
+ void io_isa_map(address_map &map);
+
private:
void map_io();
void map_ram();
@@ -42,8 +50,21 @@ private:
required_device<tseng_vga_device> m_vga;
};
+class isa8_svga_et4k_kasan16_device :
+ public isa8_svga_et4k_device
+{
+public:
+ isa8_svga_et4k_kasan16_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+private:
+ required_region_ptr<uint8_t> m_hangul_rom;
+};
// device type definition
-DECLARE_DEVICE_TYPE(ISA8_SVGA_ET4K, isa8_svga_et4k_device)
+DECLARE_DEVICE_TYPE(ISA8_SVGA_ET4K, isa8_svga_et4k_device)
+DECLARE_DEVICE_TYPE(ISA8_SVGA_ET4K_KASAN16, isa8_svga_et4k_kasan16_device)
#endif // MAME_BUS_ISA_SVGA_TSENG_H
diff --git a/src/devices/bus/isa/tekram_dc820.cpp b/src/devices/bus/isa/tekram_dc820.cpp
index 56ffd8e4ccb..665e1642560 100644
--- a/src/devices/bus/isa/tekram_dc820.cpp
+++ b/src/devices/bus/isa/tekram_dc820.cpp
@@ -26,7 +26,7 @@
#include "bus/nscsi/devices.h"
#include "cpu/i86/i186.h"
#include "machine/i82355.h"
-#include "machine/ncr5390.h"
+#include "machine/ncr53c90.h"
#include "machine/nscsi_bus.h"
DEFINE_DEVICE_TYPE(TEKRAM_DC320B, tekram_dc320b_device, "dc320b", "Tekram DC-320B SCSI Controller")
diff --git a/src/devices/bus/isa/trident.cpp b/src/devices/bus/isa/trident.cpp
deleted file mode 100644
index 943f0de3432..00000000000
--- a/src/devices/bus/isa/trident.cpp
+++ /dev/null
@@ -1,1624 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Barry Rodewald
-/*
- * trident.c
- *
- * Implementation of Trident VGA GUI accelerators
- *
- *
- */
-
-#include "emu.h"
-#include "trident.h"
-
-#include "debugger.h"
-#include "screen.h"
-
-
-DEFINE_DEVICE_TYPE(TRIDENT_VGA, tgui9860_device, "trident_vga", "Trident TGUI9860")
-DEFINE_DEVICE_TYPE(TVGA9000_VGA, tvga9000_device, "tvga9000_vga", "Trident TVGA9000")
-
-#define CRTC_PORT_ADDR ((vga.miscellaneous_output&1)?0x3d0:0x3b0)
-
-#define LOG (1)
-#define LOG_ACCEL (1)
-
-trident_vga_device::trident_vga_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
- : svga_device(mconfig, type, tag, owner, clock)
-{
-}
-
-tgui9860_device::tgui9860_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : trident_vga_device(mconfig, TRIDENT_VGA, tag, owner, clock)
-{
- m_version = 0xd3; // 0xd3 identifies at TGUI9660XGi (set to 0xe3 to identify at TGUI9440AGi)
-}
-
-tvga9000_device::tvga9000_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : trident_vga_device(mconfig, TVGA9000_VGA, tag, owner, clock)
-{
- m_version = 0x43;
-}
-
-uint8_t trident_vga_device::READPIXEL8(int16_t x, int16_t y)
-{
- return (vga.memory[((y & 0xfff)*offset() + (x & 0xfff)) % vga.svga_intf.vram_size]);
-}
-
-uint16_t trident_vga_device::READPIXEL15(int16_t x, int16_t y)
-{
- return (vga.memory[((y & 0xfff)*offset() + (x & 0xfff)*2) % vga.svga_intf.vram_size] |
- (vga.memory[((y & 0xfff)*offset() + ((x & 0xfff)*2)+1) % vga.svga_intf.vram_size] << 8));
-}
-
-uint16_t trident_vga_device::READPIXEL16(int16_t x, int16_t y)
-{
- return (vga.memory[((y & 0xfff)*offset() + (x & 0xfff)*2) % vga.svga_intf.vram_size] |
- (vga.memory[((y & 0xfff)*offset() + ((x & 0xfff)*2)+1) % vga.svga_intf.vram_size] << 8));
-}
-
-uint32_t trident_vga_device::READPIXEL32(int16_t x, int16_t y)
-{
- return (vga.memory[((y & 0xfff)*offset() + (x & 0xfff)*4) % vga.svga_intf.vram_size] |
- (vga.memory[((y & 0xfff)*offset() + ((x & 0xfff)*4)+1) % vga.svga_intf.vram_size] << 8) |
- (vga.memory[((y & 0xfff)*offset() + ((x & 0xfff)*4)+2) % vga.svga_intf.vram_size] << 16) |
- (vga.memory[((y & 0xfff)*offset() + ((x & 0xfff)*4)+3) % vga.svga_intf.vram_size] << 24));
-}
-
-void trident_vga_device::WRITEPIXEL8(int16_t x, int16_t y, uint8_t data)
-{
- if((x & 0xfff)<tri.accel_dest_x_clip && (y & 0xfff)<tri.accel_dest_y_clip)
- {
- data = handle_rop(data,READPIXEL8(x,y)) & 0xff;
- vga.memory[((y & 0xfff)*offset() + (x & 0xfff)) % vga.svga_intf.vram_size] = data;
- }
-}
-
-void trident_vga_device::WRITEPIXEL15(int16_t x, int16_t y, uint16_t data)
-{
- if((x & 0xfff)<tri.accel_dest_x_clip && (y & 0xfff)<tri.accel_dest_y_clip)
- {
- data = handle_rop(data,READPIXEL8(x,y)) & 0x7fff;
- vga.memory[((y & 0xfff)*offset() + (x & 0xfff)*2) % vga.svga_intf.vram_size] = data & 0x00ff;
- vga.memory[((y & 0xfff)*offset() + ((x & 0xfff)*2)+1) % vga.svga_intf.vram_size] = (data & 0x7f00) >> 8;
- }
-}
-
-void trident_vga_device::WRITEPIXEL16(int16_t x, int16_t y, uint16_t data)
-{
- if((x & 0xfff)<tri.accel_dest_x_clip && (y & 0xfff)<tri.accel_dest_y_clip)
- {
- data = handle_rop(data,READPIXEL8(x,y)) & 0xffff;
- vga.memory[((y & 0xfff)*offset() + (x & 0xfff)*2) % vga.svga_intf.vram_size] = data & 0x00ff;
- vga.memory[((y & 0xfff)*offset() + ((x & 0xfff)*2)+1) % vga.svga_intf.vram_size] = (data & 0xff00) >> 8;
- }
-}
-
-void trident_vga_device::WRITEPIXEL32(int16_t x, int16_t y, uint32_t data)
-{
- if((x & 0xfff)<tri.accel_dest_x_clip && (y & 0xfff)<tri.accel_dest_y_clip)
- {
- data = handle_rop(data,READPIXEL8(x,y));
- vga.memory[((y & 0xfff)*offset() + (x & 0xfff)*4) % vga.svga_intf.vram_size] = data & 0x000000ff;
- vga.memory[((y & 0xfff)*offset() + ((x & 0xfff)*4)+1) % vga.svga_intf.vram_size] = (data & 0x0000ff00) >> 8;
- vga.memory[((y & 0xfff)*offset() + ((x & 0xfff)*4)+2) % vga.svga_intf.vram_size] = (data & 0x00ff0000) >> 16;
- vga.memory[((y & 0xfff)*offset() + ((x & 0xfff)*4)+3) % vga.svga_intf.vram_size] = (data & 0xff000000) >> 24;
- }
-}
-
-uint32_t trident_vga_device::handle_rop(uint32_t src, uint32_t dst)
-{
- switch(tri.accel_fmix) // TODO: better understand this register
- {
- case 0xf0: // PAT
- case 0xcc: // SRC
- break; // pass data through
- case 0x00: // 0
- src = 0;
- break;
- case 0xff: // 1
- src = 0xffffffff;
- break;
- case 0x66: // XOR
- case 0x5a: // XOR PAT
- src = dst ^ src;
- break;
- case 0xb8: // PAT xor (SRC and (DST xor PAT)) (correct?)
- src = src & (dst ^ src);
- break;
- }
- return src;
-}
-
-uint32_t trident_vga_device::READPIXEL(int16_t x,int16_t y)
-{
- if(svga.rgb8_en)
- return READPIXEL8(x,y) & 0xff;
- if(svga.rgb15_en)
- return READPIXEL15(x,y) & 0x7fff;
- if(svga.rgb16_en)
- return READPIXEL16(x,y) & 0xffff;
- if(svga.rgb32_en)
- return READPIXEL32(x,y);
- return 0; // should never reach here
-}
-
-void trident_vga_device::WRITEPIXEL(int16_t x,int16_t y, uint32_t data)
-{
- if(svga.rgb8_en)
- WRITEPIXEL8(x,y,(((data >> 8) & 0xff) | (data & 0xff))); // XFree86 3.3 sets bits 0-7 to 0 when using mono patterns, does it OR each byte?
- if(svga.rgb15_en)
- WRITEPIXEL15(x,y,data & 0x7fff);
- if(svga.rgb16_en)
- WRITEPIXEL16(x,y,data & 0xffff);
- if(svga.rgb32_en)
- WRITEPIXEL32(x,y,data);
-}
-
-
-void trident_vga_device::device_start()
-{
- zero();
-
- for (int i = 0; i < 0x100; i++)
- set_pen_color(i, 0, 0, 0);
-
- // Avoid an infinite loop when displaying. 0 is not possible anyway.
- vga.crtc.maximum_scan_line = 1;
-
-
- // copy over interfaces
- vga.read_dipswitch.set(nullptr); //read_dipswitch;
- vga.memory = std::make_unique<uint8_t []>(vga.svga_intf.vram_size);
- memset(&vga.memory[0], 0, vga.svga_intf.vram_size);
-
- save_pointer(NAME(vga.memory), vga.svga_intf.vram_size);
- save_pointer(vga.crtc.data,"CRTC Registers",0x100);
- save_pointer(vga.sequencer.data,"Sequencer Registers",0x100);
- save_pointer(vga.attribute.data,"Attribute Registers", 0x15);
- save_pointer(tri.accel_pattern,"Pattern Data", 0x80);
- save_pointer(tri.lutdac_reg,"LUTDAC registers", 0x100);
-
- m_vblank_timer = timer_alloc(FUNC(vga_device::vblank_timer_cb), this);
- vga.svga_intf.seq_regcount = 0x0f;
- vga.svga_intf.crtc_regcount = 0x60;
- memset(&tri, 0, sizeof(tri));
-}
-
-void trident_vga_device::device_reset()
-{
- svga_device::device_reset();
- svga.id = m_version;
- tri.revision = 0x01; // revision identifies as TGUI9680
- tri.new_mode = false; // start up in old mode
- tri.dac_active = false;
- tri.linear_active = false;
- tri.mmio_active = false;
- tri.sr0f = 0x6f;
- tri.sr0c = 0x70;
- tri.cr2a = 0x03; // set ISA interface?
- tri.mem_clock = 0x2c6; // 50MHz default
- tri.vid_clock = 0;
- tri.port_3c3 = true;
- tri.accel_busy = false;
- tri.accel_memwrite_active = false;
- // Windows 3.1 TGUI9440AGi drivers do not set the pointer colour registers?
- tri.cursor_bg = 0x00000000;
- tri.cursor_fg = 0xffffffff;
- tri.pixel_depth = 0x10; //disable 8bpp mode by default
-}
-
-uint32_t trident_vga_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
-{
- svga_device::screen_update(screen,bitmap,cliprect);
- uint8_t const cur_mode = pc_vga_choosevideomode();
-
- // draw hardware graphics cursor
- if(tri.cursor_ctrl & 0x80) // if cursor is enabled
- {
- uint16_t const cx = tri.cursor_x & 0x0fff;
- uint16_t const cy = tri.cursor_y & 0x0fff;
- uint8_t const cursor_size = (tri.cursor_ctrl & 0x01) ? 64 : 32;
-
- if(cur_mode == SCREEN_OFF || cur_mode == TEXT_MODE || cur_mode == MONO_MODE || cur_mode == CGA_MODE || cur_mode == EGA_MODE)
- return 0; // cursor only works in VGA or SVGA modes
-
- uint32_t src = tri.cursor_loc * 1024; // start address is in units of 1024 bytes
-
- uint32_t bg_col, fg_col;
- if(cur_mode == RGB16_MODE)
- {
- bg_col = tri.cursor_bg;
- fg_col = tri.cursor_fg;
- }
- else /* TODO: other modes */
- {
- bg_col = pen(tri.cursor_bg & 0xff);
- fg_col = pen(tri.cursor_fg & 0xff);
- }
-
- for(int y=0;y<cursor_size;y++)
- {
- uint8_t bitcount = 31;
- uint32_t *const dst = &bitmap.pix(cy + y, cx);
- for(int x=0;x<cursor_size;x++)
- {
- uint32_t bitb = (vga.memory[(src+3) % vga.svga_intf.vram_size]
- | ((vga.memory[(src+2) % vga.svga_intf.vram_size]) << 8)
- | ((vga.memory[(src+1) % vga.svga_intf.vram_size]) << 16)
- | ((vga.memory[(src+0) % vga.svga_intf.vram_size]) << 24));
- uint32_t bita = (vga.memory[(src+7) % vga.svga_intf.vram_size]
- | ((vga.memory[(src+6) % vga.svga_intf.vram_size]) << 8)
- | ((vga.memory[(src+5) % vga.svga_intf.vram_size]) << 16)
- | ((vga.memory[(src+4) % vga.svga_intf.vram_size]) << 24));
- uint8_t const val = (BIT(bita << 1,bitcount+1) << 1 | BIT(bitb,bitcount));
- if(tri.cursor_ctrl & 0x40)
- { // X11 mode
- switch(val)
- {
- case 0x00:
- // no change
- break;
- case 0x01:
- dst[x] = bg_col;
- break;
- case 0x02:
- // no change
- break;
- case 0x03:
- dst[x] = fg_col;
- break;
- }
- }
- else
- { // Windows mode
- switch(val)
- {
- case 0x00:
- dst[x] = bg_col;
- break;
- case 0x01:
- // no change
- break;
- case 0x02: // screen data
- dst[x] = fg_col;
- break;
- case 0x03: // inverted screen data
- dst[x] = ~(dst[x]);
- break;
- }
- }
- bitcount--;
- if(x % 32 == 31)
- {
- src+=8;
- bitcount=31;
- }
- }
- }
- }
-
- return 0;
-}
-
-uint16_t trident_vga_device::offset()
-{
- uint16_t off = svga_device::offset();
-
- if (svga.rgb8_en || svga.rgb15_en || svga.rgb16_en || svga.rgb32_en)
- return vga.crtc.offset << 3; // don't know if this is right, but Eggs Playing Chicken switches off doubleword mode, but expects the same offset length
- else
- return off;
-}
-
-int trident_vga_device::calculate_clock()
-{
- // Bits 0-6: M
- // Bits 7-11: N
- // Bit 12: K
- // Later formula extends each variable by one extra bit (Providia 9685 and later)
- double freq;
- uint8_t m,n,k;
-
- m = tri.vid_clock & 0x007f;
- n = (tri.vid_clock & 0x0f80) >> 7;
- k = (tri.vid_clock & 0x1000) >> 12;
- freq = ((double)(m+8) / (double)((n+2)*(pow(2.0,k)))) * 14.31818; // there is a 14.31818MHz clock on the board
-
- return freq * 1000000;
-}
-
-void trident_vga_device::trident_define_video_mode()
-{
- int divisor = 1;
- int xtal;
-
- /* // clock select for TGUI9440CXi and earlier
- switch(tri.clock)
- {
- case 0:
- default: xtal = 25174800; break;
- case 1: xtal = 28636363; break;
- case 2: xtal = 44900000; break;
- case 3: xtal = 36000000; break;
- case 4: xtal = 57272000; break;
- case 5: xtal = 65000000; break;
- case 6: xtal = 50350000; break;
- case 7: xtal = 40000000; break;
- case 8: xtal = 88000000; break;
- case 9: xtal = 98000000; break;
- case 10: xtal = 118800000; break;
- case 11: xtal = 108000000; break;
- case 12: xtal = 72000000; break;
- case 13: xtal = 77000000; break;
- case 14: xtal = 80000000; break;
- case 15: xtal = 75000000; break;
- }
-
- switch((tri.sr0d_new & 0x06) >> 1)
- {
- case 0:
- default: break; // no division
- case 1: xtal = xtal / 2; break;
- case 2: xtal = xtal / 4; break;
- case 3: xtal = xtal / 1.5; break;
- }*/
-
-
- // TGUI9440AGi/9660/9680/9682 programmable clock
- switch((vga.miscellaneous_output & 0x0c) >> 2)
- {
- case 0:
- default: xtal = 25174800; break;
- case 1: xtal = 28636363; break;
- case 2: xtal = calculate_clock(); break;
- }
-
- if(tri.gc0f & 0x08) // 16 pixels per character clock
- xtal = xtal / 2;
-
- if(tri.port_3db & 0x20)
- xtal = xtal / 2; // correct?
-
- svga.rgb8_en = svga.rgb15_en = svga.rgb16_en = svga.rgb32_en = 0;
- switch((tri.pixel_depth & 0x0c) >> 2)
- {
- case 0:
- default: if(!(tri.pixel_depth & 0x10) || (tri.cr1e & 0x80)) svga.rgb8_en = 1; break;
- case 1: if((tri.dac & 0xf0) == 0x30) svga.rgb16_en = 1; else svga.rgb15_en = 1; break;
- case 2: svga.rgb32_en = 1; break;
- }
-
- if((tri.cr1e & 0x80) && (svga.id == 0x43))
- divisor = 2;
-
- recompute_params_clock(divisor, xtal);
-}
-
-uint8_t trident_vga_device::trident_seq_reg_read(uint8_t index)
-{
- uint8_t res;
-
- res = 0xff;
-
- if(index <= 0x04)
- res = vga.sequencer.data[index];
- else
- {
- switch(index)
- {
- case 0x09:
- res = tri.revision;
- break;
- case 0x0b:
- res = svga.id;
- tri.new_mode = true;
- break;
- case 0x0c: // Power Up Mode register 1
- res = tri.sr0c & 0xef;
- if(tri.port_3c3)
- res |= 0x10;
- break;
- case 0x0d: // Mode Control 2
- //res = svga.rgb15_en;
- if(tri.new_mode)
- res = tri.sr0d_new;
- else
- res = tri.sr0d_old;
- break;
- case 0x0e: // Mode Control 1
- if(tri.new_mode)
- res = tri.sr0e_new;
- else
- res = tri.sr0e_old;
- break;
- case 0x0f: // Power Up Mode 2
- res = tri.sr0f;
- break;
- default:
- res = vga.sequencer.data[index];
- if(!LOG) logerror("Trident: Sequencer index %02x read\n",index);
- }
- }
- if(LOG) logerror("Trident SR%02X: read %02x\n",index,res);
- return res;
-}
-
-void trident_vga_device::trident_seq_reg_write(uint8_t index, uint8_t data)
-{
- vga.sequencer.data[vga.sequencer.index] = data;
- if(index <= 0x04)
- {
- seq_reg_write(vga.sequencer.index,data);
- recompute_params();
- }
- else
- {
- switch(index)
- {
- case 0x0b:
- tri.new_mode = false;
- break;
- case 0x0c: // Power Up Mode register 1
- if(data & 0x10)
- tri.port_3c3 = true; // 'post port at 0x3c3'
- else
- tri.port_3c3 = false; // 'post port at 0x46e8'
- tri.sr0c = data;
- break;
- case 0x0d: // Mode Control 2
- if(tri.new_mode)
- {
- tri.sr0d_new = data;
- tri.clock = ((vga.miscellaneous_output & 0x0c) >> 2) | ((data & 0x01) << 2) | ((data & 0x40) >> 3);
- trident_define_video_mode();
- }
- else
- tri.sr0d_old = data;
- break;
- case 0x0e: // Mode Control 1
- if(tri.new_mode)
- {
- tri.sr0e_new = data ^ 0x02;
- svga.bank_w = (data & 0x3f) ^ 0x02; // bit 1 is inverted, used for card detection, it is not XORed on reading
- if(!(tri.gc0f & 0x01))
- svga.bank_r = (data & 0x3f) ^ 0x02;
- // TODO: handle planar modes, where bits 0 and 2 only are used
- }
- else
- {
- tri.sr0e_old = data;
- svga.bank_w = data & 0x0e;
- if(!(tri.gc0f & 0x01))
- svga.bank_r = data & 0x0e;
- }
- break;
- case 0x0f: // Power Up Mode 2
- tri.sr0f = data;
- break;
- default:
- if(!LOG) logerror("Trident: Sequencer index %02x read\n",index);
- }
- }
- if(LOG) logerror("Trident SR%02X: %s mode write %02x\n",index,tri.new_mode ? "new" : "old",data);
-}
-
-uint8_t trident_vga_device::trident_crtc_reg_read(uint8_t index)
-{
- uint8_t res = 0;
-
- if(index <= 0x18)
- res = crtc_reg_read(index);
- else
- {
- switch(index)
- {
- case 0x1e:
- res = tri.cr1e;
- break;
- case 0x1f:
- res = tri.cr1f;
- break;
- case 0x20:
- res = tri.cr20;
- break;
- case 0x21:
- res = tri.cr21;
- break;
- case 0x24:
- if(vga.attribute.state != 0)
- res |= 0x80;
- break;
- case 0x26:
- res = vga.attribute.index;
- break;
- case 0x27:
- res = (vga.crtc.start_addr & 0x60000) >> 17;
- break;
- case 0x29:
- res = tri.cr29;
- break;
- case 0x2a:
- res = tri.cr2a;
- break;
- case 0x38:
- res = tri.pixel_depth;
- break;
- case 0x39:
- res = tri.cr39;
- break;
- case 0x40:
- res = (tri.cursor_x & 0x00ff);
- break;
- case 0x41:
- res = (tri.cursor_x & 0xff00) >> 8;
- break;
- case 0x42:
- res = (tri.cursor_y & 0x00ff);
- break;
- case 0x43:
- res = (tri.cursor_y & 0xff00) >> 8;
- break;
- case 0x44:
- res = (tri.cursor_loc & 0x00ff);
- break;
- case 0x45:
- res = (tri.cursor_loc & 0xff00) >> 8;
- break;
- case 0x46:
- res = tri.cursor_x_off;
- break;
- case 0x47:
- res = tri.cursor_y_off;
- break;
- case 0x48:
- res = (tri.cursor_fg & 0x000000ff);
- break;
- case 0x49:
- res = (tri.cursor_fg & 0x0000ff00) >> 8;
- break;
- case 0x4a:
- res = (tri.cursor_fg & 0x00ff0000) >> 16;
- break;
- case 0x4b:
- res = (tri.cursor_fg & 0xff000000) >> 24;
- break;
- case 0x4c:
- res = (tri.cursor_bg & 0x000000ff);
- break;
- case 0x4d:
- res = (tri.cursor_bg & 0x0000ff00) >> 8;
- break;
- case 0x4e:
- res = (tri.cursor_bg & 0x00ff0000) >> 16;
- break;
- case 0x4f:
- res = (tri.cursor_bg & 0xff000000) >> 24;
- break;
- case 0x50:
- res = tri.cursor_ctrl;
- break;
- default:
- res = vga.crtc.data[index];
- if(!LOG) logerror("Trident: CRTC index %02x read\n",index);
- break;
- }
- }
- if(LOG) logerror("Trident CR%02X: read %02x\n",index,res);
- return res;
-}
-void trident_vga_device::trident_crtc_reg_write(uint8_t index, uint8_t data)
-{
- if(index <= 0x18)
- {
- crtc_reg_write(index,data);
- trident_define_video_mode();
- }
- else
- {
- switch(index)
- {
- case 0x1e: // Module Testing Register
- tri.cr1e = data;
- vga.crtc.start_addr = (vga.crtc.start_addr & 0xfffeffff) | ((data & 0x20)<<11);
- break;
- case 0x1f:
- tri.cr1f = data; // "Software Programming Register" written to by the BIOS
- break;
- case 0x20: // FIFO Control (old MMIO enable? no documentation of this register)
- tri.cr20 = data;
- break;
- case 0x21: // Linear aperture
- tri.cr21 = data;
- tri.linear_address = ((data & 0xc0)<<18) | ((data & 0x0f)<<20);
- tri.linear_active = data & 0x20;
- if(tri.linear_active)
- popmessage("Trident: Linear Aperture active - %08x, %s",tri.linear_address,(tri.cr21 & 0x10) ? "2MB" : "1MB" );
- break;
- case 0x27:
- vga.crtc.start_addr = (vga.crtc.start_addr & 0xfff9ffff) | ((data & 0x03)<<17);
- break;
- case 0x29:
- tri.cr29 = data;
- vga.crtc.offset = (vga.crtc.offset & 0xfeff) | ((data & 0x10)<<4);
- break;
- case 0x2a:
- tri.cr2a = data;
- break;
- case 0x38:
- // bit 0: 16 bit bus
- // bits 2-3: pixel depth (1=15/16bit, 2=24/32bit, 0=anything else)
- // bit 5: packed mode
- tri.pixel_depth = data;
- trident_define_video_mode();
- break;
- case 0x39:
- tri.cr39 = data;
- tri.mmio_active = data & 0x01;
- if(tri.mmio_active)
- popmessage("Trident: MMIO activated");
- break;
- case 0x40:
- tri.cursor_x = (tri.cursor_x & 0xff00) | data;
- break;
- case 0x41:
- tri.cursor_x = (tri.cursor_x & 0x00ff) | (data << 8);
- break;
- case 0x42:
- tri.cursor_y = (tri.cursor_y & 0xff00) | data;
- break;
- case 0x43:
- tri.cursor_y = (tri.cursor_y & 0x00ff) | (data << 8);
- break;
- case 0x44:
- tri.cursor_loc = (tri.cursor_loc & 0xff00) | data;
- break;
- case 0x45:
- tri.cursor_loc = (tri.cursor_loc & 0x00ff) | (data << 8);
- break;
- case 0x46:
- tri.cursor_x_off = data;
- break;
- case 0x47:
- tri.cursor_y_off = data;
- break;
- case 0x48:
- tri.cursor_fg = (tri.cursor_fg & 0xffffff00) | data;
- break;
- case 0x49:
- tri.cursor_fg = (tri.cursor_fg & 0xffff00ff) | (data << 8);
- break;
- case 0x4a:
- tri.cursor_fg = (tri.cursor_fg & 0xff00ffff) | (data << 16);
- break;
- case 0x4b:
- tri.cursor_fg = (tri.cursor_fg & 0x00ffffff) | (data << 24);
- break;
- case 0x4c:
- tri.cursor_bg = (tri.cursor_bg & 0xffffff00) | data;
- break;
- case 0x4d:
- tri.cursor_bg = (tri.cursor_bg & 0xffff00ff) | (data << 8);
- break;
- case 0x4e:
- tri.cursor_bg = (tri.cursor_bg & 0xff00ffff) | (data << 16);
- break;
- case 0x4f:
- tri.cursor_bg = (tri.cursor_bg & 0x00ffffff) | (data << 24);
- break;
- case 0x50:
- tri.cursor_ctrl = data;
- break;
- default:
- if(!LOG) logerror("Trident: 3D4 index %02x write %02x\n",index,data);
- break;
- }
- }
- if(LOG) logerror("Trident CR%02X: write %02x\n",index,data);
-}
-
-uint8_t trident_vga_device::trident_gc_reg_read(uint8_t index)
-{
- uint8_t res;
-
- if(index <= 0x0d)
- res = gc_reg_read(index);
- else
- {
- switch(index)
- {
- case 0x0e:
- res = tri.gc0e;
- break;
- case 0x0f:
- res = tri.gc0f;
- break;
- case 0x2f:
- res = tri.gc2f;
- break;
- default:
- res = 0xff;
- if(!LOG) logerror("Trident: Sequencer index %02x read\n",index);
- break;
- }
- }
- if(LOG) logerror("Trident GC%02X: read %02x\n",index,res);
- return res;
-}
-
-void trident_vga_device::trident_gc_reg_write(uint8_t index, uint8_t data)
-{
- if(index <= 0x0d)
- gc_reg_write(index,data);
- else
- {
- if(LOG) logerror("Trident GC%02X: write %02x\n",index,data);
- switch(index)
- {
- case 0x0e: // New Source Address Register (bit 1 is inverted here, also)
- tri.gc0e = data ^ 0x02;
- if(!(tri.gc0f & 0x04)) // if bank regs at 0x3d8/9 are not enabled
- {
- if(tri.gc0f & 0x01) // if bank regs are separated
- svga.bank_r = (data & 0x1f) ^ 0x02;
- }
- break;
- case 0x0f:
- tri.gc0f = data;
- trident_define_video_mode();
- break;
- case 0x2f: // XFree86 refers to this register as "MiscIntContReg", setting bit 2, but gives no indication as to what it does
- tri.gc2f = data;
- break;
- default:
- if(!LOG) logerror("Trident: Unimplemented GC register %02x write %02x\n",index,data);
- break;
- }
- }
- if(LOG) logerror("Trident GC%02X: write %02x\n",index,data);
-}
-
-uint8_t trident_vga_device::port_03c0_r(offs_t offset)
-{
- uint8_t res;
-
- switch(offset)
- {
- case 0x05:
- res = trident_seq_reg_read(vga.sequencer.index);
- break;
- case 0x06:
- tri.dac_count++;
- if(tri.dac_count > 3)
- tri.dac_active = true;
- if(tri.dac_active)
- res = tri.dac;
- else
- res = vga_device::port_03c0_r(offset);
- break;
- case 0x07:
- case 0x08:
- case 0x09:
- tri.dac_active = false;
- tri.dac_count = 0;
- res = vga_device::port_03c0_r(offset);
- break;
- case 0x0f:
- res = trident_gc_reg_read(vga.gc.index);
- break;
- default:
- res = vga_device::port_03c0_r(offset);
- break;
- }
-
- return res;
-}
-
-void trident_vga_device::port_03c0_w(offs_t offset, uint8_t data)
-{
- switch(offset)
- {
- case 0x05:
- trident_seq_reg_write(vga.sequencer.index,data);
- break;
- case 0x06:
- if(tri.dac_active)
- {
- tri.dac = data; // DAC command register
- tri.dac_active = false;
- tri.dac_count = 0;
- trident_define_video_mode();
- }
- else
- vga_device::port_03c0_w(offset,data);
- break;
- case 0x07:
- case 0x08:
- case 0x09:
- tri.dac_active = false;
- tri.dac_count = 0;
- vga_device::port_03c0_w(offset,data);
- break;
- case 0x0f:
- trident_gc_reg_write(vga.gc.index,data);
- break;
- default:
- vga_device::port_03c0_w(offset,data);
- break;
- }
-}
-
-
-uint8_t trident_vga_device::port_03d0_r(offs_t offset)
-{
- uint8_t res = 0xff;
-
- if (CRTC_PORT_ADDR == 0x3d0)
- {
- switch(offset)
- {
- case 5:
- res = trident_crtc_reg_read(vga.crtc.index);
- break;
- case 8:
- if(tri.gc0f & 0x04) // if enabled
- {
- res = svga.bank_w & 0x3f;
- }
- else
- res = 0xff;
- break;
- case 9:
- if(tri.gc0f & 0x04) // if enabled
- if(tri.gc0f & 0x01) // and if bank regs are separated
- res = svga.bank_r & 0x3f;
- else
- res = 0xff;
- else
- res = 0xff;
- break;
- case 11:
- res = tri.port_3db;
- break;
- default:
- res = vga_device::port_03d0_r(offset);
- break;
- }
- }
-
- return res;
-}
-
-void trident_vga_device::port_03d0_w(offs_t offset, uint8_t data)
-{
- if (CRTC_PORT_ADDR == 0x3d0)
- {
- switch(offset)
- {
- case 5:
- vga.crtc.data[vga.crtc.index] = data;
- trident_crtc_reg_write(vga.crtc.index,data);
- break;
- case 8:
- if(tri.gc0f & 0x04) // if enabled
- {
- svga.bank_w = data & 0x3f;
- if(LOG) logerror("Trident: Write Bank set to %02x\n",data);
- if(!(tri.gc0f & 0x01)) // if bank regs are not separated
- {
- svga.bank_r = data & 0x3f; // then this is also the read bank register
- if(LOG) logerror("Trident: Read Bank set to %02x\n",data);
- }
- }
- break;
- case 9:
- if(tri.gc0f & 0x04) // if enabled
- {
- if(tri.gc0f & 0x01) // and if bank regs are separated
- {
- svga.bank_r = data & 0x3f;
- if(LOG) logerror("Trident: Read Bank set to %02x\n",data);
- }
- }
- break;
- case 11:
- tri.port_3db = data; // no info on this port? Bit 5 appears to be a clock divider...
- break;
- default:
- vga_device::port_03d0_w(offset,data);
- break;
- }
- }
-}
-
-uint8_t trident_vga_device::port_43c6_r(offs_t offset)
-{
- uint8_t res = 0xff;
- switch(offset)
- {
- case 2:
- res = tri.mem_clock & 0xff;
- break;
- case 3:
- res = tri.mem_clock >> 8;
- break;
- case 4:
- res = tri.vid_clock & 0xff;
- break;
- case 5:
- res = tri.vid_clock >> 8;
- break;
- }
- return res;
-}
-
-void trident_vga_device::port_43c6_w(offs_t offset, uint8_t data)
-{
- switch(offset)
- {
- case 2:
- if(!(tri.sr0e_new & 0x02) && (tri.sr0e_new & 0x80))
- {
- tri.mem_clock = (tri.mem_clock & 0xff00) | (data);
- if(LOG) logerror("Trident: Memory clock write %04x\n",tri.mem_clock);
- }
- break;
- case 3:
- if(!(tri.sr0e_new & 0x02) && (tri.sr0e_new & 0x80))
- {
- tri.mem_clock = (tri.mem_clock & 0x00ff) | (data << 8);
- if(LOG) logerror("Trident: Memory clock write %04x\n",tri.mem_clock);
- }
- break;
- case 4:
- if(!(tri.sr0e_new & 0x02) && (tri.sr0e_new & 0x80))
- {
- tri.vid_clock = (tri.vid_clock & 0xff00) | (data);
- if(LOG) logerror("Trident: Video clock write %04x\n",tri.vid_clock);
- }
- break;
- case 5:
- if(!(tri.sr0e_new & 0x02) && (tri.sr0e_new & 0x80))
- {
- tri.vid_clock = (tri.vid_clock & 0x00ff) | (data << 8);
- if(LOG) logerror("Trident: Video clock write %04x\n",tri.vid_clock);
- }
- break;
- }
-}
-
-// Trident refers to these registers as a LUTDAC
-// Not much else is known. XFree86 uses register 4 for something related to DPMS
-uint8_t trident_vga_device::port_83c6_r(offs_t offset)
-{
- uint8_t res = 0xff;
- switch(offset)
- {
- case 2:
- res = tri.lutdac_reg[tri.lutdac_index];
- if(LOG) logerror("Trident: LUTDAC reg read %02x\n",res);
- break;
- case 4:
- res = tri.lutdac_index;
- if(LOG) logerror("Trident: LUTDAC index read %02x\n",res);
- break;
- }
- return res;
-}
-
-void trident_vga_device::port_83c6_w(offs_t offset, uint8_t data)
-{
- switch(offset)
- {
- case 2:
- if(LOG) logerror("Trident: LUTDAC reg write %02x\n",data);
- tri.lutdac_reg[tri.lutdac_index] = data;
- break;
- case 4:
- if(LOG) logerror("Trident: LUTDAC index write %02x\n",data);
- tri.lutdac_index = data;
- break;
- }
-}
-
-uint8_t trident_vga_device::vram_r(offs_t offset)
-{
- if (tri.linear_active)
- return vga.memory[offset % vga.svga_intf.vram_size];
- else
- return 0xff;
-}
-
-void trident_vga_device::vram_w(offs_t offset, uint8_t data)
-{
- if (tri.linear_active)
- {
- if(tri.accel_memwrite_active)
- {
- tri.accel_transfer = (tri.accel_transfer & (~(0x000000ff << (24-(8*(offset % 4)))))) | (data << (24-(8 * (offset % 4))));
- if(offset % 4 == 3)
- accel_data_write(tri.accel_transfer);
- return;
- }
- vga.memory[offset % vga.svga_intf.vram_size] = data;
- }
-}
-
-uint8_t trident_vga_device::mem_r(offs_t offset)
-{
- if((tri.cr20 & 0x10) && (offset >= 0x1ff00)) // correct for old MMIO?
- {
- return old_mmio_r(offset-0x1ff00);
- }
-
- if (svga.rgb8_en || svga.rgb15_en || svga.rgb16_en || svga.rgb32_en)
- {
- int data;
-
- if(tri.new_mode) // 64k from 0xA0000-0xAFFFF
- {
- offset &= 0xffff;
- data=vga.memory[(offset + (svga.bank_r*0x10000)) % vga.svga_intf.vram_size];
- }
- else // 128k from 0xA0000-0xBFFFF
- {
- data=vga.memory[(offset + (svga.bank_r*0x10000)) % vga.svga_intf.vram_size];
- }
- return data;
- }
-
- return vga_device::mem_r(offset);
-}
-
-void trident_vga_device::mem_w(offs_t offset, uint8_t data)
-{
- if((tri.cr20 & 0x10) && (offset >= 0x1ff00)) // correct for old MMIO?
- {
- old_mmio_w(offset-0x1ff00,data);
- return;
- }
-
- if(tri.accel_memwrite_active)
- {
- tri.accel_transfer = (tri.accel_transfer & (~(0x000000ff << (24-(8*(offset % 4)))))) | (data << (24-(8 * (offset % 4))));
- if(offset % 4 == 3)
- accel_data_write(tri.accel_transfer);
- return;
- }
-
- if (svga.rgb8_en || svga.rgb15_en || svga.rgb16_en || svga.rgb32_en)
- {
- if(tri.new_mode) // 64k from 0xA0000-0xAFFFF
- {
- offset &= 0xffff;
- vga.memory[(offset + (svga.bank_w*0x10000)) % vga.svga_intf.vram_size] = data;
- }
- else // 128k from 0xA0000-0xBFFFF
- {
- vga.memory[(offset + (svga.bank_w*0x10000)) % vga.svga_intf.vram_size] = data;
- }
- return;
- }
-
- vga_device::mem_w(offset,data);
-}
-
-// Old style MMIO (maps to 0xbff00)
-void trident_vga_device::old_mmio_w(offs_t offset, uint8_t data)
-{
- if(offset >= 0x20)
- accel_w(offset-0x20,data);
-}
-
-uint8_t trident_vga_device::old_mmio_r(offs_t offset)
-{
- if(offset == 0x20)
- {
- if(tri.accel_busy)
- return 0x20;
- }
- if(offset > 0x20)
- return accel_r(offset-0x20);
- else
- return 0x00;
-}
-
-
-// 2D Acceleration functions (very WIP)
-
-// From XFree86 source:
-/*
-Graphics Engine for 9440/9660/9680
-
-#define GER_STATUS 0x2120
-#define GE_BUSY 0x80
-#define GER_OPERMODE 0x2122 Byte for 9440, Word for 96xx
-#define DST_ENABLE 0x200 // Destination Transparency
-#define GER_COMMAND 0x2124
-#define GE_NOP 0x00 // No Operation
-#define GE_BLT 0x01 // BitBLT ROP3 only
-#define GE_BLT_ROP4 0x02 // BitBLT ROP4 (96xx only)
-#define GE_SCANLINE 0x03 // Scan Line
-#define GE_BRESLINE 0x04 // Bresenham Line
-#define GE_SHVECTOR 0x05 // Short Vector
-#define GE_FASTLINE 0x06 // Fast Line (96xx only)
-#define GE_TRAPEZ 0x07 // Trapezoidal fill (96xx only)
-#define GE_ELLIPSE 0x08 // Ellipse (96xx only) (RES)
-#define GE_ELLIP_FILL 0x09 // Ellipse Fill (96xx only) (RES)
-#define GER_FMIX 0x2127
-#define GER_DRAWFLAG 0x2128 // long
-#define FASTMODE 1<<28
-#define STENCIL 0x8000
-#define SOLIDFILL 0x4000
-#define TRANS_ENABLE 0x1000
-#define TRANS_REVERSE 0x2000
-#define YMAJ 0x0400
-#define XNEG 0x0200
-#define YNEG 0x0100
-#define SRCMONO 0x0040
-#define PATMONO 0x0020
-#define SCR2SCR 0x0004
-#define PAT2SCR 0x0002
-#define GER_FCOLOUR 0x212C // Word for 9440, long for 96xx
-#define GER_BCOLOUR 0x2130 // Word for 9440, long for 96xx
-#define GER_PATLOC 0x2134 // Word
-#define GER_DEST_XY 0x2138
-#define GER_DEST_X 0x2138 // Word
-#define GER_DEST_Y 0x213A // Word
-#define GER_SRC_XY 0x213C
-#define GER_SRC_X 0x213C // Word
-#define GER_SRC_Y 0x213E // Word
-#define GER_DIM_XY 0x2140
-#define GER_DIM_X 0x2140 // Word
-#define GER_DIM_Y 0x2142 // Word
-#define GER_STYLE 0x2144 // Long
-#define GER_CKEY 0x2168 // Long
-#define GER_FPATCOL 0x2178
-#define GER_BPATCOL 0x217C
-#define GER_PATTERN 0x2180 // from 0x2180 to 0x21FF
-
- Additional - Graphics Engine for 96xx
-#define GER_SRCCLIP_XY 0x2148
-#define GER_SRCCLIP_X 0x2148 // Word
-#define GER_SRCCLIP_Y 0x214A // Word
-#define GER_DSTCLIP_XY 0x214C
-#define GER_DSTCLIP_X 0x214C // Word
-#define GER_DSTCLIP_Y 0x214E // Word
-*/
-
-uint8_t trident_vga_device::accel_r(offs_t offset)
-{
- uint8_t res = 0xff;
-
- if(offset >= 0x60)
- return tri.accel_pattern[(offset-0x60) % 0x80];
-
- switch(offset)
- {
- case 0x00: // Status
- if(tri.accel_busy)
- res = 0x80;
- else
- res = 0x00;
- break;
- // Operation mode:
- // bit 8: disable clipping if set
- case 0x02: // Operation Mode
- res = tri.accel_opermode & 0x00ff;
- break;
- case 0x03:
- res = (tri.accel_opermode & 0xff00) >> 8;
- break;
- case 0x04: // Command register
- res = tri.accel_command;
- break;
- case 0x07: // Foreground Mix?
- res = tri.accel_fmix;
- break;
- default:
- logerror("Trident: unimplemented acceleration register offset %02x read\n",offset);
- }
- return res;
-}
-
-void trident_vga_device::accel_w(offs_t offset, uint8_t data)
-{
- if(offset >= 0x60)
- {
- tri.accel_pattern[(offset-0x60) % 0x80] = data;
- return;
- }
-
- switch(offset)
- {
- case 0x02: // Operation Mode
- tri.accel_opermode = (tri.accel_opermode & 0xff00) | data;
- if(LOG_ACCEL) logerror("Trident: Operation Mode set to %04x\n",tri.accel_opermode);
- break;
- case 0x03:
- tri.accel_opermode = (tri.accel_opermode & 0x00ff) | (data << 8);
- if(LOG_ACCEL) logerror("Trident: Operation Mode set to %04x\n",tri.accel_opermode);
- break;
- case 0x04: // Command register
- tri.accel_command = data;
- accel_command();
- break;
- case 0x07: // Foreground Mix?
- tri.accel_fmix = data;
- if(LOG_ACCEL) logerror("Trident: FMIX set to %02x\n",data);
- break;
- case 0x08: // Draw flags
- tri.accel_drawflags = (tri.accel_drawflags & 0xffffff00) | data;
- if(LOG_ACCEL) logerror("Trident: Draw flags set to %08x\n",tri.accel_drawflags);
- break;
- case 0x09:
- tri.accel_drawflags = (tri.accel_drawflags & 0xffff00ff) | (data << 8);
- if(LOG_ACCEL) logerror("Trident: Draw flags set to %08x\n",tri.accel_drawflags);
- break;
- case 0x0a:
- tri.accel_drawflags = (tri.accel_drawflags & 0xff00ffff) | (data << 16);
- if(LOG_ACCEL) logerror("Trident: Draw flags set to %08x\n",tri.accel_drawflags);
- break;
- case 0x0b:
- tri.accel_drawflags = (tri.accel_drawflags & 0x00ffffff) | (data << 24);
- if(LOG_ACCEL) logerror("Trident: Draw flags set to %08x\n",tri.accel_drawflags);
- break;
- case 0x0c: // Foreground Colour
- tri.accel_fgcolour = (tri.accel_fgcolour & 0xffffff00) | data;
- if(LOG_ACCEL) logerror("Trident: Foreground Colour set to %08x\n",tri.accel_fgcolour);
- break;
- case 0x0d:
- tri.accel_fgcolour = (tri.accel_fgcolour & 0xffff00ff) | (data << 8);
- if(LOG_ACCEL) logerror("Trident: Foreground Colour set to %08x\n",tri.accel_fgcolour);
- break;
- case 0x0e:
- tri.accel_fgcolour = (tri.accel_fgcolour & 0xff00ffff) | (data << 16);
- if(LOG_ACCEL) logerror("Trident: Foreground Colour set to %08x\n",tri.accel_fgcolour);
- break;
- case 0x0f:
- tri.accel_fgcolour = (tri.accel_fgcolour & 0x00ffffff) | (data << 24);
- if(LOG_ACCEL) logerror("Trident: Foreground Colour set to %08x\n",tri.accel_fgcolour);
- break;
- case 0x10: // Background Colour
- tri.accel_bgcolour = (tri.accel_bgcolour & 0xffffff00) | data;
- if(LOG_ACCEL) logerror("Trident: Background Colour set to %08x\n",tri.accel_bgcolour);
- break;
- case 0x11:
- tri.accel_bgcolour = (tri.accel_bgcolour & 0xffff00ff) | (data << 8);
- if(LOG_ACCEL) logerror("Trident: Background Colour set to %08x\n",tri.accel_bgcolour);
- break;
- case 0x12:
- tri.accel_bgcolour = (tri.accel_bgcolour & 0xff00ffff) | (data << 16);
- if(LOG_ACCEL) logerror("Trident: Background Colour set to %08x\n",tri.accel_bgcolour);
- break;
- case 0x13:
- tri.accel_bgcolour = (tri.accel_bgcolour & 0x00ffffff) | (data << 24);
- if(LOG_ACCEL) logerror("Trident: Background Colour set to %08x\n",tri.accel_bgcolour);
- break;
- case 0x14: // Pattern Location
- tri.accel_pattern_loc = (tri.accel_pattern_loc & 0xff00) | data;
- if(LOG_ACCEL) logerror("Trident: Pattern Location set to %04x\n",tri.accel_pattern_loc);
- break;
- case 0x15:
- tri.accel_pattern_loc = (tri.accel_pattern_loc & 0x00ff) | (data << 8);
- if(LOG_ACCEL) logerror("Trident: Pattern Location set to %04x\n",tri.accel_pattern_loc);
- break;
- case 0x18: // Destination X
- tri.accel_dest_x = (tri.accel_dest_x & 0xff00) | data;
- if(LOG_ACCEL) logerror("Trident: Destination X set to %04x\n",tri.accel_dest_x);
- break;
- case 0x19:
- tri.accel_dest_x = (tri.accel_dest_x & 0x00ff) | (data << 8);
- if(LOG_ACCEL) logerror("Trident: Destination X set to %04x\n",tri.accel_dest_x);
- break;
- case 0x1a: // Destination Y
- tri.accel_dest_y = (tri.accel_dest_y & 0xff00) | data;
- if(LOG_ACCEL) logerror("Trident: Destination Y set to %04x\n",tri.accel_dest_y);
- break;
- case 0x1b:
- tri.accel_dest_y = (tri.accel_dest_y & 0x00ff) | (data << 8);
- if(LOG_ACCEL) logerror("Trident: Destination Y set to %04x\n",tri.accel_dest_y);
- break;
- case 0x1c: // Source X
- tri.accel_source_x = (tri.accel_source_x & 0xff00) | data;
- if(LOG_ACCEL) logerror("Trident: Source X set to %04x\n",tri.accel_source_x);
- break;
- case 0x1d:
- tri.accel_source_x = (tri.accel_source_x & 0x00ff) | (data << 8);
- if(LOG_ACCEL) logerror("Trident: Source X set to %04x\n",tri.accel_source_x);
- break;
- case 0x1e: // Source Y
- tri.accel_source_y = (tri.accel_source_y & 0xff00) | data;
- if(LOG_ACCEL) logerror("Trident: Source Y set to %04x\n",tri.accel_source_y);
- break;
- case 0x1f:
- tri.accel_source_y = (tri.accel_source_y & 0x00ff) | (data << 8);
- if(LOG_ACCEL) logerror("Trident: Source Y set to %04x\n",tri.accel_source_y);
- break;
- case 0x20: // Dimension(?) X
- tri.accel_dim_x = (tri.accel_dim_x & 0xff00) | data;
- if(LOG_ACCEL) logerror("Trident: Dimension X set to %04x\n",tri.accel_dim_x);
- break;
- case 0x21:
- tri.accel_dim_x = (tri.accel_dim_x & 0x00ff) | (data << 8);
- if(LOG_ACCEL) logerror("Trident: Dimension X set to %04x\n",tri.accel_dim_x);
- break;
- case 0x22: // Dimension(?) Y
- tri.accel_dim_y = (tri.accel_dim_y & 0xff00) | data;
- if(LOG_ACCEL) logerror("Trident: Dimension y set to %04x\n",tri.accel_dim_y);
- break;
- case 0x23:
- tri.accel_dim_y = (tri.accel_dim_y & 0x00ff) | (data << 8);
- if(LOG_ACCEL) logerror("Trident: Dimension y set to %04x\n",tri.accel_dim_y);
- break;
- case 0x24: // Style
- tri.accel_style = (tri.accel_style & 0xffffff00) | data;
- if(LOG_ACCEL) logerror("Trident: Style set to %08x\n",tri.accel_style);
- break;
- case 0x25:
- tri.accel_style = (tri.accel_style & 0xffff00ff) | (data << 8);
- if(LOG_ACCEL) logerror("Trident: Style set to %08x\n",tri.accel_style);
- break;
- case 0x26:
- tri.accel_style = (tri.accel_style & 0xff00ffff) | (data << 16);
- if(LOG_ACCEL) logerror("Trident: Style set to %08x\n",tri.accel_style);
- break;
- case 0x27:
- tri.accel_style = (tri.accel_style & 0x00ffffff) | (data << 24);
- if(LOG_ACCEL) logerror("Trident: Style set to %08x\n",tri.accel_style);
- break;
- case 0x28: // Source Clip X
- tri.accel_source_x_clip = (tri.accel_source_x_clip & 0xff00) | data;
- if(LOG_ACCEL) logerror("Trident: Source X Clip set to %04x\n",tri.accel_source_x_clip);
- break;
- case 0x29:
- tri.accel_source_x_clip = (tri.accel_source_x_clip & 0x00ff) | (data << 8);
- if(LOG_ACCEL) logerror("Trident: Source X Clip set to %04x\n",tri.accel_source_x_clip);
- break;
- case 0x2a: // Source Clip Y
- tri.accel_source_y_clip = (tri.accel_source_y_clip & 0xff00) | data;
- if(LOG_ACCEL) logerror("Trident: Source Y Clip set to %04x\n",tri.accel_source_y_clip);
- break;
- case 0x2b:
- tri.accel_source_y_clip = (tri.accel_source_y_clip & 0x00ff) | (data << 8);
- if(LOG_ACCEL) logerror("Trident: Source Y Clip set to %04x\n",tri.accel_source_y_clip);
- break;
- case 0x2c: // Destination Clip X
- tri.accel_dest_x_clip = (tri.accel_dest_x_clip & 0xff00) | data;
- if(LOG_ACCEL) logerror("Trident: Destination X Clip set to %04x\n",tri.accel_dest_x_clip);
- break;
- case 0x2d:
- tri.accel_dest_x_clip = (tri.accel_dest_x_clip & 0x00ff) | (data << 8);
- if(LOG_ACCEL) logerror("Trident: Destination X Clip set to %04x\n",tri.accel_dest_x_clip);
- break;
- case 0x2e: // Destination Clip Y
- tri.accel_dest_y_clip = (tri.accel_dest_y_clip & 0xff00) | data;
- if(LOG_ACCEL) logerror("Trident: Destination Y Clip set to %04x\n",tri.accel_dest_y_clip);
- break;
- case 0x2f:
- tri.accel_dest_y_clip = (tri.accel_dest_y_clip & 0x00ff) | (data << 8);
- if(LOG_ACCEL) logerror("Trident: Destination Y Clip set to %04x\n",tri.accel_dest_y_clip);
- break;
- case 0x48: // CKEY (Chromakey?)
- tri.accel_ckey = (tri.accel_ckey & 0xffffff00) | data;
- if(LOG_ACCEL) logerror("Trident: CKey set to %08x\n",tri.accel_ckey);
- break;
- case 0x49:
- tri.accel_ckey = (tri.accel_ckey & 0xffff00ff) | (data << 8);
- if(LOG_ACCEL) logerror("Trident: CKey set to %08x\n",tri.accel_ckey);
- break;
- case 0x4a:
- tri.accel_ckey = (tri.accel_ckey & 0xff00ffff) | (data << 16);
- if(LOG_ACCEL) logerror("Trident: CKey set to %08x\n",tri.accel_ckey);
- break;
- case 0x4b:
- tri.accel_ckey = (tri.accel_ckey & 0x00ffffff) | (data << 24);
- if(LOG_ACCEL) logerror("Trident: CKey set to %08x\n",tri.accel_ckey);
- break;
- case 0x58: // Foreground Pattern Colour
- tri.accel_fg_pattern_colour = (tri.accel_fg_pattern_colour & 0xffffff00) | data;
- if(LOG_ACCEL) logerror("Trident: FG Pattern Colour set to %08x\n",tri.accel_fg_pattern_colour);
- break;
- case 0x59:
- tri.accel_fg_pattern_colour = (tri.accel_fg_pattern_colour & 0xffff00ff) | (data << 8);
- if(LOG_ACCEL) logerror("Trident: FG Pattern Colour set to %08x\n",tri.accel_fg_pattern_colour);
- break;
- case 0x5a:
- tri.accel_fg_pattern_colour = (tri.accel_fg_pattern_colour & 0xff00ffff) | (data << 16);
- if(LOG_ACCEL) logerror("Trident: FG Pattern Colour set to %08x\n",tri.accel_fg_pattern_colour);
- break;
- case 0x5b:
- tri.accel_fg_pattern_colour = (tri.accel_fg_pattern_colour & 0x00ffffff) | (data << 24);
- if(LOG_ACCEL) logerror("Trident: FG Pattern Colour set to %08x\n",tri.accel_fg_pattern_colour);
- break;
- case 0x5c: // Background Pattern Colour
- tri.accel_bg_pattern_colour = (tri.accel_bg_pattern_colour & 0xffffff00) | data;
- if(LOG_ACCEL) logerror("Trident: BG Pattern Colour set to %08x\n",tri.accel_bg_pattern_colour);
- break;
- case 0x5d:
- tri.accel_bg_pattern_colour = (tri.accel_bg_pattern_colour & 0xffff00ff) | (data << 8);
- if(LOG_ACCEL) logerror("Trident: BG Pattern Colour set to %08x\n",tri.accel_bg_pattern_colour);
- break;
- case 0x5e:
- tri.accel_bg_pattern_colour = (tri.accel_bg_pattern_colour & 0xff00ffff) | (data << 16);
- if(LOG_ACCEL) logerror("Trident: BG Pattern Colour set to %08x\n",tri.accel_bg_pattern_colour);
- break;
- case 0x5f:
- tri.accel_bg_pattern_colour = (tri.accel_bg_pattern_colour & 0x00ffffff) | (data << 24);
- if(LOG_ACCEL) logerror("Trident: BG Pattern Colour set to %08x\n",tri.accel_bg_pattern_colour);
- break;
- default:
- logerror("Trident: unimplemented acceleration register offset %02x write %02x\n",offset,data);
- }
-}
-
-void trident_vga_device::accel_command()
-{
- switch(tri.accel_command)
- {
- case 0x00:
- if(LOG) logerror("Trident: Command: NOP\n");
- break;
- case 0x01:
- if(LOG) logerror("Trident: Command: BitBLT ROP3 (Source %i,%i Dest %i,%i Size %i,%i)\n",tri.accel_source_x,tri.accel_source_y,tri.accel_dest_x,tri.accel_dest_y,tri.accel_dim_x,tri.accel_dim_y);
- if(LOG) logerror("BitBLT: Drawflags = %08x FMIX = %02x\n",tri.accel_drawflags,tri.accel_fmix);
- accel_bitblt();
- break;
- case 0x02:
- if(LOG) logerror("Trident: Command: BitBLT ROP4\n");
- break;
- case 0x03:
- if(LOG) logerror("Trident: Command: Scanline\n");
- break;
- case 0x04:
- if(LOG) logerror("Trident: Command: Bresenham Line (Source %i,%i Dest %i,%i Size %i,%i)\n",tri.accel_source_x,tri.accel_source_y,tri.accel_dest_x,tri.accel_dest_y,tri.accel_dim_x,tri.accel_dim_y);
- if(LOG) logerror("BLine: Drawflags = %08x FMIX = %02x\n",tri.accel_drawflags,tri.accel_fmix);
- accel_line();
- break;
- case 0x05:
- if(LOG) logerror("Trident: Command: Short Vector\n");
- break;
- case 0x06:
- if(LOG) logerror("Trident: Command: Fast Line\n");
- break;
- case 0x07:
- if(LOG) logerror("Trident: Command: Trapezoid Fill\n");
- break;
- case 0x08:
- if(LOG) logerror("Trident: Command: Ellipse\n");
- break;
- case 0x09:
- if(LOG) logerror("Trident: Command: Ellipse Fill\n");
- break;
- default:
- logerror("Trident: Unknown acceleration command %02x\n",tri.accel_command);
- }
-}
-
-void trident_vga_device::accel_bitblt()
-{
- int x,y;
- int sx,sy;
- int xdir,ydir;
- int xstart,xend,ystart,yend;
-
- if(tri.accel_drawflags & 0x0040) // TODO: handle PATMONO also
- {
- tri.accel_mem_x = tri.accel_dest_x;
- tri.accel_mem_y = tri.accel_dest_y;
- tri.accel_memwrite_active = true;
- return;
- }
-
- if(tri.accel_drawflags & 0x0200)
- {
- xdir = -1;
- xstart = tri.accel_dest_x;
- xend = tri.accel_dest_x-tri.accel_dim_x-1;
- }
- else
- {
- xdir = 1;
- xstart = tri.accel_dest_x;
- xend = tri.accel_dest_x+tri.accel_dim_x+1;
- }
- if(tri.accel_drawflags & 0x0100)
- {
- ydir = -1;
- ystart = tri.accel_dest_y;
- yend = tri.accel_dest_y-tri.accel_dim_y-1;
- }
- else
- {
- ydir = 1;
- ystart = tri.accel_dest_y;
- yend = tri.accel_dest_y+tri.accel_dim_y+1;
- }
- sy = tri.accel_source_y;
-
- for(y=ystart;y!=yend;y+=ydir,sy+=ydir)
- {
- sx = tri.accel_source_x;
- for(x=xstart;x!=xend;x+=xdir,sx+=xdir)
- {
- if(tri.accel_drawflags & 0x4000) // Solid fill
- {
- WRITEPIXEL(x,y,tri.accel_fgcolour);
- }
- else
- {
- WRITEPIXEL(x,y,READPIXEL(sx,sy));
- }
- }
- }
-}
-
-void trident_vga_device::accel_line()
-{
- uint32_t col = tri.accel_fgcolour;
-// TGUI_SRC_XY(dmin-dmaj,dmin);
-// TGUI_DEST_XY(x,y);
-// TGUI_DIM_XY(dmin+e,len);
- int16_t dx = tri.accel_source_y - tri.accel_source_x;
- int16_t dy = tri.accel_source_y;
- int16_t err = tri.accel_dim_x + tri.accel_source_y;
- int sx = (tri.accel_drawflags & 0x0200) ? -1 : 1;
- int sy = (tri.accel_drawflags & 0x0100) ? -1 : 1;
- int x,y,z;
-
- x = tri.accel_dest_x;
- y = tri.accel_dest_y;
-
- WRITEPIXEL(x,y,col);
- for(z=0;z<tri.accel_dim_y;z++)
- {
- if(tri.accel_drawflags & 0x0400)
- y += sy;
- else
- x += sx;
- if(err > 0)
- {
- if(tri.accel_drawflags & 0x0400)
- x += sx;
- else
- y += sy;
- WRITEPIXEL(x,y,col);
- err += (dy-dx);
- }
- else
- {
- WRITEPIXEL(x,y,col);
- err += dy;
- }
- }
-}
-
-// feed data written to VRAM to an active BitBLT command
-void trident_vga_device::accel_data_write(uint32_t data)
-{
- int xdir = 1,ydir = 1;
-
- if(tri.accel_drawflags & 0x0200) // XNEG
- xdir = -1;
- if(tri.accel_drawflags & 0x0100) // YNEG
- ydir = -1;
-
- for(int x=31;x>=0;x--)
- {
- if(tri.accel_mem_x <= tri.accel_dest_x+tri.accel_dim_x && tri.accel_mem_x >= tri.accel_dest_x-tri.accel_dim_x)
- {
- if(((data >> x) & 0x01) != 0)
- WRITEPIXEL(tri.accel_mem_x,tri.accel_mem_y,tri.accel_fgcolour);
- else
- WRITEPIXEL(tri.accel_mem_x,tri.accel_mem_y,tri.accel_bgcolour);
- }
- tri.accel_mem_x+=xdir;
- }
- if(tri.accel_mem_x > tri.accel_dest_x+tri.accel_dim_x || tri.accel_mem_x < tri.accel_dest_x-tri.accel_dim_x)
- {
- tri.accel_mem_x = tri.accel_dest_x;
- tri.accel_mem_y+=ydir;
- if(tri.accel_mem_y > tri.accel_dest_y+tri.accel_dim_y || tri.accel_mem_y < tri.accel_dest_y-tri.accel_dim_y)
- tri.accel_memwrite_active = false; // completed
- }
-}
diff --git a/src/devices/bus/isa/trident.h b/src/devices/bus/isa/trident.h
deleted file mode 100644
index 3dc8f63947c..00000000000
--- a/src/devices/bus/isa/trident.h
+++ /dev/null
@@ -1,168 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Barry Rodewald
-/*
- * trident.h
- *
- */
-
-#ifndef MAME_BUS_ISA_TRIDENT_H
-#define MAME_BUS_ISA_TRIDENT_H
-
-#pragma once
-
-#include "video/pc_vga.h"
-
-// ======================> trident_vga_device
-
-class trident_vga_device : public svga_device
-{
-public:
- virtual uint8_t port_03c0_r(offs_t offset) override;
- virtual void port_03c0_w(offs_t offset, uint8_t data) override;
- virtual uint8_t port_03d0_r(offs_t offset) override;
- virtual void port_03d0_w(offs_t offset, uint8_t data) override;
- uint8_t port_83c6_r(offs_t offset);
- void port_83c6_w(offs_t offset, uint8_t data);
- uint8_t port_43c6_r(offs_t offset);
- void port_43c6_w(offs_t offset, uint8_t data);
- uint8_t vram_r(offs_t offset);
- void vram_w(offs_t offset, uint8_t data);
- virtual uint8_t mem_r(offs_t offset) override;
- virtual void mem_w(offs_t offset, uint8_t data) override;
- virtual uint16_t offset() override;
-
- uint8_t accel_r(offs_t offset);
- void accel_w(offs_t offset, uint8_t data);
-
- virtual uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) override;
-
-protected:
- // construction/destruction
- trident_vga_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void device_start() override;
- virtual void device_reset() override;
-
- struct
- {
- uint8_t sr0c;
- uint8_t sr0d_old;
- uint8_t sr0d_new;
- uint8_t sr0e_old;
- uint8_t sr0e_new;
- uint8_t sr0f;
- uint8_t gc0e;
- uint8_t gc0f;
- uint8_t gc2f;
- uint8_t cr1e;
- uint8_t cr1f;
- uint8_t cr20;
- uint8_t cr21;
- uint8_t cr29;
- uint8_t cr2a;
- uint8_t cr39;
- uint8_t dac;
- uint8_t lutdac_reg[0x100];
- uint8_t lutdac_index;
- bool new_mode;
- bool port_3c3;
- uint8_t port_3db;
- uint8_t clock;
- uint8_t pixel_depth;
- uint8_t revision;
- bool dac_active;
- uint8_t dac_count;
- uint32_t linear_address;
- bool linear_active;
- bool mmio_active;
- uint16_t mem_clock; // I/O 0x43c6
- uint16_t vid_clock; // I/O 0x43c8
- uint16_t cursor_x;
- uint16_t cursor_y;
- uint16_t cursor_loc;
- uint8_t cursor_x_off;
- uint8_t cursor_y_off;
- uint32_t cursor_fg; // colour
- uint32_t cursor_bg; // colour
- uint8_t cursor_ctrl;
-
- // 2D acceleration
- uint16_t accel_opermode;
- uint8_t accel_command;
- uint8_t accel_fmix;
- uint32_t accel_drawflags;
- uint32_t accel_fgcolour;
- uint32_t accel_bgcolour;
- uint16_t accel_pattern_loc;
- int16_t accel_source_x;
- int16_t accel_source_y;
- int16_t accel_dest_x;
- int16_t accel_dest_y;
- int16_t accel_dim_x;
- int16_t accel_dim_y;
- uint32_t accel_style;
- uint32_t accel_ckey;
- int16_t accel_source_x_clip;
- int16_t accel_source_y_clip;
- int16_t accel_dest_x_clip;
- int16_t accel_dest_y_clip;
- uint32_t accel_fg_pattern_colour;
- uint32_t accel_bg_pattern_colour;
- uint8_t accel_pattern[0x80];
- bool accel_busy;
- bool accel_memwrite_active; // true when writing to VRAM will push data to an ongoing command (SRCMONO/PATMONO)
- int16_t accel_mem_x;
- int16_t accel_mem_y;
- uint32_t accel_transfer;
- } tri;
- uint8_t m_version;
-private:
- uint8_t trident_seq_reg_read(uint8_t index);
- void trident_seq_reg_write(uint8_t index, uint8_t data);
- void trident_define_video_mode();
- uint8_t trident_crtc_reg_read(uint8_t index);
- void trident_crtc_reg_write(uint8_t index, uint8_t data);
- uint8_t trident_gc_reg_read(uint8_t index);
- void trident_gc_reg_write(uint8_t index, uint8_t data);
-
- int calculate_clock();
-
- // old style MMIO (0xBFF00)
- void old_mmio_w(offs_t offset, uint8_t data);
- uint8_t old_mmio_r(offs_t offset);
-
- // 2D acceleration
- void accel_command();
- void accel_bitblt();
- void accel_line();
- void accel_data_write(uint32_t data);
- uint8_t READPIXEL8(int16_t x, int16_t y);
- uint16_t READPIXEL15(int16_t x, int16_t y);
- uint16_t READPIXEL16(int16_t x, int16_t y);
- uint32_t READPIXEL32(int16_t x, int16_t y);
- void WRITEPIXEL8(int16_t x, int16_t y, uint8_t data);
- void WRITEPIXEL15(int16_t x, int16_t y, uint16_t data);
- void WRITEPIXEL16(int16_t x, int16_t y, uint16_t data);
- void WRITEPIXEL32(int16_t x, int16_t y, uint32_t data);
- uint32_t READPIXEL(int16_t x,int16_t y);
- void WRITEPIXEL(int16_t x,int16_t y, uint32_t data);
- uint32_t handle_rop(uint32_t src, uint32_t dst);
-};
-
-class tgui9860_device : public trident_vga_device
-{
-public:
- tgui9860_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-};
-
-class tvga9000_device : public trident_vga_device
-{
-public:
- tvga9000_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-};
-
-// device type definition
-DECLARE_DEVICE_TYPE(TRIDENT_VGA, tgui9860_device)
-DECLARE_DEVICE_TYPE(TVGA9000_VGA, tvga9000_device)
-
-#endif // MAME_BUS_ISA_TRIDENT_H
diff --git a/src/devices/bus/isa/ultra14f.cpp b/src/devices/bus/isa/ultra14f.cpp
index 8b60f908139..2dcb3652ec2 100644
--- a/src/devices/bus/isa/ultra14f.cpp
+++ b/src/devices/bus/isa/ultra14f.cpp
@@ -10,8 +10,8 @@
#include "ultra14f.h"
#include "bus/nscsi/devices.h"
-#include "cpu/m68000/m68000.h"
-#include "machine/ncr5390.h"
+#include "cpu/m68000/m68008.h"
+#include "machine/ncr53c90.h"
#include "machine/nscsi_bus.h"
DEFINE_DEVICE_TYPE(ULTRA14F, ultra14f_device, "ultra14f", "Ultra-14F SCSI Host Adapter")
diff --git a/src/devices/bus/isa/ultra24f.cpp b/src/devices/bus/isa/ultra24f.cpp
index 211c1ab4b80..77d10fc0b67 100644
--- a/src/devices/bus/isa/ultra24f.cpp
+++ b/src/devices/bus/isa/ultra24f.cpp
@@ -11,7 +11,7 @@
#include "bus/nscsi/devices.h"
#include "cpu/m68000/m68000.h"
-#include "machine/ncr5390.h"
+#include "machine/ncr53c90.h"
#include "machine/nscsi_bus.h"
DEFINE_DEVICE_TYPE(ULTRA24F, ultra24f_device, "ultra24f", "Ultra-24F SCSI Host Adapter")
diff --git a/src/devices/bus/isa/vga.cpp b/src/devices/bus/isa/vga.cpp
index b573f4c5701..3fa8752ae91 100644
--- a/src/devices/bus/isa/vga.cpp
+++ b/src/devices/bus/isa/vga.cpp
@@ -62,6 +62,11 @@ isa8_vga_device::isa8_vga_device(const machine_config &mconfig, const char *tag,
{
}
+void isa8_vga_device::io_isa_map(address_map &map)
+{
+ map(0x00, 0x2f).m(m_vga, FUNC(vga_device::io_map));
+}
+
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
@@ -73,9 +78,7 @@ void isa8_vga_device::device_start()
m_isa->install_rom(this, 0xc0000, 0xc7fff, "ibm_vga");
- m_isa->install_device(0x3b0, 0x3bf, read8sm_delegate(*m_vga, FUNC(vga_device::port_03b0_r)), write8sm_delegate(*m_vga, FUNC(vga_device::port_03b0_w)));
- m_isa->install_device(0x3c0, 0x3cf, read8sm_delegate(*m_vga, FUNC(vga_device::port_03c0_r)), write8sm_delegate(*m_vga, FUNC(vga_device::port_03c0_w)));
- m_isa->install_device(0x3d0, 0x3df, read8sm_delegate(*m_vga, FUNC(vga_device::port_03d0_r)), write8sm_delegate(*m_vga, FUNC(vga_device::port_03d0_w)));
+ m_isa->install_device(0x03b0, 0x03df, *this, &isa8_vga_device::io_isa_map);
m_isa->install_memory(0xa0000, 0xbffff, read8sm_delegate(*m_vga, FUNC(vga_device::mem_r)), write8sm_delegate(*m_vga, FUNC(vga_device::mem_w)));
}
diff --git a/src/devices/bus/isa/vga.h b/src/devices/bus/isa/vga.h
index c1b4d7226aa..1a3a530160d 100644
--- a/src/devices/bus/isa/vga.h
+++ b/src/devices/bus/isa/vga.h
@@ -33,6 +33,8 @@ protected:
virtual void device_add_mconfig(machine_config &config) override;
virtual const tiny_rom_entry *device_rom_region() const override;
+ void io_isa_map(address_map &map);
+
private:
required_device<vga_device> m_vga;
};
diff --git a/src/devices/bus/isa/vga_ati.cpp b/src/devices/bus/isa/vga_ati.cpp
index aaebcf3969b..f6fcaec84fb 100644
--- a/src/devices/bus/isa/vga_ati.cpp
+++ b/src/devices/bus/isa/vga_ati.cpp
@@ -1,7 +1,7 @@
// license:BSD-3-Clause
// copyright-holders:Barry Rodewald
/*
- * isa_vga_ati.c
+ * isa_vga_ati.cpp
*
* ATi Graphics Ultra ISA Video card
* - Uses ATi 28800-6 (VGA Wonder) and ATi 38800-1 (Mach8, 8514/A clone)
@@ -17,9 +17,10 @@
#include "emu.h"
#include "vga_ati.h"
-#include "mach32.h"
-#include "video/pc_vga.h"
+#include "video/pc_vga_ati.h"
+#include "video/ati_mach8.h"
+#include "video/ati_mach32.h"
#include "screen.h"
@@ -158,6 +159,21 @@ isa16_vga_mach64_device::isa16_vga_mach64_device(const machine_config &mconfig,
{
}
+void isa16_vga_gfxultra_device::io_isa_map(address_map &map)
+{
+ map(0x00, 0x2f).m(m_vga, FUNC(ati_vga_device::io_map));
+}
+
+void isa16_vga_gfxultrapro_device::io_isa_map(address_map &map)
+{
+ map(0x00, 0x2f).m(m_vga, FUNC(mach32_device::io_map));
+}
+
+void isa16_vga_mach64_device::io_isa_map(address_map &map)
+{
+ map(0x00, 0x2f).m(m_vga, FUNC(mach64_device::io_map));
+}
+
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
@@ -173,9 +189,9 @@ void isa16_vga_gfxultra_device::device_start()
m_isa->install_device(0x1ce, 0x1cf, read8sm_delegate(*m_vga, FUNC(ati_vga_device::ati_port_ext_r)), write8sm_delegate(*m_vga, FUNC(ati_vga_device::ati_port_ext_w)));
m_isa->install_device(0x2e8, 0x2ef, read8sm_delegate(*m_8514, FUNC(mach8_device::ibm8514_status_r)), write8sm_delegate(*m_8514, FUNC(mach8_device::ibm8514_htotal_w)));
- m_isa->install_device(0x3b0, 0x3bf, read8sm_delegate(*m_vga, FUNC(ati_vga_device::port_03b0_r)), write8sm_delegate(*m_vga, FUNC(vga_device::port_03b0_w)));
- m_isa->install_device(0x3c0, 0x3cf, read8sm_delegate(*m_vga, FUNC(ati_vga_device::port_03c0_r)), write8sm_delegate(*m_vga, FUNC(vga_device::port_03c0_w)));
- m_isa->install_device(0x3d0, 0x3df, read8sm_delegate(*m_vga, FUNC(ati_vga_device::port_03d0_r)), write8sm_delegate(*m_vga, FUNC(vga_device::port_03d0_w)));
+
+ m_isa->install_device(0x03b0, 0x03df, *this, &isa16_vga_gfxultra_device::io_isa_map);
+
m_isa->install16_device(0x12e8, 0x12eb, read16smo_delegate(*m_8514, FUNC(mach8_device::ibm8514_vtotal_r)), write16smo_delegate(*m_8514, FUNC(mach8_device::ibm8514_vtotal_w)));
m_isa->install16_device(0x12ec, 0x12ef, read16smo_delegate(*m_8514, FUNC(mach8_device::mach8_config1_r)), write16smo_delegate(*this));
m_isa->install16_device(0x16e8, 0x16eb, read16smo_delegate(*m_8514, FUNC(mach8_device::ibm8514_vdisp_r)), write16smo_delegate(*m_8514, FUNC(mach8_device::ibm8514_vdisp_w)));
@@ -234,9 +250,9 @@ void isa16_vga_gfxultrapro_device::device_start()
m_isa->install_device(0x1ce, 0x1cf, read8sm_delegate(*m_vga, FUNC(mach32_device::ati_port_ext_r)), write8sm_delegate(*m_vga, FUNC(mach32_device::ati_port_ext_w)));
m_isa->install_device(0x2e8, 0x2ef, read8sm_delegate(*m_vga, FUNC(mach32_device::mach32_status_r)), write8sm_delegate(*m_vga, FUNC(mach32_device::ibm8514_htotal_w)));
- m_isa->install_device(0x3b0, 0x3bf, read8sm_delegate(*m_vga, FUNC(mach32_device::port_03b0_r)), write8sm_delegate(*m_vga, FUNC(mach32_device::port_03b0_w)));
- m_isa->install_device(0x3c0, 0x3cf, read8sm_delegate(*m_vga, FUNC(mach32_device::port_03c0_r)), write8sm_delegate(*m_vga, FUNC(mach32_device::port_03c0_w)));
- m_isa->install_device(0x3d0, 0x3df, read8sm_delegate(*m_vga, FUNC(mach32_device::port_03d0_r)), write8sm_delegate(*m_vga, FUNC(mach32_device::port_03d0_w)));
+
+ m_isa->install_device(0x03b0, 0x03df, *this, &isa16_vga_gfxultrapro_device::io_isa_map);
+
m_isa->install16_device(0xaec, 0xaef, read16sm_delegate(*m_vga, FUNC(mach32_device::mach32_readonly_sm_r)), write16sm_delegate(*m_vga, FUNC(mach32_device::mach32_cursor_l_w)));
m_isa->install16_device(0xeec, 0xeef, read16sm_delegate(*m_vga, FUNC(mach32_device::mach32_readonly_sm_r)), write16sm_delegate(*m_vga, FUNC(mach32_device::mach32_cursor_h_w)));
m_isa->install16_device(0x12e8, 0x12eb, read16smo_delegate(*m_vga, FUNC(mach32_device::ibm8514_vtotal_r)), write16smo_delegate(*m_vga, FUNC(mach32_device::ibm8514_vtotal_w)));
@@ -303,9 +319,9 @@ void isa16_vga_mach64_device::device_start()
m_isa->install_device(0x1ce, 0x1cf, read8sm_delegate(*m_vga, FUNC(mach64_device::ati_port_ext_r)), write8sm_delegate(*m_vga, FUNC(mach64_device::ati_port_ext_w)));
m_isa->install_device(0x2e8, 0x2ef, read8sm_delegate(*m_vga, FUNC(mach64_device::mach32_status_r)), write8sm_delegate(*m_vga, FUNC(mach64_device::ibm8514_htotal_w)));
- m_isa->install_device(0x3b0, 0x3bf, read8sm_delegate(*m_vga, FUNC(mach64_device::port_03b0_r)), write8sm_delegate(*m_vga, FUNC(mach64_device::port_03b0_w)));
- m_isa->install_device(0x3c0, 0x3cf, read8sm_delegate(*m_vga, FUNC(mach64_device::port_03c0_r)), write8sm_delegate(*m_vga, FUNC(mach64_device::port_03c0_w)));
- m_isa->install_device(0x3d0, 0x3df, read8sm_delegate(*m_vga, FUNC(mach64_device::port_03d0_r)), write8sm_delegate(*m_vga, FUNC(mach64_device::port_03d0_w)));
+
+ m_isa->install_device(0x03b0, 0x03df, *this, &isa16_vga_mach64_device::io_isa_map);
+
m_isa->install16_device(0x12e8, 0x12eb, read16smo_delegate(*m_vga, FUNC(mach64_device::ibm8514_vtotal_r)), write16smo_delegate(*m_vga, FUNC(mach64_device::ibm8514_vtotal_w)));
m_isa->install16_device(0x12ec, 0x12ef, read16smo_delegate(*m_vga, FUNC(mach64_device::mach32_config1_smo_r)), write16smo_delegate(*m_vga, FUNC(mach64_device::mach64_config1_w)));
m_isa->install16_device(0x16e8, 0x16eb, read16smo_delegate(*m_vga, FUNC(mach64_device::ibm8514_vdisp_r)), write16smo_delegate(*m_vga, FUNC(mach64_device::ibm8514_vdisp_w)));
diff --git a/src/devices/bus/isa/vga_ati.h b/src/devices/bus/isa/vga_ati.h
index f92f3c563ca..3b7c064bbaa 100644
--- a/src/devices/bus/isa/vga_ati.h
+++ b/src/devices/bus/isa/vga_ati.h
@@ -1,11 +1,9 @@
// license:BSD-3-Clause
// copyright-holders:Barry Rodewald
/*
- * isa_vga_ati.h
+ * isa/vga_ati.h
*
* Header for ATi Graphics Ultra/Graphics Ultra Pro ISA video cards
- *
- * Created on: 9/09/2012
*/
#ifndef MAME_BUS_ISA_VGA_ATI_H
#define MAME_BUS_ISA_VGA_ATI_H
@@ -13,8 +11,11 @@
#pragma once
#include "isa.h"
-#include "video/pc_vga.h"
-#include "mach32.h"
+
+#include "video/ati_mach32.h"
+#include "video/ati_mach8.h"
+#include "video/pc_vga_ati.h"
+
//**************************************************************************
// TYPE DEFINITIONS
@@ -41,6 +42,8 @@ protected:
virtual void device_add_mconfig(machine_config &config) override;
virtual const tiny_rom_entry *device_rom_region() const override;
+ void io_isa_map(address_map &map);
+
private:
required_device<ati_vga_device> m_vga;
required_device<mach8_device> m_8514;
@@ -65,6 +68,8 @@ protected:
virtual void device_add_mconfig(machine_config &config) override;
virtual const tiny_rom_entry *device_rom_region() const override;
+ void io_isa_map(address_map &map);
+
private:
required_device<mach32_device> m_vga;
};
@@ -88,6 +93,7 @@ protected:
virtual void device_add_mconfig(machine_config &config) override;
virtual const tiny_rom_entry *device_rom_region() const override;
+ void io_isa_map(address_map &map);
private:
required_device<mach64_device> m_vga;
};
diff --git a/src/devices/bus/isa/wdxt_gen.cpp b/src/devices/bus/isa/wdxt_gen.cpp
index fb2a8fd1965..1096e9a60d7 100644
--- a/src/devices/bus/isa/wdxt_gen.cpp
+++ b/src/devices/bus/isa/wdxt_gen.cpp
@@ -100,17 +100,17 @@ void wdxt_gen_device::wd1015_io(address_map &map)
// WD11C00_17_INTERFACE( host_intf )
//-------------------------------------------------
-WRITE_LINE_MEMBER( wdxt_gen_device::irq5_w )
+void wdxt_gen_device::irq5_w(int state)
{
m_isa->irq5_w(state);
}
-WRITE_LINE_MEMBER( wdxt_gen_device::drq3_w )
+void wdxt_gen_device::drq3_w(int state)
{
m_isa->drq3_w(state);
}
-WRITE_LINE_MEMBER( wdxt_gen_device::mr_w )
+void wdxt_gen_device::mr_w(int state)
{
if (state == ASSERT_LINE)
{
@@ -250,7 +250,7 @@ void wdxt_gen_device::dack_line_w(int line, int state)
// wd1015_t1_r -
//-------------------------------------------------
-READ_LINE_MEMBER( wdxt_gen_device::wd1015_t1_r )
+int wdxt_gen_device::wd1015_t1_r()
{
return 0; // TODO
}
diff --git a/src/devices/bus/isa/wdxt_gen.h b/src/devices/bus/isa/wdxt_gen.h
index f238f6750a1..39948ba6b5b 100644
--- a/src/devices/bus/isa/wdxt_gen.h
+++ b/src/devices/bus/isa/wdxt_gen.h
@@ -55,13 +55,13 @@ protected:
virtual void dack_line_w(int line, int state) override;
private:
- DECLARE_WRITE_LINE_MEMBER( irq5_w );
- DECLARE_WRITE_LINE_MEMBER( drq3_w );
- DECLARE_WRITE_LINE_MEMBER( mr_w );
+ void irq5_w(int state);
+ void drq3_w(int state);
+ void mr_w(int state);
uint8_t rd322_r();
uint8_t ram_r(offs_t offset);
void ram_w(offs_t offset, uint8_t data);
- DECLARE_READ_LINE_MEMBER( wd1015_t1_r );
+ int wd1015_t1_r();
uint8_t wd1015_p1_r();
void wd1015_p1_w(uint8_t data);
uint8_t wd1015_p2_r();
diff --git a/src/devices/bus/isa/xtide.cpp b/src/devices/bus/isa/xtide.cpp
index a22f69a9b13..c21b6c12d54 100644
--- a/src/devices/bus/isa/xtide.cpp
+++ b/src/devices/bus/isa/xtide.cpp
@@ -11,7 +11,7 @@ Card has jumpers for I/O base address, and ROM base address, the default
rom images being we'll emulate an I/O base of 0x300 and a ROM base of 0xC8000.
If the I/O address is changed then you will need to use XTIDECFG to configure the ROM.
-The opensource bios is available from :
+The opensource BIOS is available from :
http://code.google.com/p/xtideuniversalbios/
The data high register is connected to a pair of latches that have the MSB of
@@ -109,7 +109,7 @@ void xtide_device::write(offs_t offset, uint8_t data)
}
}
-WRITE_LINE_MEMBER(xtide_device::ide_interrupt)
+void xtide_device::ide_interrupt(int state)
{
switch (m_irq_number)
{
@@ -175,10 +175,10 @@ ROM_START( xtide )
ROM_DEFAULT_BIOS("xub200b3xt")
- ROM_SYSTEM_BIOS( 0, "xtide_010", "Hargle's Bios v0.10" )
+ ROM_SYSTEM_BIOS( 0, "xtide_010", "Hargle's BIOS v0.10" )
ROMX_LOAD( "oprom.bin,v0.10", 0x000000, 0x002000, CRC(56075ac2) SHA1(f55285a1ed8414c8ddf2364421552e0548cf548f), ROM_BIOS(0) )
- ROM_SYSTEM_BIOS( 1, "xtide_011", "Hargle's Bios v0.11" )
+ ROM_SYSTEM_BIOS( 1, "xtide_011", "Hargle's BIOS v0.11" )
ROMX_LOAD( "oprom.bin,v0.11", 0x000000, 0x002000, CRC(c5fee6c5) SHA1(cc3a015d8d36208d99de8500c962828d2daea939), ROM_BIOS(1) )
ROM_SYSTEM_BIOS( 2, "xub110xt", "XTIDE_Universal_BIOS_v1.1.0 (XT)" )
diff --git a/src/devices/bus/isa/xtide.h b/src/devices/bus/isa/xtide.h
index b06d39d5dbb..494041e2acf 100644
--- a/src/devices/bus/isa/xtide.h
+++ b/src/devices/bus/isa/xtide.h
@@ -33,7 +33,7 @@ protected:
virtual const tiny_rom_entry *device_rom_region() const override;
private:
- DECLARE_WRITE_LINE_MEMBER(ide_interrupt);
+ void ide_interrupt(int state);
required_device<ata_interface_device> m_ata;
required_device<eeprom_parallel_28xx_device> m_eeprom;
diff --git a/src/devices/bus/isbx/compis_fdc.cpp b/src/devices/bus/isbx/compis_fdc.cpp
index b4f72b220ef..cd247ccf026 100644
--- a/src/devices/bus/isbx/compis_fdc.cpp
+++ b/src/devices/bus/isbx/compis_fdc.cpp
@@ -9,6 +9,8 @@
#include "emu.h"
#include "compis_fdc.h"
+#include "formats/cpis_dsk.h"
+
//**************************************************************************
// MACROS / CONSTANTS
@@ -29,12 +31,12 @@ DEFINE_DEVICE_TYPE(COMPIS_FDC, compis_fdc_device, "compis_fdc", "Compis FDC")
// floppy_formats
//-------------------------------------------------
-WRITE_LINE_MEMBER( compis_fdc_device::fdc_irq )
+void compis_fdc_device::fdc_irq(int state)
{
m_slot->mintr1_w(state);
}
-WRITE_LINE_MEMBER( compis_fdc_device::fdc_drq )
+void compis_fdc_device::fdc_drq(int state)
{
m_slot->mdrqt_w(state);
}
@@ -61,8 +63,9 @@ void compis_fdc_device::device_add_mconfig(machine_config &config)
I8272A(config, m_fdc, 8'000'000, true);
m_fdc->intrq_wr_callback().set(FUNC(compis_fdc_device::fdc_irq));
m_fdc->drq_wr_callback().set(FUNC(compis_fdc_device::fdc_drq));
- FLOPPY_CONNECTOR(config, m_floppy0, compis_floppies, "525qd", compis_fdc_device::floppy_formats);
- FLOPPY_CONNECTOR(config, m_floppy1, compis_floppies, "525qd", compis_fdc_device::floppy_formats);
+
+ for (auto &floppy : m_floppy)
+ FLOPPY_CONNECTOR(config, floppy, compis_floppies, "525qd", compis_fdc_device::floppy_formats);
}
@@ -79,8 +82,7 @@ compis_fdc_device::compis_fdc_device(const machine_config &mconfig, const char *
device_t(mconfig, COMPIS_FDC, tag, owner, clock),
device_isbx_card_interface(mconfig, *this),
m_fdc(*this, I8272_TAG),
- m_floppy0(*this, I8272_TAG":0"),
- m_floppy1(*this, I8272_TAG":1")
+ m_floppy(*this, I8272_TAG":%u", 0U)
{
}
@@ -171,6 +173,10 @@ void compis_fdc_device::opt0_w(int state)
void compis_fdc_device::opt1_w(int state)
{
- m_floppy0->get_device()->mon_w(state);
- m_floppy1->get_device()->mon_w(state);
+ for (auto &floppy : m_floppy)
+ {
+ floppy_image_device *fd = floppy->get_device();
+ if (fd)
+ fd->mon_w(state);
+ }
}
diff --git a/src/devices/bus/isbx/compis_fdc.h b/src/devices/bus/isbx/compis_fdc.h
index 5e50b3a3696..3817ffb9ca1 100644
--- a/src/devices/bus/isbx/compis_fdc.h
+++ b/src/devices/bus/isbx/compis_fdc.h
@@ -12,7 +12,6 @@
#pragma once
#include "isbx.h"
-#include "formats/cpis_dsk.h"
#include "imagedev/floppy.h"
#include "machine/upd765.h"
@@ -48,13 +47,12 @@ protected:
virtual void opt1_w(int state) override;
private:
- DECLARE_WRITE_LINE_MEMBER( fdc_irq );
- DECLARE_WRITE_LINE_MEMBER( fdc_drq );
+ void fdc_irq(int state);
+ void fdc_drq(int state);
static void floppy_formats(format_registration &fr);
required_device<i8272a_device> m_fdc;
- required_device<floppy_connector> m_floppy0;
- required_device<floppy_connector> m_floppy1;
+ required_device_array<floppy_connector, 2> m_floppy;
};
diff --git a/src/devices/bus/isbx/isbc_218a.cpp b/src/devices/bus/isbx/isbc_218a.cpp
index 3c1dd92b4fa..a337ad96525 100644
--- a/src/devices/bus/isbx/isbc_218a.cpp
+++ b/src/devices/bus/isbx/isbc_218a.cpp
@@ -9,6 +9,8 @@
#include "emu.h"
#include "isbc_218a.h"
+#include "formats/flopimg.h"
+
//**************************************************************************
// MACROS / CONSTANTS
@@ -24,12 +26,12 @@
DEFINE_DEVICE_TYPE(ISBC_218A, isbc_218a_device, "isbc_218a", "ISBX 218a for ISBC")
-WRITE_LINE_MEMBER( isbc_218a_device::fdc_irq )
+void isbc_218a_device::fdc_irq(int state)
{
m_slot->mintr1_w(state);
}
-WRITE_LINE_MEMBER( isbc_218a_device::fdc_drq )
+void isbc_218a_device::fdc_drq(int state)
{
m_slot->mdrqt_w(state);
}
diff --git a/src/devices/bus/isbx/isbc_218a.h b/src/devices/bus/isbx/isbc_218a.h
index c654c74aae8..d170bfe7ff7 100644
--- a/src/devices/bus/isbx/isbc_218a.h
+++ b/src/devices/bus/isbx/isbc_218a.h
@@ -12,7 +12,6 @@
#pragma once
#include "isbx.h"
-#include "formats/pc_dsk.h"
#include "imagedev/floppy.h"
#include "machine/upd765.h"
@@ -49,8 +48,8 @@ protected:
virtual void opt0_w(int state) override;
private:
- DECLARE_WRITE_LINE_MEMBER( fdc_irq );
- DECLARE_WRITE_LINE_MEMBER( fdc_drq );
+ void fdc_irq(int state);
+ void fdc_drq(int state);
static void floppy_formats(format_registration &fr);
required_device<i8272a_device> m_fdc;
diff --git a/src/devices/bus/isbx/isbx.cpp b/src/devices/bus/isbx/isbx.cpp
index 373d147cadd..178f2215ab2 100644
--- a/src/devices/bus/isbx/isbx.cpp
+++ b/src/devices/bus/isbx/isbx.cpp
@@ -57,12 +57,6 @@ isbx_slot_device::isbx_slot_device(const machine_config &mconfig, const char *ta
void isbx_slot_device::device_start()
{
m_card = get_card_device();
-
- // resolve callbacks
- m_write_mintr0.resolve_safe();
- m_write_mintr1.resolve_safe();
- m_write_mdrqt.resolve_safe();
- m_write_mwait.resolve_safe();
}
diff --git a/src/devices/bus/isbx/isbx.h b/src/devices/bus/isbx/isbx.h
index af9c51aa842..7301f96dcc2 100644
--- a/src/devices/bus/isbx/isbx.h
+++ b/src/devices/bus/isbx/isbx.h
@@ -97,19 +97,19 @@ public:
void mcs1_w(offs_t offset, uint8_t data) { if (m_card) m_card->mcs1_w(offset, data); }
uint8_t mdack_r(offs_t offset) { return m_card ? m_card->mdack_r(offset) : 0xff; }
void mdack_w(offs_t offset, uint8_t data) { if (m_card) m_card->mdack_w(offset, data); }
- DECLARE_READ_LINE_MEMBER( mpst_r ) { return m_card == nullptr; }
- DECLARE_READ_LINE_MEMBER( opt0_r ) { return m_card ? m_card->opt0_r() : 1; }
- DECLARE_WRITE_LINE_MEMBER( opt0_w ) { if (m_card) m_card->opt0_w(state); }
- DECLARE_READ_LINE_MEMBER( opt1_r ) { return m_card ? m_card->opt1_r() : 1; }
- DECLARE_WRITE_LINE_MEMBER( opt1_w ) { if (m_card) m_card->opt1_w(state); }
- DECLARE_WRITE_LINE_MEMBER( tdma_w ) { if (m_card) m_card->tdma_w(state); }
- DECLARE_WRITE_LINE_MEMBER( mclk_w ) { if (m_card) m_card->mclk_w(state); }
+ int mpst_r() { return m_card == nullptr; }
+ int opt0_r() { return m_card ? m_card->opt0_r() : 1; }
+ void opt0_w(int state) { if (m_card) m_card->opt0_w(state); }
+ int opt1_r() { return m_card ? m_card->opt1_r() : 1; }
+ void opt1_w(int state) { if (m_card) m_card->opt1_w(state); }
+ void tdma_w(int state) { if (m_card) m_card->tdma_w(state); }
+ void mclk_w(int state) { if (m_card) m_card->mclk_w(state); }
// card interface
- DECLARE_WRITE_LINE_MEMBER( mintr0_w ) { m_write_mintr0(state); }
- DECLARE_WRITE_LINE_MEMBER( mintr1_w ) { m_write_mintr1(state); }
- DECLARE_WRITE_LINE_MEMBER( mdrqt_w ) { m_write_mdrqt(state); }
- DECLARE_WRITE_LINE_MEMBER( mwait_w ) { m_write_mwait(state); }
+ void mintr0_w(int state) { m_write_mintr0(state); }
+ void mintr1_w(int state) { m_write_mintr1(state); }
+ void mdrqt_w(int state) { m_write_mdrqt(state); }
+ void mwait_w(int state) { m_write_mwait(state); }
protected:
// device-level overrides
diff --git a/src/devices/bus/jakks_gamekey/slot.cpp b/src/devices/bus/jakks_gamekey/slot.cpp
index ab4908ea3be..7da3904f32c 100644
--- a/src/devices/bus/jakks_gamekey/slot.cpp
+++ b/src/devices/bus/jakks_gamekey/slot.cpp
@@ -42,7 +42,7 @@ void device_jakks_gamekey_interface::rom_alloc(uint32_t size, const char *tag)
{
if (m_rom == nullptr)
{
- m_rom = device().machine().memory().region_alloc(std::string(tag).append(JAKKSSLOT_ROM_REGION_TAG).c_str(), size, 1, ENDIANNESS_BIG)->base();
+ m_rom = device().machine().memory().region_alloc(std::string(tag).append(JAKKSSLOT_ROM_REGION_TAG), size, 1, ENDIANNESS_BIG)->base();
m_rom_size = size;
}
}
@@ -125,16 +125,15 @@ static const char *jakks_gamekey_get_slot(int type)
call load
-------------------------------------------------*/
-image_init_result jakks_gamekey_slot_device::call_load()
+std::pair<std::error_condition, std::string> jakks_gamekey_slot_device::call_load()
{
if (m_cart)
{
- uint8_t *ROM;
- uint32_t len = !loaded_through_softlist() ? length() : get_software_region_length("rom");
+ uint32_t const len = !loaded_through_softlist() ? length() : get_software_region_length("rom");
m_cart->rom_alloc(len, tag());
- ROM = m_cart->get_rom_base();
+ uint8_t *const ROM = m_cart->get_rom_base();
if (!loaded_through_softlist())
fread(ROM, len);
@@ -153,11 +152,9 @@ image_init_result jakks_gamekey_slot_device::call_load()
if (pcb_name)
m_type = jakks_gamekey_get_pcb_id(pcb_name);
}
-
- return image_init_result::PASS;
}
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
@@ -186,8 +183,7 @@ std::string jakks_gamekey_slot_device::get_default_card_software(get_default_car
hook.image_file()->length(len); // FIXME: check error return, guard against excessively large files
std::vector<uint8_t> rom(len);
- size_t actual;
- hook.image_file()->read(&rom[0], len, actual); // FIXME: check error return or read returning short
+ read(*hook.image_file(), &rom[0], len); // FIXME: check error return or read returning short
int const type = get_cart_type(&rom[0], len);
char const *const slot_string = jakks_gamekey_get_slot(type);
diff --git a/src/devices/bus/jakks_gamekey/slot.h b/src/devices/bus/jakks_gamekey/slot.h
index 0f02ca86e43..15ff833eaf0 100644
--- a/src/devices/bus/jakks_gamekey/slot.h
+++ b/src/devices/bus/jakks_gamekey/slot.h
@@ -68,15 +68,15 @@ public:
virtual ~jakks_gamekey_slot_device();
- // image-level overrides
- virtual image_init_result call_load() override;
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
virtual void call_unload() override { }
virtual bool is_reset_on_load() const noexcept override { return true; }
virtual const char *image_interface() const noexcept override { return "jakks_gamekey"; }
virtual const char *file_extensions() const noexcept override { return "bin,u1"; }
- // slot interface overrides
+ // device_slot_interface implementation
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
int get_type() { return m_type; }
@@ -92,11 +92,11 @@ public:
bool has_cart() { return m_cart ? true : false; }
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
int m_type;
- device_jakks_gamekey_interface* m_cart;
+ device_jakks_gamekey_interface *m_cart;
};
// device type definition
diff --git a/src/devices/bus/kc/d002.cpp b/src/devices/bus/kc/d002.cpp
index 288d2278578..f11dfe327c5 100644
--- a/src/devices/bus/kc/d002.cpp
+++ b/src/devices/bus/kc/d002.cpp
@@ -52,17 +52,17 @@ INPUT_PORTS_END
void kc85_cart(device_slot_interface &device);
void kc85_exp(device_slot_interface &device);
-WRITE_LINE_MEMBER(kc_d002_device::out_irq_w)
+void kc_d002_device::out_irq_w(int state)
{
m_slot->m_out_irq_cb(state);
}
-WRITE_LINE_MEMBER(kc_d002_device::out_nmi_w)
+void kc_d002_device::out_nmi_w(int state)
{
m_slot->m_out_nmi_cb(state);
}
-WRITE_LINE_MEMBER(kc_d002_device::out_halt_w)
+void kc_d002_device::out_halt_w(int state)
{
m_slot->m_out_halt_cb(state);
}
@@ -226,7 +226,7 @@ void kc_d002_device::io_write(offs_t offset, uint8_t data)
MEI line write
-------------------------------------------------*/
-WRITE_LINE_MEMBER( kc_d002_device::mei_w )
+void kc_d002_device::mei_w(int state)
{
m_expansions[0]->mei_w(state);
}
diff --git a/src/devices/bus/kc/d002.h b/src/devices/bus/kc/d002.h
index 7db1418bf5f..4c8d50108ac 100644
--- a/src/devices/bus/kc/d002.h
+++ b/src/devices/bus/kc/d002.h
@@ -35,13 +35,13 @@ protected:
virtual void write(offs_t offset, uint8_t data) override;
virtual void io_read(offs_t offset, uint8_t &data) override;
virtual void io_write(offs_t offset, uint8_t data) override;
- virtual DECLARE_WRITE_LINE_MEMBER( mei_w ) override;
+ virtual void mei_w(int state) override;
private:
// interface callbacks
- DECLARE_WRITE_LINE_MEMBER( out_irq_w );
- DECLARE_WRITE_LINE_MEMBER( out_nmi_w );
- DECLARE_WRITE_LINE_MEMBER( out_halt_w );
+ void out_irq_w(int state);
+ void out_nmi_w(int state);
+ void out_halt_w(int state);
kcexp_slot_device *m_slot;
diff --git a/src/devices/bus/kc/d004.cpp b/src/devices/bus/kc/d004.cpp
index 45905b23b1d..3d129baaf3e 100644
--- a/src/devices/bus/kc/d004.cpp
+++ b/src/devices/bus/kc/d004.cpp
@@ -348,7 +348,7 @@ void kc_d004_device::hw_terminal_count_w(uint8_t data)
m_fdc->tc_w(true);
}
-WRITE_LINE_MEMBER(kc_d004_device::fdc_irq)
+void kc_d004_device::fdc_irq(int state)
{
if (state)
m_fdc->tc_w(false);
diff --git a/src/devices/bus/kc/d004.h b/src/devices/bus/kc/d004.h
index 570f378b4fa..d4494632511 100644
--- a/src/devices/bus/kc/d004.h
+++ b/src/devices/bus/kc/d004.h
@@ -57,7 +57,7 @@ protected:
private:
static void floppy_formats(format_registration &fr);
- DECLARE_WRITE_LINE_MEMBER( fdc_irq );
+ void fdc_irq(int state);
void kc_d004_io(address_map &map);
void kc_d004_mem(address_map &map);
diff --git a/src/devices/bus/kc/kc.cpp b/src/devices/bus/kc/kc.cpp
index 5e2b67cdab3..feed0c8995e 100644
--- a/src/devices/bus/kc/kc.cpp
+++ b/src/devices/bus/kc/kc.cpp
@@ -193,11 +193,6 @@ void kcexp_slot_device::device_validity_check(validity_checker &valid) const
void kcexp_slot_device::device_start()
{
m_cart = get_card_device();
-
- // resolve callbacks
- m_out_irq_cb.resolve_safe();
- m_out_nmi_cb.resolve_safe();
- m_out_halt_cb.resolve_safe();
}
@@ -270,7 +265,7 @@ void kcexp_slot_device::io_write(offs_t offset, uint8_t data)
MEI line write
-------------------------------------------------*/
-WRITE_LINE_MEMBER( kcexp_slot_device::mei_w )
+void kcexp_slot_device::mei_w(int state)
{
LOG("KCEXP: %s MEI line\n", state != CLEAR_LINE ? "ASSERT": "CLEAR");
@@ -282,7 +277,7 @@ WRITE_LINE_MEMBER( kcexp_slot_device::mei_w )
MEO line write
-------------------------------------------------*/
-WRITE_LINE_MEMBER( kcexp_slot_device::meo_w )
+void kcexp_slot_device::meo_w(int state)
{
LOG("KCEXP: %s MEO line\n", state != CLEAR_LINE ? "ASSERT": "CLEAR");
@@ -316,15 +311,14 @@ kccart_slot_device::~kccart_slot_device()
call load
-------------------------------------------------*/
-image_init_result kccart_slot_device::call_load()
+std::pair<std::error_condition, std::string> kccart_slot_device::call_load()
{
if (m_cart)
{
- offs_t read_length;
- uint8_t *cart_base = m_cart->get_cart_base();
-
- if (cart_base != nullptr)
+ uint8_t *const cart_base = m_cart->get_cart_base();
+ if (cart_base)
{
+ offs_t read_length;
if (!loaded_through_softlist())
{
read_length = length();
@@ -337,10 +331,10 @@ image_init_result kccart_slot_device::call_load()
}
}
else
- return image_init_result::FAIL;
+ return std::make_pair(image_error::INTERNAL, std::string());
}
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
/*-------------------------------------------------
diff --git a/src/devices/bus/kc/kc.h b/src/devices/bus/kc/kc.h
index fdb9cd467ce..c7cd81287a4 100644
--- a/src/devices/bus/kc/kc.h
+++ b/src/devices/bus/kc/kc.h
@@ -35,7 +35,7 @@ public:
virtual void io_read(offs_t offset, uint8_t &data) { }
virtual void io_write(offs_t offset, uint8_t data) { }
virtual uint8_t* get_cart_base() { return nullptr; }
- virtual DECLARE_WRITE_LINE_MEMBER( mei_w ) { }
+ virtual void mei_w(int state) { }
protected:
device_kcexp_interface(const machine_config &mconfig, device_t &device);
@@ -73,8 +73,8 @@ public:
virtual void write(offs_t offset, uint8_t data);
virtual void io_read(offs_t offset, uint8_t &data);
virtual void io_write(offs_t offset, uint8_t data);
- virtual DECLARE_WRITE_LINE_MEMBER( mei_w );
- virtual DECLARE_WRITE_LINE_MEMBER( meo_w );
+ virtual void mei_w(int state);
+ virtual void meo_w(int state);
devcb_write_line m_out_irq_cb;
devcb_write_line m_out_nmi_cb;
@@ -110,14 +110,14 @@ public:
kccart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual ~kccart_slot_device();
- // image-level overrides
- virtual image_init_result call_load() override;
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
virtual bool is_reset_on_load() const noexcept override { return true; }
virtual const char *image_interface() const noexcept override { return "kc_cart"; }
virtual const char *file_extensions() const noexcept override { return "bin"; }
- // slot interface overrides
+ // device_slot_interface implementation
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
};
diff --git a/src/devices/bus/kc/ram.cpp b/src/devices/bus/kc/ram.cpp
index 5e69b397508..347e386b397 100644
--- a/src/devices/bus/kc/ram.cpp
+++ b/src/devices/bus/kc/ram.cpp
@@ -131,7 +131,7 @@ void kc_m011_device::write(offs_t offset, uint8_t data)
MEI line write
-------------------------------------------------*/
-WRITE_LINE_MEMBER( kc_m011_device::mei_w )
+void kc_m011_device::mei_w(int state)
{
m_mei = state;
diff --git a/src/devices/bus/kc/ram.h b/src/devices/bus/kc/ram.h
index 823d32bdb31..bf30ce1a83f 100644
--- a/src/devices/bus/kc/ram.h
+++ b/src/devices/bus/kc/ram.h
@@ -33,7 +33,7 @@ protected:
virtual void control_w(uint8_t data) override;
virtual void read(offs_t offset, uint8_t &data) override;
virtual void write(offs_t offset, uint8_t data) override;
- virtual DECLARE_WRITE_LINE_MEMBER( mei_w ) override;
+ virtual void mei_w(int state) override;
protected:
kcexp_slot_device *m_slot;
diff --git a/src/devices/bus/kc/rom.cpp b/src/devices/bus/kc/rom.cpp
index eca6d6a1907..d0ae2d508ba 100644
--- a/src/devices/bus/kc/rom.cpp
+++ b/src/devices/bus/kc/rom.cpp
@@ -126,7 +126,7 @@ void kc_8k_device::read(offs_t offset, uint8_t &data)
MEI line write
-------------------------------------------------*/
-WRITE_LINE_MEMBER( kc_8k_device::mei_w )
+void kc_8k_device::mei_w(int state)
{
m_mei = state;
diff --git a/src/devices/bus/kc/rom.h b/src/devices/bus/kc/rom.h
index 024969d68b4..44556948a02 100644
--- a/src/devices/bus/kc/rom.h
+++ b/src/devices/bus/kc/rom.h
@@ -34,7 +34,7 @@ protected:
virtual void control_w(uint8_t data) override;
virtual void read(offs_t offset, uint8_t &data) override;
virtual uint8_t* get_cart_base() override;
- virtual DECLARE_WRITE_LINE_MEMBER( mei_w ) override;
+ virtual void mei_w(int state) override;
protected:
kcexp_slot_device *m_slot;
diff --git a/src/devices/bus/kim1/cards.cpp b/src/devices/bus/kim1/cards.cpp
new file mode 100644
index 00000000000..a2b860ce922
--- /dev/null
+++ b/src/devices/bus/kim1/cards.cpp
@@ -0,0 +1,20 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+/***************************************************************************
+
+ KIM-1 bus slot cards
+
+***************************************************************************/
+
+#include "emu.h"
+#include "cards.h"
+
+#include "k1016_16k.h"
+#include "k1008_vismem.h"
+
+
+void kim1_cards(device_slot_interface &device)
+{
+ device.option_add("mtuk1008", KIM1BUS_K1008); // MTU K-1008 8K "Visible Memory" mono 320x200 framebuffer
+ device.option_add("mtuk1016", KIM1BUS_K1016); // MTU K-1016 16K RAM card
+}
diff --git a/src/devices/bus/kim1/cards.h b/src/devices/bus/kim1/cards.h
new file mode 100644
index 00000000000..547d5a65ba7
--- /dev/null
+++ b/src/devices/bus/kim1/cards.h
@@ -0,0 +1,16 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+/***************************************************************************
+
+ KIM-1 bus slot cards
+
+***************************************************************************/
+
+#ifndef MAME_BUS_KIM1_CARDS_H
+#define MAME_BUS_KIM1_CARDS_H
+
+#pragma once
+
+void kim1_cards(device_slot_interface &device) ATTR_COLD;
+
+#endif // MAME_BUS_KIM1_CARDS_H
diff --git a/src/devices/bus/kim1/k1008_vismem.cpp b/src/devices/bus/kim1/k1008_vismem.cpp
new file mode 100644
index 00000000000..3239b58950c
--- /dev/null
+++ b/src/devices/bus/kim1/k1008_vismem.cpp
@@ -0,0 +1,128 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+/*********************************************************************
+
+ k1008_vismem.cpp
+
+ MTU K-1008 8K RAM "Visible Memory" for the KIM-1
+ This provides an 8KiB RAM expansion that's also a monochrome
+ 320x200 framebuffer.
+
+ The MTU manual consistently spells the name as "Visable Memory",
+ except for the cover, and the card is best known with that spelling.
+
+ http://www.6502.org/users/sjgray/computer/mtu/
+
+*********************************************************************/
+
+#include "emu.h"
+
+#include "k1008_vismem.h"
+
+#include "emupal.h"
+#include "screen.h"
+
+namespace {
+
+class kim1bus_k1008_device:
+ public device_t,
+ public device_kim1bus_card_interface
+{
+public:
+ // construction/destruction
+ kim1bus_k1008_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual ioport_constructor device_input_ports() const override;
+
+private:
+ u32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
+
+ required_ioport m_dips;
+ required_device<screen_device> m_screen;
+ std::unique_ptr<u8[]> m_ram;
+ bool m_installed;
+};
+
+void kim1bus_k1008_device::device_add_mconfig(machine_config &config)
+{
+ SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
+ m_screen->set_screen_update(FUNC(kim1bus_k1008_device::screen_update));
+ m_screen->set_raw(8_MHz_XTAL, 512, 0, 320, 260, 0, 200);
+ m_screen->set_palette("palette");
+
+ PALETTE(config, "palette", palette_device::MONOCHROME);
+}
+
+static INPUT_PORTS_START( dips )
+ PORT_START("DIPS")
+ PORT_DIPNAME( 0xe000, 0x6000, "Address Range" )
+ PORT_DIPSETTING( 0x2000, "2000-3FFF" )
+ PORT_DIPSETTING( 0x4000, "4000-5FFF" )
+ PORT_DIPSETTING( 0x6000, "6000-7FFF" )
+ PORT_DIPSETTING( 0x8000, "8000-9FFF" )
+ PORT_DIPSETTING( 0xa000, "A000-BFFF" )
+ PORT_DIPSETTING( 0xc000, "C000-DFFF" )
+INPUT_PORTS_END
+
+ioport_constructor kim1bus_k1008_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(dips);
+}
+
+kim1bus_k1008_device::kim1bus_k1008_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, KIM1BUS_K1008, tag, owner, clock)
+ , device_kim1bus_card_interface(mconfig, *this)
+ , m_dips(*this, "DIPS")
+ , m_screen(*this, "screen")
+ , m_installed(false)
+{
+}
+
+void kim1bus_k1008_device::device_start()
+{
+ m_ram = std::make_unique<u8[]>(0x2000);
+
+ save_pointer(NAME(m_ram), 0x2000);
+}
+
+void kim1bus_k1008_device::device_reset()
+{
+ if (!m_installed)
+ {
+ const u16 base = m_dips->read();
+ install_bank(base, base + 0x1fff, &m_ram[0]);
+ m_installed = true;
+ }
+}
+
+u32 kim1bus_k1008_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
+{
+ auto const vram8 = &m_ram[0];
+
+ for (int y = 0; y < 200; y++)
+ {
+ u16 *scanline = &bitmap.pix(y);
+ for (int x = 0; x < 320 / 8; x++)
+ {
+ u8 const pixels = vram8[(y * 40) + x];
+
+ *scanline++ = BIT(pixels, 7);
+ *scanline++ = BIT(pixels, 6);
+ *scanline++ = BIT(pixels, 5);
+ *scanline++ = BIT(pixels, 4);
+ *scanline++ = BIT(pixels, 3);
+ *scanline++ = BIT(pixels, 2);
+ *scanline++ = BIT(pixels, 1);
+ *scanline++ = BIT(pixels, 0);
+ }
+ }
+ return 0;
+}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(KIM1BUS_K1008, device_kim1bus_card_interface, kim1bus_k1008_device, "mtu_k1008", "MTU K-1008 8K Visible Memory card")
diff --git a/src/devices/bus/kim1/k1008_vismem.h b/src/devices/bus/kim1/k1008_vismem.h
new file mode 100644
index 00000000000..5ef48f5b9c3
--- /dev/null
+++ b/src/devices/bus/kim1/k1008_vismem.h
@@ -0,0 +1,21 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+/*********************************************************************
+
+ k1008_vismem.h
+
+ MTU K-1008 8K RAM "Visible Memory" for the KIM-1
+
+*********************************************************************/
+
+#ifndef MAME_BUS_KIM1_K1008_VISMEM_H
+#define MAME_BUS_KIM1_K1008_VISMEM_H
+
+#pragma once
+
+#include "kim1bus.h"
+
+// device type declaration
+DECLARE_DEVICE_TYPE(KIM1BUS_K1008, device_kim1bus_card_interface)
+
+#endif // MAME_BUS_KIM1_K1008_VISMEM_H
diff --git a/src/devices/bus/kim1/k1016_16k.cpp b/src/devices/bus/kim1/k1016_16k.cpp
new file mode 100644
index 00000000000..426b9a6e3ed
--- /dev/null
+++ b/src/devices/bus/kim1/k1016_16k.cpp
@@ -0,0 +1,48 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+/*********************************************************************
+
+ k1016_16k.cpp
+
+ MTU K-1016 16K RAM expansion for the KIM-1
+
+*********************************************************************/
+
+#include "emu.h"
+#include "k1016_16k.h"
+
+namespace {
+
+class kim1bus_k1016_device:
+ public device_t,
+ public device_kim1bus_card_interface
+{
+public:
+ // construction/destruction
+ kim1bus_k1016_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual void device_start() override;
+
+private:
+ std::unique_ptr<u8[]> m_ram;
+};
+
+kim1bus_k1016_device::kim1bus_k1016_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, KIM1BUS_K1016, tag, owner, clock)
+ , device_kim1bus_card_interface(mconfig, *this)
+{
+}
+
+void kim1bus_k1016_device::device_start()
+{
+ m_ram = std::make_unique<u8[]>(0x4000);
+
+ install_bank(0x2000, 0x5fff, &m_ram[0]);
+
+ save_pointer(NAME(m_ram), 0x4000);
+}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(KIM1BUS_K1016, device_kim1bus_card_interface, kim1bus_k1016_device, "mtu_k1016", "MTU K-1016 16K RAM card")
diff --git a/src/devices/bus/kim1/k1016_16k.h b/src/devices/bus/kim1/k1016_16k.h
new file mode 100644
index 00000000000..af9ba9d88d0
--- /dev/null
+++ b/src/devices/bus/kim1/k1016_16k.h
@@ -0,0 +1,21 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+/*********************************************************************
+
+ k1016_6k.h
+
+ MTU K-1016 16K RAM expansion for the KIM-1
+
+*********************************************************************/
+
+#ifndef MAME_BUS_KIM1_K1016_16K_H
+#define MAME_BUS_KIM1_K1016_16K_H
+
+#pragma once
+
+#include "kim1bus.h"
+
+// device type declaration
+DECLARE_DEVICE_TYPE(KIM1BUS_K1016, device_kim1bus_card_interface)
+
+#endif // MAME_BUS_KIM1_K1016_16K_H
diff --git a/src/devices/bus/kim1/kim1bus.cpp b/src/devices/bus/kim1/kim1bus.cpp
new file mode 100644
index 00000000000..5c18fe5f8b1
--- /dev/null
+++ b/src/devices/bus/kim1/kim1bus.cpp
@@ -0,0 +1,179 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+/***************************************************************************
+
+ kim1bus.cpp - KIM-1 expansion bus emulation
+
+***************************************************************************/
+
+#include "emu.h"
+#include "kim1bus.h"
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(KIM1BUS_SLOT, kim1bus_slot_device, "kim1bus_slot", "KIM-1 Backplane Slot")
+
+template class device_finder<device_kim1bus_card_interface, false>;
+template class device_finder<device_kim1bus_card_interface, true>;
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// kim1bus_slot_device - constructor
+//-------------------------------------------------
+kim1bus_slot_device::kim1bus_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : kim1bus_slot_device(mconfig, KIM1BUS_SLOT, tag, owner, clock)
+{
+}
+
+kim1bus_slot_device::kim1bus_slot_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, type, tag, owner, clock)
+ , device_single_card_slot_interface<device_kim1bus_card_interface>(mconfig, *this)
+ , m_kim1bus(*this, finder_base::DUMMY_TAG)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void kim1bus_slot_device::device_resolve_objects()
+{
+ device_kim1bus_card_interface *const kim1bus_card(dynamic_cast<device_kim1bus_card_interface *>(get_card_device()));
+ if (kim1bus_card)
+ kim1bus_card->set_kim1bus(m_kim1bus, tag());
+}
+
+void kim1bus_slot_device::device_start()
+{
+}
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(KIM1BUS, kim1bus_device, "kim1bus", "KIM-1 Bus")
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// kim1bus_device - constructor
+//-------------------------------------------------
+
+kim1bus_device::kim1bus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : kim1bus_device(mconfig, KIM1BUS, tag, owner, clock)
+{
+}
+
+kim1bus_device::kim1bus_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, type, tag, owner, clock)
+ , m_space(*this, finder_base::DUMMY_TAG, -1)
+ , m_out_irq_cb(*this)
+ , m_out_nmi_cb(*this)
+ , m_device(nullptr)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void kim1bus_device::device_start()
+{
+ // clear slot
+ m_device = nullptr;
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void kim1bus_device::device_reset()
+{
+}
+
+device_kim1bus_card_interface *kim1bus_device::get_kim1bus_card()
+{
+ return m_device;
+}
+
+void kim1bus_device::add_kim1bus_card(device_kim1bus_card_interface *card)
+{
+ m_device = card;
+}
+
+void kim1bus_device::set_irq_line(int state)
+{
+ m_out_irq_cb(state);
+}
+
+void kim1bus_device::set_nmi_line(int state)
+{
+ m_out_nmi_cb(state);
+}
+
+void kim1bus_device::install_device(offs_t start, offs_t end, read8sm_delegate rhandler, write8sm_delegate whandler)
+{
+ m_space->install_readwrite_handler(start, end, rhandler, whandler);
+}
+
+void kim1bus_device::install_bank(offs_t start, offs_t end, uint8_t *data)
+{
+// printf("install_bank: %s @ %x->%x\n", tag, start, end);
+ m_space->install_ram(start, end, data);
+}
+
+// interrupt request from kim1bus card
+void kim1bus_device::irq_w(int state) { m_out_irq_cb(state); }
+void kim1bus_device::nmi_w(int state) { m_out_nmi_cb(state); }
+
+device_kim1bus_card_interface::device_kim1bus_card_interface(const machine_config &mconfig, device_t &device)
+ : device_interface(device, "kim1bus")
+ , m_kim1bus_finder(device, finder_base::DUMMY_TAG), m_kim1bus(nullptr)
+ , m_kim1bus_slottag(nullptr)
+{
+}
+
+device_kim1bus_card_interface::~device_kim1bus_card_interface()
+{
+}
+
+void device_kim1bus_card_interface::interface_validity_check(validity_checker &valid) const
+{
+ if (m_kim1bus_finder && m_kim1bus && (m_kim1bus != m_kim1bus_finder))
+ osd_printf_error("Contradictory buses configured (%s and %s)\n", m_kim1bus_finder->tag(), m_kim1bus->tag());
+}
+
+void device_kim1bus_card_interface::interface_pre_start()
+{
+ if (!m_kim1bus)
+ {
+ m_kim1bus = m_kim1bus_finder;
+ if (!m_kim1bus)
+ fatalerror("Can't find KIM-1 Bus device %s\n", m_kim1bus_finder.finder_tag());
+ }
+
+ if (!m_kim1bus->started())
+ throw device_missing_dependencies();
+
+ m_kim1bus->add_kim1bus_card(this);
+}
+
+void device_kim1bus_card_interface::install_device(offs_t start, offs_t end, read8sm_delegate rhandler, write8sm_delegate whandler)
+{
+ m_kim1bus->install_device(start, end, rhandler, whandler);
+}
+
+void device_kim1bus_card_interface::install_bank(offs_t start, offs_t end, uint8_t *data)
+{
+ m_kim1bus->install_bank(start, end, data);
+}
diff --git a/src/devices/bus/kim1/kim1bus.h b/src/devices/bus/kim1/kim1bus.h
new file mode 100644
index 00000000000..2512654c196
--- /dev/null
+++ b/src/devices/bus/kim1/kim1bus.h
@@ -0,0 +1,131 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+/***************************************************************************
+
+ kim1bus.h - KIM-1 expansion bus
+
+***************************************************************************/
+
+#ifndef MAME_BUS_KIM1_KIM1BUS_H
+#define MAME_BUS_KIM1_KIM1BUS_H
+
+#pragma once
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class kim1bus_device;
+class device_kim1bus_card_interface;
+
+class kim1bus_slot_device : public device_t, public device_single_card_slot_interface<device_kim1bus_card_interface>
+{
+public:
+ // construction/destruction
+ template <typename T, typename U>
+ kim1bus_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&kim1bus_tag, U &&opts, const char *dflt)
+ : kim1bus_slot_device(mconfig, tag, owner, clock)
+ {
+ option_reset();
+ opts(*this);
+ set_default_option(dflt);
+ set_fixed(false);
+ m_kim1bus.set_tag(std::forward<T>(kim1bus_tag));
+ }
+ kim1bus_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ kim1bus_slot_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ // device_t implementation
+ virtual void device_resolve_objects() override;
+ virtual void device_start() override;
+
+ // configuration
+ required_device<kim1bus_device> m_kim1bus;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(KIM1BUS_SLOT, kim1bus_slot_device)
+
+
+// ======================> kim1bus_device
+class kim1bus_device : public device_t
+{
+public:
+ // construction/destruction
+ kim1bus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ // inline configuration
+ template <typename T> void set_space(T &&tag, int spacenum) { m_space.set_tag(std::forward<T>(tag), spacenum); }
+ auto out_irq_callback() { return m_out_irq_cb.bind(); }
+ auto out_nmi_callback() { return m_out_nmi_cb.bind(); }
+
+ void add_kim1bus_card(device_kim1bus_card_interface *card);
+ device_kim1bus_card_interface *get_kim1bus_card();
+
+ void set_irq_line(int state);
+ void set_nmi_line(int state);
+
+ void install_device(offs_t start, offs_t end, read8sm_delegate rhandler, write8sm_delegate whandler);
+ void install_bank(offs_t start, offs_t end, uint8_t *data);
+
+ void irq_w(int state);
+ void nmi_w(int state);
+
+protected:
+ kim1bus_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ // device_t implementation
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ // internal state
+ required_address_space m_space;
+
+ devcb_write_line m_out_irq_cb;
+ devcb_write_line m_out_nmi_cb;
+
+ device_kim1bus_card_interface *m_device;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(KIM1BUS, kim1bus_device)
+
+// ======================> device_kim1bus_card_interface
+
+// class representing interface-specific live kim1bus card
+class device_kim1bus_card_interface : public device_interface
+{
+ friend class kim1bus_device;
+public:
+ // construction/destruction
+ virtual ~device_kim1bus_card_interface();
+
+ // inline configuration
+ void set_kim1bus(kim1bus_device *kim1bus, const char *slottag) { m_kim1bus = kim1bus; m_kim1bus_slottag = slottag; }
+ template <typename T> void set_onboard(T &&kim1bus) { m_kim1bus_finder.set_tag(std::forward<T>(kim1bus)); m_kim1bus_slottag = device().tag(); }
+
+protected:
+ void raise_slot_irq() { m_kim1bus->set_irq_line(ASSERT_LINE); }
+ void lower_slot_irq() { m_kim1bus->set_irq_line(CLEAR_LINE); }
+ void raise_slot_nmi() { m_kim1bus->set_nmi_line(ASSERT_LINE); }
+ void lower_slot_nmi() { m_kim1bus->set_nmi_line(CLEAR_LINE); }
+
+ void install_device(offs_t start, offs_t end, read8sm_delegate rhandler, write8sm_delegate whandler);
+ void install_bank(offs_t start, offs_t end, uint8_t *data);
+
+ device_kim1bus_card_interface(const machine_config &mconfig, device_t &device);
+
+ virtual void interface_validity_check(validity_checker &valid) const override;
+ virtual void interface_pre_start() override;
+
+private:
+ optional_device<kim1bus_device> m_kim1bus_finder;
+ kim1bus_device *m_kim1bus;
+ const char *m_kim1bus_slottag;
+};
+
+#endif // MAME_BUS_KIM1_KIM1BUS_H
diff --git a/src/devices/bus/lpci/cirrus.cpp b/src/devices/bus/lpci/cirrus.cpp
index 659d39677a9..b14c79f81bb 100644
--- a/src/devices/bus/lpci/cirrus.cpp
+++ b/src/devices/bus/lpci/cirrus.cpp
@@ -67,7 +67,8 @@
#include "video/pc_vga.h"
#include "cirrus.h"
-#define LOG_PCIACCESS 0
+#define VERBOSE (0)
+#include "logmacro.h"
//**************************************************************************
// DEVICE DEFINITIONS
@@ -136,8 +137,7 @@ uint32_t pci_cirrus_svga_device::pci_read(pci_bus_device *pcibus, int function,
}
}
- if (LOG_PCIACCESS)
- logerror("cirrus5430_pci_read(): function=%d offset=0x%02X result=0x%04X\n", function, offset, result);
+ LOG("cirrus5430_pci_read(): function=%d offset=0x%02X result=0x%04X\n", function, offset, result);
return result;
}
@@ -148,8 +148,7 @@ uint32_t pci_cirrus_svga_device::pci_read(pci_bus_device *pcibus, int function,
void pci_cirrus_svga_device::pci_write(pci_bus_device *pcibus, int function, int offset, uint32_t data, uint32_t mem_mask)
{
- if (LOG_PCIACCESS)
- logerror("cirrus5430_pci_write(): function=%d offset=0x%02X data=0x%04X\n", function, offset, data);
+ LOG("cirrus5430_pci_write(): function=%d offset=0x%02X data=0x%04X\n", function, offset, data);
}
/*************************************
diff --git a/src/devices/bus/lpci/i82371ab.cpp b/src/devices/bus/lpci/i82371ab.cpp
index 6d9a1c72bc3..102cd6b8b56 100644
--- a/src/devices/bus/lpci/i82371ab.cpp
+++ b/src/devices/bus/lpci/i82371ab.cpp
@@ -19,10 +19,10 @@
#include "emu.h"
#include "i82371ab.h"
-#define LOG_ISA (1U << 1)
-#define LOG_IDE (1U << 2)
-#define LOG_USB (1U << 3)
-#define LOG_ACPI (1U << 4)
+#define LOG_ISA (1U << 1)
+#define LOG_IDE (1U << 2)
+#define LOG_USB (1U << 3)
+#define LOG_ACPI (1U << 4)
#define VERBOSE (LOG_GENERAL | LOG_ISA | LOG_IDE | LOG_USB | LOG_ACPI)
//#define LOG_OUTPUT_FUNC osd_printf_info
diff --git a/src/devices/bus/lpci/i82371sb.cpp b/src/devices/bus/lpci/i82371sb.cpp
index 425fc563364..16917043332 100644
--- a/src/devices/bus/lpci/i82371sb.cpp
+++ b/src/devices/bus/lpci/i82371sb.cpp
@@ -255,8 +255,7 @@ void i82371sb_device::device_start()
southbridge_device::device_start();
m_ide_io_ports_enabled = false;
spaceio.install_readwrite_handler(0x00b0, 0x00b3, read8sm_delegate(*this, FUNC(i82371sb_device::read_apmcapms)), write8sm_delegate(*this, FUNC(i82371sb_device::write_apmcapms)), 0xffff0000);
- m_smi_callback.resolve_safe();
- m_boot_state_hook.resolve_safe();
+
// setup save states
save_item(NAME(m_regs));
}
diff --git a/src/devices/bus/lpci/i82439tx.cpp b/src/devices/bus/lpci/i82439tx.cpp
index 0966456831a..1c36412eac1 100644
--- a/src/devices/bus/lpci/i82439tx.cpp
+++ b/src/devices/bus/lpci/i82439tx.cpp
@@ -426,7 +426,7 @@ void i82439tx_device::update_smram_mappings()
}
}
-WRITE_LINE_MEMBER(i82439tx_device::smi_act_w)
+void i82439tx_device::smi_act_w(int state)
{
// state is 0 when smm is not active
// but smiact_n reflects the state of the SMIACT# pin
diff --git a/src/devices/bus/lpci/i82439tx.h b/src/devices/bus/lpci/i82439tx.h
index af5a0dcf757..b8dbc392e90 100644
--- a/src/devices/bus/lpci/i82439tx.h
+++ b/src/devices/bus/lpci/i82439tx.h
@@ -29,7 +29,7 @@ public:
virtual uint32_t pci_read(pci_bus_device *pcibus, int function, int offset, uint32_t mem_mask) override;
virtual void pci_write(pci_bus_device *pcibus, int function, int offset, uint32_t data, uint32_t mem_mask) override;
- DECLARE_WRITE_LINE_MEMBER(smi_act_w);
+ void smi_act_w(int state);
protected:
// device-level overrides
diff --git a/src/devices/bus/lpci/mpc105.cpp b/src/devices/bus/lpci/mpc105.cpp
index de6eee2dcce..8853f3eb047 100644
--- a/src/devices/bus/lpci/mpc105.cpp
+++ b/src/devices/bus/lpci/mpc105.cpp
@@ -11,7 +11,8 @@
#include "emu.h"
#include "mpc105.h"
-#define LOG_MPC105 0
+#define VERBOSE (0)
+#include "logmacro.h"
//**************************************************************************
// DEVICE DEFINITIONS
@@ -69,8 +70,7 @@ void mpc105_device::update_memory()
char bank_str[10];
u32 ram_size = m_ram->size();
- if (LOG_MPC105)
- logerror("mpc105_update_memory(machine): Updating memory (bank enable=0x%02X)\n", m_bank_enable);
+ LOG("mpc105_update_memory(machine): Updating memory (bank enable=0x%02X)\n", m_bank_enable);
if (m_bank_base > 0)
{
@@ -96,8 +96,7 @@ void mpc105_device::update_memory()
if ((begin + 0x100000) <= end)
{
- if (LOG_MPC105)
- logerror("\tbank #%d [%02d]: 0x%08X - 0x%08X [%p-%p]\n", bank, bank + m_bank_base, begin, end, m_ram->pointer(), m_ram->pointer() + (end - begin));
+ LOG("\tbank #%d [%02d]: 0x%08X - 0x%08X [%p-%p]\n", bank, bank + m_bank_base, begin, end, m_ram->pointer(), m_ram->pointer() + (end - begin));
if (m_bank_base > 0)
{
diff --git a/src/devices/bus/lpci/pci.cpp b/src/devices/bus/lpci/pci.cpp
index 34470bfa4f9..05b88948aa4 100644
--- a/src/devices/bus/lpci/pci.cpp
+++ b/src/devices/bus/lpci/pci.cpp
@@ -74,7 +74,8 @@
#include "emu.h"
#include "pci.h"
-#define LOG_PCI 0
+#define VERBOSE (0)
+#include "logmacro.h"
//**************************************************************************
// GLOBAL VARIABLES
@@ -130,8 +131,7 @@ uint32_t pci_bus_device::read(offs_t offset, uint32_t mem_mask)
break;
}
- if (LOG_PCI)
- logerror("read('%s'): offset=%d result=0x%08X\n", tag(), offset, result);
+ LOG("read('%s'): offset=%d result=0x%08X\n", tag(), offset, result);
return result;
}
@@ -162,8 +162,7 @@ void pci_bus_device::write(offs_t offset, uint32_t data, uint32_t mem_mask)
{
offset %= 2;
- if (LOG_PCI)
- logerror("write('%s'): offset=%d data=0x%08X\n", tag(), offset, data);
+ LOG("write('%s'): offset=%d data=0x%08X\n", tag(), offset, data);
switch (offset)
{
@@ -183,8 +182,7 @@ void pci_bus_device::write(offs_t offset, uint32_t data, uint32_t mem_mask)
}
else
m_devicenum = -1;
- if (LOG_PCI)
- logerror(" bus:%d device:%d\n", busnum, devicenum);
+ LOG(" bus:%d device:%d\n", busnum, devicenum);
}
break;
@@ -197,8 +195,7 @@ void pci_bus_device::write(offs_t offset, uint32_t data, uint32_t mem_mask)
int reg = (m_address >> 0) & 0xfc;
m_busnumaddr->m_device[m_devicenum]->pci_write(m_busnumaddr, function, reg, data, mem_mask);
}
- if (LOG_PCI)
- logerror(" function:%d register:%d\n", (m_address >> 8) & 0x07, (m_address >> 0) & 0xfc);
+ LOG(" function:%d register:%d\n", (m_address >> 8) & 0x07, (m_address >> 0) & 0xfc);
}
break;
}
diff --git a/src/devices/bus/lpci/southbridge.cpp b/src/devices/bus/lpci/southbridge.cpp
index 2f9faa4aab0..4a9b8641857 100644
--- a/src/devices/bus/lpci/southbridge.cpp
+++ b/src/devices/bus/lpci/southbridge.cpp
@@ -282,19 +282,19 @@ void southbridge_device::at_speaker_set_spkrdata(uint8_t data)
*
*************************************************************/
-WRITE_LINE_MEMBER( southbridge_device::at_pit8254_out0_changed )
+void southbridge_device::at_pit8254_out0_changed(int state)
{
if (m_pic8259_master)
m_pic8259_master->ir0_w(state);
}
-WRITE_LINE_MEMBER( southbridge_device::at_pit8254_out1_changed )
+void southbridge_device::at_pit8254_out1_changed(int state)
{
if(state)
m_refresh = !m_refresh;
}
-WRITE_LINE_MEMBER( southbridge_device::at_pit8254_out2_changed )
+void southbridge_device::at_pit8254_out2_changed(int state)
{
m_pit_out2 = state ? 1 : 0;
m_speaker->level_w(m_at_spkrdata & m_pit_out2);
@@ -353,7 +353,7 @@ void southbridge_device::at_page8_w(offs_t offset, uint8_t data)
}
-WRITE_LINE_MEMBER( southbridge_device::pc_dma_hrq_changed )
+void southbridge_device::pc_dma_hrq_changed(int state)
{
m_maincpu->set_input_line(INPUT_LINE_HALT, state ? ASSERT_LINE : CLEAR_LINE);
@@ -428,7 +428,7 @@ void southbridge_device::pc_dma8237_5_dack_w(uint8_t data) { m_isabus->dack_w(5,
void southbridge_device::pc_dma8237_6_dack_w(uint8_t data) { m_isabus->dack_w(6, data); }
void southbridge_device::pc_dma8237_7_dack_w(uint8_t data) { m_isabus->dack_w(7, data); }
-WRITE_LINE_MEMBER( southbridge_device::at_dma8237_out_eop )
+void southbridge_device::at_dma8237_out_eop(int state)
{
m_cur_eop = state == ASSERT_LINE;
if(m_dma_channel != -1)
@@ -450,14 +450,14 @@ void southbridge_device::pc_select_dma_channel(int channel, bool state)
}
-WRITE_LINE_MEMBER( southbridge_device::pc_dack0_w ) { pc_select_dma_channel(0, state); }
-WRITE_LINE_MEMBER( southbridge_device::pc_dack1_w ) { pc_select_dma_channel(1, state); }
-WRITE_LINE_MEMBER( southbridge_device::pc_dack2_w ) { pc_select_dma_channel(2, state); }
-WRITE_LINE_MEMBER( southbridge_device::pc_dack3_w ) { pc_select_dma_channel(3, state); }
-WRITE_LINE_MEMBER( southbridge_device::pc_dack4_w ) { m_dma8237_1->hack_w( state ? 0 : 1); } // it's inverted
-WRITE_LINE_MEMBER( southbridge_device::pc_dack5_w ) { pc_select_dma_channel(5, state); }
-WRITE_LINE_MEMBER( southbridge_device::pc_dack6_w ) { pc_select_dma_channel(6, state); }
-WRITE_LINE_MEMBER( southbridge_device::pc_dack7_w ) { pc_select_dma_channel(7, state); }
+void southbridge_device::pc_dack0_w(int state) { pc_select_dma_channel(0, state); }
+void southbridge_device::pc_dack1_w(int state) { pc_select_dma_channel(1, state); }
+void southbridge_device::pc_dack2_w(int state) { pc_select_dma_channel(2, state); }
+void southbridge_device::pc_dack3_w(int state) { pc_select_dma_channel(3, state); }
+void southbridge_device::pc_dack4_w(int state) { m_dma8237_1->hack_w( state ? 0 : 1); } // it's inverted
+void southbridge_device::pc_dack5_w(int state) { pc_select_dma_channel(5, state); }
+void southbridge_device::pc_dack6_w(int state) { pc_select_dma_channel(6, state); }
+void southbridge_device::pc_dack7_w(int state) { pc_select_dma_channel(7, state); }
uint8_t southbridge_device::at_portb_r()
{
@@ -485,7 +485,7 @@ void southbridge_device::at_portb_w(uint8_t data)
m_maincpu->set_input_line(INPUT_LINE_NMI, CLEAR_LINE);
}
-WRITE_LINE_MEMBER( southbridge_device::iochck_w )
+void southbridge_device::iochck_w(int state)
{
if (!state && !m_channel_check && m_nmi_enabled)
m_maincpu->set_input_line(INPUT_LINE_NMI, ASSERT_LINE);
@@ -561,7 +561,8 @@ void southbridge_extended_device::device_start()
spaceio.install_readwrite_handler(0x0060, 0x0063, read8smo_delegate(*m_keybc, FUNC(at_keyboard_controller_device::data_r)), write8smo_delegate(*m_keybc, FUNC(at_keyboard_controller_device::data_w)), 0x000000ff);
spaceio.install_readwrite_handler(0x0064, 0x0067, read8smo_delegate(*m_keybc, FUNC(at_keyboard_controller_device::status_r)), write8smo_delegate(*m_keybc, FUNC(at_keyboard_controller_device::command_w)), 0xffffffff);
- spaceio.install_readwrite_handler(0x0070, 0x007f, read8sm_delegate(*m_ds12885, FUNC(ds12885_device::read)), write8sm_delegate(*m_ds12885, FUNC(ds12885_device::write)), 0xffffffff);
+ spaceio.install_write_handler(0x0070, 0x007f, write8smo_delegate(*this, FUNC(southbridge_extended_device::rtc_nmi_w)), 0x00ff00ff);
+ spaceio.install_readwrite_handler(0x0070, 0x007f, read8smo_delegate(*m_ds12885, FUNC(ds12885_device::data_r)), write8smo_delegate(*m_ds12885, FUNC(ds12885_device::data_w)), 0xff00ff00);
}
//-------------------------------------------------
@@ -573,15 +574,10 @@ void southbridge_extended_device::device_reset()
southbridge_device::device_reset();
}
-void southbridge_extended_device::write_rtc(offs_t offset, uint8_t data)
+void southbridge_extended_device::rtc_nmi_w(uint8_t data)
{
- if (offset==0) {
- m_nmi_enabled = BIT(data,7);
- if (!m_nmi_enabled)
- m_maincpu->set_input_line(INPUT_LINE_NMI, CLEAR_LINE);
- m_ds12885->write(0,data);
- }
- else {
- m_ds12885->write(offset,data);
- }
+ m_nmi_enabled = BIT(data,7);
+ if (!m_nmi_enabled)
+ m_maincpu->set_input_line(INPUT_LINE_NMI, CLEAR_LINE);
+ m_ds12885->address_w(data);
}
diff --git a/src/devices/bus/lpci/southbridge.h b/src/devices/bus/lpci/southbridge.h
index 92953a5df0f..2ea3a60a2ba 100644
--- a/src/devices/bus/lpci/southbridge.h
+++ b/src/devices/bus/lpci/southbridge.h
@@ -87,12 +87,12 @@ private:
void at_page8_w(offs_t offset, uint8_t data);
uint8_t at_portb_r();
void at_portb_w(uint8_t data);
- DECLARE_WRITE_LINE_MEMBER(iochck_w);
+ void iochck_w(int state);
uint8_t get_slave_ack(offs_t offset);
- DECLARE_WRITE_LINE_MEMBER(at_pit8254_out0_changed);
- DECLARE_WRITE_LINE_MEMBER(at_pit8254_out1_changed);
- DECLARE_WRITE_LINE_MEMBER(at_pit8254_out2_changed);
- DECLARE_WRITE_LINE_MEMBER(pc_dma_hrq_changed);
+ void at_pit8254_out0_changed(int state);
+ void at_pit8254_out1_changed(int state);
+ void at_pit8254_out2_changed(int state);
+ void pc_dma_hrq_changed(int state);
uint8_t pc_dma8237_0_dack_r();
uint8_t pc_dma8237_1_dack_r();
uint8_t pc_dma8237_2_dack_r();
@@ -107,15 +107,15 @@ private:
void pc_dma8237_5_dack_w(uint8_t data);
void pc_dma8237_6_dack_w(uint8_t data);
void pc_dma8237_7_dack_w(uint8_t data);
- DECLARE_WRITE_LINE_MEMBER(at_dma8237_out_eop);
- DECLARE_WRITE_LINE_MEMBER(pc_dack0_w);
- DECLARE_WRITE_LINE_MEMBER(pc_dack1_w);
- DECLARE_WRITE_LINE_MEMBER(pc_dack2_w);
- DECLARE_WRITE_LINE_MEMBER(pc_dack3_w);
- DECLARE_WRITE_LINE_MEMBER(pc_dack4_w);
- DECLARE_WRITE_LINE_MEMBER(pc_dack5_w);
- DECLARE_WRITE_LINE_MEMBER(pc_dack6_w);
- DECLARE_WRITE_LINE_MEMBER(pc_dack7_w);
+ void at_dma8237_out_eop(int state);
+ void pc_dack0_w(int state);
+ void pc_dack1_w(int state);
+ void pc_dack2_w(int state);
+ void pc_dack3_w(int state);
+ void pc_dack4_w(int state);
+ void pc_dack5_w(int state);
+ void pc_dack6_w(int state);
+ void pc_dack7_w(int state);
uint32_t ide1_read32_cs0_r(offs_t offset, uint32_t mem_mask = ~0);
void ide1_write32_cs0_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
@@ -159,7 +159,7 @@ protected:
required_device<pc_kbdc_device> m_pc_kbdc;
private:
- void write_rtc(offs_t offset, uint8_t data);
+ void rtc_nmi_w(uint8_t data);
};
#endif // MAME_BUS_LPCI_SOUTHBRIDGE_H
diff --git a/src/devices/bus/m5/slot.cpp b/src/devices/bus/m5/slot.cpp
index 8dba25c70a5..1be35e6d997 100644
--- a/src/devices/bus/m5/slot.cpp
+++ b/src/devices/bus/m5/slot.cpp
@@ -48,7 +48,7 @@ void device_m5_cart_interface::rom_alloc(uint32_t size, const char *tag)
{
if (m_rom == nullptr)
{
- m_rom = device().machine().memory().region_alloc(std::string(tag).append(M5SLOT_ROM_REGION_TAG).c_str(), size, 1, ENDIANNESS_LITTLE)->base();
+ m_rom = device().machine().memory().region_alloc(std::string(tag).append(M5SLOT_ROM_REGION_TAG), size, 1, ENDIANNESS_LITTLE)->base();
m_rom_size = size;
}
}
@@ -145,7 +145,7 @@ static const char *m5_get_slot(int type)
call load
-------------------------------------------------*/
-image_init_result m5_cart_slot_device::call_load()
+std::pair<std::error_condition, std::string> m5_cart_slot_device::call_load()
{
if (m_cart)
{
@@ -165,10 +165,7 @@ image_init_result m5_cart_slot_device::call_load()
uint32_t size = !loaded_through_softlist() ? length() : get_software_region_length("rom");
if (size > 0x5000 && m_type == M5_STD)
- {
- seterror(image_error::INVALIDIMAGE, "Image extends beyond the expected size for an M5 cart");
- return image_init_result::FAIL;
- }
+ return std::make_pair(image_error::INVALIDLENGTH, "Image file exceeds the expected size for an M5 cart (20K)");
m_cart->rom_alloc(size, tag());
@@ -182,11 +179,10 @@ image_init_result m5_cart_slot_device::call_load()
if (get_software_region("ram"))
m_cart->ram_alloc(get_software_region_length("ram"));
-
//printf("Type: %s\n", m5_get_slot(m_type));
}
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
diff --git a/src/devices/bus/m5/slot.h b/src/devices/bus/m5/slot.h
index 4f0d578cf1b..afd727eed60 100644
--- a/src/devices/bus/m5/slot.h
+++ b/src/devices/bus/m5/slot.h
@@ -79,15 +79,15 @@ public:
m5_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
virtual ~m5_cart_slot_device();
- // image-level overrides
- virtual image_init_result call_load() override;
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
virtual void call_unload() override { }
virtual bool is_reset_on_load() const noexcept override { return true; }
virtual const char *image_interface() const noexcept override { return "m5_cart"; }
virtual const char *file_extensions() const noexcept override { return "bin,rom"; }
- // slot interface overrides
+ // device_slot_interface implementation
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
int get_type() { return m_type; }
@@ -100,11 +100,11 @@ public:
void write_ram(offs_t offset, uint8_t data);
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
int m_type;
- device_m5_cart_interface* m_cart;
+ device_m5_cart_interface *m_cart;
};
diff --git a/src/devices/bus/mackbd/keyboard.cpp b/src/devices/bus/mackbd/keyboard.cpp
index bda86980a05..9d34ad83ee4 100644
--- a/src/devices/bus/mackbd/keyboard.cpp
+++ b/src/devices/bus/mackbd/keyboard.cpp
@@ -212,7 +212,6 @@
#include "cpu/mcs48/mcs48.h"
-#define LOG_GENERAL (1U << 0)
#define LOG_WATCHDOG (1U << 1)
#define LOG_MATRIX (1U << 2)
#define LOG_COMM (1U << 3)
@@ -294,12 +293,12 @@ protected:
save_item(NAME(m_watchdog_in));
}
- virtual DECLARE_WRITE_LINE_MEMBER(data_w) override
+ virtual void data_w(int state) override
{
machine().scheduler().synchronize(timer_expired_delegate(FUNC(peripheral_base::update_host_data), this), state);
}
- DECLARE_WRITE_LINE_MEMBER(watchdog_w)
+ void watchdog_w(int state)
{
if (bool(state) != bool(m_watchdog_in))
{
@@ -322,7 +321,7 @@ protected:
required_device<i8021_device> m_mpu;
private:
- DECLARE_WRITE_LINE_MEMBER(host_clock_w)
+ void host_clock_w(int state)
{
if (bool(state) != bool(m_host_clock_out))
{
@@ -334,7 +333,7 @@ private:
}
}
- DECLARE_WRITE_LINE_MEMBER(host_data_w)
+ void host_data_w(int state)
{
if (bool(state) != bool(m_host_data_out))
{
@@ -455,7 +454,7 @@ protected:
required_device<mac_keyboard_port_device> m_keyboard_port;
private:
- DECLARE_WRITE_LINE_MEMBER(keyboard_data_out_w)
+ void keyboard_data_out_w(int state)
{
if (bool(state) != bool(m_keyboard_data_out))
{
@@ -464,12 +463,12 @@ private:
}
}
- DECLARE_WRITE_LINE_MEMBER(keyboard_clock_in_w)
+ void keyboard_clock_in_w(int state)
{
machine().scheduler().synchronize(timer_expired_delegate(FUNC(keypad_base::update_keyboard_clock), this), state);
}
- DECLARE_WRITE_LINE_MEMBER(keyboard_data_in_w)
+ void keyboard_data_in_w(int state)
{
machine().scheduler().synchronize(timer_expired_delegate(FUNC(keypad_base::update_keyboard_data), this), state);
}
@@ -591,7 +590,7 @@ INPUT_PORTS_START(keyboard_gb)
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V')
PORT_MODIFY("ROW3")
- PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR(0xa3) // £
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR(U'£')
PORT_MODIFY("ROW6")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('`') PORT_CHAR('~')
@@ -606,7 +605,7 @@ INPUT_PORTS_START(keyboard_gb)
PORT_MODIFY("ROW8")
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_RCONTROL) PORT_NAME("Enter")
- PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_TILDE) PORT_CHAR(0xa7) PORT_CHAR('#') // §
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_TILDE) PORT_CHAR(U'§') PORT_CHAR('#')
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ')
INPUT_PORTS_END
@@ -630,27 +629,27 @@ INPUT_PORTS_START(keyboard_fr)
PORT_MODIFY("ROW3")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('&') PORT_CHAR('1')
- PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR(0xe9) PORT_CHAR('2') // é
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR(U'é') PORT_CHAR('2')
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('"') PORT_CHAR('3')
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('\'') PORT_CHAR('4')
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR(0xa7) PORT_CHAR('6') // §
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR(U'§') PORT_CHAR('6')
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('(') PORT_CHAR('5')
PORT_MODIFY("ROW4")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('-') PORT_CHAR('_')
- PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR(0xe7) PORT_CHAR('9') // ç
- PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR(0xe8) PORT_CHAR('7') // è
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS) PORT_CHAR(')') PORT_CHAR(0xb0) // °
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR(U'ç') PORT_CHAR('9')
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR(U'è') PORT_CHAR('7')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS) PORT_CHAR(')') PORT_CHAR(U'°')
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('!') PORT_CHAR('8')
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR(0xe0) PORT_CHAR('0') // à
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR(U'à') PORT_CHAR('0')
PORT_MODIFY("ROW5")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR('$') PORT_CHAR('*')
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR(0x2c6) PORT_CHAR(0xa8) // ˆ ¨
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR(U'ˆ') PORT_CHAR(U'¨')
PORT_MODIFY("ROW6")
- PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('`') PORT_CHAR(0xa3) // £
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(0xf9) PORT_CHAR('%') // ù
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('`') PORT_CHAR(U'£')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(U'ù') PORT_CHAR('%')
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR('m') PORT_CHAR('M')
PORT_MODIFY("ROW7")
@@ -675,7 +674,7 @@ INPUT_PORTS_START(keyboard_it)
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('w') PORT_CHAR('W')
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X')
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C')
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR(0xf2) PORT_CHAR('!') // ò
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR(U'ò') PORT_CHAR('!')
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V')
PORT_MODIFY("ROW2")
@@ -686,22 +685,22 @@ INPUT_PORTS_START(keyboard_it)
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('"') PORT_CHAR('2')
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('\'') PORT_CHAR('3')
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('(') PORT_CHAR('4')
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR(0xe8) PORT_CHAR('6') // è
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR(0xe7) PORT_CHAR('5') // ç
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR(U'è') PORT_CHAR('6')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR(U'ç') PORT_CHAR('5')
PORT_MODIFY("ROW4")
- PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR(0xe0) PORT_CHAR('9') // à
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR(U'à') PORT_CHAR('9')
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR(')') PORT_CHAR('7')
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR(0xa3) PORT_CHAR('8') // £
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR(0xe9) PORT_CHAR('0') // é
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR(U'£') PORT_CHAR('8')
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR(U'é') PORT_CHAR('0')
PORT_MODIFY("ROW5")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR('$') PORT_CHAR('*')
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR(0xec) PORT_CHAR(0x2c6) // ì ˆ
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR(U'ì') PORT_CHAR(U'ˆ')
PORT_MODIFY("ROW6")
- PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR(0xa7) PORT_CHAR(0xb0) // § °
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(0xf9) PORT_CHAR('%') // ù
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR(U'§') PORT_CHAR(U'°')
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(U'ù') PORT_CHAR('%')
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR('m') PORT_CHAR('M')
PORT_MODIFY("ROW7")
diff --git a/src/devices/bus/mackbd/mackbd.cpp b/src/devices/bus/mackbd/mackbd.cpp
index 0e13787c9cf..3f12d89b8c6 100644
--- a/src/devices/bus/mackbd/mackbd.cpp
+++ b/src/devices/bus/mackbd/mackbd.cpp
@@ -112,18 +112,12 @@ mac_keyboard_port_device::~mac_keyboard_port_device()
{
}
-WRITE_LINE_MEMBER(mac_keyboard_port_device::data_w)
+void mac_keyboard_port_device::data_w(int state)
{
if (m_peripheral)
m_peripheral->data_w(state);
}
-void mac_keyboard_port_device::device_resolve_objects()
-{
- m_clock_cb.resolve_safe();
- m_data_cb.resolve_safe();
-}
-
void mac_keyboard_port_device::device_start()
{
m_peripheral = dynamic_cast<device_mac_keyboard_interface *>(get_card_device());
diff --git a/src/devices/bus/mackbd/mackbd.h b/src/devices/bus/mackbd/mackbd.h
index 29be2d6e4ea..bd1de2f0225 100644
--- a/src/devices/bus/mackbd/mackbd.h
+++ b/src/devices/bus/mackbd/mackbd.h
@@ -46,10 +46,9 @@ public:
auto clock_cb() { return m_clock_cb.bind(); }
auto data_cb() { return m_data_cb.bind(); }
- DECLARE_WRITE_LINE_MEMBER(data_w);
+ void data_w(int state);
protected:
- virtual void device_resolve_objects() override;
virtual void device_start() override;
private:
@@ -76,10 +75,10 @@ protected:
virtual void interface_validity_check(validity_checker &valid) const override;
- DECLARE_WRITE_LINE_MEMBER(write_clock) { if (m_host) m_host->m_clock_cb(state); }
- DECLARE_WRITE_LINE_MEMBER(write_data) { if (m_host) m_host->m_data_cb(state); }
+ void write_clock(int state) { if (m_host) m_host->m_clock_cb(state); }
+ void write_data(int state) { if (m_host) m_host->m_data_cb(state); }
- virtual DECLARE_WRITE_LINE_MEMBER(data_w) = 0;
+ virtual void data_w(int state) = 0;
private:
mac_keyboard_port_device *const m_host;
diff --git a/src/devices/bus/mackbd/pluskbd.cpp b/src/devices/bus/mackbd/pluskbd.cpp
index de744f9219b..c928b5faaca 100644
--- a/src/devices/bus/mackbd/pluskbd.cpp
+++ b/src/devices/bus/mackbd/pluskbd.cpp
@@ -74,7 +74,7 @@
The Japanese version has katakana labels on the key caps in addition
to the Latin labels, ¥ (Yen) replacing \ (backslash), and カナ
- (kana) replacing Caps Lock. It is still has the ANSI "typewriter
+ (kana) replacing Caps Lock. It still has the ANSI "typewriter
shift" arrangement for Latin characters and ASCII punctuation (it
doesn't use the JIS "bit shift" arrangement).
@@ -85,7 +85,6 @@
#include "cpu/mcs48/mcs48.h"
-#define LOG_GENERAL (1U << 0)
#define LOG_MATRIX (1U << 1)
#define LOG_COMM (1U << 2)
@@ -150,7 +149,7 @@ protected:
save_item(NAME(m_host_data_in));
}
- virtual DECLARE_WRITE_LINE_MEMBER(data_w) override
+ virtual void data_w(int state) override
{
machine().scheduler().synchronize(timer_expired_delegate(FUNC(keyboard_base::update_host_data), this), state);
}
@@ -332,11 +331,11 @@ INPUT_PORTS_START(keyboard_fr)
PORT_MODIFY("ROW0")
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('z') PORT_CHAR('Z')
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR(0xe9) PORT_CHAR('2') // é
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR(U'é') PORT_CHAR('2')
PORT_MODIFY("ROW1")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('<') PORT_CHAR('>')
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR(0x2c6) PORT_CHAR(0xa8) // ˆ ¨
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR(U'ˆ') PORT_CHAR(U'¨')
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('"') PORT_CHAR('3')
PORT_MODIFY("ROW2")
@@ -344,17 +343,17 @@ INPUT_PORTS_START(keyboard_fr)
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('\'') PORT_CHAR('4')
PORT_MODIFY("ROW3")
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(0xf9) PORT_CHAR('%') // ù
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(U'ù') PORT_CHAR('%')
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('(') PORT_CHAR('5')
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR(',') PORT_CHAR('?')
PORT_MODIFY("ROW4")
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR(0xa7) PORT_CHAR('6') // §
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR(U'§') PORT_CHAR('6')
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(';') PORT_CHAR('.')
PORT_MODIFY("ROW5")
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('-') PORT_CHAR('_')
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR(0xe8) PORT_CHAR('7') // è
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR(U'è') PORT_CHAR('7')
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR(':') PORT_CHAR('/')
PORT_MODIFY("ROW6")
@@ -364,14 +363,14 @@ INPUT_PORTS_START(keyboard_fr)
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('=') PORT_CHAR('+')
PORT_MODIFY("ROW7")
- PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR(0xe0) PORT_CHAR('0') // à
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR(U'à') PORT_CHAR('0')
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR('m') PORT_CHAR('M')
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR(0xe7) PORT_CHAR('9') // ç
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR(U'ç') PORT_CHAR('9')
PORT_MODIFY("ROW8")
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('w') PORT_CHAR('W')
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('q') PORT_CHAR('Q')
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_TILDE) PORT_CHAR('`') PORT_CHAR(0xa3) // £
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_TILDE) PORT_CHAR('`') PORT_CHAR(U'£')
PORT_MODIFY("ROW9")
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('a') PORT_CHAR('A')
@@ -389,7 +388,7 @@ INPUT_PORTS_START(keyboard_jp)
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V') PORT_NAME(u8"V \u30d2") // ヒ
PORT_MODIFY("ROW1")
- PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR(0xa5) PORT_CHAR('|') PORT_NAME(u8"¥ | \u30d8") // ヘ
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR(U'¥') PORT_CHAR('|') PORT_NAME(u8"¥ | \u30d8") // ヘ
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('[') PORT_CHAR('{') PORT_NAME(u8"[ { \u309b \u300d") // ゛ 」
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F') PORT_NAME(u8"F \u30cf") // ハ
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E') PORT_NAME(u8"E \u30a4 \u30a3") // イ ィ
diff --git a/src/devices/bus/macpds/macpds.cpp b/src/devices/bus/macpds/macpds.cpp
index 036cb51bf1f..4fa3eae6d6e 100644
--- a/src/devices/bus/macpds/macpds.cpp
+++ b/src/devices/bus/macpds/macpds.cpp
@@ -72,6 +72,12 @@ macpds_device::macpds_device(const machine_config &mconfig, device_type type, co
m_maincpu(*this, finder_base::DUMMY_TAG)
{
}
+
+macpds_device::~macpds_device()
+{
+}
+
+
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
@@ -88,9 +94,9 @@ void macpds_device::device_reset()
{
}
-void macpds_device::add_macpds_card(device_macpds_card_interface *card)
+void macpds_device::add_macpds_card(device_macpds_card_interface &card)
{
- m_device_list.append(*card);
+ m_device_list.emplace_back(card);
}
template<typename R, typename W> void macpds_device::install_device(offs_t start, offs_t end, R rhandler, W whandler, uint32_t mask)
@@ -132,9 +138,10 @@ void macpds_device::set_irq_line(int line, int state)
// device_macpds_card_interface - constructor
//-------------------------------------------------
-device_macpds_card_interface::device_macpds_card_interface(const machine_config &mconfig, device_t &device)
- : device_interface(device, "macpds"),
- m_macpds(nullptr), m_macpds_slot(nullptr), m_next(nullptr)
+device_macpds_card_interface::device_macpds_card_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "macpds"),
+ m_macpds(nullptr),
+ m_macpds_slot(nullptr)
{
}
@@ -149,7 +156,7 @@ device_macpds_card_interface::~device_macpds_card_interface()
void device_macpds_card_interface::set_macpds_device()
{
- m_macpds->add_macpds_card(this);
+ m_macpds->add_macpds_card(*this);
}
void device_macpds_card_interface::install_bank(offs_t start, offs_t end, uint8_t *data)
diff --git a/src/devices/bus/macpds/macpds.h b/src/devices/bus/macpds/macpds.h
index ad0ce6a2416..aeb860af7e7 100644
--- a/src/devices/bus/macpds/macpds.h
+++ b/src/devices/bus/macpds/macpds.h
@@ -13,6 +13,10 @@
#pragma once
+#include <functional>
+#include <utility>
+#include <vector>
+
//**************************************************************************
// TYPE DEFINITIONS
@@ -68,14 +72,14 @@ public:
}
macpds_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ ~macpds_device();
- ~macpds_device() { m_device_list.detach_all(); }
// inline configuration
template <typename T>
void set_cputag(T &&tag) { m_maincpu.set_tag(std::forward<T>(tag)); }
- void add_macpds_card(device_macpds_card_interface *card);
+ void add_macpds_card(device_macpds_card_interface &card);
template<typename R, typename W> void install_device(offs_t start, offs_t end, R rhandler, W whandler, uint32_t mask=0xffffffff);
void install_bank(offs_t start, offs_t end, uint8_t *data);
void set_irq_line(int line, int state);
@@ -90,7 +94,7 @@ protected:
// internal state
required_device<cpu_device> m_maincpu;
- simple_list<device_macpds_card_interface> m_device_list;
+ std::vector<std::reference_wrapper<device_macpds_card_interface> > m_device_list;
};
@@ -103,13 +107,10 @@ DECLARE_DEVICE_TYPE(MACPDS, macpds_device)
class device_macpds_card_interface : public device_interface
{
friend class macpds_device;
- template <class ElememtType> friend class simple_list;
public:
// construction/destruction
virtual ~device_macpds_card_interface();
- device_macpds_card_interface *next() const { return m_next; }
-
void set_macpds_device();
// helper functions for card devices
@@ -124,9 +125,6 @@ protected:
macpds_device *m_macpds;
macpds_slot_device *m_macpds_slot;
-
-private:
- device_macpds_card_interface *m_next;
};
#endif // MAME_BUS_MACPDS_MACPDS_H
diff --git a/src/devices/bus/mc10/mc10_cart.cpp b/src/devices/bus/mc10/mc10_cart.cpp
index 40047de0fb2..0100a8ae5ba 100644
--- a/src/devices/bus/mc10/mc10_cart.cpp
+++ b/src/devices/bus/mc10/mc10_cart.cpp
@@ -27,6 +27,10 @@
16 A3 33 GND
17 A5 34 GND
+ Alice 32 and Alice 90 have 2 more pins:
+ 35 IRQ (optional)
+ 36 SOUND
+
SEL is an input to the MC-10 that allows the cartridge to remove
the internal chips from the bus.
@@ -36,6 +40,7 @@
#include "mc10_cart.h"
#include "mcx128.h"
+#include "multiports_ext.h"
#include "pak.h"
#include "ram.h"
@@ -60,8 +65,8 @@ mc10cart_slot_device::mc10cart_slot_device(const machine_config &mconfig, const
device_single_card_slot_interface<device_mc10cart_interface>(mconfig, *this),
device_cartrom_image_interface(mconfig, *this),
m_nmi_callback(*this),
- m_cart(nullptr),
- m_memspace(*this, finder_base::DUMMY_TAG, -1)
+ m_memspace(*this, finder_base::DUMMY_TAG, -1),
+ m_cart(nullptr)
{
}
@@ -71,7 +76,6 @@ mc10cart_slot_device::mc10cart_slot_device(const machine_config &mconfig, const
void mc10cart_slot_device::device_start()
{
- m_nmi_callback.resolve_safe();
m_cart = get_card_device();
}
@@ -88,35 +92,30 @@ void mc10cart_slot_device::set_nmi_line(int state)
// call_load
//-------------------------------------------------
-image_init_result mc10cart_slot_device::call_load()
+std::pair<std::error_condition, std::string> mc10cart_slot_device::call_load()
{
if (!m_cart)
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
memory_region *romregion(loaded_through_softlist() ? memregion("rom") : nullptr);
if (loaded_through_softlist() && !romregion)
- {
- seterror(image_error::INVALIDIMAGE, "Software list item has no 'rom' data area");
- return image_init_result::FAIL;
- }
+ return std::make_pair(image_error::BADSOFTWARE, "Software list item has no 'rom' data area");
u32 const len(loaded_through_softlist() ? romregion->bytes() : length());
if (len > m_cart->max_rom_length())
{
- seterror(image_error::INVALIDIMAGE, "Unsupported cartridge size");
- return image_init_result::FAIL;
+ return std::make_pair(
+ image_error::INVALIDLENGTH,
+ util::string_format("Unsupported cartridge size (must be no more than %u bytes)", m_cart->max_rom_length()));
}
if (!loaded_through_softlist())
{
LOG("Allocating %u byte cartridge ROM region\n", len);
- romregion = machine().memory().region_alloc(subtag("rom").c_str(), len, 1, ENDIANNESS_BIG);
+ romregion = machine().memory().region_alloc(subtag("rom"), len, 1, ENDIANNESS_BIG);
u32 const cnt(fread(romregion->base(), len));
if (cnt != len)
- {
- seterror(image_error::UNSPECIFIED, "Error reading cartridge file");
- return image_init_result::FAIL;
- }
+ return std::make_pair(image_error::UNSPECIFIED, "Error reading cartridge file");
}
return m_cart->load();
@@ -189,9 +188,9 @@ int device_mc10cart_interface::max_rom_length() const
load
-------------------------------------------------*/
-image_init_result device_mc10cart_interface::load()
+std::pair<std::error_condition, std::string> device_mc10cart_interface::load()
{
- return image_init_result::FAIL;
+ return std::make_pair(image_error::UNSUPPORTED, std::string());
}
//-------------------------------------------------
@@ -204,6 +203,7 @@ void mc10_cart_add_basic_devices(device_slot_interface &device)
device.option_add("mcx128", MC10_PAK_MCX128);
device.option_add("pak", MC10_PAK);
device.option_add("ram", MC10_PAK_RAM);
+ device.option_add("multi", ALICE_MULTIPORTS_EXT);
}
//-------------------------------------------------
@@ -216,6 +216,7 @@ void alice_cart_add_basic_devices(device_slot_interface &device)
device.option_add("alice128", ALICE_PAK_MCX128);
device.option_add("pak", MC10_PAK);
device.option_add("ram", MC10_PAK_RAM);
+ device.option_add("multi", ALICE_MULTIPORTS_EXT);
}
//-------------------------------------------------
@@ -227,4 +228,5 @@ void alice32_cart_add_basic_devices(device_slot_interface &device)
// basic devices
device.option_add("pak", MC10_PAK);
device.option_add("ram", MC10_PAK_RAM);
+ device.option_add("multi", ALICE_MULTIPORTS_EXT);
}
diff --git a/src/devices/bus/mc10/mc10_cart.h b/src/devices/bus/mc10/mc10_cart.h
index 4a4fc02df7c..16e946e1e3e 100644
--- a/src/devices/bus/mc10/mc10_cart.h
+++ b/src/devices/bus/mc10/mc10_cart.h
@@ -28,7 +28,6 @@ class mc10cart_slot_device final : public device_t,
public device_cartrom_image_interface
{
public:
-
// construction/destruction
template <typename T>
mc10cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock, T &&opts, const char *dflt)
@@ -49,11 +48,8 @@ public:
// address map manipulations
address_space &memspace() const { return *m_memspace; }
- // device-level overrides
- virtual void device_start() override;
-
- // image-level overrides
- virtual image_init_result call_load() override;
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
virtual bool is_reset_on_load() const noexcept override { return true; }
virtual const char *image_interface() const noexcept override { return "mc10_cart"; }
@@ -63,16 +59,18 @@ public:
void set_nmi_line(int state);
devcb_write_line m_nmi_callback;
- // slot interface overrides
+ // device_slot_interface implementation
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
-private:
+protected:
+ // device_t implementation
+ virtual void device_start() override;
+ required_address_space m_memspace;
+
+private:
// cartridge
device_mc10cart_interface *m_cart;
-
-protected:
- required_address_space m_memspace;
};
// device type definition
@@ -85,7 +83,7 @@ public:
virtual ~device_mc10cart_interface();
virtual int max_rom_length() const;
- virtual image_init_result load();
+ virtual std::pair<std::error_condition, std::string> load();
protected:
void raise_cart_nmi() { m_owning_slot->set_nmi_line(ASSERT_LINE); }
diff --git a/src/devices/bus/mc10/mcx128.cpp b/src/devices/bus/mc10/mcx128.cpp
index d507ad612c5..79d8afb1f99 100644
--- a/src/devices/bus/mc10/mcx128.cpp
+++ b/src/devices/bus/mc10/mcx128.cpp
@@ -72,7 +72,7 @@ protected:
// construction/destruction
mc10_pak_mcx128_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
virtual void device_reset() override;
virtual void device_post_load() override;
diff --git a/src/devices/bus/mc10/multiports_ext.cpp b/src/devices/bus/mc10/multiports_ext.cpp
new file mode 100644
index 00000000000..90f3716ccee
--- /dev/null
+++ b/src/devices/bus/mc10/multiports_ext.cpp
@@ -0,0 +1,122 @@
+/***************************************************************************
+
+ multiports_ext.cpp
+
+ Emulation of the Alice Multiports Extension
+
+ Features:
+ The extension provides an extension doubler and two joystick ports.
+
+ The extension also provides (for the whole Alice family and MC-10):
+ - 16K of RAM expansion ($5000-$8FFF)
+ - 64K of ROM expansion in two possible configurations:
+ - 8K of ROM between $1000 and $2FFF, as 8 banks (Cartridge mode).
+ - 16K of ROM between $C000 and $FFFF, as 4 banks (ROM mode).
+
+ Only the RAM/ROM expansion is emulated here.
+
+ Banks are selected by writing to:
+ - $1000 to $1FFF in Cartridge mode (number of bank between 0 and 7)
+ - $C000 to $CFFF in ROM mode (number of bank between 0 and 3)
+
+***************************************************************************/
+
+#include "emu.h"
+#include "multiports_ext.h"
+
+
+namespace {
+
+//**************************************************************************
+// TYPE DECLARATIONS
+//**************************************************************************
+
+class mc10_multiports_ext_device : public device_t, public device_mc10cart_interface
+{
+public:
+ mc10_multiports_ext_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual int max_rom_length() const override;
+ virtual std::pair<std::error_condition, std::string> load() override;
+
+protected:
+ mc10_multiports_ext_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
+ // device_t implementation
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ void control_register_write(offs_t offset, u8 data);
+
+ void multiports_mem(address_map &map);
+ void update_bank();
+
+private:
+ memory_bank_creator m_bank;
+ uint8_t rom_bank_index;
+ memory_share_creator<u8> m_extention_ram;
+};
+
+//-------------------------------------------------
+// IMPLEMENTATION
+//-------------------------------------------------
+
+mc10_multiports_ext_device::mc10_multiports_ext_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : mc10_multiports_ext_device(mconfig, ALICE_MULTIPORTS_EXT, tag, owner, clock)
+{
+}
+
+mc10_multiports_ext_device::mc10_multiports_ext_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, type, tag, owner, clock)
+ , device_mc10cart_interface(mconfig, *this)
+ , m_bank(*this, "cart_bank")
+ , rom_bank_index(0)
+ , m_extention_ram(*this, "ext_ram", 1024 * 16, ENDIANNESS_BIG)
+{
+}
+
+int mc10_multiports_ext_device::max_rom_length() const
+{
+ return 1024 * 64;
+}
+
+void mc10_multiports_ext_device::multiports_mem(address_map &map)
+{
+ map(0x0000, 0x1fff).bankr("cart_bank").w(FUNC(mc10_multiports_ext_device::control_register_write));
+}
+
+//-------------------------------------------------
+
+void mc10_multiports_ext_device::device_start()
+{
+ owning_slot().memspace().install_device(0x1000, 0x2fff, *this, &mc10_multiports_ext_device::multiports_mem);
+ owning_slot().memspace().install_ram(0x5000, 0x8fff, &m_extention_ram[0]);
+}
+
+//-------------------------------------------------
+
+void mc10_multiports_ext_device::device_reset()
+{
+ m_bank->set_entry(0);
+}
+
+void mc10_multiports_ext_device::control_register_write(offs_t offset, u8 data)
+{
+ if (offset < 0x1000)
+ m_bank->set_entry(data & 0x07);
+}
+
+std::pair<std::error_condition, std::string> mc10_multiports_ext_device::load()
+{
+ memory_region *const romregion(memregion("^rom"));
+ if (romregion->bytes() < (0x2000 * 8))
+ return std::make_pair(image_error::INVALIDLENGTH, "Cartridge ROM must be at least 64KB");
+
+ m_bank->configure_entries(0, 8, romregion->base(), 0x2000);
+
+ return std::make_pair(std::error_condition(), std::string());
+}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(ALICE_MULTIPORTS_EXT, device_mc10cart_interface, mc10_multiports_ext_device, "mc10_multiports_ext", "Fred_72 and 6502man's Multiports Extension")
diff --git a/src/devices/bus/mc10/multiports_ext.h b/src/devices/bus/mc10/multiports_ext.h
new file mode 100644
index 00000000000..2c31b9020a4
--- /dev/null
+++ b/src/devices/bus/mc10/multiports_ext.h
@@ -0,0 +1,12 @@
+#ifndef MAME_BUS_MC10_MULTIPORTS_EXT_H
+#define MAME_BUS_MC10_MULTIPORTS_EXT_H
+
+#pragma once
+
+#include "mc10_cart.h"
+
+// device type definition
+DECLARE_DEVICE_TYPE(ALICE_MULTIPORTS_EXT, device_mc10cart_interface)
+
+#endif // MAME_BUS_MC10_MC10_MULTIPORTS_EXT_H
+
diff --git a/src/devices/bus/mc10/pak.cpp b/src/devices/bus/mc10/pak.cpp
index 8e27d58ab8b..e6de96a7995 100644
--- a/src/devices/bus/mc10/pak.cpp
+++ b/src/devices/bus/mc10/pak.cpp
@@ -53,17 +53,17 @@ void mc10_pak_device::device_start()
}
//-------------------------------------------------
-// load - install rom region
+// load - install ROM region
//-------------------------------------------------
-image_init_result mc10_pak_device::load()
+std::pair<std::error_condition, std::string> mc10_pak_device::load()
{
- // if the host has supplied a ROM space, install it
memory_region *const romregion(memregion("^rom"));
- if (romregion)
- owning_slot().memspace().install_rom(0x5000, 0x5000 + romregion->bytes(), romregion->base());
- else
- return image_init_result::FAIL;
+ if (!romregion)
+ return std::make_pair(image_error::BADSOFTWARE, "Software item lacks 'rom' data area");
+
+ // if the host has supplied a ROM space, install it
+ owning_slot().memspace().install_rom(0x5000, 0x5000 + romregion->bytes(), romregion->base());
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
diff --git a/src/devices/bus/mc10/pak.h b/src/devices/bus/mc10/pak.h
index 797cea2f691..805eae0a2a0 100644
--- a/src/devices/bus/mc10/pak.h
+++ b/src/devices/bus/mc10/pak.h
@@ -22,12 +22,12 @@ public:
mc10_pak_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
virtual int max_rom_length() const override;
- virtual image_init_result load() override;
+ virtual std::pair<std::error_condition, std::string> load() override;
protected:
mc10_pak_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
};
diff --git a/src/devices/bus/mc10/ram.cpp b/src/devices/bus/mc10/ram.cpp
index f6a6f488955..7f66e199d9a 100644
--- a/src/devices/bus/mc10/ram.cpp
+++ b/src/devices/bus/mc10/ram.cpp
@@ -34,7 +34,7 @@ namespace
mc10_pak_ram_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
private:
memory_share_creator<u8> m_share;
diff --git a/src/devices/bus/mc68000/cards.cpp b/src/devices/bus/mc68000/cards.cpp
new file mode 100644
index 00000000000..2cebfd660af
--- /dev/null
+++ b/src/devices/bus/mc68000/cards.cpp
@@ -0,0 +1,19 @@
+// license: BSD-3-Clause
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ mc-68000-Computer System Bus Cards
+
+***************************************************************************/
+
+#include "emu.h"
+#include "cards.h"
+
+#include "floppy.h"
+#include "ram.h"
+
+void mc68000_sysbus_cards(device_slot_interface &device)
+{
+ device.option_add("floppy", MC68000_FLOPPY);
+ device.option_add("ram", MC68000_RAM);
+}
diff --git a/src/devices/bus/mc68000/cards.h b/src/devices/bus/mc68000/cards.h
new file mode 100644
index 00000000000..68ecfb76741
--- /dev/null
+++ b/src/devices/bus/mc68000/cards.h
@@ -0,0 +1,16 @@
+// license: BSD-3-Clause
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ mc-68000-Computer System Bus Cards
+
+***************************************************************************/
+
+#ifndef MAME_BUS_MC68000_CARDS_H
+#define MAME_BUS_MC68000_CARDS_H
+
+#pragma once
+
+void mc68000_sysbus_cards(device_slot_interface &device);
+
+#endif // MAME_BUS_MC68000_CARDS_H
diff --git a/src/devices/bus/mc68000/floppy.cpp b/src/devices/bus/mc68000/floppy.cpp
new file mode 100644
index 00000000000..abc14640f17
--- /dev/null
+++ b/src/devices/bus/mc68000/floppy.cpp
@@ -0,0 +1,169 @@
+// license: BSD-3-Clause
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ mc-68000-Computer Floppy Interface Card
+
+ TODO:
+ - Jumpers can change the meaning of some lines
+
+ Notes:
+ - Has two bus interfaces and supports up to 8 drives
+ - Can either use the 1793 or 1797
+
+***************************************************************************/
+
+#include "emu.h"
+#include "floppy.h"
+
+#define VERBOSE 0
+
+DEFINE_DEVICE_TYPE(MC68000_FLOPPY, mc68000_floppy_device, "mc68000_floppy", "mc-68000 Floppy Interface")
+
+mc68000_floppy_device::mc68000_floppy_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, MC68000_FLOPPY, tag, owner, clock),
+ device_mc68000_sysbus_card_interface(mconfig, *this),
+ m_fdc(*this, "fdc"),
+ m_floppy(*this, "fdc:%u", 0U),
+ m_latch(0x00)
+{
+}
+
+// very flexible regarding drive support, we just add the most common ones
+static void mc68000_bus1_floppies(device_slot_interface &device)
+{
+ device.option_add("35dd", FLOPPY_35_DD);
+ device.option_add("525qd", FLOPPY_525_QD);
+}
+
+static void mc68000_bus2_floppies(device_slot_interface &device)
+{
+ device.option_add("8dsdd", FLOPPY_8_DSDD);
+}
+
+void mc68000_floppy_device::device_add_mconfig(machine_config &config)
+{
+ FD1793(config, m_fdc, 16_MHz_XTAL / 8);
+ m_fdc->intrq_wr_callback().set(FUNC(mc68000_floppy_device::intrq_w));
+ m_fdc->drq_wr_callback().set(FUNC(mc68000_floppy_device::drq_w));
+
+ // floppy drive bus 1
+ FLOPPY_CONNECTOR(config, m_floppy[0], mc68000_bus1_floppies, "525qd", floppy_image_device::default_mfm_floppy_formats);
+ FLOPPY_CONNECTOR(config, m_floppy[1], mc68000_bus1_floppies, "525qd", floppy_image_device::default_mfm_floppy_formats);
+ FLOPPY_CONNECTOR(config, m_floppy[2], mc68000_bus1_floppies, nullptr, floppy_image_device::default_mfm_floppy_formats);
+ FLOPPY_CONNECTOR(config, m_floppy[3], mc68000_bus1_floppies, nullptr, floppy_image_device::default_mfm_floppy_formats);
+
+ // floppy drive bus 2
+ FLOPPY_CONNECTOR(config, m_floppy[4], mc68000_bus2_floppies, nullptr, floppy_image_device::default_mfm_floppy_formats);
+ FLOPPY_CONNECTOR(config, m_floppy[5], mc68000_bus2_floppies, nullptr, floppy_image_device::default_mfm_floppy_formats);
+ FLOPPY_CONNECTOR(config, m_floppy[6], mc68000_bus2_floppies, nullptr, floppy_image_device::default_mfm_floppy_formats);
+ FLOPPY_CONNECTOR(config, m_floppy[7], mc68000_bus2_floppies, nullptr, floppy_image_device::default_mfm_floppy_formats);
+}
+
+void mc68000_floppy_device::device_start()
+{
+ // register for save states
+ save_item(NAME(m_latch));
+}
+
+void mc68000_floppy_device::device_reset()
+{
+ m_latch = 0x00;
+}
+
+uint16_t mc68000_floppy_device::floppy_r(offs_t offset, uint16_t mem_mask)
+{
+ uint16_t data = 0xffff;
+
+ if (ACCESSING_BITS_8_15)
+ {
+ switch (offset & 0x07)
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ data &= (m_fdc->read(offset & 0x03) << 8) | 0xff;
+ break;
+
+ case 4:
+ // 7------- intrq from fdc
+ // -6------ drq from fdc
+ // --543210 write only
+
+ data &= (m_latch << 8) | 0xff;
+ }
+ }
+
+ return data & mem_mask;
+}
+
+void mc68000_floppy_device::floppy_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ if (VERBOSE)
+ logerror("floppy_w: %06x = %04x & %04x\n", offset, data, mem_mask);
+
+ if (ACCESSING_BITS_8_15)
+ {
+ data >>= 8;
+
+ switch (offset & 0x07)
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ m_fdc->write(offset & 0x03, data);
+ break;
+
+ case 4:
+ // 76------ read only
+ // --5----- side select
+ // ---4---- force ready
+ // ----3--- density select
+ // -----2-- bus select
+ // ------10 drive select
+
+ floppy_image_device *floppy = nullptr;
+
+ if (BIT(data, 2))
+ {
+ // bus 1, drives 0 to 3 at 1 MHz
+ floppy = m_floppy[0 + (data & 0x03)]->get_device();
+ m_fdc->set_clock_scale(0.5);
+ }
+ else
+ {
+ // bus 2, drives 4 to 7 at 2 MHz
+ floppy = m_floppy[4 + (data & 0x03)]->get_device();
+ m_fdc->set_clock_scale(1.0);
+ }
+
+ m_fdc->set_floppy(floppy);
+
+ if (floppy)
+ {
+ // TODO: motor should only run for a few seconds after each access (for bus 1)
+ floppy->mon_w(0);
+ floppy->ss_w(BIT(data, 5));
+ }
+
+ m_fdc->dden_w(BIT(data, 3));
+ m_fdc->set_force_ready(BIT(data, 4));
+ }
+ }
+}
+
+void mc68000_floppy_device::intrq_w(int state)
+{
+ m_latch &= ~(1 << 7);
+ m_latch |= state << 7;
+}
+
+void mc68000_floppy_device::drq_w(int state)
+{
+ m_latch &= ~(1 << 6);
+ m_latch |= state << 6;
+
+ m_bus->irq6_w(state);
+}
diff --git a/src/devices/bus/mc68000/floppy.h b/src/devices/bus/mc68000/floppy.h
new file mode 100644
index 00000000000..e516e83cde5
--- /dev/null
+++ b/src/devices/bus/mc68000/floppy.h
@@ -0,0 +1,48 @@
+// license: BSD-3-Clause
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ mc-68000-Computer Floppy Interface Card
+
+***************************************************************************/
+
+#ifndef MAME_BUS_MC68000_FLOPPY_H
+#define MAME_BUS_MC68000_FLOPPY_H
+
+#pragma once
+
+#include "sysbus.h"
+#include "machine/wd_fdc.h"
+#include "imagedev/floppy.h"
+
+
+class mc68000_floppy_device : public device_t, public device_mc68000_sysbus_card_interface
+{
+public:
+ // construction/destruction
+ mc68000_floppy_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual uint16_t floppy_r(offs_t offset, uint16_t mem_mask = ~0) override;
+ virtual void floppy_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) override;
+
+protected:
+ // device_t implementation
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+private:
+ required_device<fd1793_device> m_fdc;
+ required_device_array<floppy_connector, 8> m_floppy;
+
+ uint8_t m_latch;
+
+ void intrq_w(int state);
+ void drq_w(int state);
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(MC68000_FLOPPY, mc68000_floppy_device)
+
+
+#endif // MAME_BUS_MC68000_FLOPPY_H
diff --git a/src/devices/bus/mc68000/ram.cpp b/src/devices/bus/mc68000/ram.cpp
new file mode 100644
index 00000000000..2baa857b9a7
--- /dev/null
+++ b/src/devices/bus/mc68000/ram.cpp
@@ -0,0 +1,41 @@
+// license: BSD-3-Clause
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ mc-68000-Computer RAM Expansion Card
+
+***************************************************************************/
+
+#include "emu.h"
+#include "ram.h"
+
+DEFINE_DEVICE_TYPE(MC68000_RAM, mc68000_ram_device, "mc68000_ram", "mc-68000 2 MB RAM Expansion")
+
+mc68000_ram_device::mc68000_ram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, MC68000_RAM, tag, owner, clock),
+ device_mc68000_sysbus_card_interface(mconfig, *this)
+{
+}
+
+void mc68000_ram_device::device_start()
+{
+ // allocate ram
+ m_ram = std::make_unique<uint16_t[]>(0x200000 / 2);
+
+ // register for save states
+ save_pointer(NAME(m_ram), 0x200000 / 2);
+}
+
+void mc68000_ram_device::device_reset()
+{
+}
+
+uint16_t mc68000_ram_device::slot_r(offs_t offset, uint16_t mem_mask)
+{
+ return m_ram[offset & (0x1fffff >> 1)] & mem_mask;
+}
+
+void mc68000_ram_device::slot_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_ram[offset & (0x1fffff >> 1)]);
+}
diff --git a/src/devices/bus/mc68000/ram.h b/src/devices/bus/mc68000/ram.h
new file mode 100644
index 00000000000..da1bef87f67
--- /dev/null
+++ b/src/devices/bus/mc68000/ram.h
@@ -0,0 +1,39 @@
+// license: BSD-3-Clause
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ mc-68000-Computer RAM Expansion Card
+
+***************************************************************************/
+
+#ifndef MAME_BUS_MC68000_RAM_H
+#define MAME_BUS_MC68000_RAM_H
+
+#pragma once
+
+#include "sysbus.h"
+
+
+class mc68000_ram_device : public device_t, public device_mc68000_sysbus_card_interface
+{
+public:
+ // construction/destruction
+ mc68000_ram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual uint16_t slot_r(offs_t offset, uint16_t mem_mask = ~0) override;
+ virtual void slot_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) override;
+
+protected:
+ // device_t implementation
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+private:
+ std::unique_ptr<uint16_t[]> m_ram;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(MC68000_RAM, mc68000_ram_device)
+
+
+#endif // MAME_BUS_MC68000_RAM_H
diff --git a/src/devices/bus/mc68000/sysbus.cpp b/src/devices/bus/mc68000/sysbus.cpp
new file mode 100644
index 00000000000..f8818ce005d
--- /dev/null
+++ b/src/devices/bus/mc68000/sysbus.cpp
@@ -0,0 +1,169 @@
+// license: BSD-3-Clause
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ mc-68000-Computer System Bus
+
+***************************************************************************/
+
+#include "emu.h"
+#include "sysbus.h"
+
+
+//**************************************************************************
+// BUS DEVICE
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(MC68000_SYSBUS, mc68000_sysbus_device, "mc68000_sysbus", "mc-68000 System Bus")
+
+mc68000_sysbus_device::mc68000_sysbus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, MC68000_SYSBUS, tag, owner, clock),
+ m_irq1_cb(*this),
+ m_irq2_cb(*this),
+ m_irq3_cb(*this),
+ m_irq4_cb(*this),
+ m_irq5_cb(*this),
+ m_irq6_cb(*this),
+ m_irq7_cb(*this)
+{
+}
+
+mc68000_sysbus_device::~mc68000_sysbus_device()
+{
+}
+
+void mc68000_sysbus_device::add_card(int slot, device_mc68000_sysbus_card_interface *card)
+{
+ m_device_list[slot] = card;
+}
+
+void mc68000_sysbus_device::device_start()
+{
+
+ // clear slots
+ std::fill(std::begin(m_device_list), std::end(m_device_list), nullptr);
+}
+
+// callbacks from slot device to the host
+void mc68000_sysbus_device::irq1_w(int state) { m_irq1_cb(state); }
+void mc68000_sysbus_device::irq2_w(int state) { m_irq2_cb(state); }
+void mc68000_sysbus_device::irq3_w(int state) { m_irq3_cb(state); }
+void mc68000_sysbus_device::irq4_w(int state) { m_irq4_cb(state); }
+void mc68000_sysbus_device::irq5_w(int state) { m_irq5_cb(state); }
+void mc68000_sysbus_device::irq6_w(int state) { m_irq6_cb(state); }
+void mc68000_sysbus_device::irq7_w(int state) { m_irq7_cb(state); }
+
+uint16_t mc68000_sysbus_device::slot_r(int slot, offs_t offset, uint16_t mem_mask)
+{
+ if (m_device_list[slot])
+ return m_device_list[slot]->slot_r(offset, mem_mask);
+ else
+ {
+ logerror("Read from unused slot %d: %06x = ffff & %04x\n", slot, offset, mem_mask);
+ return 0xffff;
+ }
+}
+
+void mc68000_sysbus_device::slot_w(int slot, offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ if (m_device_list[slot])
+ m_device_list[slot]->slot_w(offset, data, mem_mask);
+ else
+ logerror("Write to unused slot %d: %06x = %04x & %04x\n", slot, offset, data, mem_mask);
+}
+
+uint16_t mc68000_sysbus_device::floppy_r(offs_t offset, uint16_t mem_mask)
+{
+ uint16_t data = 0xffff;
+
+ for (int i = 0; i < 8; i++)
+ if (m_device_list[i])
+ data &= m_device_list[i]->floppy_r(offset, mem_mask);
+
+ return data;
+}
+
+void mc68000_sysbus_device::floppy_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ for (int i = 0; i < 8; i++)
+ if (m_device_list[i])
+ m_device_list[i]->floppy_w(offset, data, mem_mask);
+}
+
+
+//**************************************************************************
+// SLOT DEVICE
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(MC68000_SYSBUS_SLOT, mc68000_sysbus_slot_device, "mc68000_sysbus_slot", "mc-68000 System Bus Slot")
+
+mc68000_sysbus_slot_device::mc68000_sysbus_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ mc68000_sysbus_slot_device(mconfig, MC68000_SYSBUS_SLOT, tag, owner, clock)
+{
+}
+
+mc68000_sysbus_slot_device::mc68000_sysbus_slot_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, type, tag, owner, clock),
+ device_single_card_slot_interface<device_mc68000_sysbus_card_interface>(mconfig, *this)
+{
+}
+
+void mc68000_sysbus_slot_device::device_resolve_objects()
+{
+ device_mc68000_sysbus_card_interface *const card = get_card_device();
+
+ if (card)
+ {
+ mc68000_sysbus_device *bus = downcast<mc68000_sysbus_device *>(m_owner);
+ card->set_bus(bus, tag());
+ }
+}
+
+void mc68000_sysbus_slot_device::device_start()
+{
+}
+
+
+//**************************************************************************
+// CARD INTERFACE
+//**************************************************************************
+
+device_mc68000_sysbus_card_interface::device_mc68000_sysbus_card_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "mc68000sysbus"),
+ m_bus(nullptr),
+ m_next(nullptr),
+ m_slot_tag(nullptr),
+ m_slot(-1)
+{
+}
+
+device_mc68000_sysbus_card_interface::~device_mc68000_sysbus_card_interface()
+{
+}
+
+void device_mc68000_sysbus_card_interface::set_bus(mc68000_sysbus_device *bus, const char *slot_tag)
+{
+ m_slot_tag = slot_tag;
+ m_bus = bus;
+}
+
+void device_mc68000_sysbus_card_interface::interface_pre_start()
+{
+ if (!m_bus)
+ fatalerror("mc-68000 System Bus device undefined\n");
+
+ if (m_slot < 0)
+ {
+ if (!m_bus->started())
+ throw device_missing_dependencies();
+
+ // extract the slot number from the last digit of the slot tag
+ size_t const len = strlen(m_slot_tag);
+
+ m_slot = (m_slot_tag[len - 1] - '0');
+ if (m_slot < 0 || m_slot > 7)
+ fatalerror("Slot %x out of range for mc-68000 System Bus\n", m_slot);
+
+ m_bus->add_card(m_slot, this);
+ }
+}
diff --git a/src/devices/bus/mc68000/sysbus.h b/src/devices/bus/mc68000/sysbus.h
new file mode 100644
index 00000000000..2d9af7d87f8
--- /dev/null
+++ b/src/devices/bus/mc68000/sysbus.h
@@ -0,0 +1,180 @@
+// license: BSD-3-Clause
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ mc-68000-Computer System Bus
+
+ 96-pin slot
+
+ 32 +5V +5V +5V
+ 31 +12V +5V -12V
+ 30 BA8 _IRQ1 BA1
+ 29 BA9 _IRQ2 BA2
+ 28 BA10 _IRQ3 BA3
+ 27 BA11 _IRQ4 BA4
+ 26 BA12 _IRQ5 BA5
+ 25 BA13 _IRQ6 BA6
+ 24 BA14 _IRQ7 BA7
+ 23 BA15 GND _EXP
+ 22 BA16 _FLOPPY FC2
+ 21 BA17 NC FC1
+ 20 BA18 GND FC0
+ 19 BA19 +12V GND
+ 18 BA20 +12V _BAS
+ 17 BA21 GND GND
+ 16 BA22 NC _DTACK
+ 15 BA23 NC GND
+ 14 GND LPSTB BR/_W
+ 13 NC _VPA _BLDS
+ 12 _RESET _BR _BUDS
+ 11 _BERR _EXT GND
+ 10 HALT NC 16 MHZ
+ 9 GND _POR GND
+ 8 BD15 NC BD7
+ 7 BD14 B_R/W BD6
+ 6 BD13 _BVMA BD5
+ 5 BD12 BE BD4
+ 4 BD11 _BG BD3
+ 3 BD10 NC BD2
+ 2 BD9 _BGACK BD1
+ 1 BD8 _SSEL BD0
+
+***************************************************************************/
+
+#ifndef MAME_BUS_MC68000_SYSBUS_H
+#define MAME_BUS_MC68000_SYSBUS_H
+
+#pragma once
+
+
+// forward declaration
+class device_mc68000_sysbus_card_interface;
+
+
+//**************************************************************************
+// BUS DEVICE
+//**************************************************************************
+
+class mc68000_sysbus_device : public device_t
+{
+public:
+ // construction/destruction
+ mc68000_sysbus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ virtual ~mc68000_sysbus_device();
+
+ void add_card(int slot, device_mc68000_sysbus_card_interface *card);
+
+ auto irq1_cb() { return m_irq1_cb.bind(); }
+ auto irq2_cb() { return m_irq2_cb.bind(); }
+ auto irq3_cb() { return m_irq3_cb.bind(); }
+ auto irq4_cb() { return m_irq4_cb.bind(); }
+ auto irq5_cb() { return m_irq5_cb.bind(); }
+ auto irq6_cb() { return m_irq6_cb.bind(); }
+ auto irq7_cb() { return m_irq7_cb.bind(); }
+
+ // from cards
+ void irq1_w(int state);
+ void irq2_w(int state);
+ void irq3_w(int state);
+ void irq4_w(int state);
+ void irq5_w(int state);
+ void irq6_w(int state);
+ void irq7_w(int state);
+
+ // called from host
+ uint16_t slot_r(int slot, offs_t offset, uint16_t mem_mask = ~0);
+ void slot_w(int slot, offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+
+ uint16_t floppy_r(offs_t offset, uint16_t mem_mask = ~0);
+ void floppy_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+
+protected:
+ // device_t implementation
+ virtual void device_start() override;
+
+private:
+ device_mc68000_sysbus_card_interface *m_device_list[8];
+
+ devcb_write_line m_irq1_cb;
+ devcb_write_line m_irq2_cb;
+ devcb_write_line m_irq3_cb;
+ devcb_write_line m_irq4_cb;
+ devcb_write_line m_irq5_cb;
+ devcb_write_line m_irq6_cb;
+ devcb_write_line m_irq7_cb;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(MC68000_SYSBUS, mc68000_sysbus_device)
+
+
+//**************************************************************************
+// SLOT DEVICE
+//**************************************************************************
+
+class mc68000_sysbus_slot_device : public device_t, public device_single_card_slot_interface<device_mc68000_sysbus_card_interface>
+{
+public:
+ // construction/destruction
+ template <typename T>
+ mc68000_sysbus_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts, char const *dflt)
+ : mc68000_sysbus_slot_device(mconfig, tag, owner, (uint32_t)0)
+ {
+ option_reset();
+ opts(*this);
+ set_default_option(dflt);
+ set_fixed(false);
+ }
+ mc68000_sysbus_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ mc68000_sysbus_slot_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ // device_t implementation
+ virtual void device_resolve_objects() override;
+ virtual void device_start() override;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(MC68000_SYSBUS_SLOT, mc68000_sysbus_slot_device)
+
+
+//**************************************************************************
+// CARD INTERFACE
+//**************************************************************************
+
+class device_mc68000_sysbus_card_interface : public device_interface
+{
+public:
+ // construction/destruction
+ virtual ~device_mc68000_sysbus_card_interface();
+
+ void set_bus(mc68000_sysbus_device *bus, const char *slot_tag);
+
+ device_mc68000_sysbus_card_interface *next() const { return m_next; }
+
+ virtual uint16_t slot_r(offs_t offset, uint16_t mem_mask = ~0) { return 0xffff; }
+ virtual void slot_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) { }
+
+ virtual uint16_t floppy_r(offs_t offset, uint16_t mem_mask = ~0) { return 0xffff; }
+ virtual void floppy_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) { }
+
+protected:
+ device_mc68000_sysbus_card_interface(const machine_config &mconfig, device_t &device);
+
+ virtual void interface_pre_start() override;
+
+ mc68000_sysbus_device *m_bus;
+
+ device_mc68000_sysbus_card_interface *m_next;
+
+ const char *m_slot_tag;
+ int m_slot;
+};
+
+
+// include here so drivers don't need to
+#include "cards.h"
+
+
+#endif // MAME_BUS_MC68000_SYSBUS_H
diff --git a/src/devices/bus/megadrive/jcart.cpp b/src/devices/bus/megadrive/jcart.cpp
index d41116d762e..d8cad677e52 100644
--- a/src/devices/bus/megadrive/jcart.cpp
+++ b/src/devices/bus/megadrive/jcart.cpp
@@ -25,6 +25,8 @@
#include "emu.h"
#include "jcart.h"
+#include "bus/sms_ctrl/controllers.h"
+
//-------------------------------------------------
// md_rom_device - constructor
@@ -38,8 +40,7 @@ DEFINE_DEVICE_TYPE(MD_SEPROM_MM96, md_seprom_mm96_device, "md_seprom_mm9
md_jcart_device::md_jcart_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, type, tag, owner, clock)
, device_md_cart_interface(mconfig, *this)
- , m_jcart3(*this, "JCART3")
- , m_jcart4(*this, "JCART4")
+ , m_ctrl_ports(*this, "control%u", 3U)
{
}
@@ -76,59 +77,52 @@ md_seprom_mm96_device::md_seprom_mm96_device(const machine_config &mconfig, cons
// device_add_mconfig - add device configuration
//-------------------------------------------------
+void md_jcart_device::device_add_mconfig(machine_config &config)
+{
+ SMS_CONTROL_PORT(config, m_ctrl_ports[0], sms_control_port_devices, SMS_CTRL_OPTION_MD_PAD);
+ m_ctrl_ports[0]->th_handler().set(FUNC(md_jcart_device::th_in<0>));
+
+ SMS_CONTROL_PORT(config, m_ctrl_ports[1], sms_control_port_devices, SMS_CTRL_OPTION_MD_PAD);
+ m_ctrl_ports[1]->th_handler().set(FUNC(md_jcart_device::th_in<1>));
+}
+
void md_seprom_codemast_device::device_add_mconfig(machine_config &config)
{
+ md_jcart_device::device_add_mconfig(config);
+
I2C_24C08(config, m_i2cmem);
}
void md_seprom_mm96_device::device_add_mconfig(machine_config &config)
{
+ md_jcart_device::device_add_mconfig(config);
+
I2C_24C16(config, m_i2cmem); // 24C16A
}
-static INPUT_PORTS_START( jcart_ipt )
-
- PORT_START("JCART3") /* Joypad 3 on J-Cart (3 button + start) */
- PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(1) PORT_NAME("%p Up")
- PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(1) PORT_NAME("%p Down")
- PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(1) PORT_NAME("%p Left")
- PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(1) PORT_NAME("%p Right")
- PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1) PORT_NAME("%p B")
- PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(1) PORT_NAME("%p C")
- PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) PORT_NAME("%p A")
- PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_START ) PORT_PLAYER(1) PORT_NAME("%p Start")
-
- PORT_START("JCART4") /* Joypad 4 on J-Cart (3 button + start) */
- PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(2) PORT_NAME("%p Up")
- PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(2) PORT_NAME("%p Down")
- PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(2) PORT_NAME("%p Left")
- PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(2) PORT_NAME("%p Right")
- PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2) PORT_NAME("%p B")
- PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(2) PORT_NAME("%p C")
- PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) PORT_NAME("%p A")
- PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_START ) PORT_PLAYER(2) PORT_NAME("%p Start")
-INPUT_PORTS_END
-
-ioport_constructor md_jcart_device::device_input_ports() const
+void md_jcart_device::device_resolve_objects()
{
- return INPUT_PORTS_NAME( jcart_ipt );
+ m_th_in[0] = m_th_in[1] = 0x40;
+ m_th_out = 0x40;
}
void md_jcart_device::device_start()
{
- save_item(NAME(m_jcart_io_data));
+ save_item(NAME(m_th_in));
+ save_item(NAME(m_th_out));
}
void md_jcart_device::device_reset()
{
- m_jcart_io_data[0] = 0;
- m_jcart_io_data[1] = 0;
+ // TODO: does this cause the TH outputs to reset to high?
}
void md_seprom_codemast_device::device_start()
{
+ md_jcart_device::device_start();
+
save_item(NAME(m_i2c_mem));
save_item(NAME(m_i2c_clk));
save_item(NAME(m_jcart_io_data));
@@ -136,6 +130,8 @@ void md_seprom_codemast_device::device_start()
void md_seprom_codemast_device::device_reset()
{
+ md_jcart_device::device_reset();
+
m_i2c_mem = 0;
m_i2c_clk = 0;
m_jcart_io_data[0] = 0;
@@ -155,20 +151,9 @@ uint16_t md_jcart_device::read(offs_t offset)
{
if (offset == 0x38fffe/2)
{
- uint8_t joy[2];
-
- if (m_jcart_io_data[0] & 0x40)
- {
- joy[0] = m_jcart3->read();
- joy[1] = m_jcart4->read();
- return (m_jcart_io_data[0] & 0x40) | joy[0] | (joy[1] << 8);
- }
- else
- {
- joy[0] = ((m_jcart3->read() & 0xc0) >> 2) | (m_jcart3->read() & 0x03);
- joy[1] = ((m_jcart4->read() & 0xc0) >> 2) | (m_jcart4->read() & 0x03);
- return (m_jcart_io_data[0] & 0x40) | joy[0] | (joy[1] << 8);
- }
+ uint16_t const ctrl3 = (m_ctrl_ports[0]->in_r() & 0x3f) | (m_th_in[0] & m_th_out) | 0x80;
+ uint16_t const ctrl4 = (m_ctrl_ports[1]->in_r() & 0x3f) | (m_th_in[1] & m_th_out) | 0x80;
+ return ctrl3 | (ctrl4 << 8);
}
if (offset < 0x400000/2)
return m_rom[MD_ADDR(offset)];
@@ -180,11 +165,20 @@ void md_jcart_device::write(offs_t offset, uint16_t data, uint16_t mem_mask)
{
if (offset == 0x38fffe/2)
{
- m_jcart_io_data[0] = (data & 1) << 6;
- m_jcart_io_data[1] = (data & 1) << 6;
+ // assume TH only actively driven low
+ m_th_out = BIT(data, 0) << 6;
+ m_ctrl_ports[0]->out_w(m_th_out | 0x3f, ~m_th_out & 0x40);
+ m_ctrl_ports[1]->out_w(m_th_out | 0x3f, ~m_th_out & 0x40);
}
}
+template <unsigned N>
+void md_jcart_device::th_in(int state)
+{
+ m_th_in[N] = state ? 0x40 : 0x00;
+}
+
+
/*-------------------------------------------------
J-CART + SEPROM
-------------------------------------------------*/
@@ -196,27 +190,10 @@ uint16_t md_seprom_codemast_device::read(offs_t offset)
m_i2c_mem = m_i2cmem->read_sda();
return (m_i2c_mem & 1) << 7;
}
- if (offset == 0x38fffe/2)
+ else
{
- uint8_t joy[2];
-
- if (m_jcart_io_data[0] & 0x40)
- {
- joy[0] = m_jcart3->read();
- joy[1] = m_jcart4->read();
- return (m_jcart_io_data[0] & 0x40) | joy[0] | (joy[1] << 8);
- }
- else
- {
- joy[0] = ((m_jcart3->read() & 0xc0) >> 2) | (m_jcart3->read() & 0x03);
- joy[1] = ((m_jcart4->read() & 0xc0) >> 2) | (m_jcart4->read() & 0x03);
- return (m_jcart_io_data[0] & 0x40) | joy[0] | (joy[1] << 8);
- }
+ return md_jcart_device::read(offset);
}
- if (offset < 0x400000/2)
- return m_rom[MD_ADDR(offset)];
- else
- return 0xffff;
}
void md_seprom_codemast_device::write(offs_t offset, uint16_t data, uint16_t mem_mask)
@@ -228,9 +205,8 @@ void md_seprom_codemast_device::write(offs_t offset, uint16_t data, uint16_t mem
m_i2cmem->write_scl(m_i2c_clk);
m_i2cmem->write_sda(m_i2c_mem);
}
- if (offset == 0x38fffe/2)
+ else
{
- m_jcart_io_data[0] = (data & 1) << 6;
- m_jcart_io_data[1] = (data & 1) << 6;
+ md_jcart_device::write(offset, data, mem_mask);
}
}
diff --git a/src/devices/bus/megadrive/jcart.h b/src/devices/bus/megadrive/jcart.h
index 473c6ec2ce3..25916f5f4a5 100644
--- a/src/devices/bus/megadrive/jcart.h
+++ b/src/devices/bus/megadrive/jcart.h
@@ -1,9 +1,11 @@
// license:BSD-3-Clause
// copyright-holders:Fabio Priuli
-#ifndef MAME_BUS_NEGADRIVE_JCART_H
-#define MAME_BUS_NEGADRIVE_JCART_H
+#ifndef MAME_BUS_MEGADRIVE_JCART_H
+#define MAME_BUS_MEGADRIVE_JCART_H
#include "md_slot.h"
+
+#include "bus/sms_ctrl/smsctrl.h"
#include "machine/i2cmem.h"
@@ -11,8 +13,6 @@
// TYPE DEFINITIONS
//**************************************************************************
-// ======================> md_jcart_device
-
class md_jcart_device : public device_t,
public device_md_cart_interface
{
@@ -20,9 +20,6 @@ public:
// construction/destruction
md_jcart_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- // device-level overrides
- virtual ioport_constructor device_input_ports() const override;
-
// reading and writing
virtual uint16_t read(offs_t offset) override;
virtual void write(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) override;
@@ -30,17 +27,19 @@ public:
protected:
md_jcart_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_resolve_objects() override;
virtual void device_start() override;
virtual void device_reset() override;
- required_ioport m_jcart3;
- required_ioport m_jcart4;
-
private:
- uint8_t m_jcart_io_data[2];
+ template <unsigned N> void th_in(int state);
+
+ required_device_array<sms_control_port_device, 2> m_ctrl_ports;
+ uint8_t m_th_in[2];
+ uint8_t m_th_out;
};
-// ======================> md_seprom_codemast_device
class md_seprom_codemast_device : public md_jcart_device
{
@@ -68,7 +67,6 @@ private:
uint8_t m_i2c_mem, m_i2c_clk;
};
-// ======================> md_seprom_mm96_device (same read/write as codemast, but different I2C type)
class md_seprom_mm96_device : public md_seprom_codemast_device
{
@@ -87,4 +85,4 @@ DECLARE_DEVICE_TYPE(MD_JCART, md_jcart_device)
DECLARE_DEVICE_TYPE(MD_SEPROM_CODEMAST, md_seprom_codemast_device)
DECLARE_DEVICE_TYPE(MD_SEPROM_MM96, md_seprom_mm96_device)
-#endif // MAME_BUS_NEGADRIVE_JCART_H
+#endif // MAME_BUS_MEGADRIVE_JCART_H
diff --git a/src/devices/bus/megadrive/md_slot.cpp b/src/devices/bus/megadrive/md_slot.cpp
index 769bdbdc173..a7b4d2a20ac 100644
--- a/src/devices/bus/megadrive/md_slot.cpp
+++ b/src/devices/bus/megadrive/md_slot.cpp
@@ -82,11 +82,11 @@ device_md_cart_interface::~device_md_cart_interface()
// rom_alloc - alloc the space for the cart
//-------------------------------------------------
-void device_md_cart_interface::rom_alloc(size_t size, const char *tag)
+void device_md_cart_interface::rom_alloc(size_t size)
{
if (m_rom == nullptr)
{
- m_rom = (uint16_t *)device().machine().memory().region_alloc(std::string(tag).append(MDSLOT_ROM_REGION_TAG).c_str(), size, 2, ENDIANNESS_BIG)->base();
+ m_rom = (uint16_t *)device().machine().memory().region_alloc(device().subtag("^cart:rom"), size, 2, ENDIANNESS_BIG)->base();
m_rom_size = size;
}
}
@@ -309,12 +309,12 @@ static const char *md_get_slot(int type)
-------------------------------------------------*/
-image_init_result base_md_cart_slot_device::call_load()
+std::pair<std::error_condition, std::string> base_md_cart_slot_device::call_load()
{
if (m_cart)
{
m_type = SEGA_STD;
- image_init_result res;
+ std::error_condition res;
// STEP 1: load the file image and keep a copy for later banking
// STEP 2: identify the cart type
@@ -326,7 +326,7 @@ image_init_result base_md_cart_slot_device::call_load()
//printf("cart type: %d\n", m_type);
- if (res == image_init_result::PASS)
+ if (!res)
{
//speed-up rom access from SVP add-on, if present
if (m_type == SEGA_SVP)
@@ -344,14 +344,14 @@ image_init_result base_md_cart_slot_device::call_load()
file_logging((uint8_t *)m_cart->get_rom_base(), m_cart->get_rom_size(), m_cart->get_nvram_size());
}
- return res;
+ return std::make_pair(res, std::string());
}
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
-image_init_result base_md_cart_slot_device::load_list()
+std::error_condition base_md_cart_slot_device::load_list()
{
uint16_t *ROM;
uint32_t length = get_software_region_length("rom");
@@ -360,7 +360,7 @@ image_init_result base_md_cart_slot_device::load_list()
// if cart size is not (2^n * 64K), the system will see anyway that size so we need to alloc a bit more space
length = m_cart->get_padded_size(length);
- m_cart->rom_alloc(length, tag());
+ m_cart->rom_alloc(length);
ROM = m_cart->get_rom_base();
memcpy((uint8_t *)ROM, get_software_region("rom"), get_software_region_length("rom"));
@@ -377,7 +377,7 @@ image_init_result base_md_cart_slot_device::load_list()
if (m_type != SSF2 && m_type != PSOLAR && m_type != CM_2IN1)
m_cart->rom_map_setup(length);
- return image_init_result::PASS;
+ return std::error_condition();
}
@@ -453,7 +453,7 @@ static int genesis_is_SMD(unsigned char *buf, unsigned int len)
* softlist
*************************************/
-image_init_result base_md_cart_slot_device::load_nonlist()
+std::error_condition base_md_cart_slot_device::load_nonlist()
{
unsigned char *ROM;
bool is_smd, is_md;
@@ -472,8 +472,8 @@ image_init_result base_md_cart_slot_device::load_nonlist()
// if cart size is not (2^n * 64K), the system will see anyway that size so we need to alloc a bit more space
len = m_cart->get_padded_size(tmplen - offset);
- // this contains an hack for SSF2: its current bankswitch code needs larger rom space to work
- m_cart->rom_alloc((len == 0x500000) ? 0x900000 : len, tag());
+ // this contains an hack for SSF2: its current bankswitch code needs larger ROM space to work
+ m_cart->rom_alloc((len == 0x500000) ? 0x900000 : len);
// STEP 3: copy the game data in the appropriate way
ROM = (unsigned char *)m_cart->get_rom_base();
@@ -533,7 +533,7 @@ image_init_result base_md_cart_slot_device::load_nonlist()
}
#endif
- return image_init_result::PASS;
+ return std::error_condition();
}
/*-------------------------------------------------
@@ -909,8 +909,7 @@ std::string base_md_cart_slot_device::get_default_card_software(get_default_card
hook.image_file()->length(len); // FIXME: check error return, guard against excessively large files
std::vector<uint8_t> rom(len);
- size_t actual;
- hook.image_file()->read(&rom[0], len, actual); // FIXME: check error return or read returning short
+ util::read(*hook.image_file(), &rom[0], len); // FIXME: check error return or read returning short
uint32_t const offset = genesis_is_SMD(&rom[0x200], len - 0x200) ? 0x200 : 0;
@@ -920,7 +919,9 @@ std::string base_md_cart_slot_device::get_default_card_software(get_default_card
return std::string(slot_string);
}
else
+ {
return software_get_default_slot("rom");
+ }
}
@@ -1080,10 +1081,10 @@ void base_md_cart_slot_device::file_logging(uint8_t *ROM8, uint32_t rom_len, uin
}
logerror("Checksum: %X\n", checksum);
logerror(" - Calculated Checksum: %X\n", csum);
- logerror("Supported I/O Devices: %.16s\n%s", io, ctrl.c_str());
+ logerror("Supported I/O Devices: %.16s\n%s", io, ctrl);
logerror("Modem: %.12s\n", modem);
logerror("Memo: %.40s\n", memo);
- logerror("Country: %.16s\n%s", country, reg.c_str());
+ logerror("Country: %.16s\n%s", country, reg);
logerror("ROM Start: 0x%.8X\n", rom_start);
logerror("ROM End: 0x%.8X\n", rom_end);
logerror("RAM Start: 0x%.8X\n", ram_start);
diff --git a/src/devices/bus/megadrive/md_slot.h b/src/devices/bus/megadrive/md_slot.h
index ca16a38ba92..020ebb0baed 100644
--- a/src/devices/bus/megadrive/md_slot.h
+++ b/src/devices/bus/megadrive/md_slot.h
@@ -27,7 +27,7 @@ enum
// Cart + NVRAM
SEGA_SRAM, SEGA_FRAM,
HARDBALL95, /* Hardball 95 uses different sram start address */
- XINQIG, /* Xin Qigai Wangzi uses different sram start address and has no valid header */
+ XINQIG, /* Xin Qigai Wangzi uses different sram start address and has no valid header */
BEGGARP, /* Beggar Prince uses different sram start address + bankswitch tricks */
WUKONG, /* Legend of Wukong uses different sram start address + bankswitch trick for last 128K of ROM */
STARODYS, /* Star Odyssey */
@@ -35,7 +35,7 @@ enum
// EEPROM
SEGA_EEPROM, /* Wonder Boy V / Evander Holyfield's Boxing / Greatest Heavyweights of the Ring / Sports Talk Baseball / Megaman */
NBA_JAM, /* NBA Jam */
- NBA_JAM_ALT, /* NBA Jam */
+ NBA_JAM_ALT, /* NBA Jam */
NBA_JAM_TE, /* NBA Jam TE / NFL Quarterback Club */
NFL_QB_96, /* NFL Quarterback Club '96 */
C_SLAM, /* College Slam / Frank Thomas Big Hurt Baseball */
@@ -111,7 +111,7 @@ public:
// this probably should do more, like make Genesis V2 'die' if the SEGA string is not written promptly
virtual void write_tmss_bank(offs_t offset, uint16_t data) { device().logerror("Write to TMSS bank: offset %x data %x\n", 0xa14000 + (offset << 1), data); }
- virtual void rom_alloc(size_t size, const char *tag);
+ virtual void rom_alloc(size_t size);
virtual void nvram_alloc(size_t size);
virtual uint16_t* get_rom_base() { return m_rom; }
virtual uint16_t* get_nvram_base() { return &m_nvram[0]; }
@@ -156,19 +156,19 @@ public:
// construction/destruction
virtual ~base_md_cart_slot_device();
- // image-level overrides
- virtual image_init_result call_load() override;
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
virtual void call_unload() override;
virtual bool is_reset_on_load() const noexcept override { return true; }
- // slot interface overrides
+ // device_slot_interface implementation
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
int get_type() { return m_type; }
- image_init_result load_list();
- image_init_result load_nonlist();
+ std::error_condition load_list();
+ std::error_condition load_nonlist();
static int get_cart_type(const uint8_t *ROM, uint32_t len);
void setup_custom_mappers();
@@ -188,7 +188,7 @@ public:
virtual int read_test() { if (m_cart) return m_cart->read_test(); else return 0; } // used by Virtua Racing test
-// TODO: this only needs to be public because megasvp copies rom into memory region, so we need to rework that code...
+// TODO: this only needs to be public because megasvp copies ROM into memory region, so we need to rework that code...
//private:
int m_type;
@@ -197,7 +197,7 @@ public:
protected:
base_md_cart_slot_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
};
@@ -218,6 +218,8 @@ public:
}
md_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ // device_image_interface implementation
virtual const char *image_interface() const noexcept override { return "megadriv_cart"; }
virtual const char *file_extensions() const noexcept override { return "smd,bin,md,gen"; }
};
@@ -238,6 +240,8 @@ public:
set_fixed(false);
}
pico_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ // device_image_interface implementation
virtual const char *image_interface() const noexcept override { return "pico_cart"; }
virtual const char *file_extensions() const noexcept override { return "bin,md"; }
};
@@ -258,6 +262,8 @@ public:
set_fixed(false);
}
copera_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ // device_image_interface implementation
virtual const char *image_interface() const noexcept override { return "copera_cart"; }
virtual const char *file_extensions() const noexcept override { return "bin,md"; }
};
@@ -268,11 +274,4 @@ DECLARE_DEVICE_TYPE(MD_CART_SLOT, md_cart_slot_device)
DECLARE_DEVICE_TYPE(PICO_CART_SLOT, pico_cart_slot_device)
DECLARE_DEVICE_TYPE(COPERA_CART_SLOT, copera_cart_slot_device)
-
-/***************************************************************************
- DEVICE CONFIGURATION MACROS
- ***************************************************************************/
-
-#define MDSLOT_ROM_REGION_TAG ":cart:rom"
-
#endif // MAME_BUS_MEGADRIVE_MD_SLOT_H
diff --git a/src/devices/bus/midi/midi.cpp b/src/devices/bus/midi/midi.cpp
index cff94bfe159..4fb56b1e24f 100644
--- a/src/devices/bus/midi/midi.cpp
+++ b/src/devices/bus/midi/midi.cpp
@@ -25,10 +25,9 @@ void midi_port_device::device_config_complete()
void midi_port_device::device_start()
{
- m_rxd_handler.resolve_safe();
}
-WRITE_LINE_MEMBER( midi_port_device::write_txd )
+void midi_port_device::write_txd(int state)
{
if(m_dev)
m_dev->input_txd(state);
diff --git a/src/devices/bus/midi/midi.h b/src/devices/bus/midi/midi.h
index cdd89a84b6d..3479271a11f 100644
--- a/src/devices/bus/midi/midi.h
+++ b/src/devices/bus/midi/midi.h
@@ -28,9 +28,9 @@ public:
// static configuration helpers
auto rxd_handler() { return m_rxd_handler.bind(); }
- DECLARE_WRITE_LINE_MEMBER( write_txd );
+ void write_txd(int state);
- DECLARE_READ_LINE_MEMBER( rx_r ) { return m_rxd; }
+ int rx_r() { return m_rxd; }
protected:
virtual void device_start() override;
@@ -53,8 +53,8 @@ class device_midi_port_interface : public device_interface
public:
virtual ~device_midi_port_interface();
- virtual DECLARE_WRITE_LINE_MEMBER( input_txd ) { }
- DECLARE_WRITE_LINE_MEMBER( output_rxd ) { m_port->m_rxd = state; m_port->m_rxd_handler(state); }
+ virtual void input_txd(int state) { }
+ void output_rxd(int state) { m_port->m_rxd = state; m_port->m_rxd_handler(state); }
protected:
device_midi_port_interface(const machine_config &mconfig, device_t &device);
diff --git a/src/devices/bus/midi/midiinport.h b/src/devices/bus/midi/midiinport.h
index 526af88bb2a..e373002f47f 100644
--- a/src/devices/bus/midi/midiinport.h
+++ b/src/devices/bus/midi/midiinport.h
@@ -28,7 +28,7 @@ protected:
virtual void device_reset() override { }
private:
- DECLARE_WRITE_LINE_MEMBER( read ) { output_rxd(state); }
+ void read(int state) { output_rxd(state); }
required_device<midiin_device> m_midiin;
};
diff --git a/src/devices/bus/midi/midioutport.h b/src/devices/bus/midi/midioutport.h
index 2cc33ae922f..c675ecc086f 100644
--- a/src/devices/bus/midi/midioutport.h
+++ b/src/devices/bus/midi/midioutport.h
@@ -22,7 +22,7 @@ class midiout_port_device : public device_t,
public:
midiout_port_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual DECLARE_WRITE_LINE_MEMBER( input_txd ) override { if (started()) m_midiout->tx(state); }
+ virtual void input_txd(int state) override { if (started()) m_midiout->tx(state); }
protected:
virtual void device_start() override { }
diff --git a/src/devices/bus/mononcol/carts.cpp b/src/devices/bus/mononcol/carts.cpp
new file mode 100644
index 00000000000..cb34373c98a
--- /dev/null
+++ b/src/devices/bus/mononcol/carts.cpp
@@ -0,0 +1,13 @@
+// license:BSD-3-Clause
+// copyright-holders:Fabio Priuli
+
+#include "emu.h"
+#include "carts.h"
+#include "rom.h"
+
+
+device_slot_interface &mononcol_plain_slot(device_slot_interface &device)
+{
+ device.option_add_internal("rom", MONONCOL_ROM_PLAIN);
+ return device;
+}
diff --git a/src/devices/bus/mononcol/carts.h b/src/devices/bus/mononcol/carts.h
new file mode 100644
index 00000000000..b1620c0d098
--- /dev/null
+++ b/src/devices/bus/mononcol/carts.h
@@ -0,0 +1,11 @@
+// license:BSD-3-Clause
+// copyright-holders:Fabio Priuli
+
+#ifndef MAME_BUS_MONONCOL_CARTS_H
+#define MAME_BUS_MONONCOL_CARTS_H
+
+#pragma once
+
+device_slot_interface &mononcol_plain_slot(device_slot_interface &device);
+
+#endif // MAME_BUS_MONONCOL_CARTS_H
diff --git a/src/devices/bus/mononcol/rom.cpp b/src/devices/bus/mononcol/rom.cpp
new file mode 100644
index 00000000000..d3e82f34d24
--- /dev/null
+++ b/src/devices/bus/mononcol/rom.cpp
@@ -0,0 +1,38 @@
+// license:BSD-3-Clause
+// copyright-holders:Fabio Priuli
+
+#include "emu.h"
+#include "rom.h"
+
+//-------------------------------------------------
+// device type definitions
+//-------------------------------------------------
+
+DEFINE_DEVICE_TYPE(MONONCOL_ROM_PLAIN, mononcol_rom_plain_device, "mononcol_rom_plain", "Monon Color ROM cartridge")
+
+
+//-------------------------------------------------
+// constructor
+//-------------------------------------------------
+
+mononcol_rom_plain_device::mononcol_rom_plain_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : mononcol_rom_plain_device(mconfig, MONONCOL_ROM_PLAIN, tag, owner, clock)
+{
+}
+
+mononcol_rom_plain_device::mononcol_rom_plain_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, type, tag, owner, clock)
+ , device_mononcol_cart_interface(mconfig, *this)
+ , m_spi(*this, "spi")
+{
+}
+
+
+void mononcol_rom_plain_device::device_add_mconfig(machine_config &config)
+{
+ GENERIC_SPI_FLASH(config, m_spi, 0);
+}
+
+void mononcol_rom_plain_device::device_start()
+{
+}
diff --git a/src/devices/bus/mononcol/rom.h b/src/devices/bus/mononcol/rom.h
new file mode 100644
index 00000000000..7184a8d8469
--- /dev/null
+++ b/src/devices/bus/mononcol/rom.h
@@ -0,0 +1,44 @@
+// license:BSD-3-Clause
+// copyright-holders:Fabio Priuli
+#ifndef MAME_BUS_MONONCOL_ROM_H
+#define MAME_BUS_MONONCOL_ROM_H
+
+#pragma once
+
+#include "slot.h"
+
+#include "machine/generic_spi_flash.h"
+
+
+// ======================> mononcol_rom_plain_device
+
+class mononcol_rom_plain_device : public device_t, public device_mononcol_cart_interface
+{
+public:
+ // construction/destruction
+ mononcol_rom_plain_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ uint8_t read() override { return m_spi->read(); }
+ void dir_w(int state) override { m_spi->dir_w(state); }
+ void write(uint8_t data) override { m_spi->write(data); }
+ void set_ready() override { m_spi->set_ready(); }
+
+ void set_spi_region(uint8_t *region, size_t size) override { m_spi->set_rom_ptr(region); m_spi->set_rom_size(size); }
+
+protected:
+ mononcol_rom_plain_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ // device_t implementation
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_start() override;
+
+private:
+ required_device<generic_spi_flash_device> m_spi;
+
+};
+
+
+// device type declarations
+DECLARE_DEVICE_TYPE(MONONCOL_ROM_PLAIN, mononcol_rom_plain_device)
+
+#endif // MAME_BUS_MONONCOL_ROM_H
diff --git a/src/devices/bus/mononcol/slot.cpp b/src/devices/bus/mononcol/slot.cpp
new file mode 100644
index 00000000000..4a8015b54fd
--- /dev/null
+++ b/src/devices/bus/mononcol/slot.cpp
@@ -0,0 +1,100 @@
+// license:BSD-3-Clause
+// copyright-holders:Fabio Priuli
+
+#include "emu.h"
+#include "slot.h"
+
+#define VERBOSE 0
+#include "logmacro.h"
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(MONONCOL_CARTSLOT, mononcol_cartslot_device, "mononcol_cartslot", "Monon Color Cartridge Slot")
+
+
+//**************************************************************************
+// device_mononcol_cart_interface
+//**************************************************************************
+
+device_mononcol_cart_interface::device_mononcol_cart_interface(machine_config const &mconfig, device_t &device) :
+ device_interface(device, "mononcart")
+{
+}
+
+device_mononcol_cart_interface::~device_mononcol_cart_interface()
+{
+}
+
+
+
+//**************************************************************************
+// mononcol_cartslot_device
+//**************************************************************************
+
+mononcol_cartslot_device::mononcol_cartslot_device(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock) :
+ device_t(mconfig, type, tag, owner, clock),
+ device_cartrom_image_interface(mconfig, *this),
+ device_single_card_slot_interface<device_mononcol_cart_interface>(mconfig, *this),
+ m_cart(nullptr)
+{
+}
+
+
+mononcol_cartslot_device::mononcol_cartslot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ mononcol_cartslot_device(mconfig, MONONCOL_CARTSLOT, tag, owner, clock)
+{
+}
+
+mononcol_cartslot_device::~mononcol_cartslot_device()
+{
+}
+
+void mononcol_cartslot_device::device_start()
+{
+ m_cart = get_card_device();
+}
+
+
+/*-------------------------------------------------
+ call load
+ -------------------------------------------------*/
+
+std::pair<std::error_condition, std::string> mononcol_cartslot_device::call_load()
+{
+ if (m_cart)
+ {
+ memory_region *romregion(loaded_through_softlist() ? memregion("rom") : nullptr);
+ if (loaded_through_softlist() && !romregion)
+ return std::make_pair(image_error::BADSOFTWARE, "Software list item has no 'rom' data area");
+
+ const u32 len = loaded_through_softlist() ? get_software_region_length("rom") : length();
+ if (!len || ((len - 1) & len))
+ return std::make_pair(image_error::INVALIDLENGTH, "Cartridge ROM size is not a power of 2");
+
+ if (!loaded_through_softlist())
+ {
+ LOG("Allocating %u byte cartridge ROM region\n", len);
+ romregion = machine().memory().region_alloc(subtag("rom"), len, 4, ENDIANNESS_LITTLE);
+ const u32 cnt = fread(romregion->base(), len);
+ if (cnt != len)
+ return std::make_pair(image_error::UNSPECIFIED, "Error reading cartridge file");
+ }
+
+ m_cart->set_spi_region(romregion->base(), romregion->bytes());
+ }
+ return std::make_pair(std::error_condition(), std::string());
+}
+
+
+
+/*-------------------------------------------------
+ get default card software
+ -------------------------------------------------*/
+
+std::string mononcol_cartslot_device::get_default_card_software(get_default_card_software_hook &hook) const
+{
+ return software_get_default_slot("rom");
+}
diff --git a/src/devices/bus/mononcol/slot.h b/src/devices/bus/mononcol/slot.h
new file mode 100644
index 00000000000..5032044a8ca
--- /dev/null
+++ b/src/devices/bus/mononcol/slot.h
@@ -0,0 +1,97 @@
+// license:BSD-3-Clause
+// copyright-holders:Fabio Priuli
+#ifndef MAME_BUS_MONONCOL_SLOT_H
+#define MAME_BUS_MONONCOL_SLOT_H
+
+#pragma once
+
+#include "imagedev/cartrom.h"
+
+#include <cassert>
+
+/***************************************************************************
+ TYPE DEFINITIONS
+ ***************************************************************************/
+
+class device_mononcol_cart_interface : public device_interface
+{
+public:
+
+ // construction/destruction
+ virtual ~device_mononcol_cart_interface();
+
+ // reading and writing
+ virtual uint8_t read() = 0;
+ virtual void dir_w(int state) = 0;
+ virtual void write(uint8_t data) = 0;
+ virtual void set_ready() = 0;
+
+ // configuration
+ virtual void set_spi_region(uint8_t *region, size_t size) = 0;
+
+protected:
+ device_mononcol_cart_interface(machine_config const &mconfig, device_t &device);
+};
+
+
+class mononcol_cartslot_device : public device_t,
+ public device_cartrom_image_interface,
+ public device_single_card_slot_interface<device_mononcol_cart_interface>
+{
+public:
+ template <typename T>
+ mononcol_cartslot_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts)
+ : mononcol_cartslot_device(mconfig, tag, owner, u32(0))
+ {
+ opts(*this);
+ set_fixed(false);
+ }
+
+ mononcol_cartslot_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock = 0);
+
+ virtual ~mononcol_cartslot_device();
+
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
+ virtual bool is_reset_on_load() const noexcept override { return true; }
+ virtual char const *image_interface() const noexcept override { return "monon_color_cart"; }
+ virtual char const *file_extensions() const noexcept override { return "bin"; }
+
+ // device_slot_interface implementation
+ virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
+
+ uint8_t read()
+ {
+ return m_cart->read();
+ }
+
+ void dir_w(int state)
+ {
+ m_cart->dir_w(state);
+ }
+
+ void set_ready()
+ {
+ m_cart->set_ready();
+ }
+
+ void write(uint8_t data)
+ {
+ m_cart->write(data);
+ }
+
+
+protected:
+ mononcol_cartslot_device(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock);
+
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
+
+ device_mononcol_cart_interface *m_cart;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(MONONCOL_CARTSLOT, mononcol_cartslot_device)
+
+#endif // MAME_BUS_MONONCOL_SLOT_H
diff --git a/src/devices/bus/msx/beecard/beecard.cpp b/src/devices/bus/msx/beecard/beecard.cpp
new file mode 100644
index 00000000000..1f20318e0d8
--- /dev/null
+++ b/src/devices/bus/msx/beecard/beecard.cpp
@@ -0,0 +1,58 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+
+#include "emu.h"
+#include "beecard.h"
+#include "bus/msx/cart/beepack.h"
+
+
+DECLARE_DEVICE_TYPE(BEE_CARD_NOMAPPER, bee_card_interface)
+
+
+void bee_card(device_slot_interface &device)
+{
+ device.option_add_internal("nomapper", BEE_CARD_NOMAPPER);
+}
+
+
+namespace {
+
+class bee_card_nomapper_device : public device_t
+ , public bee_card_interface
+{
+public:
+ bee_card_nomapper_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override { }
+
+ virtual std::error_condition initialize_cartridge(std::string &message) override;
+
+};
+
+
+bee_card_nomapper_device::bee_card_nomapper_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, BEE_CARD_NOMAPPER, tag, owner, clock)
+ , bee_card_interface(mconfig, *this)
+{
+}
+
+std::error_condition bee_card_nomapper_device::initialize_cartridge(std::string &message)
+{
+ if (!cart_rom_region())
+ {
+ message = "bee_card_nomapper_device: Required region 'rom' was not found.";
+ return image_error::INTERNAL;
+ }
+
+ page(1)->install_rom(0x4000, 0x7fff, cart_rom_region()->base());
+ if (cart_rom_region()->bytes() == 0x8000)
+ page(2)->install_rom(0x8000, 0xbfff, cart_rom_region()->base() + 0x4000);
+
+ return std::error_condition();
+}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(BEE_CARD_NOMAPPER, bee_card_interface, bee_card_nomapper_device, "bee_card_nomapper", "Bee Card ROM")
diff --git a/src/devices/bus/msx/beecard/beecard.h b/src/devices/bus/msx/beecard/beecard.h
new file mode 100644
index 00000000000..63bf77533aa
--- /dev/null
+++ b/src/devices/bus/msx/beecard/beecard.h
@@ -0,0 +1,12 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#ifndef MAME_BUS_MSX_BEECARD_BEECARD_H
+#define MAME_BUS_MSX_BEECARD_BEECARD_H
+
+#pragma once
+
+
+void bee_card(device_slot_interface &device);
+
+
+#endif // MAME_BUS_MSX_BEECARD_BEECARD_H
diff --git a/src/devices/bus/msx/cart/arc.cpp b/src/devices/bus/msx/cart/arc.cpp
new file mode 100644
index 00000000000..db1a3dd86c6
--- /dev/null
+++ b/src/devices/bus/msx/cart/arc.cpp
@@ -0,0 +1,78 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#include "emu.h"
+#include "arc.h"
+
+namespace {
+
+class msx_cart_arc_device : public device_t, public msx_cart_interface
+{
+public:
+ msx_cart_arc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MSX_CART_ARC, tag, owner, clock)
+ , msx_cart_interface(mconfig, *this)
+ , m_7f(0)
+ { }
+
+ virtual std::error_condition initialize_cartridge(std::string &message) override;
+
+protected:
+ // device_t implementation
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+private:
+ void io_7f_w(u8 data);
+ u8 io_7f_r();
+
+ u8 m_7f;
+};
+
+void msx_cart_arc_device::device_start()
+{
+ save_item(NAME(m_7f));
+
+ // Install IO read/write handlers
+ io_space().install_write_handler(0x7f, 0x7f, emu::rw_delegate(*this, FUNC(msx_cart_arc_device::io_7f_w)));
+ io_space().install_read_handler(0x7f, 0x7f, emu::rw_delegate(*this, FUNC(msx_cart_arc_device::io_7f_r)));
+}
+
+void msx_cart_arc_device::device_reset()
+{
+ m_7f = 0;
+}
+
+std::error_condition msx_cart_arc_device::initialize_cartridge(std::string &message)
+{
+ if (!cart_rom_region())
+ {
+ message = "msx_cart_arc_device: Required region 'rom' was not found.";
+ return image_error::INTERNAL;
+ }
+
+ if (cart_rom_region()->bytes() != 0x8000)
+ {
+ message = "msx_cart_arc_device: Region 'rom' has unsupported size.";
+ return image_error::INVALIDLENGTH;
+ }
+
+ page(1)->install_rom(0x4000, 0x7fff, cart_rom_region()->base());
+ page(2)->install_rom(0x8000, 0xbfff, cart_rom_region()->base() + 0x4000);
+
+ return std::error_condition();
+}
+
+void msx_cart_arc_device::io_7f_w(u8 data)
+{
+ if (data == 0x35)
+ m_7f++;
+}
+
+u8 msx_cart_arc_device::io_7f_r()
+{
+ return ((m_7f & 0x03) == 0x03) ? 0xda : 0xff;
+}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_ARC, msx_cart_interface, msx_cart_arc_device, "msx_cart_arc", "MSX Cartridge - Arc")
diff --git a/src/devices/bus/msx/cart/arc.h b/src/devices/bus/msx/cart/arc.h
new file mode 100644
index 00000000000..18cc4716cc8
--- /dev/null
+++ b/src/devices/bus/msx/cart/arc.h
@@ -0,0 +1,13 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#ifndef MAME_BUS_MSX_CART_ARC_H
+#define MAME_BUS_MSX_CART_ARC_H
+
+#pragma once
+
+#include "bus/msx/slot/cartridge.h"
+
+
+DECLARE_DEVICE_TYPE(MSX_CART_ARC, msx_cart_interface)
+
+#endif // MAME_BUS_MSX_CART_ARC_H
diff --git a/src/devices/bus/msx/cart/ascii.cpp b/src/devices/bus/msx/cart/ascii.cpp
new file mode 100644
index 00000000000..359b7f479e5
--- /dev/null
+++ b/src/devices/bus/msx/cart/ascii.cpp
@@ -0,0 +1,366 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#include "emu.h"
+#include "ascii.h"
+
+namespace {
+
+class msx_cart_ascii8_device : public device_t, public msx_cart_interface
+{
+public:
+ msx_cart_ascii8_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MSX_CART_ASCII8, tag, owner, clock)
+ , msx_cart_interface(mconfig, *this)
+ , m_rombank(*this, "rombank%u", 0U)
+ , m_bank_mask(0)
+ { }
+
+ virtual std::error_condition initialize_cartridge(std::string &message) override;
+
+protected:
+ // device_t implementation
+ virtual void device_start() override { }
+ virtual void device_reset() override;
+
+private:
+ static constexpr size_t BANK_SIZE = 0x2000;
+
+ template <int Bank> void bank_w(u8 data);
+
+ memory_bank_array_creator<4> m_rombank;
+ u8 m_bank_mask;
+};
+
+void msx_cart_ascii8_device::device_reset()
+{
+ for (int i = 0; i < 4; i++)
+ m_rombank[i]->set_entry(0);
+}
+
+std::error_condition msx_cart_ascii8_device::initialize_cartridge(std::string &message)
+{
+ if (!cart_rom_region())
+ {
+ message = "msx_cart_ascii8_device: Required region 'rom' was not found.";
+ return image_error::INTERNAL;
+ }
+
+ const u32 size = cart_rom_region()->bytes();
+ const u16 banks = size / BANK_SIZE;
+
+ if (size > 256 * BANK_SIZE || size != banks * BANK_SIZE || (~(banks - 1) % banks))
+ {
+ message = "msx_cart_ascii8_device: Region 'rom' has unsupported size.";
+ return image_error::INVALIDLENGTH;
+ }
+
+ m_bank_mask = banks - 1;
+
+ for (int i = 0; i < 4; i++)
+ m_rombank[i]->configure_entries(0, banks, cart_rom_region()->base(), BANK_SIZE);
+
+ page(1)->install_read_bank(0x4000, 0x5fff, m_rombank[0]);
+ page(1)->install_read_bank(0x6000, 0x7fff, m_rombank[1]);
+ page(1)->install_write_handler(0x6000, 0x67ff, emu::rw_delegate(*this, FUNC(msx_cart_ascii8_device::bank_w<0>)));
+ page(1)->install_write_handler(0x6800, 0x6fff, emu::rw_delegate(*this, FUNC(msx_cart_ascii8_device::bank_w<1>)));
+ page(1)->install_write_handler(0x7000, 0x77ff, emu::rw_delegate(*this, FUNC(msx_cart_ascii8_device::bank_w<2>)));
+ page(1)->install_write_handler(0x7800, 0x7fff, emu::rw_delegate(*this, FUNC(msx_cart_ascii8_device::bank_w<3>)));
+ page(2)->install_read_bank(0x8000, 0x9fff, m_rombank[2]);
+ page(2)->install_read_bank(0xa000, 0xbfff, m_rombank[3]);
+
+ return std::error_condition();
+}
+
+template <int Bank>
+void msx_cart_ascii8_device::bank_w(u8 data)
+{
+ m_rombank[Bank]->set_entry(data & m_bank_mask);
+}
+
+
+
+class msx_cart_ascii16_device : public device_t, public msx_cart_interface
+{
+public:
+ msx_cart_ascii16_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MSX_CART_ASCII16, tag, owner, clock)
+ , msx_cart_interface(mconfig, *this)
+ , m_rombank(*this, "rombank%u", 0U)
+ , m_bank_mask(0)
+ { }
+
+ virtual std::error_condition initialize_cartridge(std::string &message) override;
+
+protected:
+ // device_t implementation
+ virtual void device_start() override { }
+ virtual void device_reset() override;
+
+private:
+ static constexpr size_t BANK_SIZE = 0x4000;
+
+ template <int Bank> void bank_w(u8 data);
+
+ memory_bank_array_creator<2> m_rombank;
+ u8 m_bank_mask;
+};
+
+void msx_cart_ascii16_device::device_reset()
+{
+ m_rombank[0]->set_entry(0);
+ m_rombank[1]->set_entry(0);
+}
+
+std::error_condition msx_cart_ascii16_device::initialize_cartridge(std::string &message)
+{
+ if (!cart_rom_region())
+ {
+ message = "msx_cart_ascii16_device: Required region 'rom' was not found.";
+ return image_error::INTERNAL;
+ }
+
+ const u32 size = cart_rom_region()->bytes();
+ const u16 banks = size / BANK_SIZE;
+
+ if (size > 256 * BANK_SIZE || size != banks * BANK_SIZE || (~(banks - 1) % banks))
+ {
+ message = "msx_cart_ascii16_device: Region 'rom' has unsupported size.";
+ return image_error::INVALIDLENGTH;
+ }
+
+ m_bank_mask = banks - 1;
+
+ for (int i = 0; i < 2; i++)
+ m_rombank[i]->configure_entries(0, banks, cart_rom_region()->base(), BANK_SIZE);
+
+ page(1)->install_read_bank(0x4000, 0x7fff, m_rombank[0]);
+ page(1)->install_write_handler(0x6000, 0x67ff, emu::rw_delegate(*this, FUNC(msx_cart_ascii16_device::bank_w<0>)));
+ page(1)->install_write_handler(0x7000, 0x77ff, emu::rw_delegate(*this, FUNC(msx_cart_ascii16_device::bank_w<1>)));
+ page(2)->install_read_bank(0x8000, 0xbfff, m_rombank[1]);
+
+ return std::error_condition();
+}
+
+template <int Bank>
+void msx_cart_ascii16_device::bank_w(u8 data)
+{
+ m_rombank[Bank]->set_entry(data & m_bank_mask);
+}
+
+
+
+
+
+class msx_cart_ascii8_sram_device : public device_t, public msx_cart_interface
+{
+public:
+ msx_cart_ascii8_sram_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MSX_CART_ASCII8_SRAM, tag, owner, clock)
+ , msx_cart_interface(mconfig, *this)
+ , m_rombank(*this, "rombank%u", 0U)
+ , m_view{ {*this, "view2"}, {*this, "view3"} }
+ , m_bank_mask(0)
+ , m_sram_select_mask(0)
+ { }
+
+ virtual std::error_condition initialize_cartridge(std::string &message) override;
+
+protected:
+ // device_t implementation
+ virtual void device_start() override { }
+ virtual void device_reset() override;
+
+private:
+ static constexpr size_t BANK_SIZE = 0x2000;
+
+ void mapper_write(offs_t offset, u8 data);
+
+ memory_bank_array_creator<4> m_rombank;
+ memory_view m_view[2];
+ u8 m_bank_mask;
+ u8 m_sram_select_mask;
+};
+
+void msx_cart_ascii8_sram_device::device_reset()
+{
+ for (int i = 0; i < 4; i++)
+ m_rombank[i]->set_entry(0);
+ m_view[0].select(0);
+ m_view[1].select(0);
+}
+
+std::error_condition msx_cart_ascii8_sram_device::initialize_cartridge(std::string &message)
+{
+ if (!cart_rom_region())
+ {
+ message = "msx_cart_ascii8_sram_device: Required region 'rom' was not found.";
+ return image_error::INTERNAL;
+ }
+
+ if (!cart_sram_region())
+ {
+ message = "msx_cart_ascii8_sram_device: Required region 'sram' was not found.";
+ return image_error::INTERNAL;
+ }
+
+ const u32 size = cart_rom_region()->bytes();
+ const u16 banks = size / BANK_SIZE;
+
+ if (size > 128 * BANK_SIZE || size != banks * BANK_SIZE || (~(banks - 1) % banks))
+ {
+ message = "msx_cart_ascii8_sram_device: Region 'rom' has unsupported size.";
+ return image_error::INVALIDLENGTH;
+ }
+
+ if (cart_sram_region()->bytes() < 0x2000)
+ {
+ message = "msx_cart_ascii8_sram_device: Region 'sram' has unsupported size.";
+ return image_error::BADSOFTWARE;
+ }
+
+ m_bank_mask = banks - 1;
+ m_sram_select_mask = banks;
+
+ for (int i = 0; i < 4; i++)
+ m_rombank[i]->configure_entries(0, banks, cart_rom_region()->base(), BANK_SIZE);
+
+ page(1)->install_read_bank(0x4000, 0x5fff, m_rombank[0]);
+ page(1)->install_read_bank(0x6000, 0x7fff, m_rombank[1]);
+ page(1)->install_write_handler(0x6000, 0x7fff, emu::rw_delegate(*this, FUNC(msx_cart_ascii8_sram_device::mapper_write)));
+ page(2)->install_view(0x8000, 0x9fff, m_view[0]);
+ m_view[0][0].install_read_bank(0x8000, 0x9fff, m_rombank[2]);
+ m_view[0][1].install_ram(0x8000, 0x9fff, cart_sram_region()->base());
+ page(2)->install_view(0xa000, 0xbfff, m_view[1]);
+ m_view[1][0].install_read_bank(0xa000, 0xbfff, m_rombank[3]);
+ m_view[1][1].install_ram(0xa000, 0xbfff, cart_sram_region()->base());
+
+ return std::error_condition();
+}
+
+void msx_cart_ascii8_sram_device::mapper_write(offs_t offset, u8 data)
+{
+ u8 bank = (offset / 0x800) & 0x03;
+ if (data & m_sram_select_mask)
+ {
+ if (BIT(bank, 1))
+ m_view[BIT(bank, 0)].select(1);
+ }
+ else
+ {
+ if (BIT(bank, 1))
+ m_view[BIT(bank, 0)].select(0);
+
+ m_rombank[bank]->set_entry(data & m_bank_mask);
+ }
+}
+
+
+
+
+class msx_cart_ascii16_sram_device : public device_t, public msx_cart_interface
+{
+public:
+ msx_cart_ascii16_sram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, MSX_CART_ASCII16_SRAM, tag, owner, clock)
+ , msx_cart_interface(mconfig, *this)
+ , m_rombank(*this, "rombank%u", 0U)
+ , m_view(*this, "view")
+ , m_bank_mask(0)
+ , m_sram_select_mask(0)
+ { }
+
+ virtual std::error_condition initialize_cartridge(std::string &message) override;
+
+protected:
+ // device_t implementation
+ virtual void device_start() override { }
+ virtual void device_reset() override;
+
+private:
+ static constexpr size_t BANK_SIZE = 0x4000;
+
+ void mapper_write_6000(u8 data);
+ void mapper_write_7000(u8 data);
+
+ memory_bank_array_creator<2> m_rombank;
+ memory_view m_view;
+ u8 m_bank_mask;
+ u8 m_sram_select_mask;
+};
+
+void msx_cart_ascii16_sram_device::device_reset()
+{
+ m_rombank[0]->set_entry(0);
+ m_view.select(0);
+ m_rombank[1]->set_entry(0);
+}
+
+std::error_condition msx_cart_ascii16_sram_device::initialize_cartridge(std::string &message)
+{
+ if (!cart_rom_region())
+ {
+ message = "msx_cart_ascii16_sram_device: Required region 'rom' was not found.";
+ return image_error::INTERNAL;
+ }
+
+ if (!cart_sram_region())
+ {
+ message = "msx_cart_ascii16_sram_device: Required region 'sram' was not found.";
+ return image_error::INTERNAL;
+ }
+
+ const u32 size = cart_rom_region()->bytes();
+ const u16 banks = size / BANK_SIZE;
+
+ if (size > 128 * BANK_SIZE || size != banks * BANK_SIZE || (~(banks - 1) % banks))
+ {
+ message = "msx_cart_ascii16_sram_device: Region 'rom' has unsupported size.";
+ return image_error::INVALIDLENGTH;
+ }
+
+ if (cart_sram_region()->bytes() < 0x800)
+ {
+ message = "msx_cart_ascii16_sram_device: Region 'sram' has unsupported size.";
+ return image_error::BADSOFTWARE;
+ }
+
+ m_bank_mask = banks - 1;
+ m_sram_select_mask = banks;
+
+ for (int i = 0; i < 2; i++)
+ m_rombank[i]->configure_entries(0, banks, cart_rom_region()->base(), BANK_SIZE);
+
+ page(1)->install_read_bank(0x4000, 0x7fff, m_rombank[0]);
+ page(1)->install_write_handler(0x6000, 0x67ff, emu::rw_delegate(*this, FUNC(msx_cart_ascii16_sram_device::mapper_write_6000)));
+ page(1)->install_write_handler(0x7000, 0x77ff, emu::rw_delegate(*this, FUNC(msx_cart_ascii16_sram_device::mapper_write_7000)));
+ page(2)->install_view(0x8000, 0xbfff, m_view);
+ m_view[0].install_read_bank(0x8000, 0xbfff, m_rombank[1]);
+ m_view[1].install_ram(0x8000, 0x87ff, 0x3800, cart_sram_region()->base());
+
+ return std::error_condition();
+}
+
+void msx_cart_ascii16_sram_device::mapper_write_6000(u8 data)
+{
+ m_rombank[0]->set_entry(data & m_bank_mask);
+}
+
+void msx_cart_ascii16_sram_device::mapper_write_7000(u8 data)
+{
+ if (data & m_sram_select_mask)
+ {
+ m_view.select(1);
+ }
+ else
+ {
+ m_view.select(0);
+ m_rombank[1]->set_entry(data & m_bank_mask);
+ }
+}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_ASCII8, msx_cart_interface, msx_cart_ascii8_device, "msx_cart_ascii8", "MSX Cartridge - ASCII8")
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_ASCII16, msx_cart_interface, msx_cart_ascii16_device, "msx_cart_ascii16", "MSX Cartridge - ASCII16")
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_ASCII8_SRAM, msx_cart_interface, msx_cart_ascii8_sram_device, "msx_cart_ascii8_sram", "MSX Cartridge - ASCII8 w/SRAM")
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_ASCII16_SRAM, msx_cart_interface, msx_cart_ascii16_sram_device, "msx_cart_ascii16_sram", "MSX Cartridge - ASCII16 w/SRAM")
diff --git a/src/devices/bus/msx/cart/ascii.h b/src/devices/bus/msx/cart/ascii.h
new file mode 100644
index 00000000000..3cf890af9fe
--- /dev/null
+++ b/src/devices/bus/msx/cart/ascii.h
@@ -0,0 +1,16 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#ifndef MAME_BUS_MSX_CART_ASCII_H
+#define MAME_BUS_MSX_CART_ASCII_H
+
+#pragma once
+
+#include "bus/msx/slot/cartridge.h"
+
+
+DECLARE_DEVICE_TYPE(MSX_CART_ASCII8, msx_cart_interface)
+DECLARE_DEVICE_TYPE(MSX_CART_ASCII16, msx_cart_interface)
+DECLARE_DEVICE_TYPE(MSX_CART_ASCII8_SRAM, msx_cart_interface)
+DECLARE_DEVICE_TYPE(MSX_CART_ASCII16_SRAM, msx_cart_interface)
+
+#endif // MAME_BUS_MSX_CART_ASCII_H
diff --git a/src/devices/bus/msx/cart/beepack.cpp b/src/devices/bus/msx/cart/beepack.cpp
new file mode 100644
index 00000000000..50623621e62
--- /dev/null
+++ b/src/devices/bus/msx/cart/beepack.cpp
@@ -0,0 +1,93 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+/***********************************************************************************
+
+Emulation for the Hudson Soft BP-0001 Bee Pack card reader cartridge.
+
+This cartridge allows Bee Cards (a predecessor of HuCards) to be used on an MSX system.
+
+***********************************************************************************/
+
+#include "emu.h"
+#include "beepack.h"
+#include "bus/msx/beecard/beecard.h"
+#include "softlist_dev.h"
+
+
+DEFINE_DEVICE_TYPE(MSX_CART_BEEPACK, msx_cart_beepack_device, "msx_cart_beepack", "Hudson Soft BP-0001 Bee Pack card reader")
+
+
+msx_cart_beepack_device::msx_cart_beepack_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MSX_CART_BEEPACK, tag, owner, clock)
+ , device_cartrom_image_interface(mconfig, *this)
+ , device_single_card_slot_interface<bee_card_interface>(mconfig, *this)
+ , msx_cart_interface(mconfig, *this)
+{
+}
+
+void msx_cart_beepack_device::device_resolve_objects()
+{
+ m_beecard = get_card_device();
+ if (m_beecard)
+ {
+ m_beecard->set_views(page(0), page(1), page(2), page(3));
+ }
+}
+
+void msx_cart_beepack_device::device_add_mconfig(machine_config &config)
+{
+ bee_card(*this);
+ SOFTWARE_LIST(config, "bee_card_list").set_original("msx1_bee_card");
+}
+
+std::pair<std::error_condition, std::string> msx_cart_beepack_device::call_load()
+{
+ if (m_beecard)
+ {
+ if (loaded_through_softlist())
+ {
+ u32 const length = get_software_region_length("rom");
+ // Only 16KB or 32KB images are supported
+ if (length != 0x4000 && length != 0x8000)
+ return std::make_pair(image_error::BADSOFTWARE, "Invalid file size for a bee card (must be 16K or 32K)");
+ }
+ else
+ {
+ u32 const length = this->length();
+ // Only 16KB or 32KB images are supported
+ if (length != 0x4000 && length != 0x8000)
+ return std::make_pair(image_error::BADSOFTWARE, "Invalid file size for a bee card (must be 16K or 32K)");
+
+ memory_region *const romregion = machine().memory().region_alloc(subtag("rom"), length, 1, ENDIANNESS_LITTLE);
+ if (fread(romregion->base(), length) != length)
+ return std::make_pair(image_error::UNSPECIFIED, "Unable to fully read file");
+ }
+
+ std::string message;
+ std::error_condition result = m_beecard->initialize_cartridge(message);
+ return std::make_pair(result, message);
+ }
+ return std::make_pair(std::error_condition(), std::string());
+}
+
+std::string msx_cart_beepack_device::get_default_card_software(get_default_card_software_hook &hook) const
+{
+ return software_get_default_slot("nomapper");
+}
+
+
+
+bee_card_interface::bee_card_interface(const machine_config &mconfig, device_t &device)
+ : device_interface(device, "beecard")
+ , m_page{nullptr, nullptr, nullptr, nullptr}
+ , m_slot(dynamic_cast<msx_cart_beepack_device *>(device.owner()))
+{
+}
+
+void bee_card_interface::set_views(memory_view::memory_view_entry *page0, memory_view::memory_view_entry *page1, memory_view::memory_view_entry *page2, memory_view::memory_view_entry *page3)
+{
+ m_page[0] = page0;
+ m_page[1] = page1;
+ m_page[2] = page2;
+ m_page[3] = page3;
+}
diff --git a/src/devices/bus/msx/cart/beepack.h b/src/devices/bus/msx/cart/beepack.h
new file mode 100644
index 00000000000..e904c2c4458
--- /dev/null
+++ b/src/devices/bus/msx/cart/beepack.h
@@ -0,0 +1,58 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#ifndef MAME_BUS_MSX_CART_BEEPACK_H
+#define MAME_BUS_MSX_CART_BEEPACK_H
+
+#pragma once
+
+#include "bus/msx/slot/cartridge.h"
+#include "imagedev/cartrom.h"
+
+
+DECLARE_DEVICE_TYPE(MSX_CART_BEEPACK, msx_cart_beepack_device)
+
+class bee_card_interface;
+
+
+class msx_cart_beepack_device : public device_t
+ , public device_cartrom_image_interface
+ , public device_single_card_slot_interface<bee_card_interface>
+ , public msx_cart_interface
+{
+public:
+ msx_cart_beepack_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
+ virtual bool is_reset_on_load() const noexcept override { return true; }
+ virtual const char *image_interface() const noexcept override { return "bee_card"; }
+ virtual const char *file_extensions() const noexcept override { return "bin,rom"; }
+
+protected:
+ virtual void device_resolve_objects() override;
+ virtual void device_start() override { }
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
+
+ bee_card_interface *m_beecard;
+};
+
+
+class bee_card_interface : public device_interface
+{
+public:
+ virtual std::error_condition initialize_cartridge(std::string &message) { return std::error_condition(); }
+ void set_views(memory_view::memory_view_entry *page0, memory_view::memory_view_entry *page1, memory_view::memory_view_entry *page2, memory_view::memory_view_entry *page3);
+
+protected:
+ bee_card_interface(const machine_config &mconfig, device_t &device);
+ memory_region *cart_rom_region() { return m_slot ? m_slot->memregion("rom") : nullptr; }
+ memory_view::memory_view_entry *page(int i) { return m_page[i]; }
+
+private:
+ memory_view::memory_view_entry *m_page[4];
+ msx_cart_beepack_device *const m_slot;
+};
+
+
+#endif // MAME_BUS_MSX_CART_BEEPACK_H
diff --git a/src/devices/bus/msx_cart/bm_012.cpp b/src/devices/bus/msx/cart/bm_012.cpp
index 020348dd843..d2a77da4bdb 100644
--- a/src/devices/bus/msx_cart/bm_012.cpp
+++ b/src/devices/bus/msx/cart/bm_012.cpp
@@ -16,20 +16,38 @@ TODO:
#include "emu.h"
#include "bm_012.h"
+#include "bus/midi/midi.h"
+#include "cpu/z80/tmpz84c015.h"
#include "cpu/z80/z80.h"
+namespace {
-DEFINE_DEVICE_TYPE(MSX_CART_BM_012, msx_cart_bm_012_device, "msx_cart_bm_012", "MSX Cartridge - BM-012")
+class msx_cart_bm_012_device : public device_t, public msx_cart_interface
+{
+public:
+ msx_cart_bm_012_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, MSX_CART_BM_012, tag, owner, clock)
+ , msx_cart_interface(mconfig, *this)
+ , m_tmpz84c015af(*this, "tmpz84c015af")
+ , m_bm012_pio(*this, "bm012_pio")
+ , m_mdthru(*this, "mdthru")
+ { }
+protected:
+ // device_t implementation
+ virtual void device_start() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
-msx_cart_bm_012_device::msx_cart_bm_012_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, MSX_CART_BM_012, tag, owner, clock)
- , msx_cart_interface(mconfig, *this)
- , m_tmpz84c015af(*this, "tmpz84c015af")
- , m_bm012_pio(*this, "bm012_pio")
- , m_mdthru(*this, "mdthru")
-{
-}
+private:
+ void midi_in(int state);
+
+ void bm_012_memory_map(address_map &map);
+
+ required_device<tmpz84c015_device> m_tmpz84c015af;
+ required_device<z80pio_device> m_bm012_pio;
+ required_device<midi_port_device> m_mdthru;
+};
void msx_cart_bm_012_device::bm_012_memory_map(address_map &map)
@@ -94,13 +112,17 @@ const tiny_rom_entry *msx_cart_bm_012_device::device_rom_region() const
void msx_cart_bm_012_device::device_start()
{
// Install IO read/write handlers
- io_space().install_write_handler(0x70, 0x73, write8sm_delegate(*m_bm012_pio, FUNC(z80pio_device::write_alt)));
- io_space().install_read_handler(0x70, 0x73, read8sm_delegate(*m_bm012_pio, FUNC(z80pio_device::read_alt)));
+ io_space().install_write_handler(0x70, 0x73, emu::rw_delegate(*m_bm012_pio, FUNC(z80pio_device::write_alt)));
+ io_space().install_read_handler(0x70, 0x73, emu::rw_delegate(*m_bm012_pio, FUNC(z80pio_device::read_alt)));
}
-WRITE_LINE_MEMBER(msx_cart_bm_012_device::midi_in)
+void msx_cart_bm_012_device::midi_in(int state)
{
m_mdthru->write_txd(state);
m_tmpz84c015af->rxb_w(state);
}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_BM_012, msx_cart_interface, msx_cart_bm_012_device, "msx_cart_bm_012", "MSX Cartridge - BM-012")
diff --git a/src/devices/bus/msx/cart/bm_012.h b/src/devices/bus/msx/cart/bm_012.h
new file mode 100644
index 00000000000..3eb41be9a66
--- /dev/null
+++ b/src/devices/bus/msx/cart/bm_012.h
@@ -0,0 +1,13 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#ifndef MAME_BUS_MSX_CART_BM_012_H
+#define MAME_BUS_MSX_CART_BM_012_H
+
+#pragma once
+
+#include "bus/msx/slot/cartridge.h"
+
+
+DECLARE_DEVICE_TYPE(MSX_CART_BM_012, msx_cart_interface)
+
+#endif // MAME_BUS_MSX_CART_BM_012_H
diff --git a/src/devices/bus/msx/cart/cartridge.cpp b/src/devices/bus/msx/cart/cartridge.cpp
new file mode 100644
index 00000000000..7fc7e863349
--- /dev/null
+++ b/src/devices/bus/msx/cart/cartridge.cpp
@@ -0,0 +1,241 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+
+#include "emu.h"
+#include "cartridge.h"
+
+#include "arc.h"
+#include "ascii.h"
+#include "beepack.h"
+#include "bm_012.h"
+#include "crossblaim.h"
+#include "disk.h"
+#include "dooly.h"
+#include "easi_speech.h"
+#include "fmpac.h"
+#include "fs_sr021.h"
+#include "fs_sr022.h"
+#include "halnote.h"
+#include "hbi55.h"
+#include "hfox.h"
+#include "holy_quran.h"
+#include "ink.h"
+#include "kanji.h"
+#include "konami.h"
+#include "korean.h"
+#include "loveplus.h"
+#include "majutsushi.h"
+#include "matra.h"
+#include "moonsound.h"
+#include "msx_audio.h"
+#include "msxdos2.h"
+#include "nomapper.h"
+#include "quickdisk.h"
+#include "ram.h"
+#include "rtype.h"
+#include "scsi.h"
+#include "slotexpander.h"
+#include "slotoptions.h"
+#include "softcard.h"
+#include "super_swangi.h"
+#include "superloderunner.h"
+#include "yamaha_ucn01.h"
+
+#include "bus/msx/slot/cartridge.h"
+
+
+DEFINE_DEVICE_TYPE(MSX_SLOT_CARTRIDGE, msx_slot_cartridge_device, "msx_slot_cartridge", "MSX Cartridge slot")
+
+
+void msx_cart(device_slot_interface &device, bool is_in_subslot)
+{
+ using namespace bus::msx::cart;
+ msx_cart_disk_register_options(device);
+ msx_cart_ram_register_options(device);
+ device.option_add_internal(slotoptions::ARC, MSX_CART_ARC);
+ device.option_add_internal(slotoptions::ASCII8, MSX_CART_ASCII8);
+ device.option_add_internal(slotoptions::ASCII8_SRAM, MSX_CART_ASCII8_SRAM);
+ device.option_add_internal(slotoptions::ASCII16, MSX_CART_ASCII16);
+ device.option_add_internal(slotoptions::ASCII16_SRAM, MSX_CART_ASCII16_SRAM);
+ device.option_add_internal(slotoptions::CROSS_BLAIM, MSX_CART_CROSSBLAIM);
+ device.option_add_internal(slotoptions::DOOLY, MSX_CART_DOOLY);
+ device.option_add_internal(slotoptions::EASISPEECH, MSX_CART_EASISPEECH);
+ device.option_add_internal(slotoptions::FMPAC, MSX_CART_FMPAC);
+ device.option_add_internal(slotoptions::FS_SR021, MSX_CART_FS_SR021);
+ device.option_add_internal(slotoptions::FS_SR022, MSX_CART_FS_SR022);
+ device.option_add_internal(slotoptions::GAMEMASTER2, MSX_CART_GAMEMASTER2);
+ device.option_add_internal(slotoptions::GOUDA_SCSI, MSX_CART_GOUDA_SCSI);
+ device.option_add_internal(slotoptions::HALNOTE, MSX_CART_HALNOTE);
+ device.option_add_internal(slotoptions::HFOX, MSX_CART_HFOX);
+ device.option_add_internal(slotoptions::HOLY_QURAN, MSX_CART_HOLY_QURAN);
+ device.option_add_internal(slotoptions::INK, MSX_CART_INK);
+ device.option_add_internal(slotoptions::KANJI, MSX_CART_KANJI);
+ device.option_add_internal(slotoptions::KEYBOARD_MASTER, MSX_CART_KEYBOARD_MASTER);
+ device.option_add_internal(slotoptions::KONAMI, MSX_CART_KONAMI);
+ device.option_add_internal(slotoptions::KONAMI_SCC, MSX_CART_KONAMI_SCC);
+ device.option_add_internal(slotoptions::KOREAN_25IN1, MSX_CART_KOREAN_25IN1);
+ device.option_add_internal(slotoptions::KOREAN_80IN1, MSX_CART_KOREAN_80IN1);
+ device.option_add_internal(slotoptions::KOREAN_90IN1, MSX_CART_KOREAN_90IN1);
+ device.option_add_internal(slotoptions::KOREAN_126IN1, MSX_CART_KOREAN_126IN1);
+ device.option_add_internal(slotoptions::KOREAN_HYDLIDE2, MSX_CART_KOREAN_HYDLIDE2);
+ device.option_add_internal(slotoptions::LOVEPLUS, MSX_CART_LOVEPLUS);
+ device.option_add_internal(slotoptions::MAJUSTUSHI, MSX_CART_MAJUTSUSHI);
+ device.option_add_internal(slotoptions::MATRA_COMP, MSX_CART_MATRA_COMP);
+ device.option_add_internal(slotoptions::MEGA_SCSI, MSX_CART_MEGA_SCSI);
+ device.option_add_internal(slotoptions::MSXAUD_FSCA1, MSX_CART_MSX_AUDIO_FSCA1);
+ device.option_add_internal(slotoptions::MSXAUD_HXMU900, MSX_CART_MSX_AUDIO_HXMU900);
+ device.option_add_internal(slotoptions::MSXAUD_NMS1205, MSX_CART_MSX_AUDIO_NMS1205);
+ device.option_add_internal(slotoptions::MSXDOS2J, MSX_CART_MSXDOS2J);
+ device.option_add_internal(slotoptions::MSXDOS2E, MSX_CART_MSXDOS2E);
+ device.option_add_internal(slotoptions::MSXWRITE, MSX_CART_MSXWRITE);
+ device.option_add_internal(slotoptions::NOMAPPER, MSX_CART_NOMAPPER);
+ device.option_add_internal(slotoptions::QUICKDISK, MSX_CART_QUICKDISK);
+ device.option_add_internal(slotoptions::RTYPE, MSX_CART_RTYPE);
+ device.option_add_internal(slotoptions::SOUND_SNATCHER, MSX_CART_SOUND_SNATCHER);
+ device.option_add_internal(slotoptions::SOUND_SDSNATCH, MSX_CART_SOUND_SDSNATCHER);
+ device.option_add_internal(slotoptions::SUNRISE_SCC, MSX_CART_SUNRISE_SCC);
+ device.option_add_internal(slotoptions::SUPER_SWANGI, MSX_CART_SUPER_SWANGI);
+ device.option_add_internal(slotoptions::SUPERLODERUNNER, MSX_CART_SUPERLODERUNNER);
+ device.option_add_internal(slotoptions::SYNTHESIZER, MSX_CART_SYNTHESIZER);
+ device.option_add_internal(slotoptions::EC701, MSX_CART_EC701);
+ device.option_add(slotoptions::BEEPACK, MSX_CART_BEEPACK);
+ device.option_add(slotoptions::BM_012, MSX_CART_BM_012);
+ device.option_add(slotoptions::HBI55, MSX_CART_HBI55);
+ device.option_add(slotoptions::MOONSOUND, MSX_CART_MOONSOUND);
+ device.option_add(slotoptions::SOFTCARD, MSX_CART_SOFTCARD);
+ device.option_add(slotoptions::UCN01, MSX_CART_UCN01);
+ if (!is_in_subslot)
+ {
+ device.option_add(slotoptions::SLOTEXP, MSX_CART_SLOTEXPANDER);
+ }
+}
+
+
+msx_slot_cartridge_device::msx_slot_cartridge_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : msx_slot_cartridge_base_device(mconfig, MSX_SLOT_CARTRIDGE, tag, owner, clock)
+{
+}
+
+std::string msx_slot_cartridge_device::get_default_card_software(get_default_card_software_hook &hook) const
+{
+ using namespace bus::msx::cart;
+ if (hook.image_file())
+ {
+ // Check if there's some mapper related information in the hashfiles
+ std::string extrainfo;
+ if (hook.hashfile_extrainfo(extrainfo))
+ {
+ int extrainfo_type = -1;
+ if (1 == sscanf(extrainfo.c_str(), "%d", &extrainfo_type))
+ {
+ static const struct {int extrainfo; char const *const mapper;} extrainfo_map[] = {
+ { 0, slotoptions::NOMAPPER },
+ { 1, slotoptions::MSXDOS2E },
+ { 2, slotoptions::KONAMI_SCC },
+ { 3, slotoptions::KONAMI },
+ { 4, slotoptions::ASCII8 },
+ { 5, slotoptions::ASCII16 },
+ { 6, slotoptions::GAMEMASTER2 },
+ { 7, slotoptions::ASCII8_SRAM },
+ { 8, slotoptions::ASCII16_SRAM },
+ { 9, slotoptions::RTYPE },
+ { 10, slotoptions::MAJUSTUSHI },
+ { 11, slotoptions::FMPAC },
+ { 12, slotoptions::SUPERLODERUNNER },
+ { 13, slotoptions::SYNTHESIZER },
+ { 14, slotoptions::CROSS_BLAIM },
+ { 16, slotoptions::KOREAN_80IN1 },
+ { 17, slotoptions::KOREAN_126IN1 }
+ };
+
+ for (auto & elem : extrainfo_map)
+ {
+ if (elem.extrainfo == extrainfo_type)
+ {
+ return std::string(elem.mapper);
+ }
+ }
+ }
+ }
+
+ // Not identified through hashfile, try automatic detection
+ u64 length;
+ if (hook.image_file()->length(length))
+ {
+ osd_printf_warning("[%s] Error getting cartridge ROM length\n", tag());
+ return std::string(slotoptions::NOMAPPER);
+ }
+ length = std::min<u64>(length, 4 * 1024 * 1024);
+ auto const [err, rom, actual] = read(*hook.image_file(), length);
+ if (err || (actual != length))
+ {
+ osd_printf_warning("[%s] Error reading from file\n", tag());
+ return std::string(slotoptions::NOMAPPER);
+ }
+ return std::string(get_cart_type(&rom[0], length));
+ }
+ return software_get_default_slot(bus::msx::cart::slotoptions::NOMAPPER);
+}
+
+
+char const *const msx_slot_cartridge_device::get_cart_type(const u8 *rom, u32 length)
+{
+ using namespace bus::msx::cart;
+ if (length < 0x10000)
+ {
+ return slotoptions::NOMAPPER;
+ }
+
+ if ((rom[0x10] == 'Y') && (rom[0x11] == 'Z') && (length > 0x18000))
+ {
+ return slotoptions::GAMEMASTER2;
+ }
+
+ int kon4 = 0, kon5 = 0, asc8 = 0, asc16 = 0;
+
+ for (int i=0; i < length-3; i++)
+ {
+ if (rom[i] == 0x32 && rom[i+1] == 0)
+ {
+ switch (rom[i+2])
+ {
+ case 0x60:
+ case 0x70:
+ asc16++;
+ asc8++;
+ break;
+
+ case 0x68:
+ case 0x78:
+ asc8++;
+ asc16--;
+ break;
+ }
+
+ switch (rom[i+2])
+ {
+ case 0x60:
+ case 0x80:
+ case 0xa0:
+ kon4++;
+ break;
+
+ case 0x50:
+ case 0x70:
+ case 0x90:
+ case 0xb0:
+ kon5++;
+ break;
+ }
+ }
+ }
+
+ if (std::max(kon4, kon5) > std::max(asc8, asc16))
+ {
+ return (kon5 > kon4) ? slotoptions::KONAMI_SCC : slotoptions::KONAMI;
+ }
+ else
+ {
+ return (asc8 > asc16) ? slotoptions::ASCII8 : slotoptions::ASCII16;
+ }
+}
diff --git a/src/devices/bus/msx/cart/cartridge.h b/src/devices/bus/msx/cart/cartridge.h
new file mode 100644
index 00000000000..812b4eccb12
--- /dev/null
+++ b/src/devices/bus/msx/cart/cartridge.h
@@ -0,0 +1,28 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#ifndef MAME_BUS_MSX_CART_CARTRIDGE_H
+#define MAME_BUS_MSX_CART_CARTRIDGE_H
+
+#pragma once
+
+#include "bus/msx/slot/cartridge.h"
+
+
+void msx_cart(device_slot_interface &device, bool is_in_subslot);
+
+
+DECLARE_DEVICE_TYPE(MSX_SLOT_CARTRIDGE, msx_slot_cartridge_device)
+
+
+class msx_slot_cartridge_device : public msx_slot_cartridge_base_device
+{
+public:
+ msx_slot_cartridge_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
+
+protected:
+ static char const *const get_cart_type(const u8 *rom, u32 length);
+};
+
+#endif // MAME_BUS_MSX_CART_CARTRIDGE_H
diff --git a/src/devices/bus/msx/cart/crossblaim.cpp b/src/devices/bus/msx/cart/crossblaim.cpp
new file mode 100644
index 00000000000..da337f44472
--- /dev/null
+++ b/src/devices/bus/msx/cart/crossblaim.cpp
@@ -0,0 +1,63 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#include "emu.h"
+#include "crossblaim.h"
+
+namespace {
+
+class msx_cart_crossblaim_device : public device_t, public msx_cart_interface
+{
+public:
+ msx_cart_crossblaim_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, MSX_CART_CROSSBLAIM, tag, owner, clock)
+ , msx_cart_interface(mconfig, *this)
+ , m_rombank(*this, "rombank")
+ { }
+
+ virtual std::error_condition initialize_cartridge(std::string &message) override;
+
+protected:
+ // device_t implementation
+ virtual void device_start() override { }
+
+private:
+ void mapper_write(u8 data);
+
+ memory_bank_creator m_rombank;
+};
+
+std::error_condition msx_cart_crossblaim_device::initialize_cartridge(std::string &message)
+{
+ if (!cart_rom_region())
+ {
+ message = "msx_cart_crossblaim_device: Required region 'rom' was not found.";
+ return image_error::INTERNAL;
+ }
+
+ if (cart_rom_region()->bytes() != 0x10000)
+ {
+ message = "msx_cart_crossblaim_device: Region 'rom' has unsupported size.";
+ return image_error::INVALIDLENGTH;
+ }
+
+ m_rombank->configure_entries(0, 4, cart_rom_region()->base(), 0x4000);
+
+ page(1)->install_rom(0x4000, 0x7fff, cart_rom_region()->base());
+ page(1)->install_write_handler(0x4045, 0x4045, emu::rw_delegate(*this, FUNC(msx_cart_crossblaim_device::mapper_write)));
+ page(2)->install_read_bank(0x8000, 0xbfff, m_rombank);
+
+ return std::error_condition();
+}
+
+void msx_cart_crossblaim_device::mapper_write(u8 data)
+{
+ data &= 0x03;
+ if (!data)
+ data = 1;
+
+ m_rombank->set_entry(data);
+}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_CROSSBLAIM, msx_cart_interface, msx_cart_crossblaim_device, "msx_cart_crossblaim", "MSX Cartridge Cross Blaim")
diff --git a/src/devices/bus/msx/cart/crossblaim.h b/src/devices/bus/msx/cart/crossblaim.h
new file mode 100644
index 00000000000..24177f5d823
--- /dev/null
+++ b/src/devices/bus/msx/cart/crossblaim.h
@@ -0,0 +1,13 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#ifndef MAME_BUS_MSX_CART_CROSSBLAIM_H
+#define MAME_BUS_MSX_CART_CROSSBLAIM_H
+
+#pragma once
+
+#include "bus/msx/slot/cartridge.h"
+
+
+DECLARE_DEVICE_TYPE(MSX_CART_CROSSBLAIM, msx_cart_interface)
+
+#endif // MAME_BUS_MSX_CART_CROSSBLAIM_H
diff --git a/src/devices/bus/msx/cart/disk.cpp b/src/devices/bus/msx/cart/disk.cpp
new file mode 100644
index 00000000000..88449c413bf
--- /dev/null
+++ b/src/devices/bus/msx/cart/disk.cpp
@@ -0,0 +1,1405 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+/*****************************************************************************
+ *
+ * MSX Floopy drive interface add-on cartridges
+ *
+ * Currently supported:
+ * - AVT DPF-550 + DD 5.25" Drive - FD1770 or FD179x?
+ * - Digital Design Drive DDX + DD 5.25" Drive - WD2793
+ * - Microsol CDX-2 + DD 5.25" Drive - WD2793?
+ * - Mitsubishi ML-30DC + ML-30FD DSDD 3.5" Drive - WD2793
+ * - National FS-CF351 + FS-FD351 DSDD 3.5" Drive - MB8877A
+ * - Panasonic FS-FD1 + DSDD 3.5" Drive - WD2793?
+ * - Panasonic FS-FD1A with DSDD 3.5" Drive - TC8566F
+ * - Rom label reads: "FDC BIOS V1.0 / COPYRIGHT MEI / 1987 DASFD1AA1"
+ * - Philips NMS-1200 - Floppy interface - WD2793?
+ * - Philips VY-0010 (Interface cartridge + 1 3.5" SS floppy drive)
+ * - Sanyo MFD-001 + DS 5.25" Drive - MB8877?
+ * - Sharp Epcom HB-3600 + HB-6000 DD 5.25" Drive - WD2793
+ * - Sony HBD-20W + DSDD 3.5" Drive - WD2793
+ * - Sony HBD-50 + SSDD 3.5" Drive - WD2793
+ * - Missing version SNYJX130
+ * - Sony HBD-F1 + DSDD 3.5" Drive - WD2793
+ * - Talent DPF-550 + SS 5.25" Drive - WD1770
+ * - Toshiba HX-F101PE + SS 3.5" Drive - WD2793
+ * - Yamaha FD-03 + SSDD 3.5" Floppy drive - FD1793 (according to service manual)
+ * - Yamaha FD-051 + FD-05 DSDD 3.5" Drive - WD2793
+ * - Loading seems slower than other units
+ *
+ * Not supported yet:
+ * - Canon VF-100 - DSDD 3.5" Floppy drive + interface + 1 floppy disk containing MSX-DOS
+ * - Talent DPF-555 - WD1772 - DSDD 5.25" Floppy drive (360KB) plus interface (manufactured by Daewoo)
+ * - Rom label markings: MSX DISK / DPF 555D
+ *
+ * Drive only:
+ * - Philps VY-0011 - 3.5" SSDD Floppy drive
+ * - Talent DPF-560 - DSDD 5.25" Floppy drive
+ *
+ * To be investigated:
+ * - Daewoo CPF-350C - DD 3.5" Floppy drive
+ * - Daewoo CPF-360C - DD 3.5" Floppy drive
+ * - Daewoo MPF-550 - DSDD 5.25" Floppy drive + interface
+ * = Daewoo MPF-560 - DSDD 5.25" Floppy drive
+ * - DMX Interface para drive - Interface + 1 floppy disk containg MSX-DOS 1.0
+ * - Fenner FD-300 - DSDD 3.5" Floppy drive
+ * - Fenner FD-400 - Floppy interface for FD-300
+ * - Hitachi MPF-310CH - DSDD Floppy drive
+ * - hitachi MPC-310CH - Interface for MPF-310CH
+ * - JVC HC-F303 - Floppy drive
+ * - Philips NMS-9111 - 3.5" Floppy drive
+ * - Philips NMS-9113 - 3.5" Floppy drive
+ * - Sakir AFD-01 - SSDD 3.5" Floppy drive
+ * - Sanyo MFD-002 - 360KB 5.25" Floppy drive (2nd drive for MFD-001?)
+ * - Sanyo MFD-25FD - DSDD 3.5" Floppy drive
+ * - Sanyo MFD-35 - SSDD 3.5" Floppy drive + interface
+ * - Sony HBD-100 - SSDD 3.5" Floppy drive
+ * - Sony HBD-30X/30W - DSDD 3.5" drive
+ * - Sony HBX-30 (interface only, meant for 30W) - WD2793
+ * - Spectravideo SVI-213 - MB8877A - Floppy interface for SVI-707
+ * - Spectravideo SVI-707 - MB8877A - 5.25" SSDD? drive (320KB) - There seem to be 2 ROMs on the PCB, apparently one is for MSX and one is for CP/M operation?
+ * - See https://plus.google.com/photos/115644813183575095400/albums/5223347091895442113?banner=pwa
+ * - Spectravideo SVI-717 - Interface for 2 drives?
+ * - Spectravideo SVI-787 - SSDD 3.5" Floppy drive
+ * - Spectravideo SVI-801 - Interface
+ * - Toshiba HX-F100 - Interface + SSDD 3.5" Floppy drive
+ * - Toshiba HX-F101 - Interface + SSDD or DSDD 3.5" Floppy drive
+ * - Yamaha FD-01 - Interface + SSDD 3.5" Floppy drive
+ * - Other models:
+ * - ACVS 3.5" Floppy drive interface
+ * - Tradeco floppy interface
+ * - Angeisa 3.5" Floppy drive
+ * - Angeisa 5.25" 360KB Floppy drive
+ * - Angeisa 5.25" 720KB Floppy drive
+ * - Angeisa floppy drive interface
+ * - Datagame floppy drive interface
+ * - Digital Design DSDD 3.5" Floppy drive
+ * - Digital Design 5.25" 360KB Floppy drive
+ * - Digital Design 5.25" 720KB Floppy drive
+ * - Digital Design floppy drive interface
+ * - DMX 3.5" Floppy drive
+ * - DMX floppy drive interface
+ * - Liftron 3.5" Floppy drive
+ * - Liftron floppy drive interface
+ * - Microsol DRX-180 5.25" Floppy drive FS
+ * - Microsol DRX-360 5.25" Floppy drive FD
+ * - Microsol DRX-720 5.25" Floppy drive 80 track (720KB)
+ * - Microsol CDX-1 floppy interface
+ * - Racidata 3.5" Floppy drive
+ * - Racidata 5.25" Floppy drive
+ * - Racidata floppy interface
+ * - Sileman Triton-s 3.5" FS Floppy drive
+ * - Sileman Triton-d 3.5" FD Floppy drive
+ * - Talent TPF-723 5.25" Floppy drive
+ * - Talent TPF-725 5.25" Flpppy drive
+ * - Technohead Leopard 3.5" Floppy drive
+ * - Technohead Leopard 5.25" Floppy drive
+ * - Technohead floppy interface
+ * - More??
+ *
+ * Several model references found in Vitropedia (ISBN 9781409212774)
+ *
+ ****************************************************************************/
+
+#include "emu.h"
+#include "disk.h"
+#include "slotoptions.h"
+
+#include "bus/msx/slot/cartridge.h"
+#include "imagedev/floppy.h"
+#include "machine/wd_fdc.h"
+#include "machine/upd765.h"
+
+#include "softlist_dev.h"
+
+#include "formats/dmk_dsk.h"
+#include "formats/msx_dsk.h"
+
+
+DECLARE_DEVICE_TYPE(MSX_CART_AVDPF550, msx_cart_interface)
+DECLARE_DEVICE_TYPE(MSX_CART_CDX2, msx_cart_interface)
+DECLARE_DEVICE_TYPE(MSX_CART_DDX3, msx_cart_interface)
+DECLARE_DEVICE_TYPE(MSX_CART_FD03, msx_cart_interface)
+DECLARE_DEVICE_TYPE(MSX_CART_FD051, msx_cart_interface)
+DECLARE_DEVICE_TYPE(MSX_CART_FSCF351, msx_cart_interface)
+DECLARE_DEVICE_TYPE(MSX_CART_FSFD1, msx_cart_interface)
+DECLARE_DEVICE_TYPE(MSX_CART_FSFD1A, msx_cart_interface)
+DECLARE_DEVICE_TYPE(MSX_CART_HB3600, msx_cart_interface)
+DECLARE_DEVICE_TYPE(MSX_CART_HBD20W, msx_cart_interface)
+DECLARE_DEVICE_TYPE(MSX_CART_HBD50, msx_cart_interface)
+DECLARE_DEVICE_TYPE(MSX_CART_HBDF1, msx_cart_interface)
+DECLARE_DEVICE_TYPE(MSX_CART_HXF101PE, msx_cart_interface)
+DECLARE_DEVICE_TYPE(MSX_CART_MFD001, msx_cart_interface)
+DECLARE_DEVICE_TYPE(MSX_CART_ML30DC, msx_cart_interface)
+DECLARE_DEVICE_TYPE(MSX_CART_NMS1200, msx_cart_interface)
+DECLARE_DEVICE_TYPE(MSX_CART_TADPF550, msx_cart_interface)
+DECLARE_DEVICE_TYPE(MSX_CART_VY0010, msx_cart_interface)
+
+
+void msx_cart_disk_register_options(device_slot_interface &device)
+{
+ using namespace bus::msx::cart;
+ device.option_add_internal(slotoptions::DISK_AVDPF550, MSX_CART_AVDPF550);
+ device.option_add_internal(slotoptions::DISK_CDX2, MSX_CART_CDX2);
+ device.option_add_internal(slotoptions::DISK_DDX3, MSX_CART_DDX3);
+ device.option_add_internal(slotoptions::DISK_FD03, MSX_CART_FD03);
+ device.option_add_internal(slotoptions::DISK_FD051, MSX_CART_FD051);
+ device.option_add_internal(slotoptions::DISK_FSCF351, MSX_CART_FSCF351);
+ device.option_add_internal(slotoptions::DISK_FSFD1, MSX_CART_FSFD1);
+ device.option_add_internal(slotoptions::DISK_FSFD1A, MSX_CART_FSFD1A);
+ device.option_add_internal(slotoptions::DISK_HB3600, MSX_CART_HB3600);
+ device.option_add_internal(slotoptions::DISK_HBD20W, MSX_CART_HBD20W);
+ device.option_add_internal(slotoptions::DISK_HBD50, MSX_CART_HBD50);
+ device.option_add_internal(slotoptions::DISK_HBDF1, MSX_CART_HBDF1);
+ device.option_add_internal(slotoptions::DISK_HXF101PE, MSX_CART_HXF101PE);
+ device.option_add_internal(slotoptions::DISK_MFD001, MSX_CART_MFD001);
+ device.option_add_internal(slotoptions::DISK_ML30DC, MSX_CART_ML30DC);
+ device.option_add_internal(slotoptions::DISK_NMS1200, MSX_CART_NMS1200);
+ device.option_add_internal(slotoptions::DISK_TADPF550, MSX_CART_TADPF550);
+ device.option_add_internal(slotoptions::DISK_VY0010, MSX_CART_VY0010);
+}
+
+
+namespace {
+
+void msx_floppies(device_slot_interface &device)
+{
+ device.option_add("35dd", FLOPPY_35_DD);
+ device.option_add("35ssdd", FLOPPY_35_SSDD);
+ device.option_add("525dd", FLOPPY_525_DD);
+ device.option_add("525ssdd", FLOPPY_525_SSDD);
+}
+
+
+
+class msx_cart_disk_device : public device_t, public msx_cart_interface
+{
+public:
+ virtual std::error_condition initialize_cartridge(std::string &message) override;
+
+protected:
+ msx_cart_disk_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, int fdc_regs_start_page, int fdc_regs_end_page)
+ : device_t(mconfig, type, tag, owner, clock)
+ , msx_cart_interface(mconfig, *this)
+ , m_floppy0(*this, "fdc:0")
+ , m_floppy1(*this, "fdc:1")
+ , m_floppy(nullptr)
+ , m_fdc_regs_start_page(fdc_regs_start_page)
+ , m_fdc_regs_end_page(fdc_regs_end_page)
+ { }
+
+ static void floppy_formats(format_registration &fr);
+ void softlist_35(machine_config &config);
+ void softlist_525(machine_config &config);
+ template <bool Is35, bool IsDS> void add_floppy_mconfig(machine_config &config);
+
+ static constexpr int PAGE0 = 0;
+ static constexpr int PAGE1 = 1;
+ static constexpr int PAGE2 = 2;
+ static constexpr int PAGE3 = 3;
+ static constexpr bool F35 = true;
+ static constexpr bool F525 = false;
+ static constexpr bool DS = true;
+ static constexpr bool SS = false;
+ static constexpr bool FORCE_READY = true;
+
+ required_device<floppy_connector> m_floppy0;
+ optional_device<floppy_connector> m_floppy1;
+ floppy_image_device *m_floppy;
+ int m_fdc_regs_start_page;
+ int m_fdc_regs_end_page;
+};
+
+void msx_cart_disk_device::floppy_formats(format_registration &fr)
+{
+ fr.add_mfm_containers();
+ fr.add(FLOPPY_MSX_FORMAT);
+ fr.add(FLOPPY_DMK_FORMAT);
+}
+
+std::error_condition msx_cart_disk_device::initialize_cartridge(std::string &message)
+{
+ if (!cart_rom_region())
+ {
+ message = "msx_cart_disk_device: Required region 'rom' was not found.";
+ return image_error::INTERNAL;
+ }
+
+ if (cart_rom_region()->bytes() != 0x4000)
+ {
+ message = "msx_cart_disk_device: Region 'rom' has unsupported size.";
+ return image_error::INVALIDLENGTH;
+ }
+
+ return std::error_condition();
+}
+
+void msx_cart_disk_device::softlist_35(machine_config &config)
+{
+ // Attach software lists
+ // We do not know in what kind of machine the user has inserted the floppy interface
+ // so we list all msx floppy software lists.
+ //
+ SOFTWARE_LIST(config, "msx2_flop_list").set_original("msx2_flop");
+ SOFTWARE_LIST(config, "msx1_flop_list").set_compatible("msx1_flop");
+}
+
+void msx_cart_disk_device::softlist_525(machine_config &config)
+{
+ // Attach software lists
+ SOFTWARE_LIST(config, "msx1_flop_525_list").set_compatible("msx1_flop_525");
+}
+
+template <bool Is35, bool IsDS>
+void msx_cart_disk_device::add_floppy_mconfig(machine_config &config)
+{
+ FLOPPY_CONNECTOR(config, "fdc:0", msx_floppies, Is35 ? (IsDS ? "35dd" : "35ssdd") : (IsDS ? "525dd" : "525ssdd"), msx_cart_disk_device::floppy_formats).enable_sound(true);
+ if (Is35)
+ softlist_35(config);
+ else
+ softlist_525(config);
+}
+
+
+
+
+class disk_tc8566_device : public msx_cart_disk_device
+{
+protected:
+ disk_tc8566_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
+ : msx_cart_disk_device(mconfig, type, tag, owner, clock, PAGE1, PAGE2)
+ , m_fdc(*this, "fdc")
+ { }
+
+ required_device<tc8566af_device> m_fdc;
+};
+
+
+
+class disk_wd_device : public msx_cart_disk_device
+{
+protected:
+ disk_wd_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, int fdc_regs_start_page = PAGE1, int fdc_regs_end_page = PAGE2)
+ : msx_cart_disk_device(mconfig, type, tag, owner, clock, fdc_regs_start_page, fdc_regs_end_page)
+ , m_fdc(*this, "fdc")
+ { }
+
+ required_device<wd_fdc_device_base> m_fdc;
+
+ virtual void device_reset() override
+ {
+ m_fdc->dden_w(false);
+ }
+
+ template <bool Is35, bool IsDS, typename FDCType> void add_mconfig(machine_config &config, FDCType &&type)
+ {
+ add_mconfig<Is35, IsDS, false>(config, type);
+ }
+
+ template <bool Is35, bool IsDS, bool ForceReady, typename FDCType> void add_mconfig(machine_config &config, FDCType &&type)
+ {
+ std::forward<FDCType>(type)(config, m_fdc, 4_MHz_XTAL / 4);
+ if (ForceReady)
+ m_fdc->set_force_ready(true);
+ add_floppy_mconfig<Is35, IsDS>(config);
+ }
+};
+
+
+
+class disk_type1_device : public disk_wd_device
+{
+public:
+ virtual std::error_condition initialize_cartridge(std::string &message) override;
+
+protected:
+ disk_type1_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, int fdc_regs_start_page = PAGE1, int fdc_regs_end_page = PAGE2)
+ : disk_wd_device(mconfig, type, tag, owner, clock, fdc_regs_start_page, fdc_regs_end_page)
+ , m_led(*this, "led0")
+ , m_side_control(0)
+ , m_control(0)
+ { }
+
+ // device_t implementation
+ virtual void device_start() override;
+ virtual void device_post_load() override;
+
+ u8 side_control_r();
+ u8 control_r();
+ u8 status_r();
+ void set_side_control(u8 data);
+ void set_control(u8 data);
+
+ output_finder<> m_led;
+ u8 m_side_control;
+ u8 m_control;
+};
+
+void disk_type1_device::device_start()
+{
+ m_led.resolve();
+
+ save_item(NAME(m_side_control));
+ save_item(NAME(m_control));
+}
+
+std::error_condition disk_type1_device::initialize_cartridge(std::string &message)
+{
+ std::error_condition result = disk_wd_device::initialize_cartridge(message);
+ if (result)
+ return result;
+
+ page(1)->install_rom(0x4000, 0x7fff, cart_rom_region()->base());
+ for (int i = m_fdc_regs_start_page; i <= m_fdc_regs_end_page; i++)
+ {
+ const offs_t base = 0x4000 * i;
+ page(i)->install_read_handler(base + 0x3ff8, base + 0x3ff8, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::status_r)));
+ page(i)->install_read_handler(base + 0x3ff9, base + 0x3ff9, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::track_r)));
+ page(i)->install_read_handler(base + 0x3ffa, base + 0x3ffa, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::sector_r)));
+ page(i)->install_read_handler(base + 0x3ffb, base + 0x3ffb, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::data_r)));
+ page(i)->install_read_handler(base + 0x3ffc, base + 0x3ffc, emu::rw_delegate(*this, FUNC(disk_type1_device::side_control_r)));
+ page(i)->install_read_handler(base + 0x3ffd, base + 0x3ffd, emu::rw_delegate(*this, FUNC(disk_type1_device::control_r)));
+ page(i)->install_read_handler(base + 0x3fff, base + 0x3fff, emu::rw_delegate(*this, FUNC(disk_type1_device::status_r)));
+ page(i)->install_write_handler(base + 0x3ff8, base + 0x3ff8, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::cmd_w)));
+ page(i)->install_write_handler(base + 0x3ff9, base + 0x3ff9, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::track_w)));
+ page(i)->install_write_handler(base + 0x3ffa, base + 0x3ffa, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::sector_w)));
+ page(i)->install_write_handler(base + 0x3ffb, base + 0x3ffb, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::data_w)));
+ page(i)->install_write_handler(base + 0x3ffc, base + 0x3ffc, emu::rw_delegate(*this, FUNC(disk_type1_device::set_side_control)));
+ page(i)->install_write_handler(base + 0x3ffd, base + 0x3ffd, emu::rw_delegate(*this, FUNC(disk_type1_device::set_control)));
+ }
+
+ return std::error_condition();
+}
+
+void disk_type1_device::device_post_load()
+{
+ set_control(m_control);
+}
+
+void disk_type1_device::set_control(u8 data)
+{
+ u8 old_m_control = m_control;
+
+ m_control = data;
+
+ switch (m_control & 0x03)
+ {
+ case 0:
+ case 2:
+ m_floppy = m_floppy0 ? m_floppy0->get_device() : nullptr;
+ break;
+
+ case 1:
+ m_floppy = m_floppy1 ? m_floppy1->get_device() : nullptr;
+ break;
+
+ default:
+ m_floppy = nullptr;
+ break;
+ }
+
+ if (m_floppy)
+ {
+ m_floppy->mon_w((m_control & 0x80) ? 0 : 1);
+ m_floppy->ss_w(m_side_control & 0x01);
+ }
+
+ m_fdc->set_floppy(m_floppy);
+
+ if ((old_m_control ^ m_control) & 0x40)
+ {
+ m_led = BIT(~m_control, 6);
+ }
+}
+
+void disk_type1_device::set_side_control(u8 data)
+{
+ m_side_control = data;
+
+ if (m_floppy)
+ {
+ m_floppy->ss_w(m_side_control & 0x01);
+ }
+}
+
+u8 disk_type1_device::side_control_r()
+{
+ return 0xfe | (m_side_control & 0x01);
+}
+
+u8 disk_type1_device::control_r()
+{
+ return (m_control & 0x83) | 0x78;
+}
+
+u8 disk_type1_device::status_r()
+{
+ return 0x3f | (m_fdc->intrq_r() ? 0 : 0x40) | (m_fdc->drq_r() ? 0 : 0x80);
+}
+
+
+
+class fd051_device : public disk_type1_device
+{
+public:
+ fd051_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : disk_type1_device(mconfig, MSX_CART_FD051, tag, owner, clock, PAGE0, PAGE3)
+ { }
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override
+ {
+ add_mconfig<F35, DS, FORCE_READY>(config, WD2793);
+ }
+};
+
+
+
+class fsfd1_device : public disk_type1_device
+{
+public:
+ fsfd1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : disk_type1_device(mconfig, MSX_CART_FSFD1, tag, owner, clock)
+ { }
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override
+ {
+ add_mconfig<F35, DS>(config, WD2793);
+ }
+};
+
+
+
+class hb3600_device : public disk_type1_device
+{
+public:
+ hb3600_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : disk_type1_device(mconfig, MSX_CART_HB3600, tag, owner, clock)
+ { }
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override
+ {
+ add_mconfig<F525, DS, FORCE_READY>(config, WD2793);
+ }
+};
+
+
+
+class hbd20w_device : public disk_type1_device
+{
+public:
+ hbd20w_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : disk_type1_device(mconfig, MSX_CART_HBD20W, tag, owner, clock)
+ { }
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override
+ {
+ add_mconfig<F35, DS>(config, WD2793);
+ }
+};
+
+
+
+class hbd50_device : public disk_type1_device
+{
+public:
+ hbd50_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : disk_type1_device(mconfig, MSX_CART_HBD50, tag, owner, clock, PAGE0, PAGE3)
+ { }
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override
+ {
+ add_mconfig<F35, SS>(config, WD2793);
+ }
+};
+
+
+
+class hbdf1_device : public disk_type1_device
+{
+public:
+ hbdf1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : disk_type1_device(mconfig, MSX_CART_HBDF1, tag, owner, clock)
+ { }
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override
+ {
+ add_mconfig<F35, DS>(config, WD2793);
+ }
+};
+
+
+
+class ml30dc_device : public disk_type1_device
+{
+public:
+ ml30dc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : disk_type1_device(mconfig, MSX_CART_ML30DC, tag, owner, clock)
+ { }
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override
+ {
+ add_mconfig<F35, DS, FORCE_READY>(config, WD2793);
+ // Optional second drive in the same enclosure
+ //FLOPPY_CONNECTOR(config, "fdc:1", msx_floppies, "35dd", msx_cart_disk_device::floppy_formats);
+ }
+};
+
+
+
+class nms1200_device : public disk_type1_device
+{
+public:
+ nms1200_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : disk_type1_device(mconfig, MSX_CART_NMS1200, tag, owner, clock)
+ { }
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override
+ {
+ add_mconfig<F35, DS, FORCE_READY>(config, WD2793);
+ }
+};
+
+
+
+class vy0010_device : public disk_type1_device
+{
+public:
+ vy0010_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : disk_type1_device(mconfig, MSX_CART_VY0010, tag, owner, clock)
+ { }
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override
+ {
+ add_mconfig<F35, SS, FORCE_READY>(config, WD2793);
+ }
+};
+
+
+
+class disk_type2_device : public disk_wd_device
+{
+public:
+ virtual std::error_condition initialize_cartridge(std::string &message) override;
+
+protected:
+ disk_type2_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, int fdc_regs_start_page = PAGE1, int fdc_regs_end_page = PAGE2)
+ : disk_wd_device(mconfig, type, tag, owner, clock, fdc_regs_start_page, fdc_regs_end_page)
+ , m_led(*this, "led0")
+ , m_control(0)
+ { }
+
+ // device_t implementation
+ virtual void device_start() override;
+ virtual void device_post_load() override;
+
+ void set_control(u8 data);
+ u8 status_r();
+
+ output_finder<> m_led;
+ u8 m_control;
+};
+
+void disk_type2_device::device_start()
+{
+ m_led.resolve();
+
+ save_item(NAME(m_control));
+}
+
+void disk_type2_device::device_post_load()
+{
+ set_control(m_control);
+}
+
+std::error_condition disk_type2_device::initialize_cartridge(std::string &message)
+{
+ std::error_condition result = disk_wd_device::initialize_cartridge(message);
+ if (result)
+ return result;
+
+ page(1)->install_rom(0x4000, 0x7fff, cart_rom_region()->base());
+ for (int i = m_fdc_regs_start_page; i <= m_fdc_regs_end_page; i++)
+ {
+ const offs_t base = 0x4000 * i;
+ page(i)->install_read_handler(base + 0x3fb8, base + 0x3fb8, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::status_r)));
+ page(i)->install_read_handler(base + 0x3fb9, base + 0x3fb9, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::track_r)));
+ page(i)->install_read_handler(base + 0x3fba, base + 0x3fba, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::sector_r)));
+ page(i)->install_read_handler(base + 0x3fbb, base + 0x3fbb, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::data_r)));
+ page(i)->install_read_handler(base + 0x3fbc, base + 0x3fbc, emu::rw_delegate(*this, FUNC(disk_type2_device::status_r)));
+ page(i)->install_write_handler(base + 0x3fb8, base + 0x3fb8, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::cmd_w)));
+ page(i)->install_write_handler(base + 0x3fb9, base + 0x3fb9, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::track_w)));
+ page(i)->install_write_handler(base + 0x3fba, base + 0x3fba, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::sector_w)));
+ page(i)->install_write_handler(base + 0x3fbb, base + 0x3fbb, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::data_w)));
+ page(i)->install_write_handler(base + 0x3fbc, base + 0x3fbc, emu::rw_delegate(*this, FUNC(disk_type2_device::set_control)));
+ }
+
+ return std::error_condition();
+}
+
+void disk_type2_device::set_control(u8 data)
+{
+ uint8_t old_m_control = m_control;
+
+ m_control = data;
+
+ switch (m_control & 3)
+ {
+ case 1:
+ m_floppy = m_floppy0 ? m_floppy0->get_device() : nullptr;
+ break;
+
+ case 2:
+ m_floppy = m_floppy1 ? m_floppy1->get_device() : nullptr;
+ break;
+
+ default:
+ m_floppy = nullptr;
+ break;
+ }
+
+ if (m_floppy)
+ {
+ m_floppy->mon_w((m_control & 0x08) ? 0 : 1);
+ m_floppy->ss_w((m_control & 0x04) ? 1 : 0);
+ }
+
+ m_fdc->set_floppy(m_floppy);
+
+ if ((old_m_control ^ m_control) & 0x40)
+ {
+ m_led = BIT(~m_control, 6);
+ }
+}
+
+u8 disk_type2_device::status_r()
+{
+ return 0x3f | (m_fdc->drq_r() ? 0 : 0x40) | (m_fdc->intrq_r() ? 0x80 : 0);
+}
+
+
+
+class fscf351_device : public disk_type2_device
+{
+public:
+ fscf351_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : disk_type2_device(mconfig, MSX_CART_FSCF351, tag, owner, clock)
+ { }
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override
+ {
+ add_mconfig<F35, DS, FORCE_READY>(config, MB8877);
+ }
+};
+
+
+
+class tadpf550_device : public disk_type2_device
+{
+public:
+ tadpf550_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : disk_type2_device(mconfig, MSX_CART_TADPF550, tag, owner, clock)
+ { }
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override
+ {
+ WD1770(config, m_fdc, 8_MHz_XTAL);
+ add_floppy_mconfig<F525, SS>(config);
+ }
+};
+
+
+
+class disk_type5_device : public disk_wd_device
+{
+public:
+ virtual std::error_condition initialize_cartridge(std::string &message) override;
+
+protected:
+ disk_type5_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
+ : disk_wd_device(mconfig, type, tag, owner, clock)
+ , m_control(0)
+ { }
+
+ // device_t implementation
+ virtual void device_start() override;
+ virtual void device_post_load() override;
+
+ void control_w(u8 control);
+ virtual u8 status_r();
+
+ u8 m_control;
+};
+
+void disk_type5_device::device_start()
+{
+ save_item(NAME(m_control));
+}
+
+std::error_condition disk_type5_device::initialize_cartridge(std::string &message)
+{
+ std::error_condition result = disk_wd_device::initialize_cartridge(message);
+ if (result)
+ return result;
+
+ page(1)->install_rom(0x4000, 0x7fff, cart_rom_region()->base());
+
+ // Install IO read/write handlers
+ io_space().install_write_handler(0xd0, 0xd0, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::cmd_w)));
+ io_space().install_write_handler(0xd1, 0xd1, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::track_w)));
+ io_space().install_write_handler(0xd2, 0xd2, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::sector_w)));
+ io_space().install_write_handler(0xd3, 0xd3, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::data_w)));
+ io_space().install_write_handler(0xd4, 0xd4, emu::rw_delegate(*this, FUNC(disk_type5_device::control_w)));
+ io_space().install_read_handler(0xd0, 0xd0, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::status_r)));
+ io_space().install_read_handler(0xd1, 0xd1, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::track_r)));
+ io_space().install_read_handler(0xd2, 0xd2, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::sector_r)));
+ io_space().install_read_handler(0xd3, 0xd3, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::data_r)));
+ io_space().install_read_handler(0xd4, 0xd4, emu::rw_delegate(*this, FUNC(disk_type5_device::status_r)));
+
+ return std::error_condition();
+}
+
+void disk_type5_device::device_post_load()
+{
+ control_w(m_control);
+}
+
+void disk_type5_device::control_w(u8 control)
+{
+ m_control = control;
+
+ switch (m_control & 0x0f)
+ {
+ case 0x01:
+ m_floppy = m_floppy0 ? m_floppy0->get_device() : nullptr;
+ break;
+
+ case 0x02:
+ m_floppy = m_floppy1 ? m_floppy1->get_device() : nullptr;
+ break;
+
+ default:
+ m_floppy = nullptr;
+ break;
+ }
+
+ if (m_floppy)
+ {
+ m_floppy->mon_w(BIT(m_control, 5) ? 0 : 1);
+ m_floppy->ss_w(BIT(m_control, 4) ? 1 : 0);
+ }
+
+ m_fdc->set_floppy(m_floppy);
+}
+
+u8 disk_type5_device::status_r()
+{
+ return 0x3f | (m_fdc->drq_r() ? 0 : 0x40) | (m_fdc->intrq_r() ? 0x80 : 0);
+}
+
+
+class cdx2_device : public disk_type5_device
+{
+public:
+ cdx2_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : disk_type5_device(mconfig, MSX_CART_CDX2, tag, owner, clock)
+ { }
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override
+ {
+ add_mconfig<F525, DS>(config, WD2793);
+ }
+};
+
+
+class ddx3_device : public disk_type5_device
+{
+public:
+ ddx3_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : disk_type5_device(mconfig, MSX_CART_DDX3, tag, owner, clock)
+ { }
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override
+ {
+ add_mconfig<F525, DS, FORCE_READY>(config, WD2793);
+ }
+};
+
+
+
+class fsfd1a_device : public disk_tc8566_device
+{
+public:
+ fsfd1a_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : disk_tc8566_device(mconfig, MSX_CART_FSFD1A, tag, owner, clock)
+ { }
+
+ virtual std::error_condition initialize_cartridge(std::string &message) override;
+
+protected:
+ // device_t implementation
+ virtual void device_start() override { }
+ virtual void device_add_mconfig(machine_config &config) override
+ {
+ TC8566AF(config, m_fdc, 16'000'000);
+ add_floppy_mconfig<F35, DS>(config);
+ }
+};
+
+std::error_condition fsfd1a_device::initialize_cartridge(std::string &message)
+{
+ std::error_condition result = disk_tc8566_device::initialize_cartridge(message);
+ if (result)
+ return result;
+
+ page(1)->install_rom(0x4000, 0x7fff, cart_rom_region()->base());
+ for (int i = m_fdc_regs_start_page; i <= m_fdc_regs_end_page; i++)
+ {
+ const offs_t base = 0x4000 * i;
+ page(i)->install_read_handler(base + 0x3ffa, base + 0x3ffa, emu::rw_delegate(*m_fdc, FUNC(tc8566af_device::msr_r)));
+ page(i)->install_read_handler(base + 0x3ffb, base + 0x3ffb, emu::rw_delegate(*m_fdc, FUNC(tc8566af_device::fifo_r)));
+ page(i)->install_write_handler(base + 0x3ff8, base + 0x3ff8, emu::rw_delegate(*m_fdc, FUNC(tc8566af_device::dor_w)));
+ page(i)->install_write_handler(base + 0x3ff9, base + 0x3ff9, emu::rw_delegate(*m_fdc, FUNC(tc8566af_device::cr1_w)));
+ page(i)->install_write_handler(base + 0x3ffb, base + 0x3ffb, emu::rw_delegate(*m_fdc, FUNC(tc8566af_device::fifo_w)));
+ }
+
+ return std::error_condition();
+}
+
+
+
+class fd03_device : public disk_wd_device
+{
+public:
+ fd03_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : disk_wd_device(mconfig, MSX_CART_FD03, tag, owner, clock)
+ , m_led(*this, "led0")
+ , m_control(0)
+ { }
+
+ virtual std::error_condition initialize_cartridge(std::string &message) override;
+
+protected:
+ // device_t implementation
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_start() override;
+ virtual void device_post_load() override;
+
+ u8 status_r();
+ u8 dskchg_r();
+ void set_control(u8 data);
+ void dskchg_w(u8 data);
+
+ output_finder<> m_led;
+ u8 m_control;
+};
+
+void fd03_device::device_add_mconfig(machine_config &config)
+{
+ add_mconfig<F35, SS>(config, FD1793);
+}
+
+void fd03_device::device_start()
+{
+ m_led.resolve();
+
+ save_item(NAME(m_control));
+}
+
+std::error_condition fd03_device::initialize_cartridge(std::string &message)
+{
+ if (!cart_rom_region())
+ {
+ message = "fd03_device:: Required region 'rom' was not found.";
+ return image_error::INTERNAL;
+ }
+
+ if (cart_rom_region()->bytes() != 0x4000 && cart_rom_region()->bytes() != 0x8000)
+ {
+ message = "fd03_device: Region 'rom' has unsupported size.";
+ return image_error::INVALIDLENGTH;
+ }
+
+ page(1)->install_rom(0x4000, 0x7fff, cart_rom_region()->base());
+ if (cart_rom_region()->bytes() >= 0x8000)
+ page(2)->install_rom(0x8000,0xbfff, cart_rom_region()->base() + 0x4000);
+
+ for (int i = m_fdc_regs_start_page; i <= m_fdc_regs_end_page; i++)
+ {
+ const offs_t base = 0x4000 * i;
+ page(i)->install_read_handler(base + 0x3fc0, base + 0x3fc0, 0, 0x001c, 0, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::status_r)));
+ page(i)->install_read_handler(base + 0x3fc1, base + 0x3fc1, 0, 0x001c, 0, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::track_r)));
+ page(i)->install_read_handler(base + 0x3fc2, base + 0x3fc2, 0, 0x001c, 0, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::sector_r)));
+ page(i)->install_read_handler(base + 0x3fc3, base + 0x3fc3, 0, 0x001c, 0, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::data_r)));
+ page(i)->install_read_handler(base + 0x3fe0, base + 0x3fef, emu::rw_delegate(*this, FUNC(fd03_device::status_r)));
+ page(i)->install_read_handler(base + 0x3ff0, base + 0x3fff, emu::rw_delegate(*this, FUNC(fd03_device::dskchg_r)));
+ page(i)->install_write_handler(base + 0x3fc0, base + 0x3fc0, 0, 0x001c, 0, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::cmd_w)));
+ page(i)->install_write_handler(base + 0x3fc1, base + 0x3fc1, 0, 0x001c, 0, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::track_w)));
+ page(i)->install_write_handler(base + 0x3fc2, base + 0x3fc2, 0, 0x001c, 0, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::sector_w)));
+ page(i)->install_write_handler(base + 0x3fc3, base + 0x3fc3, 0, 0x001c, 0, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::data_w)));
+ page(i)->install_write_handler(base + 0x3fe0, base + 0x3fef, emu::rw_delegate(*this, FUNC(fd03_device::set_control)));
+ page(i)->install_write_handler(base + 0x3ff0, base + 0x3fff, emu::rw_delegate(*this, FUNC(fd03_device::dskchg_w)));
+ }
+
+ return std::error_condition();
+}
+
+void fd03_device::device_post_load()
+{
+ set_control(m_control);
+}
+
+void fd03_device::set_control(u8 data)
+{
+ u8 old_m_control = m_control;
+
+ m_control = data;
+
+ switch (m_control & 0x03)
+ {
+ case 1:
+ m_floppy = m_floppy0 ? m_floppy0->get_device() : nullptr;
+ break;
+
+ case 2:
+ m_floppy = m_floppy1 ? m_floppy1->get_device() : nullptr;
+ break;
+
+ default:
+ m_floppy = nullptr;
+ break;
+ }
+
+ if (m_floppy)
+ {
+ m_floppy->mon_w(BIT(m_control, 2) ? 0 : 1);
+ }
+
+ m_fdc->set_floppy(m_floppy);
+
+ if ((old_m_control ^ m_control) & 0x40)
+ {
+ m_led = BIT(~m_control, 6);
+ }
+}
+
+u8 fd03_device::status_r()
+{
+ // bit 0 - drive 0 ready / has media
+ // bit 1 - drive 1 ready / has media
+ // bit 2 - diskchange drive 0
+ // bit 3 - diskchange drive 1
+ u8 result = 0x30;
+ if (!m_floppy0)
+ result |= 0x01;
+ if (!m_floppy1)
+ result |= 0x02;
+ if (m_floppy0 && m_floppy0->get_device()->dskchg_r())
+ result |= 0x04;
+ if (m_floppy1 && m_floppy1->get_device()->dskchg_r())
+ result |= 0x08;
+
+ return result | (m_fdc->intrq_r() ? 0x80 : 0) | (m_fdc->drq_r() ? 0x40 : 0);
+}
+
+u8 fd03_device::dskchg_r()
+{
+ if (m_floppy1)
+ m_floppy1->get_device()->dskchg_w(0);
+
+ return 0xff;
+}
+
+void fd03_device::dskchg_w(u8 data)
+{
+ if (m_floppy0)
+ m_floppy0->get_device()->dskchg_w(0);
+}
+
+
+
+class hxf101pe_device : public disk_wd_device
+{
+public:
+ hxf101pe_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : disk_wd_device(mconfig, MSX_CART_HXF101PE, tag, owner, clock, PAGE1, PAGE1)
+ , m_side_motor(0)
+ , m_drive_select0(0)
+ , m_drive_select1(0)
+ { }
+
+ virtual std::error_condition initialize_cartridge(std::string &message) override;
+
+protected:
+ // device_t implementation
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_start() override;
+ virtual void device_post_load() override;
+
+ void set_side_motor();
+ void select_drive();
+ u8 side_motor_r();
+ u8 select0_r();
+ u8 select1_r();
+ u8 status_r();
+ void side_motor_w(u8 data);
+ void select0_w(u8 data);
+ void select1_w(u8 data);
+
+ u8 m_side_motor;
+ u8 m_drive_select0;
+ u8 m_drive_select1;
+};
+
+void hxf101pe_device::device_add_mconfig(machine_config &config)
+{
+ add_mconfig<F35, SS>(config, WD2793);
+}
+
+void hxf101pe_device::device_start()
+{
+ save_item(NAME(m_side_motor));
+ save_item(NAME(m_drive_select0));
+ save_item(NAME(m_drive_select1));
+}
+
+std::error_condition hxf101pe_device::initialize_cartridge(std::string &message)
+{
+ std::error_condition result = disk_wd_device::initialize_cartridge(message);
+ if (result)
+ return result;
+
+ page(1)->install_rom(0x4000, 0x7fff, cart_rom_region()->base());
+ page(1)->install_read_handler(0x7ff0, 0x7ff0, 0, 0x0008, 0, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::status_r)));
+ page(1)->install_read_handler(0x7ff1, 0x7ff1, 0, 0x0008, 0, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::track_r)));
+ page(1)->install_read_handler(0x7ff2, 0x7ff2, 0, 0x0008, 0, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::sector_r)));
+ page(1)->install_read_handler(0x7ff3, 0x7ff3, 0, 0x0008, 0, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::data_r)));
+ page(1)->install_read_handler(0x7ff4, 0x7ff4, 0, 0x0008, 0, emu::rw_delegate(*this, FUNC(hxf101pe_device::side_motor_r)));
+ page(1)->install_read_handler(0x7ff5, 0x7ff5, 0, 0x0008, 0, emu::rw_delegate(*this, FUNC(hxf101pe_device::select0_r)));
+ page(1)->install_read_handler(0x7ff6, 0x7ff6, 0, 0x0008, 0, emu::rw_delegate(*this, FUNC(hxf101pe_device::select1_r)));
+ page(1)->install_read_handler(0x7ff7, 0x7ff7, 0, 0x0008, 0, emu::rw_delegate(*this, FUNC(hxf101pe_device::status_r)));
+ page(1)->install_write_handler(0x7ff0, 0x7ff0, 0, 0x0008, 0, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::cmd_w)));
+ page(1)->install_write_handler(0x7ff1, 0x7ff1, 0, 0x0008, 0, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::track_w)));
+ page(1)->install_write_handler(0x7ff2, 0x7ff2, 0, 0x0008, 0, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::sector_w)));
+ page(1)->install_write_handler(0x7ff3, 0x7ff3, 0, 0x0008, 0, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::data_w)));
+ page(1)->install_write_handler(0x7ff4, 0x7ff4, 0, 0x0008, 0, emu::rw_delegate(*this, FUNC(hxf101pe_device::side_motor_w)));
+ page(1)->install_write_handler(0x7ff5, 0x7ff5, 0, 0x0008, 0, emu::rw_delegate(*this, FUNC(hxf101pe_device::select0_w)));
+ page(1)->install_write_handler(0x7ff6, 0x7ff6, 0, 0x0008, 0, emu::rw_delegate(*this, FUNC(hxf101pe_device::select1_w)));
+
+ return std::error_condition();
+}
+
+void hxf101pe_device::device_post_load()
+{
+ select_drive();
+}
+
+void hxf101pe_device::select_drive()
+{
+ if (m_drive_select1)
+ {
+ m_floppy = m_floppy1 ? m_floppy1->get_device() : nullptr;
+ if (!m_floppy)
+ m_drive_select1 = 0;
+ }
+
+ if (m_drive_select0)
+ {
+ m_floppy = m_floppy0 ? m_floppy0->get_device() : nullptr;
+ if (!m_floppy)
+ m_drive_select0 = 0;
+ }
+
+ m_fdc->set_floppy(m_floppy);
+
+ set_side_motor();
+}
+
+void hxf101pe_device::set_side_motor()
+{
+ if (m_floppy)
+ {
+ m_floppy->mon_w(BIT(m_side_motor, 1) ? 0 : 1);
+ m_floppy->ss_w(BIT(m_side_motor, 0));
+ }
+}
+
+u8 hxf101pe_device::side_motor_r()
+{
+ // bit 0 = side control
+ // bit 1 = motor control
+ return 0xfc | m_side_motor;
+}
+
+u8 hxf101pe_device::select0_r()
+{
+ // This reads back a 1 in bit 0 if drive0 is present and selected
+ return 0xfe | m_drive_select0;
+}
+
+u8 hxf101pe_device::select1_r()
+{
+ // This reads back a 1 in bit 0 if drive1 is present and selected
+ return 0xfe | m_drive_select1;
+}
+
+u8 hxf101pe_device::status_r()
+{
+ return 0x3f | (m_fdc->intrq_r() ? 0 : 0x40) | (m_fdc->drq_r() ? 0 : 0x80);
+}
+
+void hxf101pe_device::side_motor_w(u8 data)
+{
+ // Side and motor control
+ // bit 0 = side select
+ // bit 1 = motor on/off
+ m_side_motor = data;
+ set_side_motor();
+}
+
+void hxf101pe_device::select0_w(u8 data)
+{
+ // bit 0 - select drive 0
+ m_drive_select0 = data;
+ select_drive();
+}
+
+void hxf101pe_device::select1_w(u8 data)
+{
+ // bit 1 - select drive 1
+ m_drive_select1 = data;
+ select_drive();
+}
+
+
+
+class mfd001_device : public disk_wd_device
+{
+public:
+ mfd001_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : disk_wd_device(mconfig, MSX_CART_MFD001, tag, owner, clock)
+ , m_control(0)
+ { }
+
+ virtual std::error_condition initialize_cartridge(std::string &message) override;
+
+protected:
+ // device_t implementation
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_start() override;
+ virtual void device_post_load() override;
+
+ void set_side_motor();
+ void select_drive();
+ u8 status_r();
+ void control_w(u8 data);
+
+ u8 m_control;
+};
+
+void mfd001_device::device_add_mconfig(machine_config &config)
+{
+ add_mconfig<F525, DS>(config, MB8877);
+}
+
+std::error_condition mfd001_device::initialize_cartridge(std::string &message)
+{
+ std::error_condition result = disk_wd_device::initialize_cartridge(message);
+ if (result)
+ return result;
+
+ page(1)->install_rom(0x4000, 0x7fff, cart_rom_region()->base());
+
+ for (int i = m_fdc_regs_start_page; i <= m_fdc_regs_end_page; i++)
+ {
+ const offs_t base = 0x4000 * i;
+ page(i)->install_read_handler(base + 0x3ff8, base + 0x3ff8, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::status_r)));
+ page(i)->install_read_handler(base + 0x3ff9, base + 0x3ff9, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::track_r)));
+ page(i)->install_read_handler(base + 0x3ffa, base + 0x3ffa, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::sector_r)));
+ page(i)->install_read_handler(base + 0x3ffb, base + 0x3ffb, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::data_r)));
+ page(i)->install_read_handler(base + 0x3ffc, base + 0x3ffc, emu::rw_delegate(*this, FUNC(mfd001_device::status_r)));
+ page(i)->install_write_handler(base + 0x3ff8, base + 0x3ff8, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::cmd_w)));
+ page(i)->install_write_handler(base + 0x3ff9, base + 0x3ff9, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::track_w)));
+ page(i)->install_write_handler(base + 0x3ffa, base + 0x3ffa, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::sector_w)));
+ page(i)->install_write_handler(base + 0x3ffb, base + 0x3ffb, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::data_w)));
+ page(i)->install_write_handler(base + 0x3ffc, base + 0x3ffc, emu::rw_delegate(*this, FUNC(mfd001_device::control_w)));
+ }
+
+ return std::error_condition();
+}
+
+void mfd001_device::device_start()
+{
+ save_item(NAME(m_control));
+}
+
+void mfd001_device::device_post_load()
+{
+ select_drive();
+}
+
+void mfd001_device::select_drive()
+{
+ if (BIT(m_control, 0))
+ {
+ m_floppy = m_floppy0 ? m_floppy0->get_device() : nullptr;
+ }
+
+ if (BIT(m_control, 1))
+ {
+ m_floppy = m_floppy1 ? m_floppy1->get_device() : nullptr;
+ }
+
+ m_fdc->set_floppy(m_floppy);
+
+ if (m_floppy)
+ {
+ m_floppy->mon_w(BIT(m_control, 3) ? 0 : 1);
+ m_floppy->ss_w(BIT(m_control, 2));
+ }
+}
+
+u8 mfd001_device::status_r()
+{
+ return 0x3f | (m_fdc->intrq_r() ? 0x80 : 0) | (m_fdc->drq_r() ? 0x40 : 0);
+}
+
+void mfd001_device::control_w(u8 data)
+{
+ // Drive, side and motor control
+ // bit 0 = select drive 0
+ // bit 1 = select drive 1
+ // bit 2 = side select
+ // bit 3 = motor on/off
+ m_control = data;
+ select_drive();
+}
+
+
+class avdpf550_device : public disk_wd_device
+{
+public:
+ avdpf550_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : disk_wd_device(mconfig, MSX_CART_AVDPF550, tag, owner, clock)
+ , m_control(0)
+ { }
+
+ virtual std::error_condition initialize_cartridge(std::string &message) override;
+
+protected:
+ // device_t implementation
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_start() override;
+ virtual void device_post_load() override;
+
+ void control_w(u8 control);
+ virtual u8 status_r();
+
+ u8 m_control;
+};
+
+void avdpf550_device::device_add_mconfig(machine_config &config)
+{
+ WD1770(config, m_fdc, 8_MHz_XTAL);
+ add_floppy_mconfig<F525, SS>(config);
+}
+
+void avdpf550_device::device_start()
+{
+ save_item(NAME(m_control));
+}
+
+std::error_condition avdpf550_device::initialize_cartridge(std::string &message)
+{
+ std::error_condition result = disk_wd_device::initialize_cartridge(message);
+ if (result)
+ return result;
+
+ page(1)->install_rom(0x4000, 0x7fff, cart_rom_region()->base());
+
+ // Install IO read/write handlers
+ io_space().install_write_handler(0xd0, 0xd0, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::cmd_w)));
+ io_space().install_write_handler(0xd1, 0xd1, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::track_w)));
+ io_space().install_write_handler(0xd2, 0xd2, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::sector_w)));
+ io_space().install_write_handler(0xd3, 0xd3, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::data_w)));
+ io_space().install_write_handler(0xd5, 0xd5, emu::rw_delegate(*this, FUNC(avdpf550_device::control_w)));
+ io_space().install_read_handler(0xd0, 0xd0, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::status_r)));
+ io_space().install_read_handler(0xd1, 0xd1, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::track_r)));
+ io_space().install_read_handler(0xd2, 0xd2, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::sector_r)));
+ io_space().install_read_handler(0xd3, 0xd3, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::data_r)));
+ io_space().install_read_handler(0xd4, 0xd4, emu::rw_delegate(*this, FUNC(avdpf550_device::status_r)));
+
+ return std::error_condition();
+}
+
+void avdpf550_device::device_post_load()
+{
+ control_w(m_control);
+}
+
+void avdpf550_device::control_w(u8 control)
+{
+ m_control = control;
+
+ switch (m_control & 0x03)
+ {
+ case 0x01:
+ m_floppy = m_floppy0 ? m_floppy0->get_device() : nullptr;
+ break;
+
+ case 0x02:
+ m_floppy = m_floppy1 ? m_floppy1->get_device() : nullptr;
+ break;
+
+ default:
+ m_floppy = nullptr;
+ break;
+ }
+
+ if (m_floppy)
+ {
+ m_floppy->mon_w(0);
+ m_floppy->ss_w(BIT(m_control, 2) ? 1 : 0);
+ }
+
+ m_fdc->set_floppy(m_floppy);
+}
+
+u8 avdpf550_device::status_r()
+{
+ return 0x3f | (m_fdc->drq_r() ? 0 : 0x40) | (m_fdc->intrq_r() ? 0x80 : 0);
+}
+
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_AVDPF550, msx_cart_interface, avdpf550_device, "msx_cart_avdpf550", "MSX Cartridge - AVT DPF-550")
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_CDX2, msx_cart_interface, cdx2_device, "msx_cart_cdx2", "MSX Cartridge - CDX-2")
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_DDX3, msx_cart_interface, ddx3_device, "msx_cart_ddx3", "MSX Cartridge - DDX3.0")
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_FD03, msx_cart_interface, fd03_device, "msx_cart_fd03", "MSX Cartridge - FD-03")
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_FD051, msx_cart_interface, fd051_device, "msx_cart_fd051", "MSX Cartridge - FD-051")
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_FSFD1, msx_cart_interface, fsfd1_device, "msx_cart_fsfd1", "MSX Cartridge - FS-FD1")
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_FSFD1A, msx_cart_interface, fsfd1a_device, "msx_cart_fsfd1a", "MSX Cartridge - FS-FD1A")
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_FSCF351, msx_cart_interface, fscf351_device, "msx_cart_fscf351", "MSX Cartridge - FS-CF351")
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_HB3600, msx_cart_interface, hb3600_device, "msx_cart_hb3600", "MSX Cartridge - HB-3600")
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_HBD20W, msx_cart_interface, hbd20w_device, "msx_cart_hbd20w", "MSX Cartridge - HBD-20W")
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_HBD50, msx_cart_interface, hbd50_device, "msx_cart_hbd50", "MSX Cartridge - HBD-50")
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_HBDF1, msx_cart_interface, hbdf1_device, "msx_cart_hbdf1", "MSX Cartridge - HBD-F1")
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_HXF101PE, msx_cart_interface, hxf101pe_device, "msx_cart_hxf101pe", "MSX Cartridge - HX-F101PE")
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_MFD001, msx_cart_interface, mfd001_device, "msx_cart_mfd001", "MSX Cartridge - MFD-001")
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_ML30DC, msx_cart_interface, ml30dc_device, "msx_cart_ml30dc", "MSX Cartridge - ML-30DC")
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_NMS1200, msx_cart_interface, nms1200_device, "msx_cart_nms1200", "MSX Cartridge - NMS-1200")
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_TADPF550, msx_cart_interface, tadpf550_device, "msx_cart_tadpf550", "MSX Cartridge - Talent DPF-550")
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_VY0010, msx_cart_interface, vy0010_device, "msx_cart_vy0010", "MSX Cartridge - VY0010")
diff --git a/src/devices/bus/msx/cart/disk.h b/src/devices/bus/msx/cart/disk.h
new file mode 100644
index 00000000000..0f6c12b183d
--- /dev/null
+++ b/src/devices/bus/msx/cart/disk.h
@@ -0,0 +1,10 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#ifndef MAME_BUS_MSX_CART_DISK_H
+#define MAME_BUS_MSX_CART_DISK_H
+
+#pragma once
+
+void msx_cart_disk_register_options(device_slot_interface &device);
+
+#endif // MAME_BUS_MSX_CART_DISK_H
diff --git a/src/devices/bus/msx/cart/dooly.cpp b/src/devices/bus/msx/cart/dooly.cpp
new file mode 100644
index 00000000000..b01baf35bf2
--- /dev/null
+++ b/src/devices/bus/msx/cart/dooly.cpp
@@ -0,0 +1,84 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#include "emu.h"
+#include "dooly.h"
+
+namespace {
+
+class msx_cart_dooly_device : public device_t, public msx_cart_interface
+{
+public:
+ msx_cart_dooly_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MSX_CART_DOOLY, tag, owner, clock)
+ , msx_cart_interface(mconfig, *this)
+ , m_rombank(*this, "bank%u", 0U)
+ { }
+
+ virtual std::error_condition initialize_cartridge(std::string &message) override;
+
+protected:
+ // device_t implementation
+ virtual void device_start() override { }
+ virtual void device_reset() override;
+
+private:
+ void prot_w(u8 data);
+ u8 mode4_page1_r(offs_t offset);
+ u8 mode4_page2_r(offs_t offset);
+
+ std::unique_ptr<u8[]> m_bitswapped;
+ memory_bank_array_creator<2> m_rombank;
+};
+
+void msx_cart_dooly_device::device_reset()
+{
+ m_rombank[0]->set_entry(0);
+ m_rombank[1]->set_entry(0);
+}
+
+std::error_condition msx_cart_dooly_device::initialize_cartridge(std::string &message)
+{
+ if (!cart_rom_region())
+ {
+ message = "msx_cart_dooly_device: Required region 'rom' was not found.";
+ return image_error::INTERNAL;
+ }
+
+ if (cart_rom_region()->bytes() != 0x8000)
+ {
+ message = "msx_cart_dooly_device: Region 'rom' has unsupported size.";
+ return image_error::INVALIDLENGTH;
+ }
+
+ m_bitswapped = std::make_unique<u8[]>(0x8000);
+ for (int i = 0; i < 0x8000; i++)
+ m_bitswapped[i] = bitswap<8>(cart_rom_region()->base()[i], 7, 6, 5, 4, 3, 1, 0, 2);
+
+ m_rombank[0]->configure_entry(0, cart_rom_region()->base());
+ m_rombank[0]->configure_entry(1, m_bitswapped.get());
+ m_rombank[1]->configure_entry(0, cart_rom_region()->base() + 0x4000);
+ m_rombank[1]->configure_entry(1, m_bitswapped.get() + 0x4000);
+
+ page(1)->install_read_bank(0x4000, 0x7fff, m_rombank[0]);
+ page(1)->install_write_handler(0x4000, 0x7fff, emu::rw_delegate(*this, FUNC(msx_cart_dooly_device::prot_w)));
+ page(2)->install_read_bank(0x8000, 0xbfff, m_rombank[1]);
+ page(2)->install_write_handler(0x8000, 0xbfff, emu::rw_delegate(*this, FUNC(msx_cart_dooly_device::prot_w)));
+
+ return std::error_condition();
+}
+
+void msx_cart_dooly_device::prot_w(u8 data)
+{
+ data &= 0x07;
+ m_rombank[0]->set_entry(BIT(data, 2) ? 1 : 0);
+ m_rombank[1]->set_entry(BIT(data, 2) ? 1 : 0);
+
+ if (data != 0 && data != 4)
+ {
+ logerror("msx_cart_dooly_device: unhandled protection mode %02x\n", data);
+ }
+}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_DOOLY, msx_cart_interface, msx_cart_dooly_device, "msx_cart_dooly", "MSX Cartridge - Dooly")
diff --git a/src/devices/bus/msx/cart/dooly.h b/src/devices/bus/msx/cart/dooly.h
new file mode 100644
index 00000000000..cccba10daef
--- /dev/null
+++ b/src/devices/bus/msx/cart/dooly.h
@@ -0,0 +1,13 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#ifndef MAME_BUS_MSX_CART_DOOLY_H
+#define MAME_BUS_MSX_CART_DOOLY_H
+
+#pragma once
+
+#include "bus/msx/slot/cartridge.h"
+
+
+DECLARE_DEVICE_TYPE(MSX_CART_DOOLY, msx_cart_interface)
+
+#endif // MAME_BUS_MSX_CART_DOOLY_H
diff --git a/src/devices/bus/msx/cart/easi_speech.cpp b/src/devices/bus/msx/cart/easi_speech.cpp
new file mode 100644
index 00000000000..8b9b1f087f3
--- /dev/null
+++ b/src/devices/bus/msx/cart/easi_speech.cpp
@@ -0,0 +1,98 @@
+// license:BSD-3-Clause
+// copyright-holders:hap
+/******************************************************************************
+
+Easi-Speech cartridge (R.Amy, 1987)
+It has a GI SP0256A-AL2 (no XTAL)
+
+The program adds a hook to 0xfd29, usage appears to be something like this:
+n%=(number 0-511):a=usr9(n%)
+or a=usr9(number)
+
+Or a custom string:
+a$="hello world":a$=usr9(a$)
+or a$=usr9("string")
+
+******************************************************************************/
+
+#include "emu.h"
+#include "easi_speech.h"
+#include "sound/sp0256.h"
+
+namespace {
+
+class msx_cart_easispeech_device : public device_t, public msx_cart_interface
+{
+public:
+ msx_cart_easispeech_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MSX_CART_EASISPEECH, tag, owner, clock)
+ , msx_cart_interface(mconfig, *this)
+ , m_speech(*this, "speech")
+ { }
+
+ virtual std::error_condition initialize_cartridge(std::string &message) override;
+
+protected:
+ // device_t implementation
+ virtual void device_start() override { }
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+private:
+ u8 speech_r();
+ void speech_w(u8 data);
+
+ required_device<sp0256_device> m_speech;
+};
+
+ROM_START(msx_cart_easispeech)
+ ROM_REGION(0x10000, "speech", 0)
+ ROM_LOAD("sp0256a-al2", 0x1000, 0x0800, CRC(b504ac15) SHA1(e60fcb5fa16ff3f3b69d36c7a6e955744d3feafc) )
+ROM_END
+
+const tiny_rom_entry *msx_cart_easispeech_device::device_rom_region() const
+{
+ return ROM_NAME(msx_cart_easispeech);
+}
+
+void msx_cart_easispeech_device::device_add_mconfig(machine_config &config)
+{
+ SP0256(config, m_speech, DERIVED_CLOCK(1, 1)); // appears to be connected to slot CLOCK pin
+ if (parent_slot())
+ m_speech->add_route(ALL_OUTPUTS, soundin(), 1.0);
+}
+
+std::error_condition msx_cart_easispeech_device::initialize_cartridge(std::string &message)
+{
+ if (!cart_rom_region())
+ {
+ message = "msx_cart_easispeech_device: Required region 'rom' was not found.";
+ return image_error::INTERNAL;
+ }
+
+ if (cart_rom_region()->bytes() != 0x2000)
+ {
+ message = "msx_cart_easispeech_device: Region 'rom' has unsupported size.";
+ return image_error::INVALIDLENGTH;
+ }
+
+ page(1)->install_rom(0x4000, 0x5fff, 0x2000, cart_rom_region()->base());
+ page(2)->install_read_handler(0x8000, 0x8000, emu::rw_delegate(*this, FUNC(msx_cart_easispeech_device::speech_r)));
+ page(2)->install_write_handler(0x8000, 0x8000, emu::rw_delegate(*this, FUNC(msx_cart_easispeech_device::speech_w)));
+
+ return std::error_condition();
+}
+
+u8 msx_cart_easispeech_device::speech_r()
+{
+ return m_speech->lrq_r() << 7;
+}
+
+void msx_cart_easispeech_device::speech_w(u8 data)
+{
+ m_speech->ald_w(bitswap<6>(data,3,5,7,6,4,2));
+}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_EASISPEECH, msx_cart_interface, msx_cart_easispeech_device, "msx_cart_easispeech", "MSX Cartridge - Easi-Speech")
diff --git a/src/devices/bus/msx/cart/easi_speech.h b/src/devices/bus/msx/cart/easi_speech.h
new file mode 100644
index 00000000000..2403603c02a
--- /dev/null
+++ b/src/devices/bus/msx/cart/easi_speech.h
@@ -0,0 +1,13 @@
+// license:BSD-3-Clause
+// copyright-holders:hap
+#ifndef MAME_BUS_MSX_CART_EASISPEECH_H
+#define MAME_BUS_MSX_CART_EASISPEECH_H
+
+#pragma once
+
+#include "bus/msx/slot/cartridge.h"
+
+
+DECLARE_DEVICE_TYPE(MSX_CART_EASISPEECH, msx_cart_interface)
+
+#endif // MAME_BUS_MSX_CART_EASISPEECH_H
diff --git a/src/devices/bus/msx/cart/fmpac.cpp b/src/devices/bus/msx/cart/fmpac.cpp
new file mode 100644
index 00000000000..b9251656f0a
--- /dev/null
+++ b/src/devices/bus/msx/cart/fmpac.cpp
@@ -0,0 +1,178 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+/**********************************************************************************
+
+When backing up the SRAM from an FM-PAC the file seems to be prefixed
+with: PAC2 BACKUP DATA. We only store the raw sram contents.
+
+**********************************************************************************/
+
+#include "emu.h"
+#include "fmpac.h"
+
+#include "sound/ymopl.h"
+
+#include "speaker.h"
+
+
+namespace {
+
+class msx_cart_fmpac_device : public device_t, public msx_cart_interface
+{
+public:
+ msx_cart_fmpac_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MSX_CART_FMPAC, tag, owner, clock)
+ , msx_cart_interface(mconfig, *this)
+ , m_ym2413(*this, "ym2413")
+ , m_rombank(*this, "rombank")
+ , m_view(*this, "view")
+ , m_sram_active(false)
+ , m_opll_active(false)
+ , m_sram_unlock{0, 0}
+ , m_control(0)
+ { }
+
+ virtual std::error_condition initialize_cartridge(std::string &message) override;
+
+protected:
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ // device_t implementation
+ virtual void device_add_mconfig(machine_config &config) override;
+
+private:
+ void write_ym2413(offs_t offset, u8 data);
+ void sram_unlock(offs_t offset, u8 data);
+ u8 control_r();
+ void control_w(u8 data);
+ u8 bank_r();
+ void bank_w(u8 data);
+
+ required_device<ym2413_device> m_ym2413;
+ memory_bank_creator m_rombank;
+ memory_view m_view;
+
+ bool m_sram_active;
+ bool m_opll_active;
+ u8 m_sram_unlock[2];
+ u8 m_control;
+};
+
+void msx_cart_fmpac_device::device_add_mconfig(machine_config &config)
+{
+ YM2413(config, m_ym2413, DERIVED_CLOCK(1, 1));
+ if (parent_slot())
+ m_ym2413->add_route(ALL_OUTPUTS, soundin(), 0.8);
+}
+
+void msx_cart_fmpac_device::device_start()
+{
+ save_item(NAME(m_sram_active));
+ save_item(NAME(m_opll_active));
+ save_item(NAME(m_sram_unlock));
+ save_item(NAME(m_control));
+
+ // Install IO read/write handlers
+ io_space().install_write_handler(0x7c, 0x7d, emu::rw_delegate(*this, FUNC(msx_cart_fmpac_device::write_ym2413)));
+}
+
+void msx_cart_fmpac_device::device_reset()
+{
+ m_sram_active = false;
+ m_opll_active = false;
+ m_sram_unlock[0] = 0;
+ m_sram_unlock[1] = 0;
+ m_control = 0;
+ m_view.select(0);
+ m_rombank->set_entry(0);
+
+}
+
+std::error_condition msx_cart_fmpac_device::initialize_cartridge(std::string &message)
+{
+ if (!cart_rom_region())
+ {
+ message = "msx_cart_fmpac_device: Required region 'rom' was not found.";
+ return image_error::INTERNAL;
+ }
+
+ if (!cart_sram_region())
+ {
+ message = "msx_cart_fmpac_device: Required region 'sram' was not found.";
+ return image_error::INTERNAL;
+ }
+
+ if (cart_rom_region()->bytes() != 0x10000)
+ {
+ message = "msx_cart_fmpac_device: Region 'rom' has unsupported size.";
+ return image_error::INVALIDLENGTH;
+ }
+
+ if (cart_sram_region()->bytes() < 0x2000)
+ {
+ message = "msx_cart_fmpac_device: Region 'sram' has unsupported size.";
+ return image_error::BADSOFTWARE;
+ }
+
+ m_rombank->configure_entries(0, 4, cart_rom_region()->base(), 0x4000);
+
+ page(1)->install_view(0x4000, 0x7fff, m_view);
+ m_view[0].install_read_bank(0x4000, 0x7fff, m_rombank);
+ m_view[0].install_write_handler(0x5ffe, 0x5fff, emu::rw_delegate(*this, FUNC(msx_cart_fmpac_device::sram_unlock)));
+ m_view[0].install_write_handler(0x7ff4, 0x7ff5, emu::rw_delegate(*this, FUNC(msx_cart_fmpac_device::write_ym2413)));
+ m_view[0].install_read_handler(0x7ff6, 0x7ff6, emu::rw_delegate(*this, FUNC(msx_cart_fmpac_device::control_r)));
+ m_view[0].install_write_handler(0x7ff6, 0x7ff6, emu::rw_delegate(*this, FUNC(msx_cart_fmpac_device::control_w)));
+ m_view[0].install_read_handler(0x7ff7, 0x7ff7, emu::rw_delegate(*this, FUNC(msx_cart_fmpac_device::bank_r)));
+ m_view[0].install_write_handler(0x7ff7, 0x7ff7, emu::rw_delegate(*this, FUNC(msx_cart_fmpac_device::bank_w)));
+
+ m_view[1].install_ram(0x4000, 0x5fff, cart_sram_region()->base());
+ m_view[1].install_write_handler(0x5ffe, 0x5fff, emu::rw_delegate(*this, FUNC(msx_cart_fmpac_device::sram_unlock)));
+ m_view[1].install_write_handler(0x7ff4, 0x7ff5, emu::rw_delegate(*this, FUNC(msx_cart_fmpac_device::write_ym2413)));
+ m_view[1].install_read_handler(0x7ff6, 0x7ff6, emu::rw_delegate(*this, FUNC(msx_cart_fmpac_device::control_r)));
+ m_view[1].install_write_handler(0x7ff6, 0x7ff6, emu::rw_delegate(*this, FUNC(msx_cart_fmpac_device::control_w)));
+ m_view[1].install_read_handler(0x7ff7, 0x7ff7, emu::rw_delegate(*this, FUNC(msx_cart_fmpac_device::bank_r)));
+ m_view[1].install_write_handler(0x7ff7, 0x7ff7, emu::rw_delegate(*this, FUNC(msx_cart_fmpac_device::bank_w)));
+
+ return std::error_condition();
+}
+
+void msx_cart_fmpac_device::sram_unlock(offs_t offset, u8 data)
+{
+ m_sram_unlock[offset] = data;
+ m_sram_active = m_sram_unlock[0] == 0x4d && m_sram_unlock[1] == 0x69;
+ m_view.select(m_sram_active ? 1 : 0);
+}
+
+u8 msx_cart_fmpac_device::control_r()
+{
+ return m_control;
+}
+
+void msx_cart_fmpac_device::control_w(u8 data)
+{
+ m_control = data & 0x11;
+ m_opll_active = BIT(data, 0);
+}
+
+u8 msx_cart_fmpac_device::bank_r()
+{
+ return m_rombank->entry();
+}
+
+void msx_cart_fmpac_device::bank_w(u8 data)
+{
+ m_rombank->set_entry(data);
+}
+
+void msx_cart_fmpac_device::write_ym2413(offs_t offset, u8 data)
+{
+ if (m_opll_active)
+ {
+ m_ym2413->write(offset & 1, data);
+ }
+}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_FMPAC, msx_cart_interface, msx_cart_fmpac_device, "msx_cart_fmpac", "MSX Cartridge - FM-PAC")
diff --git a/src/devices/bus/msx/cart/fmpac.h b/src/devices/bus/msx/cart/fmpac.h
new file mode 100644
index 00000000000..8052423960d
--- /dev/null
+++ b/src/devices/bus/msx/cart/fmpac.h
@@ -0,0 +1,13 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#ifndef MAME_BUS_MSX_CART_FMPAC_H
+#define MAME_BUS_MSX_CART_FMPAC_H
+
+#pragma once
+
+#include "bus/msx/slot/cartridge.h"
+
+
+DECLARE_DEVICE_TYPE(MSX_CART_FMPAC, msx_cart_interface)
+
+#endif // MAME_BUS_MSX_CART_FMPAC_H
diff --git a/src/devices/bus/msx/cart/fs_sr021.cpp b/src/devices/bus/msx/cart/fs_sr021.cpp
new file mode 100644
index 00000000000..ada85937b7a
--- /dev/null
+++ b/src/devices/bus/msx/cart/fs_sr021.cpp
@@ -0,0 +1,192 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+/***********************************************************************************
+
+Emulation of the FS-SR021 MSX2 Word Processor Cartridge.
+
+TODO:
+- Display of JIS level 1 characters might not be fully correct, the tools do seem to display fine.
+- Unknown how JIS level 2 characters are input/displayed.
+
+***********************************************************************************/
+#include "emu.h"
+#include "fs_sr021.h"
+
+namespace {
+
+class msx_cart_fs_sr021_device : public device_t, public msx_cart_interface
+{
+public:
+ msx_cart_fs_sr021_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, MSX_CART_FS_SR021, tag, owner, clock)
+ , msx_cart_interface(mconfig, *this)
+ , m_bank(*this, "bank%u", 0U)
+ , m_view{ {*this, "view0000"}, {*this, "view2000"}, {*this, "view4000"}, {*this, "view6000"}, {*this, "view8000"}, {*this, "viewa000"} }
+ { }
+
+ virtual std::error_condition initialize_cartridge(std::string &message) override;
+
+protected:
+ // device_t implementation
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+private:
+ static constexpr size_t BANK_SIZE = 0x2000;
+
+ template <int Bank> void bank_w(u8 data);
+ template <int Bank> void set_view();
+ void control_w(u8 data);
+ u8 bank_r(offs_t offset);
+ u8 kanji_r(offs_t offset);
+ void kanji_w(offs_t offset, u8 data);
+
+ memory_bank_array_creator<6> m_bank;
+ memory_view m_view[6];
+ u8 m_selected_bank[6];
+ u8 m_control;
+ u32 m_kanji_latch;
+};
+
+void msx_cart_fs_sr021_device::device_start()
+{
+ save_item(NAME(m_selected_bank));
+ save_item(NAME(m_control));
+ save_item(NAME(m_kanji_latch));
+}
+
+void msx_cart_fs_sr021_device::device_reset()
+{
+ m_control = 0;
+ for (int i = 0; i < 6; i++)
+ m_view[i].select(0);
+ m_bank[2]->set_entry(0);
+}
+
+std::error_condition msx_cart_fs_sr021_device::initialize_cartridge(std::string &message)
+{
+ if (!cart_rom_region())
+ {
+ message = "msx_cart_fs_sr021_device: Required region 'rom' was not found.";
+ return image_error::INTERNAL;
+ }
+
+ if (cart_rom_region()->bytes() != 0x200000)
+ {
+ message = "msx_cart_fs_sr021_device: Region 'rom' has unsupported size.";
+ return image_error::INVALIDLENGTH;
+ }
+
+ if (!cart_sram_region())
+ {
+ message = "msx_cart_fs_sr021_device: Required region 'sram' was not found.";
+ return image_error::INTERNAL;
+ }
+
+ if (cart_sram_region()->bytes() != 0x4000)
+ {
+ message = "msx_cart_fs_sr021_device: Region 'sram' has unsupported size.";
+ return image_error::BADSOFTWARE;
+ }
+
+ const u32 size = cart_rom_region()->bytes();
+ const u16 banks = size / BANK_SIZE;
+
+ for (int i = 0; i < 6; i++)
+ {
+ m_bank[i]->configure_entries(0, banks, cart_rom_region()->base(), BANK_SIZE);
+ m_bank[i]->configure_entry(0x80, cart_sram_region()->base());
+ m_bank[i]->configure_entry(0x81, cart_sram_region()->base() + BANK_SIZE);
+ }
+
+ for (int pg = 0; pg < 3; pg++)
+ {
+ const offs_t start = pg * 0x4000;
+ const int index = pg * 2;
+ page(pg)->install_view(start, start + 0x1fff, m_view[index]);
+ m_view[index][0].install_read_bank(start, start + 0x1fff, m_bank[index]);
+ m_view[index][1].install_readwrite_bank(start, start + 0x1fff, m_bank[index]);
+ page(pg)->install_view(start + 0x2000, start + 0x3fff, m_view[index + 1]);
+ m_view[index + 1][0].install_read_bank(start + 0x2000, start + 0x3fff, m_bank[index + 1]);
+ m_view[index + 1][1].install_readwrite_bank(start + 0x2000, start + 0x3fff, m_bank[index + 1]);
+ }
+
+ m_view[3][2].install_read_bank(0x6000, 0x7fff, m_bank[3]);
+ m_view[3][2].install_read_handler(0x7ff0, 0x7ff5, emu::rw_delegate(*this, FUNC(msx_cart_fs_sr021_device::bank_r)));
+ m_view[3][3].install_readwrite_bank(0x6000, 0x7fff, m_bank[3]);
+ m_view[3][3].install_read_handler(0x7ff0, 0x7ff5, emu::rw_delegate(*this, FUNC(msx_cart_fs_sr021_device::bank_r)));
+
+ page(1)->install_write_handler(0x6000, 0x6000, emu::rw_delegate(*this, FUNC(msx_cart_fs_sr021_device::bank_w<0>))); // 0000-1fff
+ page(1)->install_write_handler(0x6400, 0x6400, emu::rw_delegate(*this, FUNC(msx_cart_fs_sr021_device::bank_w<1>))); // 2000-3fff
+ page(1)->install_write_handler(0x6800, 0x6800, emu::rw_delegate(*this, FUNC(msx_cart_fs_sr021_device::bank_w<2>))); // 4000-5fff
+ page(1)->install_write_handler(0x6c00, 0x6c00, emu::rw_delegate(*this, FUNC(msx_cart_fs_sr021_device::bank_w<3>))); // 6000-7fff
+ page(1)->install_write_handler(0x7000, 0x7000, emu::rw_delegate(*this, FUNC(msx_cart_fs_sr021_device::bank_w<4>))); // 8000-9fff
+ page(1)->install_write_handler(0x7800, 0x7800, emu::rw_delegate(*this, FUNC(msx_cart_fs_sr021_device::bank_w<5>))); // a000-bfff
+ page(1)->install_write_handler(0x7ff9, 0x7ff9, emu::rw_delegate(*this, FUNC(msx_cart_fs_sr021_device::control_w)));
+
+ // Takes over kanji from base system?
+ io_space().install_write_handler(0xd8, 0xd9, emu::rw_delegate(*this, FUNC(msx_cart_fs_sr021_device::kanji_w)));
+ io_space().install_read_handler(0xd9, 0xd9, emu::rw_delegate(*this, FUNC(msx_cart_fs_sr021_device::kanji_r)));
+
+ return std::error_condition();
+}
+
+template <int Bank>
+void msx_cart_fs_sr021_device::set_view()
+{
+ bool ram_active = (m_selected_bank[Bank] >= 0x80 && m_selected_bank[Bank] < 0x82);
+ if (Bank == 3)
+ m_view[Bank].select((BIT(m_control, 2) ? 2 : 0) | (ram_active ? 1 : 0));
+ else
+ m_view[Bank].select(ram_active ? 1 : 0);
+}
+
+template <int Bank>
+void msx_cart_fs_sr021_device::bank_w(u8 data)
+{
+ m_selected_bank[Bank] = data;
+ m_bank[Bank]->set_entry(data);
+ set_view<Bank>();
+}
+
+void msx_cart_fs_sr021_device::control_w(u8 data)
+{
+ m_control = data;
+ set_view<3>();
+}
+
+u8 msx_cart_fs_sr021_device::bank_r(offs_t offset)
+{
+ return m_selected_bank[offset];
+}
+
+u8 msx_cart_fs_sr021_device::kanji_r(offs_t offset)
+{
+ u8 result = 0xff;
+
+ u32 latch = bitswap<17>(m_kanji_latch, 4, 3, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 2, 1, 0);
+ // This might not be correct, fixes most characters on the menu screen.
+ if (!(latch & 0x18000))
+ {
+ latch |= 0x40000;
+ }
+ result = cart_rom_region()->base()[0x100000 | latch];
+
+ if (!machine().side_effects_disabled())
+ {
+ m_kanji_latch = (m_kanji_latch & ~0x1f) | ((m_kanji_latch + 1) & 0x1f);
+ }
+ return result;
+}
+
+void msx_cart_fs_sr021_device::kanji_w(offs_t offset, u8 data)
+{
+ if (offset)
+ m_kanji_latch = (m_kanji_latch & 0x007e0) | ((data & 0x3f) << 11);
+ else
+ m_kanji_latch = (m_kanji_latch & 0x1f800) | ((data & 0x3f) << 5);
+}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_FS_SR021, msx_cart_interface, msx_cart_fs_sr021_device, "msx_cart_fs_sr021", "MSX Cartridge - FS-SR021")
diff --git a/src/devices/bus/msx/cart/fs_sr021.h b/src/devices/bus/msx/cart/fs_sr021.h
new file mode 100644
index 00000000000..04737b99b3d
--- /dev/null
+++ b/src/devices/bus/msx/cart/fs_sr021.h
@@ -0,0 +1,13 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#ifndef MAME_BUS_MSX_CART_FS_SR021_H
+#define MAME_BUS_MSX_CART_FS_SR021_H
+
+#pragma once
+
+#include "bus/msx/slot/cartridge.h"
+
+
+DECLARE_DEVICE_TYPE(MSX_CART_FS_SR021, msx_cart_interface)
+
+#endif // MAME_BUS_MSX_CART_FS_SR021_H
diff --git a/src/devices/bus/msx/cart/fs_sr022.cpp b/src/devices/bus/msx/cart/fs_sr022.cpp
new file mode 100644
index 00000000000..2f5bc62af58
--- /dev/null
+++ b/src/devices/bus/msx/cart/fs_sr022.cpp
@@ -0,0 +1,95 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#include "emu.h"
+#include "fs_sr022.h"
+
+namespace {
+
+class msx_cart_fs_sr022_device : public device_t, public msx_cart_interface
+{
+public:
+ msx_cart_fs_sr022_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, MSX_CART_FS_SR022, tag, owner, clock)
+ , msx_cart_interface(mconfig, *this)
+ , m_bunsetsu_rom(nullptr)
+ , m_bunsetsu_address(0)
+ { }
+
+ virtual std::error_condition initialize_cartridge(std::string &message) override;
+
+protected:
+ // device_t implementation
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+private:
+ u8 buns_r();
+ void buns_w(offs_t offset, u8 data);
+
+ u8 *m_bunsetsu_rom;
+ u32 m_bunsetsu_address;
+};
+
+void msx_cart_fs_sr022_device::device_start()
+{
+ save_item(NAME(m_bunsetsu_address));
+}
+
+void msx_cart_fs_sr022_device::device_reset()
+{
+ m_bunsetsu_address = 0;
+}
+
+std::error_condition msx_cart_fs_sr022_device::initialize_cartridge(std::string &message)
+{
+ if (!cart_rom_region())
+ {
+ message = "msx_cart_fs_sr022_device: Required region 'rom' was not found.";
+ return image_error::INTERNAL;
+ }
+
+ if (cart_rom_region()->bytes() != 0x40000)
+ {
+ message = "msx_cart_fs_sr022_device: Region 'rom' has unsupported size.";
+ return image_error::INVALIDLENGTH;
+ }
+
+ m_bunsetsu_rom = cart_rom_region()->base() + 0x20000;
+
+ page(1)->install_rom(0x4000, 0x7fff, cart_rom_region()->base());
+ page(2)->install_rom(0x8000, 0xbfff, cart_rom_region()->base() + 0x4000);
+ page(2)->install_read_handler(0xbfff, 0xbfff, emu::rw_delegate(*this, FUNC(msx_cart_fs_sr022_device::buns_r)));
+ page(2)->install_write_handler(0xbffc, 0xbffe, emu::rw_delegate(*this, FUNC(msx_cart_fs_sr022_device::buns_w)));
+
+ return std::error_condition();
+}
+
+u8 msx_cart_fs_sr022_device::buns_r()
+{
+ u8 data = m_bunsetsu_rom[m_bunsetsu_address & 0x1ffff];
+ if (!machine().side_effects_disabled())
+ m_bunsetsu_address++;
+ return data;
+}
+
+void msx_cart_fs_sr022_device::buns_w(offs_t offset, uint8_t data)
+{
+ switch (offset)
+ {
+ case 0:
+ m_bunsetsu_address = (m_bunsetsu_address & 0xffff00) | data;
+ break;
+
+ case 1:
+ m_bunsetsu_address = (m_bunsetsu_address & 0xff00ff) | (data << 8);
+ break;
+
+ case 2:
+ m_bunsetsu_address = (m_bunsetsu_address & 0x00ffff) | (data << 16);
+ break;
+ }
+}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_FS_SR022, msx_cart_interface, msx_cart_fs_sr022_device, "msx_cart_fs_sr022", "MSX Cartridge - FS-SR022")
diff --git a/src/devices/bus/msx/cart/fs_sr022.h b/src/devices/bus/msx/cart/fs_sr022.h
new file mode 100644
index 00000000000..568fc10fc21
--- /dev/null
+++ b/src/devices/bus/msx/cart/fs_sr022.h
@@ -0,0 +1,13 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#ifndef MAME_BUS_MSX_CART_FS_SR022_H
+#define MAME_BUS_MSX_CART_FS_SR022_H
+
+#pragma once
+
+#include "bus/msx/slot/cartridge.h"
+
+
+DECLARE_DEVICE_TYPE(MSX_CART_FS_SR022, msx_cart_interface)
+
+#endif // MAME_BUS_MSX_CART_FS_SR022_H
diff --git a/src/devices/bus/msx/cart/halnote.cpp b/src/devices/bus/msx/cart/halnote.cpp
new file mode 100644
index 00000000000..cc9c5dcfca3
--- /dev/null
+++ b/src/devices/bus/msx/cart/halnote.cpp
@@ -0,0 +1,121 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#include "emu.h"
+#include "halnote.h"
+
+namespace {
+
+class msx_cart_halnote_device : public device_t, public msx_cart_interface
+{
+public:
+ msx_cart_halnote_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MSX_CART_HALNOTE, tag, owner, clock)
+ , msx_cart_interface(mconfig, *this)
+ , m_rombank(*this, "rombank%u", 0U)
+ , m_view{ {*this, "view0"}, {*this, "view1"} }
+ { }
+
+ virtual std::error_condition initialize_cartridge(std::string &message) override;
+
+protected:
+ // device_t implementation
+ virtual void device_start() override { }
+ virtual void device_reset() override;
+
+private:
+ static constexpr u8 BANK_MASK = (0x100000 / 0x2000) - 1;
+
+ template <int Bank> void bank_w(u8 data);
+ void bank0_w(u8 data);
+ void bank1_w(u8 data);
+ void bank2_w(u8 data);
+ void bank3_w(u8 data);
+ template <int Bank> void bank_small_w(u8 data);
+
+ memory_bank_array_creator<6> m_rombank;
+ memory_view m_view[2];
+};
+
+void msx_cart_halnote_device::device_reset()
+{
+ for (int i = 0; i < 6; i++)
+ m_rombank[i]->set_entry(0);
+
+ m_view[0].disable();
+ m_view[1].select(0);
+}
+
+std::error_condition msx_cart_halnote_device::initialize_cartridge(std::string &message)
+{
+ if (!cart_rom_region())
+ {
+ message = "msx_cart_halnote_device: Required region 'rom' was not found.";
+ return image_error::INTERNAL;
+ }
+
+ if (!cart_sram_region())
+ {
+ message = "msx_cart_halnote_device: Required region 'sram' was not found.";
+ return image_error::INTERNAL;
+ }
+
+ if (cart_rom_region()->bytes() != 0x100000)
+ {
+ message = "msx_cart_halnote_device: Region 'rom' has unsupported size.";
+ return image_error::INVALIDLENGTH;
+ }
+
+ if (cart_sram_region()->bytes() < 0x4000)
+ {
+ message = "msx_cart_halnote_device: Region 'sram' has unsupported size.";
+ return image_error::BADSOFTWARE;
+ }
+
+ for (int i = 0; i < 4; i++)
+ {
+ m_rombank[i]->configure_entries(0, 0x80, cart_rom_region()->base(), 0x2000);
+ }
+ m_rombank[4]->configure_entries(0, 0x100, cart_rom_region()->base() + 0x80000, 0x800);
+ m_rombank[5]->configure_entries(0, 0x100, cart_rom_region()->base() + 0x80000, 0x800);
+
+ page(0)->install_view(0x0000, 0x3fff, m_view[0]);
+ m_view[0][0];
+ m_view[0][1].install_ram(0x0000, 0x3fff, cart_sram_region()->base());
+ page(1)->install_read_bank(0x4000, 0x5fff, m_rombank[0]);
+ page(1)->install_write_handler(0x4fff, 0x4fff, emu::rw_delegate(*this, FUNC(msx_cart_halnote_device::bank_w<0>)));
+ page(1)->install_view(0x6000, 0x7fff, m_view[1]);
+ m_view[1][0].install_read_bank(0x6000, 0x7fff, m_rombank[1]);
+ m_view[1][0].install_write_handler(0x6fff, 0x6fff, emu::rw_delegate(*this, FUNC(msx_cart_halnote_device::bank_w<1>)));
+ m_view[1][0].install_write_handler(0x77ff, 0x77ff, emu::rw_delegate(*this, FUNC(msx_cart_halnote_device::bank_small_w<4>)));
+ m_view[1][0].install_write_handler(0x7fff, 0x7fff, emu::rw_delegate(*this, FUNC(msx_cart_halnote_device::bank_small_w<5>)));
+ m_view[1][1].install_read_bank(0x6000, 0x6fff, m_rombank[1]);
+ m_view[1][1].install_write_handler(0x6fff, 0x6fff, emu::rw_delegate(*this, FUNC(msx_cart_halnote_device::bank_w<1>)));
+ m_view[1][1].install_read_bank(0x7000, 0x77ff, m_rombank[4]);
+ m_view[1][1].install_write_handler(0x77ff, 0x77ff, emu::rw_delegate(*this, FUNC(msx_cart_halnote_device::bank_small_w<4>)));
+ m_view[1][1].install_read_bank(0x7800, 0x7fff, m_rombank[5]);
+ m_view[1][1].install_write_handler(0x7fff, 0x7fff, emu::rw_delegate(*this, FUNC(msx_cart_halnote_device::bank_small_w<5>)));
+ page(2)->install_read_bank(0x8000, 0x9fff, m_rombank[2]);
+ page(2)->install_write_handler(0x8fff, 0x8fff, emu::rw_delegate(*this, FUNC(msx_cart_halnote_device::bank_w<2>)));
+ page(2)->install_read_bank(0xa000, 0xbfff, m_rombank[3]);
+ page(2)->install_write_handler(0xafff, 0xafff, emu::rw_delegate(*this, FUNC(msx_cart_halnote_device::bank_w<3>)));
+
+ return std::error_condition();
+}
+
+template <int Bank>
+void msx_cart_halnote_device::bank_w(u8 data)
+{
+ m_rombank[Bank]->set_entry(data & 0x7f);
+ if (Bank == 0 || Bank == 3)
+ m_view[Bank ? 1 : 0].select(BIT(data, 7) ? 1 : 0);
+}
+
+template <int Bank>
+void msx_cart_halnote_device::bank_small_w(u8 data)
+{
+ m_rombank[Bank]->set_entry(data);
+}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_HALNOTE, msx_cart_interface, msx_cart_halnote_device, "msx_cart_halnote", "MSX Cartridge - Halnote")
diff --git a/src/devices/bus/msx/cart/halnote.h b/src/devices/bus/msx/cart/halnote.h
new file mode 100644
index 00000000000..7552e3d6e2f
--- /dev/null
+++ b/src/devices/bus/msx/cart/halnote.h
@@ -0,0 +1,13 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#ifndef MAME_BUS_MSX_CART_HALNOTE_H
+#define MAME_BUS_MSX_CART_HALNOTE_H
+
+#pragma once
+
+#include "bus/msx/slot/cartridge.h"
+
+
+DECLARE_DEVICE_TYPE(MSX_CART_HALNOTE, msx_cart_interface)
+
+#endif // MAME_BUS_MSX_CART_HALNOTE_H
diff --git a/src/devices/bus/msx/cart/hbi55.cpp b/src/devices/bus/msx/cart/hbi55.cpp
new file mode 100644
index 00000000000..b779a2dede0
--- /dev/null
+++ b/src/devices/bus/msx/cart/hbi55.cpp
@@ -0,0 +1,182 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#include "emu.h"
+#include "hbi55.h"
+
+#include "imagedev/memcard.h"
+#include "machine/i8255.h"
+
+#include <memory>
+#include <string>
+#include <system_error>
+#include <utility>
+
+
+namespace {
+
+/*
+Emulation of Sony HBI-55 and Yamaha UDC-01 data cartridges.
+Internally these two data cartridges are the same.
+
+In theory these battery-backed RAM cartridges could use up to 8 x 2KB SRAM
+chips but only cartridges using 2 2KB SRAM chips were produced.
+*/
+
+class msx_cart_hbi55_device : public device_t, public msx_cart_interface, public device_memcard_image_interface
+{
+public:
+ msx_cart_hbi55_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, MSX_CART_HBI55, tag, owner, clock)
+ , msx_cart_interface(mconfig, *this)
+ , device_memcard_image_interface(mconfig, *this)
+ , m_i8255(*this, "i8255")
+ , m_address(0)
+ , m_ce(false)
+ , m_oe(false)
+ , m_last_c(0)
+ { }
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual bool is_reset_on_load() const noexcept override { return false; }
+ virtual char const *file_extensions() const noexcept override { return "bin"; }
+ virtual std::pair<std::error_condition, std::string> call_create(int format_type, util::option_resolution *format_options) override;
+ virtual std::pair<std::error_condition, std::string> call_load() override;
+ virtual void call_unload() override;
+
+private:
+ static constexpr u32 SRAM_SIZE = 0x1000;
+
+ void ppi_port_a_w(u8 data);
+ void ppi_port_b_w(u8 data);
+ void ppi_port_c_w(u8 data);
+ u8 ppi_port_c_r();
+ void sram_update();
+ void clear_sram();
+
+ required_device<i8255_device> m_i8255;
+ std::unique_ptr<u8[]> m_sram;
+ u16 m_address;
+ bool m_ce;
+ bool m_oe;
+ u8 m_last_c;
+};
+
+std::pair<std::error_condition, std::string> msx_cart_hbi55_device::call_load()
+{
+ if (length() != SRAM_SIZE)
+ return std::make_pair(image_error::INVALIDLENGTH, std::string());
+
+ if (fread(m_sram.get(), SRAM_SIZE) != SRAM_SIZE)
+ return std::make_pair(std::errc::io_error, std::string());
+
+ return std::make_pair(std::error_condition(), std::string());
+}
+
+void msx_cart_hbi55_device::call_unload()
+{
+ if (!is_readonly())
+ {
+ fseek(0, SEEK_SET);
+ fwrite(m_sram.get(), SRAM_SIZE);
+ }
+ clear_sram();
+}
+
+std::pair<std::error_condition, std::string> msx_cart_hbi55_device::call_create(int format_type, util::option_resolution *format_options)
+{
+ clear_sram();
+
+ if (fwrite(m_sram.get(), SRAM_SIZE) != SRAM_SIZE)
+ return std::make_pair(std::errc::io_error, std::string());
+
+ return std::make_pair(std::error_condition(), std::string());
+}
+
+void msx_cart_hbi55_device::device_add_mconfig(machine_config &config)
+{
+ I8255(config, m_i8255);
+ m_i8255->out_pa_callback().set(FUNC(msx_cart_hbi55_device::ppi_port_a_w));
+ m_i8255->out_pb_callback().set(FUNC(msx_cart_hbi55_device::ppi_port_b_w));
+ m_i8255->out_pc_callback().set(FUNC(msx_cart_hbi55_device::ppi_port_c_w));
+ m_i8255->in_pc_callback().set(FUNC(msx_cart_hbi55_device::ppi_port_c_r));
+}
+
+void msx_cart_hbi55_device::device_start()
+{
+ m_sram = std::make_unique<u8[]>(SRAM_SIZE);
+ clear_sram();
+
+ save_pointer(NAME(m_sram), SRAM_SIZE);
+ save_item(NAME(m_address));
+ save_item(NAME(m_ce));
+ save_item(NAME(m_oe));
+ save_item(NAME(m_last_c));
+
+ io_space().install_write_handler(0xb0, 0xb3, write8sm_delegate(*m_i8255, FUNC(i8255_device::write)));
+ io_space().install_read_handler(0xb0, 0xb3, read8sm_delegate(*m_i8255, FUNC(i8255_device::read)));
+}
+
+void msx_cart_hbi55_device::device_reset()
+{
+ m_address = 0;
+ m_ce = false;
+ m_oe = false;
+ m_last_c = 0;
+}
+
+void msx_cart_hbi55_device::clear_sram()
+{
+ std::fill_n(m_sram.get(), SRAM_SIZE, 0);
+}
+
+void msx_cart_hbi55_device::ppi_port_a_w(u8 data)
+{
+ // address bits 0-7
+ m_address = (m_address & 0xff00) | data;
+ sram_update();
+}
+
+void msx_cart_hbi55_device::ppi_port_b_w(u8 data)
+{
+ // 76543210
+ // |||||\\\-- address bits 8-10
+ // ||\\\----- to SRAM chip select TC40H138 demux (only Y0 and Y1 are used)
+ // |\-------- SRAM CE (1 = enable)
+ // \--------- SRAM OE (1 = output enable, 0 = write enable)
+ m_address = (m_address & 0x00ff) | ((data & 0x3f) << 8);
+ m_ce = BIT(data, 6);
+ m_oe = BIT(data, 7);
+ sram_update();
+}
+
+void msx_cart_hbi55_device::ppi_port_c_w(u8 data)
+{
+ m_last_c = data;
+ sram_update();
+}
+
+u8 msx_cart_hbi55_device::ppi_port_c_r()
+{
+ if (m_ce && m_oe && m_address < SRAM_SIZE)
+ {
+ return m_sram[m_address];
+ }
+ // should actually be floating bus
+ return 0xff;
+}
+
+void msx_cart_hbi55_device::sram_update()
+{
+ if (m_ce && !m_oe && m_address < SRAM_SIZE)
+ {
+ m_sram[m_address] = m_last_c;
+ }
+}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_HBI55, msx_cart_interface, msx_cart_hbi55_device, "msx_cart_hbi55", "Sony HBI-55/Yamaha UDC-01 Data Cartridge (4KB SRAM)")
+
diff --git a/src/devices/bus/msx/cart/hbi55.h b/src/devices/bus/msx/cart/hbi55.h
new file mode 100644
index 00000000000..0016f28f37c
--- /dev/null
+++ b/src/devices/bus/msx/cart/hbi55.h
@@ -0,0 +1,13 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#ifndef MAME_BUS_MSX_CART_HBI55_H
+#define MAME_BUS_MSX_CART_HBI55_H
+
+#pragma once
+
+#include "bus/msx/slot/cartridge.h"
+
+
+DECLARE_DEVICE_TYPE(MSX_CART_HBI55, msx_cart_interface)
+
+#endif // MAME_BUS_MSX_CART_HBI55_H
diff --git a/src/devices/bus/msx/cart/hfox.cpp b/src/devices/bus/msx/cart/hfox.cpp
new file mode 100644
index 00000000000..80c25bd86e3
--- /dev/null
+++ b/src/devices/bus/msx/cart/hfox.cpp
@@ -0,0 +1,76 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#include "emu.h"
+#include "hfox.h"
+
+namespace {
+
+class msx_cart_hfox_device : public device_t, public msx_cart_interface
+{
+public:
+ msx_cart_hfox_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, MSX_CART_HFOX, tag, owner, clock)
+ , msx_cart_interface(mconfig, *this)
+ , m_rombank(*this, "rombank%u", 0U)
+ { }
+
+ virtual std::error_condition initialize_cartridge(std::string &message) override;
+
+protected:
+ // device_t implementation
+ virtual void device_start() override { }
+ virtual void device_reset() override;
+
+private:
+ template <int Bank> void bank_w(u8 data);
+
+ memory_bank_array_creator<2> m_rombank;
+
+ u8 m_bank_mask;
+};
+
+void msx_cart_hfox_device::device_reset()
+{
+ m_rombank[0]->set_entry(0);
+ m_rombank[1]->set_entry(0);
+}
+
+std::error_condition msx_cart_hfox_device::initialize_cartridge(std::string &message)
+{
+ if (!cart_rom_region())
+ {
+ message = "msx_cart_hfox_device: Required region 'rom' was not found.";
+ return image_error::INTERNAL;
+ }
+
+ const u32 size = cart_rom_region()->bytes();
+ const u16 banks = size / 0x8000;
+
+ if (size > 256 * 0x8000 || size < 0x10000 || size != banks * 0x8000 || (~(banks - 1) % banks))
+ {
+ message = "msx_cart_hfox_device: Region 'rom' has unsupported size.";
+ return image_error::INVALIDLENGTH;
+ }
+
+ m_bank_mask = banks - 1;
+
+ m_rombank[0]->configure_entries(0, 4, cart_rom_region()->base(), 0x8000);
+ m_rombank[1]->configure_entries(0, 4, cart_rom_region()->base() + 0x4000, 0x8000);
+
+ page(1)->install_read_bank(0x4000, 0x7fff, m_rombank[0]);
+ page(1)->install_write_handler(0x6000, 0x6000, emu::rw_delegate(*this, FUNC(msx_cart_hfox_device::bank_w<0>)));
+ page(1)->install_write_handler(0x7000, 0x7000, emu::rw_delegate(*this, FUNC(msx_cart_hfox_device::bank_w<1>)));
+ page(2)->install_read_bank(0x8000, 0xbfff, m_rombank[1]);
+
+ return std::error_condition();
+}
+
+template <int Bank>
+void msx_cart_hfox_device::bank_w(u8 data)
+{
+ m_rombank[Bank]->set_entry(data & m_bank_mask);
+}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_HFOX, msx_cart_interface, msx_cart_hfox_device, "msx_cart_hfox", "MSX Cartridge - Hurry Fox")
diff --git a/src/devices/bus/msx/cart/hfox.h b/src/devices/bus/msx/cart/hfox.h
new file mode 100644
index 00000000000..c52a0a1d8d2
--- /dev/null
+++ b/src/devices/bus/msx/cart/hfox.h
@@ -0,0 +1,13 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#ifndef MAME_BUS_MSX_CART_HFOX_H
+#define MAME_BUS_MSX_CART_HFOX_H
+
+#pragma once
+
+#include "bus/msx/slot/cartridge.h"
+
+
+DECLARE_DEVICE_TYPE(MSX_CART_HFOX, msx_cart_interface)
+
+#endif // MAME_BUS_MSX_CART_HFOX_H
diff --git a/src/devices/bus/msx/cart/holy_quran.cpp b/src/devices/bus/msx/cart/holy_quran.cpp
new file mode 100644
index 00000000000..327651ed96a
--- /dev/null
+++ b/src/devices/bus/msx/cart/holy_quran.cpp
@@ -0,0 +1,136 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+/******************************************************************************
+
+Al-Alamiah Al-Qur'an Al-Karim
+Only works on Arabian MSXes.
+
+GCMK-16X PCB, 2 ROM chips, Yamaha XE297A0 mapper chip.
+
+******************************************************************************/
+
+#include "emu.h"
+#include "holy_quran.h"
+
+namespace {
+
+class msx_cart_holy_quran_device : public device_t, public msx_cart_interface
+{
+public:
+ msx_cart_holy_quran_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MSX_CART_HOLY_QURAN, tag, owner, clock)
+ , msx_cart_interface(mconfig, *this)
+ , m_rombank(*this, "rombank%u", 0U)
+ , m_view{ {*this, "view1"}, {*this, "view2"} }
+ { }
+
+ virtual std::error_condition initialize_cartridge(std::string &message) override;
+
+protected:
+ // device_t implementation
+ virtual void device_start() override { }
+ virtual void device_reset() override;
+
+private:
+ static constexpr size_t BANK_SIZE = 0x2000;
+
+ u8 read(offs_t offset);
+ u8 read2(offs_t offset);
+ template <int Bank> void bank_w(u8 data);
+
+ memory_bank_array_creator<4> m_rombank;
+ memory_view m_view[2];
+
+ std::vector<u8> m_decrypted;
+ u8 m_bank_mask;
+};
+
+std::error_condition msx_cart_holy_quran_device::initialize_cartridge(std::string &message)
+{
+ if (!cart_rom_region())
+ {
+ message = "msx_cart_holy_quran_device: Required region 'rom' was not found.";
+ return image_error::INTERNAL;
+ }
+
+ const u32 size = cart_rom_region()->bytes();
+ const u16 banks = size / BANK_SIZE;
+
+ if (size > 256 * BANK_SIZE || size < 0x10000 || size != banks * BANK_SIZE || (~(banks - 1) % banks))
+ {
+ message = "msx_cart_holy_quran_device: Region 'rom' has unsupported size.";
+ return image_error::INVALIDLENGTH;
+ }
+
+ m_bank_mask = banks - 1;
+
+ m_decrypted.resize(size);
+
+ // protection uses a simple rotation on databus, some lines inverted
+ u8 *rom = cart_rom_region()->base();
+ for (u32 i = 0; i < size; i++)
+ m_decrypted[i] = bitswap<8>(rom[i],6,2,4,0,1,5,7,3) ^ 0x4d;
+
+ for (int i = 0; i < 4; i++)
+ m_rombank[i]->configure_entries(0, banks, m_decrypted.data(), BANK_SIZE);
+
+ page(1)->install_view(0x4000, 0x7fff, m_view[0]);
+ m_view[0][0].install_read_handler(0x4000, 0x7fff, emu::rw_delegate(*this, FUNC(msx_cart_holy_quran_device::read)));
+ m_view[0][1].install_read_bank(0x4000, 0x5fff, m_rombank[0]);
+ m_view[0][1].install_read_bank(0x6000, 0x7fff, m_rombank[1]);
+ m_view[0][1].install_write_handler(0x5000, 0x5000, emu::rw_delegate(*this, FUNC(msx_cart_holy_quran_device::bank_w<0>)));
+ m_view[0][1].install_write_handler(0x5400, 0x5400, emu::rw_delegate(*this, FUNC(msx_cart_holy_quran_device::bank_w<1>)));
+ m_view[0][1].install_write_handler(0x5800, 0x5800, emu::rw_delegate(*this, FUNC(msx_cart_holy_quran_device::bank_w<2>)));
+ m_view[0][1].install_write_handler(0x5c00, 0x5c00, emu::rw_delegate(*this, FUNC(msx_cart_holy_quran_device::bank_w<3>)));
+
+ page(2)->install_view(0x8000, 0xbfff, m_view[1]);
+ m_view[1][0].install_read_handler(0x8000, 0xbfff, emu::rw_delegate(*this, FUNC(msx_cart_holy_quran_device::read2)));
+ m_view[1][1].install_read_bank(0x8000, 0x9fff, m_rombank[2]);
+ m_view[1][1].install_read_bank(0xa000, 0xbfff, m_rombank[3]);
+
+ return std::error_condition();
+}
+
+void msx_cart_holy_quran_device::device_reset()
+{
+ m_view[0].select(0);
+ m_view[1].select(0);
+ for (int i = 0; i < 4; i++)
+ m_rombank[i]->set_entry(0);
+}
+
+u8 msx_cart_holy_quran_device::read(offs_t offset)
+{
+ u8 data = cart_rom_region()->base()[offset];
+ // The decryption should actually start working after the first M1 cycle executing something from the cartridge.
+ if (offset + 0x4000 == ((cart_rom_region()->base()[3] << 8) | cart_rom_region()->base()[2]) && !machine().side_effects_disabled())
+ {
+ // Switch to decrypted contents
+ m_view[0].select(1);
+ m_view[1].select(1);
+ }
+ return data;
+}
+
+u8 msx_cart_holy_quran_device::read2(offs_t offset)
+{
+ u8 data = cart_rom_region()->base()[offset + 0x4000];
+ // The decryption should actually start working after the first M1 cycle executing something from the cartridge.
+ if (offset + 0x8000 == ((cart_rom_region()->base()[3] << 8) | cart_rom_region()->base()[2]) && !machine().side_effects_disabled())
+ {
+ // Switch to decrypted contents
+ m_view[0].select(1);
+ m_view[1].select(1);
+ }
+ return data;
+}
+
+template <int Bank>
+void msx_cart_holy_quran_device::bank_w(u8 data)
+{
+ m_rombank[Bank]->set_entry(data & m_bank_mask);
+}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_HOLY_QURAN, msx_cart_interface, msx_cart_holy_quran_device, "msx_cart_holy_quran", "MSX Cartridge - Holy Quran")
diff --git a/src/devices/bus/msx/cart/holy_quran.h b/src/devices/bus/msx/cart/holy_quran.h
new file mode 100644
index 00000000000..3765e8f9c90
--- /dev/null
+++ b/src/devices/bus/msx/cart/holy_quran.h
@@ -0,0 +1,13 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#ifndef MAME_BUS_MSX_CART_HOLY_QURAN_H
+#define MAME_BUS_MSX_CART_HOLY_QURAN_H
+
+#pragma once
+
+#include "bus/msx/slot/cartridge.h"
+
+
+DECLARE_DEVICE_TYPE(MSX_CART_HOLY_QURAN, msx_cart_interface)
+
+#endif // MAME_BUS_MSX_CART_HOLY_QURAN_H
diff --git a/src/devices/bus/msx/cart/ink.cpp b/src/devices/bus/msx/cart/ink.cpp
new file mode 100644
index 00000000000..9e008e62726
--- /dev/null
+++ b/src/devices/bus/msx/cart/ink.cpp
@@ -0,0 +1,92 @@
+// license:BSD-3-Clause
+// copyright-holders:hap
+/******************************************************************************
+
+Ink cartridge (Matra, 2006)
+
+48KB ROM data on an AMD Am29F040B(label scratched off), the game uses it
+for protection.
+
+******************************************************************************/
+
+#include "emu.h"
+#include "ink.h"
+#include "machine/intelfsh.h"
+
+namespace {
+
+class msx_cart_ink_device : public device_t, public msx_cart_interface
+{
+public:
+ msx_cart_ink_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, MSX_CART_INK, tag, owner, clock)
+ , msx_cart_interface(mconfig, *this)
+ , m_flash(*this, "flash")
+ { }
+
+ virtual std::error_condition initialize_cartridge(std::string &message) override;
+
+protected:
+ // device_t implementation
+ virtual void device_start() override { }
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+private:
+ required_device<amd_29f040_device> m_flash;
+
+ template <int Page> u8 read_page(offs_t offset);
+ template <int Page> void write_page(offs_t offset, u8 data);
+};
+
+ROM_START(msx_cart_ink)
+ ROM_REGION(0x80000, "flash", ROMREGION_ERASEFF)
+ROM_END
+
+const tiny_rom_entry *msx_cart_ink_device::device_rom_region() const
+{
+ return ROM_NAME(msx_cart_ink);
+}
+
+void msx_cart_ink_device::device_add_mconfig(machine_config &config)
+{
+ AMD_29F040(config, m_flash);
+}
+
+std::error_condition msx_cart_ink_device::initialize_cartridge(std::string &message)
+{
+ if (!cart_rom_region())
+ {
+ message = "msx_cart_ink_device: Required region 'rom' was not found.";
+ return image_error::INTERNAL;
+ }
+
+ const size_t size = std::min<size_t>(0x80000, cart_rom_region()->bytes());
+
+ u8 *flash = memregion("flash")->base();
+ memcpy(flash, cart_rom_region()->base(), size);
+
+ page(0)->install_readwrite_handler(0x0000, 0x3fff, emu::rw_delegate(*this, FUNC(msx_cart_ink_device::read_page<0>)), emu::rw_delegate(*this, FUNC(msx_cart_ink_device::write_page<0>)));
+ page(1)->install_readwrite_handler(0x4000, 0x7fff, emu::rw_delegate(*this, FUNC(msx_cart_ink_device::read_page<1>)), emu::rw_delegate(*this, FUNC(msx_cart_ink_device::write_page<1>)));
+ page(2)->install_readwrite_handler(0x8000, 0xbfff, emu::rw_delegate(*this, FUNC(msx_cart_ink_device::read_page<2>)), emu::rw_delegate(*this, FUNC(msx_cart_ink_device::write_page<2>)));
+ page(3)->install_readwrite_handler(0xc000, 0xffff, emu::rw_delegate(*this, FUNC(msx_cart_ink_device::read_page<3>)), emu::rw_delegate(*this, FUNC(msx_cart_ink_device::write_page<3>)));
+
+ return std::error_condition();
+}
+
+template <int Page>
+u8 msx_cart_ink_device::read_page(offs_t offset)
+{
+ return m_flash->read(offset | (Page * 0x4000));
+}
+
+template <int Page>
+void msx_cart_ink_device::write_page(offs_t offset, u8 data)
+{
+ // /RD connects to flashrom A16-A18
+ m_flash->write(offset | 0x70000 | (Page * 0x4000), data);
+}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_INK, msx_cart_interface, msx_cart_ink_device, "msx_cart_ink", "MSX Cartridge - Ink")
diff --git a/src/devices/bus/msx/cart/ink.h b/src/devices/bus/msx/cart/ink.h
new file mode 100644
index 00000000000..658b6e67e29
--- /dev/null
+++ b/src/devices/bus/msx/cart/ink.h
@@ -0,0 +1,13 @@
+// license:BSD-3-Clause
+// copyright-holders:hap
+#ifndef MAME_BUS_MSX_CART_INK_H
+#define MAME_BUS_MSX_CART_INK_H
+
+#pragma once
+
+#include "bus/msx/slot/cartridge.h"
+
+
+DECLARE_DEVICE_TYPE(MSX_CART_INK, msx_cart_interface)
+
+#endif // MAME_BUS_MSX_CART_INK_H
diff --git a/src/devices/bus/msx/cart/kanji.cpp b/src/devices/bus/msx/cart/kanji.cpp
new file mode 100644
index 00000000000..2fd8447fa51
--- /dev/null
+++ b/src/devices/bus/msx/cart/kanji.cpp
@@ -0,0 +1,221 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+/**********************************************************************************
+
+TODO:
+- Verify real contents of the kanji roms. The current dumps seem to have
+ been read from inside a running MSX machine. The content retrieved that
+ way may not be how they are stored in the rom.
+
+**********************************************************************************/
+
+#include "emu.h"
+#include "kanji.h"
+
+#include "speaker.h"
+
+#define VERBOSE 0
+#include "logmacro.h"
+
+namespace {
+
+class msx_cart_kanji_device : public device_t, public msx_cart_interface
+{
+public:
+ msx_cart_kanji_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : msx_cart_kanji_device(mconfig, MSX_CART_KANJI, tag, owner, clock)
+ { }
+
+ virtual std::error_condition initialize_cartridge(std::string &message) override;
+
+protected:
+ msx_cart_kanji_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
+ // device_t implementation
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ std::error_condition validate_kanji_regions(std::string &message);
+ void install_kanji_handlers();
+
+ u8 kanji_r(offs_t offset);
+ void kanji_w(offs_t offset, u8 data);
+
+ u32 m_kanji_mask;
+ u32 m_kanji_address;
+};
+
+msx_cart_kanji_device::msx_cart_kanji_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, type, tag, owner, clock)
+ , msx_cart_interface(mconfig, *this)
+ , m_kanji_mask(0)
+ , m_kanji_address(0)
+{
+}
+
+void msx_cart_kanji_device::device_reset()
+{
+ m_kanji_address = 0;
+}
+
+void msx_cart_kanji_device::device_start()
+{
+ save_item(NAME(m_kanji_address));
+}
+
+std::error_condition msx_cart_kanji_device::validate_kanji_regions(std::string &message)
+{
+ if (!cart_kanji_region())
+ {
+ message = "msx_cart_kanji_device: Required region 'kanji' was not found.";
+ return image_error::INTERNAL;
+ }
+
+ if (cart_kanji_region()->bytes() != 0x20000)
+ {
+ message = "msx_cart_kanji_device: Region 'rom' has unsupported size.";
+ return image_error::INVALIDLENGTH;
+ }
+
+ return std::error_condition();
+}
+
+void msx_cart_kanji_device::install_kanji_handlers()
+{
+ m_kanji_mask = cart_kanji_region()->bytes() - 1;
+
+ // Install IO read/write handlers
+ io_space().install_write_handler(0xd8, 0xd9, emu::rw_delegate(*this, FUNC(msx_cart_kanji_device::kanji_w)));
+ io_space().install_read_handler(0xd9, 0xd9, emu::rw_delegate(*this, FUNC(msx_cart_kanji_device::kanji_r)));
+}
+
+std::error_condition msx_cart_kanji_device::initialize_cartridge(std::string &message)
+{
+ std::error_condition result = validate_kanji_regions(message);
+ if (result)
+ return result;
+
+ install_kanji_handlers();
+
+ return std::error_condition();
+}
+
+u8 msx_cart_kanji_device::kanji_r(offs_t offset)
+{
+ u8 result = cart_kanji_region()->base()[m_kanji_address];
+
+ if (!machine().side_effects_disabled())
+ {
+ m_kanji_address = (m_kanji_address & ~0x1f) | ((m_kanji_address + 1) & 0x1f);
+ }
+ return result;
+}
+
+void msx_cart_kanji_device::kanji_w(offs_t offset, u8 data)
+{
+ if (offset)
+ m_kanji_address = (m_kanji_address & 0x007e0) | ((data & 0x3f) << 11);
+ else
+ m_kanji_address = (m_kanji_address & 0x1f800) | ((data & 0x3f) << 5);
+
+ m_kanji_address = m_kanji_address & m_kanji_mask;
+}
+
+
+
+class msx_cart_msxwrite_device : public msx_cart_kanji_device
+{
+public:
+ msx_cart_msxwrite_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : msx_cart_kanji_device(mconfig, MSX_CART_MSXWRITE, tag, owner, clock)
+ , m_rombank(*this, "rombank%u", 0U)
+ , m_kanji_switch(*this, "KANJI")
+ , m_bank_mask(0)
+ { }
+
+ virtual std::error_condition initialize_cartridge(std::string &message) override;
+
+protected:
+ // device_t implementation
+ virtual void device_reset() override;
+ virtual ioport_constructor device_input_ports() const override;
+
+private:
+ static constexpr size_t BANK_SIZE = 0x4000;
+
+ template <int Bank> void bank_w(u8 data);
+
+ memory_bank_array_creator<2> m_rombank;
+ required_ioport m_kanji_switch;
+ u8 m_bank_mask;
+};
+
+static INPUT_PORTS_START(msxwrite_kanji_enable_switch)
+ PORT_START("KANJI")
+ PORT_CONFNAME(0x01, 0x01, "Kanji is")
+ PORT_CONFSETTING(0x00, "disabled")
+ PORT_CONFSETTING(0x01, "enabled")
+INPUT_PORTS_END
+
+ioport_constructor msx_cart_msxwrite_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(msxwrite_kanji_enable_switch);
+}
+
+void msx_cart_msxwrite_device::device_reset()
+{
+ msx_cart_kanji_device::device_reset();
+
+ m_rombank[0]->set_entry(0);
+ m_rombank[1]->set_entry(0);
+
+ if (BIT(m_kanji_switch->read(), 0))
+ install_kanji_handlers();
+}
+
+std::error_condition msx_cart_msxwrite_device::initialize_cartridge(std::string &message)
+{
+ std::error_condition result = validate_kanji_regions(message);
+ if (result)
+ return result;
+
+ if (!cart_rom_region())
+ {
+ message = "msx_cart_msxwrite_device: Required region 'rom' was not found.";
+ return image_error::INTERNAL;
+ }
+
+ const u32 size = cart_rom_region()->bytes();
+ const u16 banks = size / BANK_SIZE;
+
+ if (size > 256 * BANK_SIZE || size != banks * BANK_SIZE || (~(banks - 1) % banks))
+ {
+ message = "msx_cart_msxwrite_device: Region 'rom' has unsupported size.";
+ return image_error::INVALIDLENGTH;
+ }
+
+ m_bank_mask = banks - 1;
+
+ for (int i = 0; i < 2; i++)
+ m_rombank[i]->configure_entries(0, banks, cart_rom_region()->base(), BANK_SIZE);
+
+ page(1)->install_read_bank(0x4000, 0x7fff, m_rombank[0]);
+ // The rom writes to 6fff and 7fff for banking, unknown whether
+ // other locations also trigger banking.
+ page(1)->install_write_handler(0x6fff, 0x6fff, emu::rw_delegate(*this, FUNC(msx_cart_msxwrite_device::bank_w<0>)));
+ page(1)->install_write_handler(0x7fff, 0x7fff, emu::rw_delegate(*this, FUNC(msx_cart_msxwrite_device::bank_w<1>)));
+ page(2)->install_read_bank(0x8000, 0xbfff, m_rombank[1]);
+
+ return std::error_condition();
+}
+
+template <int Bank>
+void msx_cart_msxwrite_device::bank_w(u8 data)
+{
+ m_rombank[Bank]->set_entry(data & m_bank_mask);
+}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_KANJI, msx_cart_interface, msx_cart_kanji_device, "msx_cart_kanji", "MSX Cartridge - Kanji")
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_MSXWRITE, msx_cart_interface, msx_cart_msxwrite_device, "msx_cart_msxwrite", "MSX Cartridge - MSXWRITE")
diff --git a/src/devices/bus/msx/cart/kanji.h b/src/devices/bus/msx/cart/kanji.h
new file mode 100644
index 00000000000..b0815cf3b24
--- /dev/null
+++ b/src/devices/bus/msx/cart/kanji.h
@@ -0,0 +1,14 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#ifndef MAME_BUS_MSX_CART_KANJI_H
+#define MAME_BUS_MSX_CART_KANJI_H
+
+#pragma once
+
+#include "bus/msx/slot/cartridge.h"
+
+
+DECLARE_DEVICE_TYPE(MSX_CART_KANJI, msx_cart_interface)
+DECLARE_DEVICE_TYPE(MSX_CART_MSXWRITE, msx_cart_interface)
+
+#endif // MAME_BUS_MSX_CART_KANJI_H
diff --git a/src/devices/bus/msx/cart/konami.cpp b/src/devices/bus/msx/cart/konami.cpp
new file mode 100644
index 00000000000..0cee367d2e5
--- /dev/null
+++ b/src/devices/bus/msx/cart/konami.cpp
@@ -0,0 +1,941 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#include "emu.h"
+#include "konami.h"
+
+#include "machine/intelfsh.h"
+
+#include "sound/k051649.h"
+#include "sound/vlm5030.h"
+#include "sound/dac.h"
+
+#include "speaker.h"
+
+
+namespace {
+
+class msx_cart_konami_device : public device_t, public msx_cart_interface
+{
+public:
+ msx_cart_konami_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MSX_CART_KONAMI, tag, owner, clock)
+ , msx_cart_interface(mconfig, *this)
+ , m_rombank(*this, "rombank%u", 0U)
+ , m_bank_mask(0)
+ { }
+
+ virtual std::error_condition initialize_cartridge(std::string &message) override;
+
+protected:
+ // device_t implementation
+ virtual void device_start() override { }
+ virtual void device_reset() override;
+
+private:
+ template <int Bank> void bank_w(u8 data);
+
+ memory_bank_array_creator<4> m_rombank;
+ u8 m_bank_mask;
+};
+
+void msx_cart_konami_device::device_reset()
+{
+ for (int i = 0; i < 4; i++)
+ m_rombank[i]->set_entry(i);
+}
+
+std::error_condition msx_cart_konami_device::initialize_cartridge(std::string &message)
+{
+ if (!cart_rom_region())
+ {
+ message = "msx_cart_konami_device: Required region 'rom' was not found.";
+ return image_error::INTERNAL;
+ }
+
+ const u32 size = cart_rom_region()->bytes();
+ const u16 banks = size / 0x2000;
+
+ if (size > 256 * 0x2000 || size < 4 * 0x2000 || size != banks * 0x2000 || (~(banks - 1) % banks))
+ {
+ message = "msx_cart_konami_device: Region 'rom' has unsupported size.";
+ return image_error::INVALIDLENGTH;
+ }
+
+ m_bank_mask = banks - 1;
+
+ for (int i = 0; i < 4; i++)
+ m_rombank[i]->configure_entries(0, banks, cart_rom_region()->base(), 0x2000);
+
+ page(0)->install_read_bank(0x0000, 0x1fff, m_rombank[0]);
+ page(0)->install_read_bank(0x2000, 0x3fff, m_rombank[1]);
+ page(1)->install_read_bank(0x4000, 0x5fff, m_rombank[0]);
+ page(1)->install_write_handler(0x4000, 0x47ff, 0, 0x1000, 0, emu::rw_delegate(*this, FUNC(msx_cart_konami_device::bank_w<0>)));
+ page(1)->install_read_bank(0x6000, 0x7fff, m_rombank[1]);
+ page(1)->install_write_handler(0x6000, 0x67ff, 0, 0x1000, 0, emu::rw_delegate(*this, FUNC(msx_cart_konami_device::bank_w<1>)));
+ page(2)->install_read_bank(0x8000, 0x9fff, m_rombank[2]);
+ page(2)->install_write_handler(0x8000, 0x87ff, 0, 0x1000, 0, emu::rw_delegate(*this, FUNC(msx_cart_konami_device::bank_w<2>)));
+ page(2)->install_read_bank(0xa000, 0xbfff, m_rombank[3]);
+ page(2)->install_write_handler(0xa000, 0xa7ff, 0, 0x1000, 0, emu::rw_delegate(*this, FUNC(msx_cart_konami_device::bank_w<3>)));
+ page(3)->install_read_bank(0xc000, 0xdfff, m_rombank[2]);
+ page(3)->install_read_bank(0xe000, 0xffff, m_rombank[3]);
+
+ return std::error_condition();
+}
+
+template <int Bank>
+void msx_cart_konami_device::bank_w(u8 data)
+{
+ m_rombank[Bank]->set_entry(data & m_bank_mask);
+}
+
+
+
+
+class msx_cart_konami_scc_device : public device_t, public msx_cart_interface
+{
+public:
+ msx_cart_konami_scc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, MSX_CART_KONAMI_SCC, tag, owner, clock)
+ , msx_cart_interface(mconfig, *this)
+ , m_k051649(*this, "k051649")
+ , m_rombank(*this, "rombank%u", 0U)
+ , m_scc_view(*this, "scc_view")
+ , m_bank_mask(0)
+ { }
+
+ virtual std::error_condition initialize_cartridge(std::string &message) override;
+
+protected:
+ // device_t implementation
+ virtual void device_start() override { }
+ virtual void device_reset() override;
+
+ virtual void device_add_mconfig(machine_config &config) override;
+
+private:
+ template <int Bank> void bank_w(u8 data);
+
+ required_device<k051649_device> m_k051649;
+ memory_bank_array_creator<4> m_rombank;
+ memory_view m_scc_view;
+
+ u8 m_bank_mask;
+};
+
+void msx_cart_konami_scc_device::device_add_mconfig(machine_config &config)
+{
+ K051649(config, m_k051649, DERIVED_CLOCK(1, 1));
+ if (parent_slot())
+ m_k051649->add_route(ALL_OUTPUTS, soundin(), 0.4);
+}
+
+void msx_cart_konami_scc_device::device_reset()
+{
+ m_scc_view.select(0);
+ for (int i = 0; i < 4; i++)
+ m_rombank[i]->set_entry(i);
+}
+
+std::error_condition msx_cart_konami_scc_device::initialize_cartridge(std::string &message)
+{
+ if (!cart_rom_region())
+ {
+ message = "msx_cart_konami_scc_device: Required region 'rom' was not found.";
+ return image_error::INTERNAL;
+ }
+
+ const u32 size = cart_rom_region()->bytes();
+ const u16 banks = size / 0x2000;
+
+ if (size > 256 * 0x2000 || size < 0x8000 || size != banks * 0x2000 || (~(banks - 1) % banks))
+ {
+ message = "msx_cart_konami_scc_device: Region 'rom' has unsupported size.";
+ return image_error::INVALIDLENGTH;
+ }
+
+ m_bank_mask = banks - 1;
+
+ for (int i = 0; i < 4; i++)
+ m_rombank[i]->configure_entries(0, banks, cart_rom_region()->base(), 0x2000);
+
+ page(0)->install_read_bank(0x0000, 0x1fff, m_rombank[2]);
+ page(0)->install_read_bank(0x2000, 0x3fff, m_rombank[3]);
+ page(1)->install_read_bank(0x4000, 0x5fff, m_rombank[0]);
+ page(1)->install_write_handler(0x5000, 0x57ff, emu::rw_delegate(*this, FUNC(msx_cart_konami_scc_device::bank_w<0>)));
+ page(1)->install_read_bank(0x6000, 0x7fff, m_rombank[1]);
+ page(1)->install_write_handler(0x7000, 0x77ff, emu::rw_delegate(*this, FUNC(msx_cart_konami_scc_device::bank_w<1>)));
+ page(2)->install_view(0x8000, 0x9fff, m_scc_view);
+ m_scc_view[0].install_read_bank(0x8000, 0x9fff, m_rombank[2]);
+ m_scc_view[0].install_write_handler(0x9000, 0x97ff, emu::rw_delegate(*this, FUNC(msx_cart_konami_scc_device::bank_w<2>)));
+ m_scc_view[1].install_read_bank(0x8000, 0x9fff, m_rombank[2]);
+ m_scc_view[1].install_write_handler(0x9000, 0x97ff, emu::rw_delegate(*this, FUNC(msx_cart_konami_scc_device::bank_w<2>)));
+ m_scc_view[1].install_read_handler(0x9800, 0x987f, 0, 0x0700, 0, emu::rw_delegate(m_k051649, FUNC(k051649_device::k051649_waveform_r)));
+ m_scc_view[1].install_write_handler(0x9800, 0x987f, 0, 0x0700, 0, emu::rw_delegate(m_k051649, FUNC(k051649_device::k051649_waveform_w)));
+ m_scc_view[1].install_write_handler(0x9880, 0x9889, 0, 0x0710, 0, emu::rw_delegate(m_k051649, FUNC(k051649_device::k051649_frequency_w)));
+ m_scc_view[1].install_write_handler(0x988a, 0x988e, 0, 0x0710, 0, emu::rw_delegate(m_k051649, FUNC(k051649_device::k051649_volume_w)));
+ m_scc_view[1].install_write_handler(0x988f, 0x988f, 0, 0x0710, 0, emu::rw_delegate(m_k051649, FUNC(k051649_device::k051649_keyonoff_w)));
+ m_scc_view[1].install_read_handler(0x98e0, 0x98e0, 0, 0x071f, 0, emu::rw_delegate(m_k051649, FUNC(k051649_device::k051649_test_r)));
+ m_scc_view[1].install_write_handler(0x98e0, 0x98e0, 0, 0x071f, 0, emu::rw_delegate(m_k051649, FUNC(k051649_device::k051649_test_w)));
+ page(2)->install_read_bank(0x8000, 0x9fff, m_rombank[2]);
+ page(2)->install_write_handler(0x9000, 0x97ff, emu::rw_delegate(*this, FUNC(msx_cart_konami_scc_device::bank_w<2>)));
+ page(2)->install_read_bank(0xa000, 0xbfff, m_rombank[3]);
+ page(2)->install_write_handler(0xb000, 0xb7ff, emu::rw_delegate(*this, FUNC(msx_cart_konami_scc_device::bank_w<3>)));
+ page(3)->install_read_bank(0xc000, 0xdfff, m_rombank[0]);
+ page(3)->install_read_bank(0xe000, 0xffff, m_rombank[1]);
+
+ return std::error_condition();
+}
+
+template <int Bank>
+void msx_cart_konami_scc_device::bank_w(u8 data)
+{
+ m_rombank[Bank]->set_entry(data & m_bank_mask);
+ if (Bank == 2)
+ {
+ m_scc_view.select(((data & 0x3f) == 0x3f) ? 1 : 0);
+ }
+}
+
+
+
+
+
+
+class msx_cart_sunrise_scc_device : public device_t, public msx_cart_interface
+{
+public:
+ msx_cart_sunrise_scc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, MSX_CART_SUNRISE_SCC, tag, owner, clock)
+ , msx_cart_interface(mconfig, *this)
+ , m_k051649(*this, "k051649")
+ , m_flash(*this, "flash")
+ , m_scc_view(*this, "scc_view")
+ { }
+
+ virtual std::error_condition initialize_cartridge(std::string &message) override;
+
+protected:
+ // device_t implementation
+ virtual void device_start() override { save_item(NAME(m_selected_bank)); }
+ virtual void device_reset() override;
+
+ virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override;
+
+private:
+ template <int Bank> u8 flash_r(offs_t offset);
+ template <int Bank> void flash_w(offs_t offset, u8 data);
+ template <int Bank> void bank_w(offs_t offset, u8 data);
+
+ required_device<k051649_device> m_k051649;
+ required_device<intelfsh8_device> m_flash;
+ memory_view m_scc_view;
+
+ u8 m_selected_bank[4];
+};
+
+ROM_START(msx_cart_sunrise_scc)
+ ROM_REGION(0x80000, "flash", ROMREGION_ERASEFF)
+ROM_END
+
+const tiny_rom_entry *msx_cart_sunrise_scc_device::device_rom_region() const
+{
+ return ROM_NAME(msx_cart_sunrise_scc);
+}
+
+void msx_cart_sunrise_scc_device::device_add_mconfig(machine_config &config)
+{
+ K051649(config, m_k051649, DERIVED_CLOCK(1, 1));
+ if (parent_slot())
+ m_k051649->add_route(ALL_OUTPUTS, soundin(), 0.4);
+
+ AMD_29F040(config, m_flash);
+}
+
+void msx_cart_sunrise_scc_device::device_reset()
+{
+ m_scc_view.select(0);
+ for (int i = 0; i < 4; i++)
+ m_selected_bank[i] = i;
+}
+
+std::error_condition msx_cart_sunrise_scc_device::initialize_cartridge(std::string &message)
+{
+ if (!cart_rom_region())
+ {
+ message = "msx_cart_sunrise_scc_device: Required region 'rom' was not found.";
+ return image_error::INTERNAL;
+ }
+
+ const u32 size = cart_rom_region()->bytes();
+ if (size != 0x80000)
+ {
+ message = "msx_cart_sunrise_scc_device: Region 'rom' has unsupported size.";
+ return image_error::INVALIDLENGTH;
+ }
+
+ u8 *flash = memregion("flash")->base();
+ memcpy(flash, cart_rom_region()->base(), size);
+
+ page(0)->install_read_handler(0x0000, 0x1fff, emu::rw_delegate(*this, FUNC(msx_cart_sunrise_scc_device::flash_r<2>)));
+ page(0)->install_write_handler(0x0000, 0x1fff, emu::rw_delegate(*this, FUNC(msx_cart_sunrise_scc_device::flash_w<2>)));
+ page(0)->install_read_handler(0x2000, 0x3fff, emu::rw_delegate(*this, FUNC(msx_cart_sunrise_scc_device::flash_r<3>)));
+ page(0)->install_write_handler(0x2000, 0x3fff, emu::rw_delegate(*this, FUNC(msx_cart_sunrise_scc_device::flash_w<3>)));
+ page(1)->install_read_handler(0x4000, 0x5fff, emu::rw_delegate(*this, FUNC(msx_cart_sunrise_scc_device::flash_r<0>)));
+ page(1)->install_write_handler(0x4000, 0x5fff, emu::rw_delegate(*this, FUNC(msx_cart_sunrise_scc_device::bank_w<0>)));
+ page(1)->install_read_handler(0x6000, 0x7fff, emu::rw_delegate(*this, FUNC(msx_cart_sunrise_scc_device::flash_r<1>)));
+ page(1)->install_write_handler(0x6000, 0x7fff, emu::rw_delegate(*this, FUNC(msx_cart_sunrise_scc_device::bank_w<1>)));
+ page(2)->install_view(0x8000, 0x9fff, m_scc_view);
+ m_scc_view[0].install_read_handler(0x8000, 0x9fff, emu::rw_delegate(*this, FUNC(msx_cart_sunrise_scc_device::flash_r<2>)));
+ m_scc_view[0].install_write_handler(0x8000, 0x97ff, emu::rw_delegate(*this, FUNC(msx_cart_sunrise_scc_device::bank_w<2>)));
+ m_scc_view[1].install_read_handler(0x8000, 0x97ff, emu::rw_delegate(*this, FUNC(msx_cart_sunrise_scc_device::flash_r<2>)));
+ m_scc_view[1].install_write_handler(0x8000, 0x97ff, emu::rw_delegate(*this, FUNC(msx_cart_sunrise_scc_device::bank_w<2>)));
+ m_scc_view[1].install_read_handler(0x9800, 0x987f, 0, 0x0700, 0, emu::rw_delegate(m_k051649, FUNC(k051649_device::k051649_waveform_r)));
+ m_scc_view[1].install_write_handler(0x9800, 0x987f, 0, 0x0700, 0, emu::rw_delegate(m_k051649, FUNC(k051649_device::k051649_waveform_w)));
+ m_scc_view[1].install_write_handler(0x9880, 0x9889, 0, 0x0710, 0, emu::rw_delegate(m_k051649, FUNC(k051649_device::k051649_frequency_w)));
+ m_scc_view[1].install_write_handler(0x988a, 0x988e, 0, 0x0710, 0, emu::rw_delegate(m_k051649, FUNC(k051649_device::k051649_volume_w)));
+ m_scc_view[1].install_write_handler(0x988f, 0x988f, 0, 0x0710, 0, emu::rw_delegate(m_k051649, FUNC(k051649_device::k051649_keyonoff_w)));
+ m_scc_view[1].install_read_handler(0x98e0, 0x98e0, 0, 0x071f, 0, emu::rw_delegate(m_k051649, FUNC(k051649_device::k051649_test_r)));
+ m_scc_view[1].install_write_handler(0x98e0, 0x98e0, 0, 0x071f, 0, emu::rw_delegate(m_k051649, FUNC(k051649_device::k051649_test_w)));
+ page(2)->install_read_handler(0xa000, 0xbfff, emu::rw_delegate(*this, FUNC(msx_cart_sunrise_scc_device::flash_r<3>)));
+ page(2)->install_write_handler(0xa000, 0xbfff, emu::rw_delegate(*this, FUNC(msx_cart_sunrise_scc_device::bank_w<3>)));
+ page(3)->install_read_handler(0xc000, 0xdfff, emu::rw_delegate(*this, FUNC(msx_cart_sunrise_scc_device::flash_r<0>)));
+ page(3)->install_write_handler(0xc000, 0xdfff, emu::rw_delegate(*this, FUNC(msx_cart_sunrise_scc_device::flash_w<0>)));
+ page(3)->install_read_handler(0xe000, 0xffff, emu::rw_delegate(*this, FUNC(msx_cart_sunrise_scc_device::flash_r<1>)));
+ page(3)->install_write_handler(0xe000, 0xffff, emu::rw_delegate(*this, FUNC(msx_cart_sunrise_scc_device::flash_w<1>)));
+
+ return std::error_condition();
+}
+
+template <int Bank>
+u8 msx_cart_sunrise_scc_device::flash_r(offs_t offset)
+{
+ return m_flash->read(m_selected_bank[Bank] * 0x2000 + offset);
+}
+
+template <int Bank>
+void msx_cart_sunrise_scc_device::flash_w(offs_t offset, u8 data)
+{
+ m_flash->write(m_selected_bank[Bank] * 0x2000 + offset, data);
+}
+
+template <int Bank>
+void msx_cart_sunrise_scc_device::bank_w(offs_t offset, u8 data)
+{
+ if ((offset & 0x1800) == 0x1000)
+ {
+ m_selected_bank[Bank] = data & 0x3f;
+ if (Bank == 2)
+ m_scc_view.select(((data & 0x3f) == 0x3f) ? 1 : 0);
+ }
+ else
+ m_flash->write(m_selected_bank[Bank] * 0x2000 + offset, data);
+}
+
+
+
+
+
+
+class msx_cart_gamemaster2_device : public device_t, public msx_cart_interface
+{
+public:
+ msx_cart_gamemaster2_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MSX_CART_GAMEMASTER2, tag, owner, clock)
+ , msx_cart_interface(mconfig, *this)
+ , m_rombank(*this, "rombank%u", 0U)
+ , m_rambank(*this, "rambank%u", 0U)
+ , m_view{ {*this, "view0"}, {*this, "view1"}, {*this, "view2"} }
+ { }
+
+ virtual std::error_condition initialize_cartridge(std::string &message) override;
+
+protected:
+ // device_t implementation
+ virtual void device_start() override { }
+ virtual void device_reset() override;
+
+private:
+ template <int Bank> void bank_w(u8 data);
+
+ memory_bank_array_creator<3> m_rombank;
+ memory_bank_array_creator<3> m_rambank;
+ memory_view m_view[3];
+};
+
+void msx_cart_gamemaster2_device::device_reset()
+{
+ m_rombank[0]->set_entry(1);
+ m_rombank[1]->set_entry(1);
+ m_rombank[2]->set_entry(2);
+ for (int i = 0; i < 3; i++)
+ m_view[i].select(0);
+}
+
+std::error_condition msx_cart_gamemaster2_device::initialize_cartridge(std::string &message)
+{
+ if (!cart_rom_region())
+ {
+ message = "msx_cart_gamemaster2_device: Required region 'rom' was not found.";
+ return image_error::INTERNAL;
+ }
+
+ if (!cart_sram_region())
+ {
+ message = "msx_cart_gamemaster2_device: Required region 'sram' was not found.";
+ return image_error::INTERNAL;
+ }
+
+ const u32 size = cart_rom_region()->bytes();
+ const u16 banks = size / 0x2000;
+
+ if (size != 0x20000)
+ {
+ message = "msx_cart_gamemaster2_device: Region 'rom' has unsupported size.";
+ return image_error::INVALIDLENGTH;
+ }
+
+ if (cart_sram_region()->bytes() != 0x2000)
+ {
+ message = "msx_cart_gamemaster2_device: Region 'sram' has unsupported size.";
+ return image_error::BADSOFTWARE;
+ }
+
+ for (int i = 0; i < 3; i++)
+ {
+ m_rombank[i]->configure_entries(0, banks, cart_rom_region()->base(), 0x2000);
+ m_rambank[i]->configure_entries(0, 2, cart_sram_region()->base(), 0x1000);
+ }
+
+ page(1)->install_rom(0x4000, 0x5fff, cart_rom_region()->base());
+
+ page(1)->install_view(0x6000, 0x7fff, m_view[0]);
+ m_view[0][0].install_read_bank(0x6000, 0x7fff, m_rombank[0]);
+ m_view[0][0].install_write_handler(0x6000, 0x6fff, emu::rw_delegate(*this, FUNC(msx_cart_gamemaster2_device::bank_w<0>)));
+ m_view[0][1].install_read_bank(0x6000, 0x6fff, 0x1000, m_rambank[0]);
+ m_view[0][1].install_write_handler(0x6000, 0x6fff, emu::rw_delegate(*this, FUNC(msx_cart_gamemaster2_device::bank_w<0>)));
+
+ page(2)->install_view(0x8000, 0x9fff, m_view[1]);
+ m_view[1][0].install_read_bank(0x8000, 0x9fff, m_rombank[1]);
+ m_view[1][0].install_write_handler(0x8000, 0x8fff, emu::rw_delegate(*this, FUNC(msx_cart_gamemaster2_device::bank_w<1>)));
+ m_view[1][1].install_read_bank(0x8000, 0x8fff, 0x1000, m_rambank[1]);
+ m_view[1][1].install_write_handler(0x8000, 0x8fff, emu::rw_delegate(*this, FUNC(msx_cart_gamemaster2_device::bank_w<1>)));
+
+ page(2)->install_view(0xa000, 0xbfff, m_view[2]);
+ m_view[2][0].install_read_bank(0xa000, 0xbfff, m_rombank[2]);
+ m_view[2][0].install_write_handler(0xa000, 0xafff, emu::rw_delegate(*this, FUNC(msx_cart_gamemaster2_device::bank_w<2>)));
+ m_view[2][1].install_read_bank(0xa000, 0xafff, m_rambank[2]);
+ m_view[2][1].install_write_handler(0xa000, 0xafff, emu::rw_delegate(*this, FUNC(msx_cart_gamemaster2_device::bank_w<2>)));
+ m_view[2][1].install_readwrite_bank(0xb000, 0xbfff, m_rambank[2]);
+
+ return std::error_condition();
+}
+
+template <int Bank>
+void msx_cart_gamemaster2_device::bank_w(u8 data)
+{
+ m_rombank[Bank]->set_entry(data & 0x0f);
+ m_rambank[Bank]->set_entry(BIT(data, 5) ? 1 : 0);
+ m_view[Bank].select(BIT(data, 4) ? 1 : 0);
+}
+
+
+
+
+
+class msx_cart_synthesizer_device : public device_t, public msx_cart_interface
+{
+public:
+ msx_cart_synthesizer_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MSX_CART_SYNTHESIZER, tag, owner, clock)
+ , msx_cart_interface(mconfig, *this)
+ , m_dac(*this, "dac")
+ { }
+
+ virtual std::error_condition initialize_cartridge(std::string &message) override;
+
+protected:
+ // device_t implementation
+ virtual void device_start() override { }
+
+ virtual void device_add_mconfig(machine_config &config) override;
+
+private:
+ required_device<dac_8bit_r2r_device> m_dac;
+};
+
+void msx_cart_synthesizer_device::device_add_mconfig(machine_config &config)
+{
+ DAC_8BIT_R2R(config, m_dac, 0); // unknown DAC
+ if (parent_slot())
+ m_dac->add_route(ALL_OUTPUTS, soundin(), 0.3);
+}
+
+std::error_condition msx_cart_synthesizer_device::initialize_cartridge(std::string &message)
+{
+ if (!cart_rom_region())
+ {
+ message = "msx_cart_synthesizer_device: Required region 'rom' was not found.";
+ return image_error::INTERNAL;
+ }
+
+ if (cart_rom_region()->bytes() != 0x8000)
+ {
+ message = "msx_cart_synthesizer_device: Region 'rom' has unsupported size.";
+ return image_error::BADSOFTWARE;
+ }
+
+ page(1)->install_rom(0x4000, 0x7fff, cart_rom_region()->base());
+ page(1)->install_write_handler(0x4000, 0x4000, 0, 0x3fef, 0, emu::rw_delegate(m_dac, FUNC(dac_byte_interface::write)));
+ page(2)->install_rom(0x8000, 0xbfff, cart_rom_region()->base() + 0x4000);
+
+ return std::error_condition();
+}
+
+
+
+
+class msx_cart_konami_sound_device : public device_t, public msx_cart_interface
+{
+public:
+ virtual std::error_condition initialize_cartridge(std::string &message) override;
+
+protected:
+ msx_cart_konami_sound_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u8 min_rambank, u8 max_rambank)
+ : device_t(mconfig, type, tag, owner, clock)
+ , msx_cart_interface(mconfig, *this)
+ , m_k052539(*this, "k052539")
+ , m_rambank(*this, "rambank%u", 0U)
+ , m_view{ {*this, "view0"}, {*this, "view1"}, {*this, "view2"}, {*this, "view3"} }
+ , m_min_rambank(min_rambank)
+ , m_max_rambank(max_rambank)
+ , m_selected_bank{0, 0, 0, 0}
+ , m_control(0)
+ { }
+
+ // device_t implementation
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ virtual void device_add_mconfig(machine_config &config) override;
+
+private:
+ static constexpr u8 VIEW_READ = 0;
+ static constexpr u8 VIEW_RAM = 1;
+ static constexpr u8 VIEW_INVALID = 2;
+ static constexpr u8 VIEW_SCC = 4;
+
+ template <int Bank> void bank_w(u8 data);
+ template <int Bank> void switch_bank();
+ void control_w(u8 data);
+
+ // This is actually a K052539
+ required_device<k051649_device> m_k052539;
+ memory_bank_array_creator<4> m_rambank;
+ memory_view m_view[4];
+
+ u8 m_min_rambank;
+ u8 m_max_rambank;
+ u8 m_selected_bank[4];
+ u8 m_control;
+};
+
+void msx_cart_konami_sound_device::device_add_mconfig(machine_config &config)
+{
+ K051649(config, m_k052539, DERIVED_CLOCK(1, 1));
+ if (parent_slot())
+ m_k052539->add_route(ALL_OUTPUTS, soundin(), 0.4);
+}
+
+void msx_cart_konami_sound_device::device_start()
+{
+ save_item(NAME(m_selected_bank));
+ save_item(NAME(m_control));
+}
+
+void msx_cart_konami_sound_device::device_reset()
+{
+ m_control = 0;
+ for (int i = 0; i < 4; i++)
+ {
+ m_selected_bank[i] = i;
+ }
+ switch_bank<0>();
+ switch_bank<1>();
+ switch_bank<2>();
+ switch_bank<3>();
+}
+
+std::error_condition msx_cart_konami_sound_device::initialize_cartridge(std::string &message)
+{
+ for (int i = 0; i < 4; i++)
+ {
+ m_rambank[i]->configure_entries(0, 8, cart_ram_region()->base(), 0x2000);
+ }
+
+ // TODO Mirrors at 0000-3fff and c000-ffff
+
+ page(1)->install_view(0x4000, 0x5fff, m_view[0]);
+ m_view[0][VIEW_READ].install_read_bank(0x4000, 0x5fff, m_rambank[0]);
+ m_view[0][VIEW_READ].install_write_handler(0x5000, 0x57ff, emu::rw_delegate(*this, FUNC(msx_cart_konami_sound_device::bank_w<0>)));
+ m_view[0][VIEW_RAM].install_readwrite_bank(0x4000, 0x5fff, m_rambank[0]);
+ m_view[0][VIEW_INVALID].install_write_handler(0x5000, 0x57ff, emu::rw_delegate(*this, FUNC(msx_cart_konami_sound_device::bank_w<0>)));
+ m_view[0][VIEW_INVALID | VIEW_RAM];
+
+ page(1)->install_view(0x6000, 0x7fff, m_view[1]);
+ m_view[1][VIEW_READ].install_read_bank(0x6000, 0x7fff, m_rambank[1]);
+ m_view[1][VIEW_READ].install_write_handler(0x7000, 0x77ff, emu::rw_delegate(*this, FUNC(msx_cart_konami_sound_device::bank_w<1>)));
+ m_view[1][VIEW_RAM].install_readwrite_bank(0x6000, 0x7fff, m_rambank[1]);
+ m_view[1][VIEW_INVALID].install_write_handler(0x7000, 0x77ff, emu::rw_delegate(*this, FUNC(msx_cart_konami_sound_device::bank_w<1>)));
+ m_view[1][VIEW_INVALID | VIEW_RAM];
+
+ page(2)->install_view(0x8000, 0x9fff, m_view[2]);
+ m_view[2][VIEW_READ].install_read_bank(0x8000, 0x9fff, m_rambank[2]);
+ m_view[2][VIEW_READ].install_write_handler(0x9000, 0x97ff, emu::rw_delegate(*this, FUNC(msx_cart_konami_sound_device::bank_w<2>)));
+ m_view[2][VIEW_RAM].install_readwrite_bank(0x8000, 0x9fff, m_rambank[2]);
+ m_view[2][VIEW_INVALID].install_write_handler(0x9000, 0x97ff, emu::rw_delegate(*this, FUNC(msx_cart_konami_sound_device::bank_w<2>)));
+ m_view[2][VIEW_INVALID | VIEW_RAM];
+ m_view[2][VIEW_SCC | VIEW_READ].install_read_bank(0x8000, 0x9fff, m_rambank[2]);
+ m_view[2][VIEW_SCC | VIEW_READ].install_write_handler(0x9000, 0x97ff, emu::rw_delegate(*this, FUNC(msx_cart_konami_sound_device::bank_w<2>)));
+ m_view[2][VIEW_SCC | VIEW_READ].install_read_handler(0x9800, 0x987f, 0, 0x0700, 0, emu::rw_delegate(m_k052539, FUNC(k051649_device::k051649_waveform_r)));
+ m_view[2][VIEW_SCC | VIEW_READ].install_write_handler(0x9800, 0x987f, 0, 0x0700, 0, emu::rw_delegate(m_k052539, FUNC(k051649_device::k051649_waveform_w)));
+ m_view[2][VIEW_SCC | VIEW_READ].install_write_handler(0x9880, 0x9889, 0, 0x0710, 0, emu::rw_delegate(m_k052539, FUNC(k051649_device::k051649_frequency_w)));
+ m_view[2][VIEW_SCC | VIEW_READ].install_write_handler(0x988a, 0x988e, 0, 0x0710, 0, emu::rw_delegate(m_k052539, FUNC(k051649_device::k051649_volume_w)));
+ m_view[2][VIEW_SCC | VIEW_READ].install_write_handler(0x988f, 0x988f, 0, 0x0710, 0, emu::rw_delegate(m_k052539, FUNC(k051649_device::k051649_keyonoff_w)));
+ m_view[2][VIEW_SCC | VIEW_READ].install_read_handler(0x98c0, 0x98c0, 0, 0x071f, 0, emu::rw_delegate(m_k052539, FUNC(k051649_device::k051649_test_r)));
+ m_view[2][VIEW_SCC | VIEW_READ].install_write_handler(0x98c0, 0x98c0, 0, 0x071f, 0, emu::rw_delegate(m_k052539, FUNC(k051649_device::k051649_test_w)));
+ m_view[2][VIEW_SCC | VIEW_RAM].install_readwrite_bank(0x8000, 0x9fff, m_rambank[2]);
+ m_view[2][VIEW_SCC | VIEW_RAM].install_read_handler(0x9800, 0x987f, 0, 0x0700, 0, emu::rw_delegate(m_k052539, FUNC(k051649_device::k051649_waveform_r)));
+ m_view[2][VIEW_SCC | VIEW_RAM].install_read_handler(0x98c0, 0x98c0, 0, 0x071f, 0, emu::rw_delegate(m_k052539, FUNC(k051649_device::k051649_test_r)));
+ m_view[2][VIEW_SCC | VIEW_INVALID].install_write_handler(0x9000, 0x97ff, emu::rw_delegate(*this, FUNC(msx_cart_konami_sound_device::bank_w<2>)));
+ m_view[2][VIEW_SCC | VIEW_INVALID].install_read_handler(0x9800, 0x987f, 0, 0x0700, 0, emu::rw_delegate(m_k052539, FUNC(k051649_device::k051649_waveform_r)));
+ m_view[2][VIEW_SCC | VIEW_INVALID].install_write_handler(0x9800, 0x987f, 0, 0x0700, 0, emu::rw_delegate(m_k052539, FUNC(k051649_device::k051649_waveform_w)));
+ m_view[2][VIEW_SCC | VIEW_INVALID].install_write_handler(0x9880, 0x9889, 0, 0x0710, 0, emu::rw_delegate(m_k052539, FUNC(k051649_device::k051649_frequency_w)));
+ m_view[2][VIEW_SCC | VIEW_INVALID].install_write_handler(0x988a, 0x988e, 0, 0x0710, 0, emu::rw_delegate(m_k052539, FUNC(k051649_device::k051649_volume_w)));
+ m_view[2][VIEW_SCC | VIEW_INVALID].install_write_handler(0x988f, 0x988f, 0, 0x0710, 0, emu::rw_delegate(m_k052539, FUNC(k051649_device::k051649_keyonoff_w)));
+ m_view[2][VIEW_SCC | VIEW_INVALID].install_read_handler(0x98c0, 0x98c0, 0, 0x071f, 0, emu::rw_delegate(m_k052539, FUNC(k051649_device::k051649_test_r)));
+ m_view[2][VIEW_SCC | VIEW_INVALID].install_write_handler(0x98c0, 0x98c0, 0, 0x071f, 0, emu::rw_delegate(m_k052539, FUNC(k051649_device::k051649_test_w)));
+ m_view[2][VIEW_SCC | VIEW_INVALID | VIEW_RAM];
+ m_view[2][VIEW_SCC | VIEW_INVALID | VIEW_RAM].install_read_handler(0x9800, 0x987f, 0, 0x0700, 0, emu::rw_delegate(m_k052539, FUNC(k051649_device::k051649_waveform_r)));
+ m_view[2][VIEW_SCC | VIEW_INVALID | VIEW_RAM].install_read_handler(0x98c0, 0x98c0, 0, 0x071f, 0, emu::rw_delegate(m_k052539, FUNC(k051649_device::k051649_test_r)));
+
+ page(2)->install_view(0xa000, 0xbfff, m_view[3]);
+ m_view[3][VIEW_READ].install_read_bank(0xa000, 0xbfff, m_rambank[3]);
+ m_view[3][VIEW_READ].install_write_handler(0xb000, 0xb7ff, emu::rw_delegate(*this, FUNC(msx_cart_konami_sound_device::bank_w<3>)));
+ m_view[3][VIEW_RAM].install_readwrite_bank(0xa000, 0xbfff, m_rambank[3]);
+ m_view[3][VIEW_INVALID].install_write_handler(0xb000, 0xb7ff, emu::rw_delegate(*this, FUNC(msx_cart_konami_sound_device::bank_w<3>)));
+ m_view[3][VIEW_INVALID | VIEW_RAM];
+ m_view[3][VIEW_SCC | VIEW_READ].install_read_bank(0xa000, 0xbfff, m_rambank[3]);
+ m_view[3][VIEW_SCC | VIEW_READ].install_write_handler(0xb000, 0xb7ff, emu::rw_delegate(*this, FUNC(msx_cart_konami_sound_device::bank_w<3>)));
+ m_view[3][VIEW_SCC | VIEW_READ].install_read_handler(0xb800, 0xb89f, 0, 0x0700, 0, emu::rw_delegate(m_k052539, FUNC(k051649_device::k052539_waveform_r)));
+ m_view[3][VIEW_SCC | VIEW_READ].install_write_handler(0xb800, 0xb89f, 0, 0x0700, 0, emu::rw_delegate(m_k052539, FUNC(k051649_device::k052539_waveform_w)));
+ m_view[3][VIEW_SCC | VIEW_READ].install_write_handler(0xb8a0, 0xb8a9, 0, 0x0710, 0, emu::rw_delegate(m_k052539, FUNC(k051649_device::k051649_frequency_w)));
+ m_view[3][VIEW_SCC | VIEW_READ].install_write_handler(0xb8aa, 0xb8ae, 0, 0x0710, 0, emu::rw_delegate(m_k052539, FUNC(k051649_device::k051649_volume_w)));
+ m_view[3][VIEW_SCC | VIEW_READ].install_write_handler(0xb8af, 0xb8af, 0, 0x0710, 0, emu::rw_delegate(m_k052539, FUNC(k051649_device::k051649_keyonoff_w)));
+ m_view[3][VIEW_SCC | VIEW_READ].install_read_handler(0xb8c0, 0xb8c0, 0, 0x071f, 0, emu::rw_delegate(m_k052539, FUNC(k051649_device::k051649_test_r)));
+ m_view[3][VIEW_SCC | VIEW_READ].install_write_handler(0xb8c0, 0xb8c0, 0, 0x071f, 0, emu::rw_delegate(m_k052539, FUNC(k051649_device::k051649_test_w)));
+ m_view[3][VIEW_SCC | VIEW_RAM].install_readwrite_bank(0xa000, 0xbfff, m_rambank[3]);
+ m_view[3][VIEW_SCC | VIEW_RAM].install_read_handler(0xb800, 0xb89f, 0, 0x0700, 0, emu::rw_delegate(m_k052539, FUNC(k051649_device::k052539_waveform_r)));
+ m_view[3][VIEW_SCC | VIEW_RAM].install_read_handler(0xb8c0, 0xb8c0, 0, 0x071f, 0, emu::rw_delegate(m_k052539, FUNC(k051649_device::k051649_test_r)));
+ m_view[3][VIEW_SCC | VIEW_INVALID].install_write_handler(0xb000, 0xb7ff, emu::rw_delegate(*this, FUNC(msx_cart_konami_sound_device::bank_w<3>)));
+ m_view[3][VIEW_SCC | VIEW_INVALID].install_read_handler(0xb800, 0xb89f, 0, 0x0700, 0, emu::rw_delegate(m_k052539, FUNC(k051649_device::k052539_waveform_r)));
+ m_view[3][VIEW_SCC | VIEW_INVALID].install_write_handler(0xb800, 0xb89f, 0, 0x0700, 0, emu::rw_delegate(m_k052539, FUNC(k051649_device::k052539_waveform_w)));
+ m_view[3][VIEW_SCC | VIEW_INVALID].install_write_handler(0xb8a0, 0xb8a9, 0, 0x0710, 0, emu::rw_delegate(m_k052539, FUNC(k051649_device::k051649_frequency_w)));
+ m_view[3][VIEW_SCC | VIEW_INVALID].install_write_handler(0xb8aa, 0xb8ae, 0, 0x0710, 0, emu::rw_delegate(m_k052539, FUNC(k051649_device::k051649_volume_w)));
+ m_view[3][VIEW_SCC | VIEW_INVALID].install_write_handler(0xb8af, 0xb8af, 0, 0x0710, 0, emu::rw_delegate(m_k052539, FUNC(k051649_device::k051649_keyonoff_w)));
+ m_view[3][VIEW_SCC | VIEW_INVALID].install_read_handler(0xb8c0, 0xb8c0, 0, 0x071f, 0, emu::rw_delegate(m_k052539, FUNC(k051649_device::k051649_test_r)));
+ m_view[3][VIEW_SCC | VIEW_INVALID].install_write_handler(0xb8c0, 0xb8c0, 0, 0x071f, 0, emu::rw_delegate(m_k052539, FUNC(k051649_device::k051649_test_w)));
+ m_view[3][VIEW_SCC | VIEW_INVALID | VIEW_RAM];
+ m_view[3][VIEW_SCC | VIEW_INVALID| VIEW_RAM].install_read_handler(0xb800, 0xb89f, 0, 0x0700, 0, emu::rw_delegate(m_k052539, FUNC(k051649_device::k052539_waveform_r)));
+ m_view[3][VIEW_SCC | VIEW_INVALID| VIEW_RAM].install_read_handler(0xb8c0, 0xb8c0, 0, 0x071f, 0, emu::rw_delegate(m_k052539, FUNC(k051649_device::k051649_test_r)));
+
+ page(2)->install_write_handler(0xbffe, 0xbfff, emu::rw_delegate(*this, FUNC(msx_cart_konami_sound_device::control_w)));
+
+ return std::error_condition();
+}
+
+void msx_cart_konami_sound_device::control_w(u8 data)
+{
+ m_control = data;
+
+ switch_bank<0>();
+ switch_bank<1>();
+ switch_bank<2>();
+ switch_bank<3>();
+}
+
+template <int Bank>
+void msx_cart_konami_sound_device::switch_bank()
+{
+ u8 view = VIEW_READ;
+ if ((m_selected_bank[Bank] & 0x0f) >= m_min_rambank && (m_selected_bank[Bank] & 0x0f) <= m_max_rambank)
+ m_rambank[Bank]->set_entry(m_selected_bank[Bank] & 0x07);
+ else
+ view |= VIEW_INVALID;
+ if (BIT(m_control, 4))
+ view |= VIEW_RAM;
+ else
+ {
+ if (Bank < 2 && BIT(m_control, Bank))
+ view |= VIEW_RAM;
+ else if (Bank == 2 && BIT(m_control, Bank) && BIT(m_control, 5))
+ view |= VIEW_RAM;
+ }
+ if (Bank == 2 && !BIT(m_control, 5) && (m_selected_bank[2] & 0x3f) == 0x3f)
+ view |= VIEW_SCC;
+ if (Bank == 3 && BIT(m_control, 5) && BIT(m_selected_bank[3], 7))
+ view |= VIEW_SCC;
+
+ m_view[Bank].select(view);
+}
+
+template <int Bank>
+void msx_cart_konami_sound_device::bank_w(u8 data)
+{
+ m_selected_bank[Bank] = data;
+ switch_bank<Bank>();
+}
+
+
+
+class msx_cart_konami_sound_snatcher_device : public msx_cart_konami_sound_device
+{
+public:
+ // The Snatcher Sound cartridge has 64KB RAM available by selecting ram banks 0-7
+ msx_cart_konami_sound_snatcher_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : msx_cart_konami_sound_device(mconfig, MSX_CART_SOUND_SNATCHER, tag, owner, clock, 0, 7)
+ { }
+
+ virtual std::error_condition initialize_cartridge(std::string &message) override;
+};
+
+std::error_condition msx_cart_konami_sound_snatcher_device::initialize_cartridge(std::string &message)
+{
+ if (!cart_ram_region())
+ {
+ message = "msx_cart_konami_sound_snatcher_device: Required region 'ram' was not found.";
+ return image_error::INTERNAL;
+ }
+
+ if (cart_ram_region()->bytes() != 0x10000)
+ {
+ message = "msx_cart_konami_sound_snatcher_device: Region 'ram' has unsupported size.";
+ return image_error::BADSOFTWARE;
+ }
+
+ return msx_cart_konami_sound_device::initialize_cartridge(message);
+}
+
+
+class msx_cart_konami_sound_sdsnatcher_device : public msx_cart_konami_sound_device
+{
+public:
+ // The SD Snatcher Sound cartridge has 64KB RAM available by selecting ram banks 8-15
+ msx_cart_konami_sound_sdsnatcher_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : msx_cart_konami_sound_device(mconfig, MSX_CART_SOUND_SDSNATCHER, tag, owner, clock, 8, 15)
+ { }
+
+ virtual std::error_condition initialize_cartridge(std::string &message) override;
+};
+
+std::error_condition msx_cart_konami_sound_sdsnatcher_device::initialize_cartridge(std::string &message)
+{
+ if (!cart_ram_region())
+ {
+ message = "msx_cart_konami_sound_sdsnatcher_device: Required region 'ram' was not found.";
+ return image_error::INTERNAL;
+ }
+
+ if (cart_ram_region()->bytes() != 0x10000)
+ {
+ message = "msx_cart_konami_sound_sdsnatcher_device: Region 'ram' has unsupported size.";
+ return image_error::BADSOFTWARE;
+ }
+
+ return msx_cart_konami_sound_device::initialize_cartridge(message);
+}
+
+
+
+class msx_cart_keyboard_master_device : public device_t, public msx_cart_interface
+{
+public:
+ msx_cart_keyboard_master_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MSX_CART_KEYBOARD_MASTER, tag, owner, clock)
+ , msx_cart_interface(mconfig, *this)
+ , m_vlm5030(*this, "vlm5030")
+ { }
+
+protected:
+ // device_t implementation
+ virtual void device_start() override;
+
+ virtual void device_add_mconfig(machine_config &config) override;
+
+ virtual std::error_condition initialize_cartridge(std::string &message) override;
+
+private:
+ required_device<vlm5030_device> m_vlm5030;
+
+ uint8_t read_vlm(offs_t offset);
+ void io_20_w(uint8_t data);
+ uint8_t io_00_r();
+
+ void vlm_map(address_map &map);
+};
+
+void msx_cart_keyboard_master_device::vlm_map(address_map &map)
+{
+ map(0x0000, 0xffff).r(FUNC(msx_cart_keyboard_master_device::read_vlm));
+}
+
+void msx_cart_keyboard_master_device::device_add_mconfig(machine_config &config)
+{
+ VLM5030(config, m_vlm5030, DERIVED_CLOCK(1, 1));
+ if (parent_slot())
+ m_vlm5030->add_route(ALL_OUTPUTS, soundin(), 1.0);
+ m_vlm5030->set_addrmap(0, &msx_cart_keyboard_master_device::vlm_map);
+}
+
+void msx_cart_keyboard_master_device::device_start()
+{
+ // Install IO read/write handlers
+ io_space().install_write_handler(0x00, 0x00, emu::rw_delegate(*m_vlm5030, FUNC(vlm5030_device::data_w)));
+ io_space().install_write_handler(0x20, 0x20, emu::rw_delegate(*this, FUNC(msx_cart_keyboard_master_device::io_20_w)));
+ io_space().install_read_handler(0x00, 0x00, emu::rw_delegate(*this, FUNC(msx_cart_keyboard_master_device::io_00_r)));
+}
+
+std::error_condition msx_cart_keyboard_master_device::initialize_cartridge(std::string &message)
+{
+ if (!cart_rom_region())
+ {
+ message = "msx_cart_keyboard_master_device: Required region 'rom' was not found.";
+ return image_error::INTERNAL;
+ }
+
+ if (!cart_vlm5030_region())
+ {
+ message = "msx_cart_keyboard_master_device: Required region 'vlm5030' was not found.";
+ return image_error::INTERNAL;
+ }
+
+ if (cart_rom_region()->bytes() != 0x4000)
+ {
+ message = "msx_cart_keyboard_master_device: Region 'rom' has unsupported size.";
+ return image_error::BADSOFTWARE;
+ }
+
+ page(1)->install_rom(0x4000, 0x7fff, cart_rom_region()->base());
+
+ return std::error_condition();
+}
+
+uint8_t msx_cart_keyboard_master_device::read_vlm(offs_t offset)
+{
+ if (offset < cart_vlm5030_region()->bytes())
+ return cart_vlm5030_region()->base()[offset];
+ else
+ return 0xff;
+}
+
+void msx_cart_keyboard_master_device::io_20_w(uint8_t data)
+{
+ m_vlm5030->rst(BIT(data, 0) ? 1 : 0);
+ m_vlm5030->vcu(BIT(data, 2) ? 1 : 0);
+ m_vlm5030->st(BIT(data, 1) ? 1 : 0);
+}
+
+uint8_t msx_cart_keyboard_master_device::io_00_r()
+{
+ return m_vlm5030->bsy() ? 0x10 : 0x00;
+}
+
+
+
+class msx_cart_ec701_device : public device_t, public msx_cart_interface
+{
+public:
+ msx_cart_ec701_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MSX_CART_EC701, tag, owner, clock)
+ , msx_cart_interface(mconfig, *this)
+ , m_rombank(*this, "rombank")
+ , m_view(*this, "view")
+ { }
+
+protected:
+ // device_t implementation
+ virtual void device_start() override { }
+ virtual void device_reset() override;
+
+ virtual std::error_condition initialize_cartridge(std::string &message) override;
+
+private:
+ void bank_w(u8 data);
+
+ memory_bank_creator m_rombank;
+ memory_view m_view;
+};
+
+void msx_cart_ec701_device::device_reset()
+{
+ m_view.select(0);
+}
+
+std::error_condition msx_cart_ec701_device::initialize_cartridge(std::string &message)
+{
+ if (!cart_rom_region())
+ {
+ message = "msx_cart_ec701_device: Required region 'rom' was not found.";
+ return image_error::INTERNAL;
+ }
+
+ m_rombank->configure_entries(0, 24, cart_rom_region()->base() + 0x20000, 0x4000);
+
+ page(1)->install_view(0x4000, 0x7fff, m_view);
+ m_view[0].install_rom(0x4000, 0x7fff, cart_rom_region()->base());
+ m_view[1].install_read_bank(0x4000, 0x7fff, m_rombank);
+ m_view[2].nop_read(0x4000, 0x7fff);
+
+ page(2)->install_rom(0x8000, 0xbfff, cart_rom_region()->base() + 0x4000);
+ page(2)->install_write_handler(0xbff8, 0xbfff, emu::rw_delegate(*this, FUNC(msx_cart_ec701_device::bank_w)));
+
+ return std::error_condition();
+}
+
+void msx_cart_ec701_device::bank_w(u8 data)
+{
+ data = ~data;
+ switch (data & 0x38)
+ {
+ case 0x00: // ic1
+ m_view.select(0);
+ break;
+ case 0x20: // ic2
+ m_view.select(1);
+ m_rombank->set_entry(data & 0x07);
+ break;
+ case 0x28: // ic3
+ m_view.select(1);
+ m_rombank->set_entry(0x08 + (data & 0x07));
+ break;
+ case 0x30: // ic4
+ m_view.select(1);
+ m_rombank->set_entry(0x10 + (data & 0x07));
+ break;
+ default:
+ m_view.select(2);
+ break;
+ }
+}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_KONAMI, msx_cart_interface, msx_cart_konami_device, "msx_cart_konami", "MSX Cartridge - KONAMI")
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_KONAMI_SCC, msx_cart_interface, msx_cart_konami_scc_device, "msx_cart_konami_scc", "MSX Cartridge - KONAMI+SCC")
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_SUNRISE_SCC, msx_cart_interface, msx_cart_sunrise_scc_device, "msx_cart_sunrise_scc", "MSX Cartridge - Sunrise+SCC")
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_GAMEMASTER2, msx_cart_interface, msx_cart_gamemaster2_device, "msx_cart_gamemaster2", "MSX Cartridge - GAMEMASTER2")
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_SYNTHESIZER, msx_cart_interface, msx_cart_synthesizer_device, "msx_cart_synthesizer", "MSX Cartridge - Synthesizer")
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_SOUND_SNATCHER, msx_cart_interface, msx_cart_konami_sound_snatcher_device, "msx_cart_sound_snatcher", "MSX Cartridge - Sound Snatcher")
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_SOUND_SDSNATCHER, msx_cart_interface, msx_cart_konami_sound_sdsnatcher_device, "msx_cart_sound_sdsnatcher", "MSX Cartridge - Sound SD Snatcher")
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_KEYBOARD_MASTER, msx_cart_interface, msx_cart_keyboard_master_device, "msx_cart_keyboard_master", "MSX Cartridge - Keyboard Master")
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_EC701, msx_cart_interface, msx_cart_ec701_device, "msx_cart_ec701", "MSX Cartridge - Konami EC-701")
diff --git a/src/devices/bus/msx/cart/konami.h b/src/devices/bus/msx/cart/konami.h
new file mode 100644
index 00000000000..70809f3bf95
--- /dev/null
+++ b/src/devices/bus/msx/cart/konami.h
@@ -0,0 +1,21 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#ifndef MAME_BUS_MSX_CART_KONAMI_H
+#define MAME_BUS_MSX_CART_KONAMI_H
+
+#pragma once
+
+#include "bus/msx/slot/cartridge.h"
+
+
+DECLARE_DEVICE_TYPE(MSX_CART_KONAMI, msx_cart_interface)
+DECLARE_DEVICE_TYPE(MSX_CART_KONAMI_SCC, msx_cart_interface)
+DECLARE_DEVICE_TYPE(MSX_CART_SUNRISE_SCC, msx_cart_interface)
+DECLARE_DEVICE_TYPE(MSX_CART_GAMEMASTER2, msx_cart_interface)
+DECLARE_DEVICE_TYPE(MSX_CART_SYNTHESIZER, msx_cart_interface)
+DECLARE_DEVICE_TYPE(MSX_CART_SOUND_SNATCHER, msx_cart_interface)
+DECLARE_DEVICE_TYPE(MSX_CART_SOUND_SDSNATCHER, msx_cart_interface)
+DECLARE_DEVICE_TYPE(MSX_CART_KEYBOARD_MASTER, msx_cart_interface)
+DECLARE_DEVICE_TYPE(MSX_CART_EC701, msx_cart_interface)
+
+#endif // MAME_BUS_MSX_CART_KONAMI_H
diff --git a/src/devices/bus/msx/cart/korean.cpp b/src/devices/bus/msx/cart/korean.cpp
new file mode 100644
index 00000000000..cf28d2be631
--- /dev/null
+++ b/src/devices/bus/msx/cart/korean.cpp
@@ -0,0 +1,381 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#include "emu.h"
+#include "korean.h"
+
+
+namespace {
+
+class msx_cart_korean_25in1_device : public device_t, public msx_cart_interface
+{
+public:
+ msx_cart_korean_25in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, MSX_CART_KOREAN_25IN1, tag, owner, clock)
+ , msx_cart_interface(mconfig, *this)
+ , m_rombank(*this, "rombank%u", 0U)
+ , m_bank_mask(0)
+ { }
+
+ virtual std::error_condition initialize_cartridge(std::string &message) override;
+
+protected:
+ // device_t implementation
+ virtual void device_start() override { }
+ virtual void device_reset() override;
+
+private:
+ void bank_w(u8 data);
+
+ memory_bank_array_creator<4> m_rombank;
+
+ u8 m_bank_mask;
+};
+
+void msx_cart_korean_25in1_device::device_reset()
+{
+ for (int i = 0; i < 4; i++)
+ m_rombank[i]->set_entry(m_bank_mask);
+}
+
+std::error_condition msx_cart_korean_25in1_device::initialize_cartridge(std::string &message)
+{
+ if (!cart_rom_region())
+ {
+ message = "msx_cart_korean_25in1_device: Required region 'rom' was not found.";
+ return image_error::INTERNAL;
+ }
+
+ const u32 size = cart_rom_region()->bytes();
+ const u16 banks = size / 0x2000;
+
+ if (size > 256 * 0x2000 || size < 0x8000 || size != banks * 0x2000 || (~(banks - 1) % banks))
+ {
+ message = "msx_cart_korean_25in1_device: Region 'rom' has unsupported size.";
+ return image_error::INVALIDLENGTH;
+ }
+
+ m_bank_mask = banks - 1;
+
+ for (int i = 0; i < 4; i++)
+ m_rombank[i]->configure_entries(0, banks, cart_rom_region()->base(), 0x2000);
+
+ page(0)->install_rom(0x0000, 0x1fff, cart_rom_region()->base() + (m_bank_mask * 0x2000));
+ page(0)->install_write_handler(0x0000, 0x0000, emu::rw_delegate(*this, FUNC(msx_cart_korean_25in1_device::bank_w)));
+ page(1)->install_read_bank(0x4000, 0x5fff, m_rombank[0]);
+ page(1)->install_read_bank(0x6000, 0x7fff, m_rombank[1]);
+ page(2)->install_read_bank(0x8000, 0x9fff, m_rombank[2]);
+ page(2)->install_read_bank(0xa000, 0xbfff, m_rombank[3]);
+
+ return std::error_condition();
+}
+
+void msx_cart_korean_25in1_device::bank_w(u8 data)
+{
+ for (int i = 0; i < 4; i++)
+ {
+ m_rombank[i]->set_entry((data - i) & m_bank_mask);
+ }
+}
+
+
+
+
+
+class msx_cart_korean_80in1_device : public device_t, public msx_cart_interface
+{
+public:
+ msx_cart_korean_80in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, MSX_CART_KOREAN_80IN1, tag, owner, clock)
+ , msx_cart_interface(mconfig, *this)
+ , m_rombank(*this, "rombank%u", 0U)
+ , m_bank_mask(0)
+ { }
+
+ virtual std::error_condition initialize_cartridge(std::string &message) override;
+
+protected:
+ // device_t implementation
+ virtual void device_start() override { }
+ virtual void device_reset() override;
+
+private:
+ void bank_w(offs_t offset, u8 data);
+
+ memory_bank_array_creator<4> m_rombank;
+
+ u8 m_bank_mask;
+};
+
+void msx_cart_korean_80in1_device::device_reset()
+{
+ for (int i = 0; i < 4; i++)
+ m_rombank[i]->set_entry(i);
+}
+
+std::error_condition msx_cart_korean_80in1_device::initialize_cartridge(std::string &message)
+{
+ if (!cart_rom_region())
+ {
+ message = "msx_cart_korean_80in1_device: Required region 'rom' was not found.";
+ return image_error::INTERNAL;
+ }
+
+ const u32 size = cart_rom_region()->bytes();
+ const u16 banks = size / 0x2000;
+
+ if (size > 256 * 0x2000 || size < 0x8000 || size != banks * 0x2000 || (~(banks - 1) % banks))
+ {
+ message = "msx_cart_korean_80in1_device: Region 'rom' has unsupported size.";
+ return image_error::INVALIDLENGTH;
+ }
+
+ m_bank_mask = banks - 1;
+
+ for (int i = 0; i < 4; i++)
+ m_rombank[i]->configure_entries(0, banks, cart_rom_region()->base(), 0x2000);
+
+ page(1)->install_read_bank(0x4000, 0x5fff, m_rombank[0]);
+ page(1)->install_write_handler(0x4000, 0x4003, emu::rw_delegate(*this, FUNC(msx_cart_korean_80in1_device::bank_w)));
+ page(1)->install_read_bank(0x6000, 0x7fff, m_rombank[1]);
+ page(2)->install_read_bank(0x8000, 0x9fff, m_rombank[2]);
+ page(2)->install_read_bank(0xa000, 0xbfff, m_rombank[3]);
+
+ return std::error_condition();
+}
+
+void msx_cart_korean_80in1_device::bank_w(offs_t offset, u8 data)
+{
+ m_rombank[offset & 0x03]->set_entry(data & m_bank_mask);
+}
+
+
+
+
+
+class msx_cart_korean_90in1_device : public device_t, public msx_cart_interface
+{
+public:
+ msx_cart_korean_90in1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MSX_CART_KOREAN_90IN1, tag, owner, clock)
+ , msx_cart_interface(mconfig, *this)
+ , m_rombank(*this, "rombank%u", 0U)
+ , m_view(*this, "view")
+ , m_bank_mask(0)
+ { }
+
+ virtual std::error_condition initialize_cartridge(std::string &message) override;
+
+protected:
+ // device_t implementation
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+private:
+ void banking(u8 data);
+
+ memory_bank_array_creator<3> m_rombank;
+ memory_view m_view;
+ u8 m_bank_mask;
+};
+
+void msx_cart_korean_90in1_device::device_start()
+{
+ // Install IO read/write handlers
+ io_space().install_write_handler(0x77, 0x77, emu::rw_delegate(*this, FUNC(msx_cart_korean_90in1_device::banking)));
+}
+
+void msx_cart_korean_90in1_device::device_reset()
+{
+ m_view.select(0);
+ m_rombank[0]->set_entry(0);
+ m_rombank[1]->set_entry(0);
+ m_rombank[2]->set_entry(0);
+}
+
+std::error_condition msx_cart_korean_90in1_device::initialize_cartridge(std::string &message)
+{
+ if (!cart_rom_region())
+ {
+ message = "msx_cart_korean_90in1_device: Required region 'rom' was not found.";
+ return image_error::INTERNAL;
+ }
+
+ const u32 size = cart_rom_region()->bytes();
+ const u16 banks = size / 0x4000;
+
+ if (size > 64 * 0x4000 || size < 0x8000 || size != banks * 0x4000 || (~(banks - 1) % banks))
+ {
+ message = "msx_cart_korean_90in1_device: Region 'rom' has unsupported size.";
+ return image_error::INVALIDLENGTH;
+ }
+
+ m_bank_mask = banks - 1;
+
+ m_rombank[0]->configure_entries(0, banks, cart_rom_region()->base(), 0x4000);
+ m_rombank[1]->configure_entries(0, banks, cart_rom_region()->base(), 0x4000);
+ m_rombank[2]->configure_entries(0, banks, cart_rom_region()->base() + 0x2000, 0x4000);
+
+ page(1)->install_read_bank(0x4000, 0x7fff, m_rombank[0]);
+
+ page(2)->install_view(0x8000, 0xbfff, m_view);
+ m_view[0].install_read_bank(0x8000, 0x9fff, m_rombank[1]);
+ m_view[0].install_read_bank(0xa000, 0xbfff, m_rombank[2]);
+ m_view[1].install_read_bank(0x8000, 0x9fff, m_rombank[2]);
+ m_view[1].install_read_bank(0xa000, 0xbfff, m_rombank[1]);
+
+ return std::error_condition();
+}
+
+void msx_cart_korean_90in1_device::banking(u8 data)
+{
+ if (BIT(data, 7) && !BIT(data, 6))
+ data &= 0xfe;
+
+ m_rombank[0]->set_entry(data & m_bank_mask);
+ m_rombank[1]->set_entry((data + (BIT(data, 7) ? 1 : 0)) & m_bank_mask);
+ m_rombank[2]->set_entry((data + (BIT(data, 7) ? 1 : 0)) & m_bank_mask);
+
+ m_view.select((BIT(data, 7) && BIT(data, 6)) ? 1 : 0);
+}
+
+
+
+
+
+class msx_cart_korean_126in1_device : public device_t, public msx_cart_interface
+{
+public:
+ msx_cart_korean_126in1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MSX_CART_KOREAN_126IN1, tag, owner, clock)
+ , msx_cart_interface(mconfig, *this)
+ , m_rombank(*this, "rombank%u", 0U)
+ , m_bank_mask(0)
+ { }
+
+ virtual std::error_condition initialize_cartridge(std::string &message) override;
+
+protected:
+ // device_t implementation
+ virtual void device_start() override { }
+ virtual void device_reset() override;
+
+private:
+ void bank_w(offs_t offset, u8 data);
+
+ memory_bank_array_creator<2> m_rombank;
+ u8 m_bank_mask;
+};
+
+void msx_cart_korean_126in1_device::device_reset()
+{
+ m_rombank[0]->set_entry(0);
+ m_rombank[1]->set_entry(1);
+}
+
+std::error_condition msx_cart_korean_126in1_device::initialize_cartridge(std::string &message)
+{
+ if (!cart_rom_region())
+ {
+ message = "msx_cart_korean_126in1_device: Required region 'rom' was not found.";
+ return image_error::INTERNAL;
+ }
+
+ const u32 size = cart_rom_region()->bytes();
+ const u16 banks = size / 0x4000;
+
+ if (size > 256 * 0x4000 || size < 0x8000 || size != banks * 0x4000 || (~(banks - 1) % banks))
+ {
+ message = "msx_cart_korean_126in1_device: Region 'rom' has unsupported size.";
+ return image_error::INVALIDLENGTH;
+ }
+
+ m_bank_mask = banks - 1;
+
+ m_rombank[0]->configure_entries(0, banks, cart_rom_region()->base(), 0x4000);
+ m_rombank[1]->configure_entries(0, banks, cart_rom_region()->base(), 0x4000);
+
+ page(1)->install_read_bank(0x4000, 0x7fff, m_rombank[0]);
+ page(1)->install_write_handler(0x4000, 0x4001, emu::rw_delegate(*this, FUNC(msx_cart_korean_126in1_device::bank_w)));
+ page(2)->install_read_bank(0x8000, 0xbfff, m_rombank[1]);
+
+ return std::error_condition();
+}
+
+void msx_cart_korean_126in1_device::bank_w(offs_t offset, uint8_t data)
+{
+ m_rombank[offset & 0x01]->set_entry(data & m_bank_mask);
+}
+
+
+
+
+
+class msx_cart_korean_hydlide2_device : public device_t, public msx_cart_interface
+{
+public:
+ msx_cart_korean_hydlide2_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MSX_CART_KOREAN_HYDLIDE2, tag, owner, clock)
+ , msx_cart_interface(mconfig, *this)
+ , m_rombank(*this, "rombank")
+ , m_bank_mask(0)
+ { }
+
+ virtual std::error_condition initialize_cartridge(std::string &message) override;
+
+protected:
+ // device_t implementation
+ virtual void device_start() override { }
+ virtual void device_reset() override;
+
+private:
+ void bank_w(u8 data);
+
+ memory_bank_creator m_rombank;
+ u8 m_bank_mask;
+};
+
+void msx_cart_korean_hydlide2_device::device_reset()
+{
+ m_rombank->set_entry(0);
+}
+
+std::error_condition msx_cart_korean_hydlide2_device::initialize_cartridge(std::string &message)
+{
+ if (!cart_rom_region())
+ {
+ message = "msx_cart_korean_hydlide2_device: Required region 'rom' was not found.";
+ return image_error::INTERNAL;
+ }
+
+ const u32 size = cart_rom_region()->bytes();
+ const u16 banks = size / 0x4000;
+
+ if (size > 256 * 0x4000 || size < 0x8000 || size != banks * 0x4000 || (~(banks - 1) % banks))
+ {
+ message = "msx_cart_korean_hydlide2_device: Region 'rom' has unsupported size.";
+ return image_error::INVALIDLENGTH;
+ }
+
+ m_bank_mask = banks - 1;
+
+ m_rombank->configure_entries(0, banks, cart_rom_region()->base(), 0x4000);
+
+ page(1)->install_rom(0x4000, 0x7fff, cart_rom_region()->base());
+ page(2)->install_read_bank(0x8000, 0xbfff, m_rombank);
+ page(2)->install_write_handler(0x8000, 0x8000, emu::rw_delegate(*this, FUNC(msx_cart_korean_hydlide2_device::bank_w)));
+
+ return std::error_condition();
+}
+
+void msx_cart_korean_hydlide2_device::bank_w(uint8_t data)
+{
+ m_rombank->set_entry(data & m_bank_mask);
+}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_KOREAN_25IN1, msx_cart_interface, msx_cart_korean_25in1_device, "msx_cart_korean_25in1", "MSX Cartridge - Korean 25-in-1")
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_KOREAN_80IN1, msx_cart_interface, msx_cart_korean_80in1_device, "msx_cart_korean_80in1", "MSX Cartridge - Korean 80-in-1")
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_KOREAN_90IN1, msx_cart_interface, msx_cart_korean_90in1_device, "msx_cart_korean_90in1", "MSX Cartridge - Korean 90-in-1")
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_KOREAN_126IN1, msx_cart_interface, msx_cart_korean_126in1_device, "msx_cart_korean_126in1", "MSX Cartridge - Korean 126-in-1")
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_KOREAN_HYDLIDE2, msx_cart_interface, msx_cart_korean_hydlide2_device, "msx_cart_korean_hydlide2", "MSX Cartridge - Korean Hydlide 2")
diff --git a/src/devices/bus/msx/cart/korean.h b/src/devices/bus/msx/cart/korean.h
new file mode 100644
index 00000000000..4737e0ea126
--- /dev/null
+++ b/src/devices/bus/msx/cart/korean.h
@@ -0,0 +1,17 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#ifndef MAME_BUS_MSX_CART_KOREAN_H
+#define MAME_BUS_MSX_CART_KOREAN_H
+
+#pragma once
+
+#include "bus/msx/slot/cartridge.h"
+
+
+DECLARE_DEVICE_TYPE(MSX_CART_KOREAN_25IN1, msx_cart_interface)
+DECLARE_DEVICE_TYPE(MSX_CART_KOREAN_80IN1, msx_cart_interface)
+DECLARE_DEVICE_TYPE(MSX_CART_KOREAN_90IN1, msx_cart_interface)
+DECLARE_DEVICE_TYPE(MSX_CART_KOREAN_126IN1, msx_cart_interface)
+DECLARE_DEVICE_TYPE(MSX_CART_KOREAN_HYDLIDE2, msx_cart_interface)
+
+#endif // MAME_BUS_MSX_CART_KOREAN_H
diff --git a/src/devices/bus/msx/cart/loveplus.cpp b/src/devices/bus/msx/cart/loveplus.cpp
new file mode 100644
index 00000000000..fa29e0911dc
--- /dev/null
+++ b/src/devices/bus/msx/cart/loveplus.cpp
@@ -0,0 +1,116 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+/******************************************************************************
+
+Banking for Love Plus Pack 0, Korean 83-in-1 pirate.
+
+******************************************************************************/
+#include "emu.h"
+#include "loveplus.h"
+
+
+namespace {
+
+class msx_cart_loveplus_device : public device_t, public msx_cart_interface
+{
+public:
+ msx_cart_loveplus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, MSX_CART_LOVEPLUS, tag, owner, clock)
+ , msx_cart_interface(mconfig, *this)
+ , m_rombank(*this, "rombank%u", 0U)
+ { }
+
+ virtual std::error_condition initialize_cartridge(std::string &message) override;
+
+protected:
+ // device_t implementation
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+private:
+ template <int Bank> void bank_w(u8 data);
+ void bank_9000_w(u8 data);
+
+ memory_bank_array_creator<4> m_rombank;
+
+ u8 m_bank_mask;
+ bool m_bank_locked[4];
+};
+
+
+void msx_cart_loveplus_device::device_start()
+{
+ save_item(NAME(m_bank_locked));
+}
+
+void msx_cart_loveplus_device::device_reset()
+{
+ m_rombank[0]->set_entry(0);
+ m_rombank[1]->set_entry(1);
+ m_rombank[2]->set_entry(2);
+ m_rombank[3]->set_entry(3);
+}
+
+std::error_condition msx_cart_loveplus_device::initialize_cartridge(std::string &message)
+{
+ if (!cart_rom_region())
+ {
+ message = "msx_cart_loveplus_device: Required region 'rom' was not found.";
+ return image_error::INTERNAL;
+ }
+
+ const u32 size = cart_rom_region()->bytes();
+ const u16 banks = size / 0x2000;
+
+ if (size > 256 * 0x8000 || size < 0x10000 || size != banks * 0x2000 || (~(banks - 1) % banks))
+ {
+ message = "msx_cart_loveplus_device: Region 'rom' has unsupported size.";
+ return image_error::INVALIDLENGTH;
+ }
+
+ m_bank_mask = banks - 1;
+
+ m_rombank[0]->configure_entries(0, banks, cart_rom_region()->base(), 0x2000);
+ m_rombank[1]->configure_entries(0, banks, cart_rom_region()->base(), 0x2000);
+ m_rombank[2]->configure_entries(0, banks, cart_rom_region()->base(), 0x2000);
+ m_rombank[3]->configure_entries(0, banks, cart_rom_region()->base(), 0x2000);
+
+ page(1)->install_read_bank(0x4000, 0x5fff, m_rombank[0]);
+ page(1)->install_read_bank(0x6000, 0x7fff, m_rombank[1]);
+ page(1)->nop_write(0x5000, 0x5000); // Referenced from code but never used
+ page(1)->install_write_handler(0x6000, 0x6000, emu::rw_delegate(*this, FUNC(msx_cart_loveplus_device::bank_w<0>)));
+ page(1)->install_write_handler(0x6800, 0x6800, emu::rw_delegate(*this, FUNC(msx_cart_loveplus_device::bank_w<1>)));
+ page(1)->install_write_handler(0x7000, 0x7000, emu::rw_delegate(*this, FUNC(msx_cart_loveplus_device::bank_w<2>)));
+ page(1)->install_write_handler(0x7800, 0x7800, emu::rw_delegate(*this, FUNC(msx_cart_loveplus_device::bank_w<3>)));
+ page(2)->install_read_bank(0x8000, 0x9fff, m_rombank[2]);
+ page(2)->install_read_bank(0xa000, 0xbfff, m_rombank[3]);
+ page(2)->install_write_handler(0x9000, 0x9000, emu::rw_delegate(*this, FUNC(msx_cart_loveplus_device::bank_9000_w)));
+ page(2)->nop_write(0xb000, 0xb000); // Referenced from code but never used
+
+ return std::error_condition();
+}
+
+template <int Bank>
+void msx_cart_loveplus_device::bank_w(u8 data)
+{
+ // The banking registers can be only written to once otherwise Q-Bert will not
+ // start and drop back to Basic.
+ if (!m_bank_locked[Bank])
+ {
+ m_rombank[Bank]->set_entry(data & m_bank_mask);
+ m_bank_locked[Bank] = true;
+ }
+}
+
+void msx_cart_loveplus_device::bank_9000_w(u8 data)
+{
+ // Before switching to a game the sequence 00, 3f, c2 is written here.
+ // This unlocks and/or configures the write-once banking somehow
+ for (int i = 0; i < 4; i++)
+ m_bank_locked[i] = false;
+}
+
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_LOVEPLUS, msx_cart_interface, msx_cart_loveplus_device, "msx_cart_loveplus", "MSX Cartridge - Love Plus Pack")
diff --git a/src/devices/bus/msx/cart/loveplus.h b/src/devices/bus/msx/cart/loveplus.h
new file mode 100644
index 00000000000..cae9251f12f
--- /dev/null
+++ b/src/devices/bus/msx/cart/loveplus.h
@@ -0,0 +1,13 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#ifndef MAME_BUS_MSX_CART_LOVEPLUS_H
+#define MAME_BUS_MSX_CART_LOVEPLUS_H
+
+#pragma once
+
+#include "bus/msx/slot/cartridge.h"
+
+
+DECLARE_DEVICE_TYPE(MSX_CART_LOVEPLUS, msx_cart_interface)
+
+#endif // MAME_BUS_MSX_CART_LOVEPLUS_H
diff --git a/src/devices/bus/msx/cart/majutsushi.cpp b/src/devices/bus/msx/cart/majutsushi.cpp
new file mode 100644
index 00000000000..988bec33b11
--- /dev/null
+++ b/src/devices/bus/msx/cart/majutsushi.cpp
@@ -0,0 +1,92 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#include "emu.h"
+#include "majutsushi.h"
+
+#include "sound/dac.h"
+
+#include "speaker.h"
+
+
+namespace {
+
+class msx_cart_majutsushi_device : public device_t, public msx_cart_interface
+{
+public:
+ msx_cart_majutsushi_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MSX_CART_MAJUTSUSHI, tag, owner, clock)
+ , msx_cart_interface(mconfig, *this)
+ , m_dac(*this, "dac")
+ , m_rombank(*this, "rombank%u", 0U)
+ { }
+
+ virtual std::error_condition initialize_cartridge(std::string &message) override;
+
+protected:
+ // device_t implementation
+ virtual void device_start() override { }
+
+ virtual void device_add_mconfig(machine_config &config) override;
+
+private:
+ template <int Bank> void bank_w(u8 data);
+
+ required_device<dac_8bit_r2r_device> m_dac;
+ memory_bank_array_creator<3> m_rombank;
+};
+
+void msx_cart_majutsushi_device::device_add_mconfig(machine_config &config)
+{
+ DAC_8BIT_R2R(config, m_dac, 0); // unknown DAC
+ if (parent_slot())
+ m_dac->add_route(ALL_OUTPUTS, soundin(), 0.15);
+}
+
+std::error_condition msx_cart_majutsushi_device::initialize_cartridge(std::string &message)
+{
+ if (!cart_rom_region())
+ {
+ message = "msx_cart_majutsushi_device: Required region 'rom' was not found.";
+ return image_error::INTERNAL;
+ }
+
+ if (cart_rom_region()->bytes() != 0x20000)
+ {
+ message = "msx_cart_majutsushi_device: Region 'rom' has unsupported size.";
+ return image_error::INVALIDLENGTH;
+ }
+
+ for (int i = 0; i < 3; i++)
+ m_rombank[i]->configure_entries(0, 16, cart_rom_region()->base(), 0x2000);
+
+ page(0)->install_rom(0x0000, 0x1fff, cart_rom_region()->base());
+ page(0)->install_read_bank(0x2000, 0x3fff, m_rombank[0]);
+ page(1)->install_rom(0x4000, 0x5fff, cart_rom_region()->base());
+ page(1)->install_write_handler(0x5000, 0x5000, 0, 0x0fff, 0, emu::rw_delegate(m_dac, FUNC(dac_8bit_r2r_device::write)));
+ page(1)->install_read_bank(0x6000, 0x7fff, m_rombank[0]);
+ page(1)->install_write_handler(0x6000, 0x6000, 0, 0x1fff, 0, emu::rw_delegate(*this, FUNC(msx_cart_majutsushi_device::bank_w<0>)));
+ page(1)->install_write_handler(0x6000, 0x6000, 0, 0x1fff, 0, emu::rw_delegate(*this, FUNC(msx_cart_majutsushi_device::bank_w<0>)));
+ page(1)->install_write_handler(0x6000, 0x6000, 0, 0x1fff, 0, emu::rw_delegate(*this, FUNC(msx_cart_majutsushi_device::bank_w<0>)));
+ page(2)->install_read_bank(0x8000, 0x9fff, m_rombank[1]);
+ page(2)->install_write_handler(0x8000, 0x8000, 0, 0x1fff, 0, emu::rw_delegate(*this, FUNC(msx_cart_majutsushi_device::bank_w<1>)));
+ page(2)->install_write_handler(0x8000, 0x8000, 0, 0x1fff, 0, emu::rw_delegate(*this, FUNC(msx_cart_majutsushi_device::bank_w<1>)));
+ page(2)->install_write_handler(0x8000, 0x8000, 0, 0x1fff, 0, emu::rw_delegate(*this, FUNC(msx_cart_majutsushi_device::bank_w<1>)));
+ page(2)->install_read_bank(0xa000, 0xbfff, m_rombank[2]);
+ page(2)->install_write_handler(0xa000, 0xa000, 0, 0x1fff, 0, emu::rw_delegate(*this, FUNC(msx_cart_majutsushi_device::bank_w<2>)));
+ page(2)->install_write_handler(0xa000, 0xa000, 0, 0x1fff, 0, emu::rw_delegate(*this, FUNC(msx_cart_majutsushi_device::bank_w<2>)));
+ page(2)->install_write_handler(0xa000, 0xa000, 0, 0x1fff, 0, emu::rw_delegate(*this, FUNC(msx_cart_majutsushi_device::bank_w<2>)));
+ page(3)->install_read_bank(0xc000, 0xdfff, m_rombank[1]);
+ page(3)->install_read_bank(0xe000, 0xffff, m_rombank[2]);
+
+ return std::error_condition();
+}
+
+template <int Bank>
+void msx_cart_majutsushi_device::bank_w(u8 data)
+{
+ m_rombank[Bank]->set_entry(data & 0x0f);
+}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_MAJUTSUSHI, msx_cart_interface, msx_cart_majutsushi_device, "msx_cart_majutsushi", "MSX Cartridge - Majutsushi")
diff --git a/src/devices/bus/msx/cart/majutsushi.h b/src/devices/bus/msx/cart/majutsushi.h
new file mode 100644
index 00000000000..7686c05fff1
--- /dev/null
+++ b/src/devices/bus/msx/cart/majutsushi.h
@@ -0,0 +1,13 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#ifndef MAME_BUS_MSX_CART_MAJUTSUSHI_H
+#define MAME_BUS_MSX_CART_MAJUTSUSHI_H
+
+#pragma once
+
+#include "bus/msx/slot/cartridge.h"
+
+
+DECLARE_DEVICE_TYPE(MSX_CART_MAJUTSUSHI, msx_cart_interface)
+
+#endif // MAME_BUS_MSX_CART_MAJUTSUSHI_H
diff --git a/src/devices/bus/msx/cart/matra.cpp b/src/devices/bus/msx/cart/matra.cpp
new file mode 100644
index 00000000000..d43ba9c8369
--- /dev/null
+++ b/src/devices/bus/msx/cart/matra.cpp
@@ -0,0 +1,98 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#include "emu.h"
+#include "matra.h"
+
+namespace {
+
+class msx_cart_matra_comp_device : public device_t, public msx_cart_interface
+{
+public:
+ msx_cart_matra_comp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, MSX_CART_MATRA_COMP, tag, owner, clock)
+ , msx_cart_interface(mconfig, *this)
+ , m_rombank(*this, "rombank%u", 0U)
+ , m_bank_mask(0)
+ , m_banking_enabled(true)
+ { }
+
+ virtual std::error_condition initialize_cartridge(std::string &message) override;
+
+protected:
+ // device_t implementation
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+private:
+ template <int Bank> void bank_w(u8 data);
+ void disable_banking_w(u8 data);
+
+ memory_bank_array_creator<4> m_rombank;
+
+ u8 m_bank_mask;
+ bool m_banking_enabled;
+};
+
+void msx_cart_matra_comp_device::device_start()
+{
+ save_item(NAME(m_banking_enabled));
+}
+
+void msx_cart_matra_comp_device::device_reset()
+{
+ for (int i = 0; i < 4; i++)
+ m_rombank[i]->set_entry(i);
+ m_banking_enabled = true;
+}
+
+std::error_condition msx_cart_matra_comp_device::initialize_cartridge(std::string &message)
+{
+ if (!cart_rom_region())
+ {
+ message = "msx_cart_matra_comp_device: Required region 'rom' was not found.";
+ return image_error::INTERNAL;
+ }
+
+ const u32 size = cart_rom_region()->bytes();
+ const u16 banks = size / 0x2000;
+
+ if (size > 256 * 0x2000 || size < 0x8000 || size != banks * 0x2000 || (~(banks - 1) % banks))
+ {
+ message = "msx_cart_matra_comp_device: Region 'rom' has unsupported size.";
+ return image_error::INVALIDLENGTH;
+ }
+
+ m_bank_mask = banks - 1;
+
+ for (int i = 0; i < 4; i++)
+ m_rombank[i]->configure_entries(0, banks, cart_rom_region()->base(), 0x2000);
+
+ page(1)->install_read_bank(0x4000, 0x5fff, m_rombank[0]);
+ page(1)->install_write_handler(0x5000, 0x5000, emu::rw_delegate(*this, FUNC(msx_cart_matra_comp_device::bank_w<0>)));
+ page(1)->install_read_bank(0x6000, 0x7fff, m_rombank[1]);
+ page(1)->install_write_handler(0x6000, 0x6000, emu::rw_delegate(*this, FUNC(msx_cart_matra_comp_device::bank_w<1>)));
+ page(2)->install_read_bank(0x8000, 0x9fff, m_rombank[2]);
+ page(2)->install_write_handler(0x8000, 0x8000, emu::rw_delegate(*this, FUNC(msx_cart_matra_comp_device::bank_w<2>)));
+ page(2)->install_read_bank(0xa000, 0xbfff, m_rombank[3]);
+ page(2)->install_write_handler(0xa000, 0xa000, emu::rw_delegate(*this, FUNC(msx_cart_matra_comp_device::bank_w<3>)));
+ page(2)->install_write_handler(0xba00, 0xba00, emu::rw_delegate(*this, FUNC(msx_cart_matra_comp_device::disable_banking_w)));
+
+ return std::error_condition();
+}
+
+template <int Bank>
+void msx_cart_matra_comp_device::bank_w(u8 data)
+{
+ if (m_banking_enabled)
+ m_rombank[Bank]->set_entry(data & m_bank_mask);
+}
+
+void msx_cart_matra_comp_device::disable_banking_w(u8 data)
+{
+ // Assuming that any write here disables banking
+ m_banking_enabled = false;
+}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_MATRA_COMP, msx_cart_interface, msx_cart_matra_comp_device, "msx_cart_matra_comp", "MSX Cartridge - Matra Compilation")
diff --git a/src/devices/bus/msx/cart/matra.h b/src/devices/bus/msx/cart/matra.h
new file mode 100644
index 00000000000..1816243f01a
--- /dev/null
+++ b/src/devices/bus/msx/cart/matra.h
@@ -0,0 +1,13 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#ifndef MAME_BUS_MSX_CART_MATRA_H
+#define MAME_BUS_MSX_CART_MATRA_H
+
+#pragma once
+
+#include "bus/msx/slot/cartridge.h"
+
+
+DECLARE_DEVICE_TYPE(MSX_CART_MATRA_COMP, msx_cart_interface)
+
+#endif // MAME_BUS_MSX_CART_MATRA_H
diff --git a/src/devices/bus/msx_cart/moonsound.cpp b/src/devices/bus/msx/cart/moonsound.cpp
index 07ae53f6fca..8de78bf5d40 100644
--- a/src/devices/bus/msx_cart/moonsound.cpp
+++ b/src/devices/bus/msx/cart/moonsound.cpp
@@ -11,23 +11,42 @@ TODO:
#include "emu.h"
#include "moonsound.h"
+#include "sound/ymopl.h"
+
#include "speaker.h"
#define VERBOSE 0
#include "logmacro.h"
+namespace {
-DEFINE_DEVICE_TYPE(MSX_CART_MOONSOUND, msx_cart_moonsound_device, "msx_moonsound", "MSX Cartridge - MoonSound")
-
-
-msx_cart_moonsound_device::msx_cart_moonsound_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, MSX_CART_MOONSOUND, tag, owner, clock)
- , msx_cart_interface(mconfig, *this)
- , m_ymf278b(*this, "ymf278b")
+class msx_cart_moonsound_device : public device_t, public msx_cart_interface
{
-}
-
+public:
+ msx_cart_moonsound_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MSX_CART_MOONSOUND, tag, owner, clock)
+ , msx_cart_interface(mconfig, *this)
+ , m_ymf278b(*this, "ymf278b")
+ { }
+
+protected:
+ // device_t implementation
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+private:
+ void irq_w(int state);
+ void write_ymf278b_pcm(offs_t offset, u8 data);
+ u8 read_ymf278b_pcm(offs_t offset);
+ u8 read_c0();
+ void ymf278b_map(address_map &map);
+
+ required_device<ymf278b_device> m_ymf278b;
+};
void msx_cart_moonsound_device::ymf278b_map(address_map &map)
{
@@ -35,7 +54,6 @@ void msx_cart_moonsound_device::ymf278b_map(address_map &map)
map(0x200000, 0x3fffff).ram(); // 2MB sram for testing
}
-
void msx_cart_moonsound_device::device_add_mconfig(machine_config &config)
{
// The moonsound cartridge has a separate stereo output.
@@ -53,71 +71,53 @@ void msx_cart_moonsound_device::device_add_mconfig(machine_config &config)
m_ymf278b->add_route(5, "rspeaker", 0.50);
}
-
-ROM_START( msx_cart_moonsound )
+ROM_START(msx_cart_moonsound)
ROM_REGION(0x400000, "ymf278b", 0)
ROM_LOAD("yrw801.rom", 0x0, 0x200000, CRC(2a9d8d43) SHA1(32760893ce06dbe3930627755ba065cc3d8ec6ca))
ROM_END
-
const tiny_rom_entry *msx_cart_moonsound_device::device_rom_region() const
{
- return ROM_NAME( msx_cart_moonsound );
+ return ROM_NAME(msx_cart_moonsound);
}
-
void msx_cart_moonsound_device::device_start()
{
// Install IO read/write handlers
- io_space().install_readwrite_handler(0x7e, 0x7f, read8sm_delegate(*this, FUNC(msx_cart_moonsound_device::read_ymf278b_pcm)), write8sm_delegate(*this, FUNC(msx_cart_moonsound_device::write_ymf278b_pcm)));
- io_space().install_readwrite_handler(0xc4, 0xc7, read8sm_delegate(*this, FUNC(msx_cart_moonsound_device::read_ymf278b_fm)), write8sm_delegate(*this, FUNC(msx_cart_moonsound_device::write_ymf278b_fm)));
- io_space().install_read_handler(0xc0, 0xc0, read8smo_delegate(*this, FUNC(msx_cart_moonsound_device::read_c0)));
+ io_space().install_readwrite_handler(0x7e, 0x7f, emu::rw_delegate(*this, FUNC(msx_cart_moonsound_device::read_ymf278b_pcm)), emu::rw_delegate(*this, FUNC(msx_cart_moonsound_device::write_ymf278b_pcm)));
+ io_space().install_readwrite_handler(0xc4, 0xc7, emu::rw_delegate(m_ymf278b, FUNC(ymf278b_device::read)), emu::rw_delegate(m_ymf278b, FUNC(ymf278b_device::write)));
+ io_space().install_read_handler(0xc0, 0xc0, emu::rw_delegate(*this, FUNC(msx_cart_moonsound_device::read_c0)));
}
-
void msx_cart_moonsound_device::device_reset()
{
}
-
-WRITE_LINE_MEMBER(msx_cart_moonsound_device::irq_w)
+void msx_cart_moonsound_device::irq_w(int state)
{
LOG("moonsound: irq state %d\n", state);
irq_out(state);
}
-
-void msx_cart_moonsound_device::write_ymf278b_fm(offs_t offset, uint8_t data)
-{
- LOG("moonsound: write 0x%02x, data 0x%02x\n", 0xc4 + offset, data);
- m_ymf278b->write(offset, data);
-}
-
-
-uint8_t msx_cart_moonsound_device::read_ymf278b_fm(offs_t offset)
-{
- LOG("moonsound: read 0x%02x\n", 0xc4 + offset);
- return m_ymf278b->read(offset);
-}
-
-
-void msx_cart_moonsound_device::write_ymf278b_pcm(offs_t offset, uint8_t data)
+void msx_cart_moonsound_device::write_ymf278b_pcm(offs_t offset, u8 data)
{
LOG("moonsound: write 0x%02x, data 0x%02x\n", 0x7e + offset, data);
m_ymf278b->write(4 + offset, data);
}
-
-uint8_t msx_cart_moonsound_device::read_ymf278b_pcm(offs_t offset)
+u8 msx_cart_moonsound_device::read_ymf278b_pcm(offs_t offset)
{
LOG("moonsound: read 0x%02x\n", 0x7e + offset);
return m_ymf278b->read(4 + offset);
}
-
// For detecting presence of moonsound cartridge
-uint8_t msx_cart_moonsound_device::read_c0()
+u8 msx_cart_moonsound_device::read_c0()
{
LOG("moonsound: read 0xc0\n");
return 0x00;
}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_MOONSOUND, msx_cart_interface, msx_cart_moonsound_device, "msx_moonsound", "MSX Cartridge - MoonSound")
diff --git a/src/devices/bus/msx/cart/moonsound.h b/src/devices/bus/msx/cart/moonsound.h
new file mode 100644
index 00000000000..3f3ce88f5ac
--- /dev/null
+++ b/src/devices/bus/msx/cart/moonsound.h
@@ -0,0 +1,13 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#ifndef MAME_BUS_MSX_CART_MOONSOUND_H
+#define MAME_BUS_MSX_CART_MOONSOUND_H
+
+#pragma once
+
+#include "bus/msx/slot/cartridge.h"
+
+
+DECLARE_DEVICE_TYPE(MSX_CART_MOONSOUND, msx_cart_interface)
+
+#endif // MAME_BUS_MSX_CART_MOONSOUND_H
diff --git a/src/devices/bus/msx/cart/msx_audio.cpp b/src/devices/bus/msx/cart/msx_audio.cpp
new file mode 100644
index 00000000000..1baae1488a0
--- /dev/null
+++ b/src/devices/bus/msx/cart/msx_audio.cpp
@@ -0,0 +1,437 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+/**********************************************************************************
+
+Emulation of the different MSX-AUDIO devices:
+
+- Panasonic FS-CA1
+ - Y8950
+ - 4KB ram
+ - Connector for Toshiba HX-MU901 keyboard
+
+- Toshiba HX-MU900
+ - Y8950
+ - No midi ports
+ - No ram
+ - Connector for Toshiba HX-MU901 keyboard
+
+- Philips NMS-1205
+ - Y8950
+ - Midi ports
+ - 32KB sample ram
+ - Connector for Philips NMS-1160 keyboard
+
+
+The keyboards:
+- Toshiba HX-MU901
+ - 49 keys: 4 full octaves + high C
+ - ENTER key
+ - SELECT key
+ - multi sensor (?)
+
+- Philips NMS-1160
+ - 61 keys: 5 full octaves + high C
+ - Different wiring, so incompatible with the other keyboards
+
+- Panasonic YK-20
+ - 49 keys: 4 full octaves + high C
+
+
+TODO:
+- Test MIDI in/out/through
+- Sample RAM, doesn't seem to get written to
+- Test NMS-1160 keyboard
+- HX-MU901: ENTER/SELECT keys and multi sensors
+- NMS1160: Test the keyboard
+- NMS1205: Add DAC
+- NMS1205/FSCA1: Add muting of dac and y8950 based on io config writes.
+
+
+For testing the sample ram (playback of a cuckoo sound, the volume of the sound is quite low):
+- Disable firmware on the fs-ca1
+- Execute the following basic commands:
+ - CALL AUDIO
+ - CALL COPY PCM(#1,0)
+ - CALL PLAY PCM(0)
+
+See also https://www.msxcomputermagazine.nl/mccm/millennium/milc/gc/topic_26.htm (dutch)
+and/or http://ngs.no.coocan.jp/doc/wiki.cgi/datapack?page=4.2+MSX-AUDIO+%B3%C8%C4%A5BASIC (japanese)
+
+
+**********************************************************************************/
+
+#include "emu.h"
+#include "msx_audio.h"
+
+#include "msx_audio_kb.h"
+
+#include "bus/midi/midi.h"
+#include "machine/6850acia.h"
+#include "sound/ymopl.h"
+
+#include "speaker.h"
+
+
+namespace {
+
+class msx_cart_msx_audio_hxmu900_device : public device_t, public msx_cart_interface
+{
+public:
+ msx_cart_msx_audio_hxmu900_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MSX_CART_MSX_AUDIO_HXMU900, tag, owner, clock)
+ , msx_cart_interface(mconfig, *this)
+ , m_y8950(*this, "y8950")
+ { }
+
+ virtual std::error_condition initialize_cartridge(std::string &message) override;
+
+protected:
+ // device_t implementation
+ virtual void device_start() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+private:
+ required_device<y8950_device> m_y8950;
+};
+
+void msx_cart_msx_audio_hxmu900_device::device_add_mconfig(machine_config &config)
+{
+ Y8950(config, m_y8950, DERIVED_CLOCK(1, 1)); // Not verified
+ if (parent_slot())
+ m_y8950->add_route(ALL_OUTPUTS, soundin(), 0.8);
+ m_y8950->keyboard_write().set("kbdc", FUNC(msx_audio_kbdc_port_device::write));
+ m_y8950->keyboard_read().set("kbdc", FUNC(msx_audio_kbdc_port_device::read));
+
+ MSX_AUDIO_KBDC_PORT(config, "kbdc", msx_audio_keyboards, nullptr);
+}
+
+void msx_cart_msx_audio_hxmu900_device::device_start()
+{
+ // Install IO read/write handlers
+ io_space().install_write_handler(0xc0, 0xc1, emu::rw_delegate(*m_y8950, FUNC(y8950_device::write)));
+ io_space().install_read_handler(0xc0, 0xc1, emu::rw_delegate(*m_y8950, FUNC(y8950_device::read)));
+}
+
+std::error_condition msx_cart_msx_audio_hxmu900_device::initialize_cartridge(std::string &message)
+{
+ if (!cart_rom_region())
+ {
+ message = "msx_cart_msx_audio_hxmu900_device: Required region 'rom' was not found.";
+ return image_error::INTERNAL;
+ }
+
+ if (cart_rom_region()->bytes() < 0x8000)
+ {
+ message = "msx_cart_msx_audio_hxmu900_device: Region 'rom' has unsupported size.";
+ return image_error::INVALIDLENGTH;
+ }
+
+ page(1)->install_rom(0x4000, 0x7fff, cart_rom_region()->base());
+ page(2)->install_rom(0x8000, 0xbfff, cart_rom_region()->base() + 0x4000);
+
+ return std::error_condition();
+}
+
+ROM_START(msx_hxmu)
+ ROM_REGION(0x8000, "y8950", ROMREGION_ERASE00)
+ROM_END
+
+const tiny_rom_entry *msx_cart_msx_audio_hxmu900_device::device_rom_region() const
+{
+ return ROM_NAME(msx_hxmu);
+}
+
+
+
+
+
+class msx_cart_msx_audio_nms1205_device : public device_t, public msx_cart_interface
+{
+public:
+ msx_cart_msx_audio_nms1205_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MSX_CART_MSX_AUDIO_NMS1205, tag, owner, clock)
+ , msx_cart_interface(mconfig, *this)
+ , m_y8950(*this, "y8950")
+ , m_acia6850(*this, "acia6850")
+ , m_mdout(*this, "mdout")
+ , m_mdthru(*this, "mdthru")
+ { }
+
+ virtual std::error_condition initialize_cartridge(std::string &message) override;
+
+protected:
+ // device_t implementation
+ virtual void device_start() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+private:
+ void midi_in(int state);
+ void irq_write(int state);
+
+ required_device<y8950_device> m_y8950;
+ required_device<acia6850_device> m_acia6850;
+ required_device<midi_port_device> m_mdout;
+ required_device<midi_port_device> m_mdthru;
+};
+
+void msx_cart_msx_audio_nms1205_device::device_add_mconfig(machine_config &config)
+{
+ // At the same time the sound is also output on two outputs on the nms1205 cartridge itself
+ Y8950(config, m_y8950, DERIVED_CLOCK(1, 1));
+ if (parent_slot())
+ m_y8950->add_route(ALL_OUTPUTS, soundin(), 0.8);
+ m_y8950->keyboard_write().set("kbdc", FUNC(msx_audio_kbdc_port_device::write));
+ m_y8950->keyboard_read().set("kbdc", FUNC(msx_audio_kbdc_port_device::read));
+ m_y8950->irq_handler().set(FUNC(msx_cart_msx_audio_nms1205_device::irq_write));
+
+ MSX_AUDIO_KBDC_PORT(config, "kbdc", msx_audio_keyboards, nullptr);
+
+ // There is a 2 MHz crystal on the PCB, the 6850 TX and RX clocks are derived from it
+ ACIA6850(config, m_acia6850, 0);
+ m_acia6850->txd_handler().set("mdout", FUNC(midi_port_device::write_txd));
+
+ MIDI_PORT(config, "mdin", midiin_slot, "midiin").rxd_handler().set(FUNC(msx_cart_msx_audio_nms1205_device::midi_in));
+ MIDI_PORT(config, m_mdthru, midiout_slot, "midiout");
+ MIDI_PORT(config, m_mdout, midiout_slot, "midiout");
+}
+
+ROM_START(msx_nms1205)
+ ROM_REGION(0x8000, "y8950", ROMREGION_ERASE00)
+ROM_END
+
+const tiny_rom_entry *msx_cart_msx_audio_nms1205_device::device_rom_region() const
+{
+ return ROM_NAME(msx_nms1205);
+}
+
+void msx_cart_msx_audio_nms1205_device::irq_write(int state)
+{
+ // Trigger IRQ on the maincpu
+ // The 8950 seems to trigger an irq on reset, this causes an infinite loop of continuously triggering
+ // the MSX's interrupt handler. The 8950 irq will never be cleared the nms1205's irq handler hook hasn't
+ // been installed yet.
+// m_out_irq_cb(state);
+}
+
+void msx_cart_msx_audio_nms1205_device::midi_in(int state)
+{
+ // MIDI in signals is sent to both the 6850 and the MIDI thru output port
+ m_acia6850->write_rxd(state);
+ m_mdthru->write_txd(state);
+}
+
+void msx_cart_msx_audio_nms1205_device::device_start()
+{
+ // Install IO read/write handlers
+ io_space().install_write_handler(0xc0, 0xc1, emu::rw_delegate(*m_y8950, FUNC(y8950_device::write)));
+ io_space().install_read_handler(0xc0, 0xc1, emu::rw_delegate(*m_y8950, FUNC(y8950_device::read)));
+ io_space().install_write_handler(0x00, 0x01, emu::rw_delegate(*m_acia6850, FUNC(acia6850_device::write)));
+ io_space().install_read_handler(0x04, 0x05, emu::rw_delegate(*m_acia6850, FUNC(acia6850_device::read)));
+}
+
+std::error_condition msx_cart_msx_audio_nms1205_device::initialize_cartridge(std::string &message)
+{
+ if (!cart_rom_region())
+ {
+ message = "msx_cart_msx_audio_nms1205_device: Required region 'rom' was not found.";
+ return image_error::INTERNAL;
+ }
+
+ if (cart_rom_region()->bytes() < 0x8000)
+ {
+ message = "msx_cart_msx_audio_nms1205_device: Region 'rom' has unsupported size.";
+ return image_error::INVALIDLENGTH;
+ }
+
+ page(1)->install_rom(0x4000, 0x7fff, cart_rom_region()->base());
+ page(2)->install_rom(0x8000, 0xbfff, cart_rom_region()->base() + 0x4000);
+
+ return std::error_condition();
+}
+
+
+
+
+
+
+
+class msx_cart_msx_audio_fsca1_device : public device_t, public msx_cart_interface
+{
+public:
+ msx_cart_msx_audio_fsca1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MSX_CART_MSX_AUDIO_FSCA1, tag, owner, clock)
+ , msx_cart_interface(mconfig, *this)
+ , m_y8950(*this, "y8950")
+ , m_io_config(*this, "CONFIG")
+ , m_region_y8950(*this, "y8950")
+ , m_rombank(*this, "rombank%u", 0U)
+ , m_view{ {*this, "view0"}, {*this, "view1"} }
+ , m_7fff(0)
+ { }
+
+ virtual std::error_condition initialize_cartridge(std::string &message) override;
+
+protected:
+ // device_t implementation
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual ioport_constructor device_input_ports() const override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+private:
+ void write_y8950(offs_t offset, u8 data);
+ u8 read_y8950(offs_t offset);
+ void y8950_io_w(u8 data);
+ u8 y8950_io_r();
+ void bank_w(u8 data);
+ void write_7fff(u8 data);
+
+ required_device<y8950_device> m_y8950;
+ required_ioport m_io_config;
+ required_memory_region m_region_y8950;
+ memory_bank_array_creator<2> m_rombank;
+ memory_view m_view[2];
+ u8 m_7fff;
+};
+
+void msx_cart_msx_audio_fsca1_device::device_add_mconfig(machine_config &config)
+{
+ Y8950(config, m_y8950, DERIVED_CLOCK(1, 1));
+ if (parent_slot())
+ m_y8950->add_route(ALL_OUTPUTS, soundin(), 0.8);
+ m_y8950->keyboard_write().set("kbdc", FUNC(msx_audio_kbdc_port_device::write));
+ m_y8950->keyboard_read().set("kbdc", FUNC(msx_audio_kbdc_port_device::read));
+ m_y8950->io_read().set(FUNC(msx_cart_msx_audio_fsca1_device::y8950_io_r));
+ m_y8950->io_write().set(FUNC(msx_cart_msx_audio_fsca1_device::y8950_io_w));
+
+ MSX_AUDIO_KBDC_PORT(config, "kbdc", msx_audio_keyboards, nullptr);
+}
+
+static INPUT_PORTS_START(msx_audio_fsca1)
+ PORT_START("CONFIG")
+ PORT_CONFNAME( 0x04, 0x04, "FS-CA1 Firmware switch")
+ PORT_CONFSETTING( 0x04, "On" )
+ PORT_CONFSETTING( 0x00, "Off" )
+ PORT_BIT(0xFB, IP_ACTIVE_HIGH, IPT_UNKNOWN)
+INPUT_PORTS_END
+
+ioport_constructor msx_cart_msx_audio_fsca1_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(msx_audio_fsca1);
+}
+
+ROM_START(msx_fsca1)
+ ROM_REGION(0x8000, "y8950", ROMREGION_ERASE00)
+ROM_END
+
+const tiny_rom_entry *msx_cart_msx_audio_fsca1_device::device_rom_region() const
+{
+ return ROM_NAME(msx_fsca1);
+}
+
+void msx_cart_msx_audio_fsca1_device::device_start()
+{
+ // Install IO read/write handlers
+ io_space().install_write_handler(0xc0, 0xc3, emu::rw_delegate(*this, FUNC(msx_cart_msx_audio_fsca1_device::write_y8950)));
+ io_space().install_read_handler(0xc0, 0xc3, emu::rw_delegate(*this, FUNC(msx_cart_msx_audio_fsca1_device::read_y8950)));
+ save_item(NAME(m_7fff));
+}
+
+void msx_cart_msx_audio_fsca1_device::device_reset()
+{
+ for (int i = 0; i < 2; i++)
+ {
+ m_view[i].select(0);
+ m_rombank[i]->set_entry(0);
+ }
+}
+
+std::error_condition msx_cart_msx_audio_fsca1_device::initialize_cartridge(std::string &message)
+{
+ if (!cart_rom_region())
+ {
+ message = "msx_cart_msx_audio_fsca1_device: Required region 'rom' was not found.";
+ return image_error::INTERNAL;
+ }
+
+ if (cart_rom_region()->bytes() < 0x20000)
+ {
+ message = "msx_cart_msx_audio_fsca1_device: Region 'rom' has unsupported size";
+ return image_error::INVALIDLENGTH;
+ }
+
+ m_rombank[0]->configure_entries(0, 4, cart_rom_region()->base(), 0x8000);
+ m_rombank[1]->configure_entries(0, 4, cart_rom_region()->base() + 0x4000, 0x8000);
+
+ page(0)->install_view(0x0000, 0x3fff, m_view[0]);
+ m_view[0][0].install_read_bank(0x0000, 0x3fff, m_rombank[0]);
+ m_view[0][0].install_ram(0x3000, 0x3fff, cart_sram_region()->base());
+ m_view[0][1].install_read_bank(0x0000, 0x3fff, m_rombank[0]);
+
+ page(1)->install_view(0x4000, 0x7fff, m_view[1]);
+ m_view[1][0].install_read_bank(0x4000, 0x7ffd, m_rombank[1]);
+ m_view[1][0].install_ram(0x7000, 0x7ffd, cart_sram_region()->base());
+ m_view[1][1].install_read_bank(0x4000, 0x7ffd, m_rombank[1]);
+ page(1)->install_write_handler(0x7ffe, 0x7ffe, emu::rw_delegate(*this, FUNC(msx_cart_msx_audio_fsca1_device::bank_w)));
+ page(1)->install_write_handler(0x7fff, 0x7fff, emu::rw_delegate(*this, FUNC(msx_cart_msx_audio_fsca1_device::write_7fff)));
+
+ page(2)->install_read_bank(0x8000, 0xbfff, m_rombank[0]);
+ page(3)->install_read_bank(0xc000, 0xffff, m_rombank[1]);
+
+ return std::error_condition();
+}
+
+void msx_cart_msx_audio_fsca1_device::bank_w(u8 data)
+{
+ for (int i = 0; i < 2; i++)
+ {
+ m_rombank[i]->set_entry(data & 0x03);
+ m_view[i].select((data != 0) ? 1 : 0);
+ }
+}
+
+void msx_cart_msx_audio_fsca1_device::write_7fff(u8 data)
+{
+ m_7fff = data;
+}
+
+void msx_cart_msx_audio_fsca1_device::write_y8950(offs_t offset, u8 data)
+{
+ if (BIT(offset, 1))
+ {
+ if (BIT(m_7fff, 1))
+ m_y8950->write(offset, data);
+ }
+ else
+ {
+ if (BIT(m_7fff, 0))
+ m_y8950->write(offset, data);
+ }
+}
+
+u8 msx_cart_msx_audio_fsca1_device::read_y8950(offs_t offset)
+{
+ if (BIT(offset, 1))
+ return BIT(m_7fff, 1) ? m_y8950->read(offset) : 0xff;
+ else
+ return BIT(m_7fff, 0) ? m_y8950->read(offset) : 0xff;
+}
+
+void msx_cart_msx_audio_fsca1_device::y8950_io_w(u8 data)
+{
+ logerror("msx_fsca1::y8950_io_w: %02x\n", data);
+}
+
+u8 msx_cart_msx_audio_fsca1_device::y8950_io_r()
+{
+ return m_io_config->read();
+}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_MSX_AUDIO_HXMU900, msx_cart_interface, msx_cart_msx_audio_hxmu900_device, "msx_audio_hxmu900", "MSX Cartridge - MSX-AUDIO HX-MU900")
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_MSX_AUDIO_NMS1205, msx_cart_interface, msx_cart_msx_audio_nms1205_device, "msx_audio_nms1205", "MSX Cartridge - MSX-AUDIO NMS-1205")
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_MSX_AUDIO_FSCA1, msx_cart_interface, msx_cart_msx_audio_fsca1_device, "msx_audio_fsca1", "MSX Cartridge - MSX-AUDIO FS-CA1")
diff --git a/src/devices/bus/msx/cart/msx_audio.h b/src/devices/bus/msx/cart/msx_audio.h
new file mode 100644
index 00000000000..cf5fcf74fe3
--- /dev/null
+++ b/src/devices/bus/msx/cart/msx_audio.h
@@ -0,0 +1,15 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#ifndef MAME_BUS_MSX_CART_MSX_AUDIO_H
+#define MAME_BUS_MSX_CART_MSX_AUDIO_H
+
+#pragma once
+
+#include "bus/msx/slot/cartridge.h"
+
+
+DECLARE_DEVICE_TYPE(MSX_CART_MSX_AUDIO_HXMU900, msx_cart_interface)
+DECLARE_DEVICE_TYPE(MSX_CART_MSX_AUDIO_NMS1205, msx_cart_interface)
+DECLARE_DEVICE_TYPE(MSX_CART_MSX_AUDIO_FSCA1, msx_cart_interface)
+
+#endif // MAME_BUS_MSX_CART_MSX_AUDIO_H
diff --git a/src/devices/bus/msx_cart/msx_audio_kb.cpp b/src/devices/bus/msx/cart/msx_audio_kb.cpp
index aba915ed718..94b712a9429 100644
--- a/src/devices/bus/msx_cart/msx_audio_kb.cpp
+++ b/src/devices/bus/msx/cart/msx_audio_kb.cpp
@@ -13,7 +13,7 @@ msx_audio_kb_port_interface::msx_audio_kb_port_interface(machine_config const &m
}
-msx_audio_kbdc_port_device::msx_audio_kbdc_port_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+msx_audio_kbdc_port_device::msx_audio_kbdc_port_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: device_t(mconfig, MSX_AUDIO_KBDC_PORT, tag, owner, clock)
, device_single_card_slot_interface<msx_audio_kb_port_interface>(mconfig, *this)
, m_keyboard(nullptr)
@@ -27,14 +27,14 @@ void msx_audio_kbdc_port_device::device_start()
}
-void msx_audio_kbdc_port_device::write(uint8_t data)
+void msx_audio_kbdc_port_device::write(u8 data)
{
if (m_keyboard)
m_keyboard->write(data);
}
-uint8_t msx_audio_kbdc_port_device::read()
+u8 msx_audio_kbdc_port_device::read()
{
if (m_keyboard)
return m_keyboard->read();
@@ -50,7 +50,7 @@ DECLARE_DEVICE_TYPE(MSX_AUDIO_KB_NMS1160, msx_nms1160_device)
class msx_hxmu901_device : public device_t, public msx_audio_kb_port_interface
{
public:
- msx_hxmu901_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ msx_hxmu901_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: device_t(mconfig, MSX_AUDIO_KB_HXMU901, tag, owner, clock)
, msx_audio_kb_port_interface(mconfig, *this)
, m_row(0)
@@ -60,9 +60,9 @@ public:
virtual ioport_constructor device_input_ports() const override;
- virtual uint8_t read() override
+ virtual u8 read() override
{
- uint8_t result = 0xff;
+ u8 result = 0xff;
for (int i = 0; i < 8; i++)
{
@@ -74,7 +74,7 @@ public:
return result;
}
- virtual void write(uint8_t data) override
+ virtual void write(u8 data) override
{
m_row = data;
}
@@ -88,7 +88,7 @@ private:
};
-static INPUT_PORTS_START( hxmu901)
+static INPUT_PORTS_START(hxmu901)
PORT_START("KEY.0")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C#1")
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("D1")
@@ -173,14 +173,14 @@ INPUT_PORTS_END
ioport_constructor msx_hxmu901_device::device_input_ports() const
{
- return INPUT_PORTS_NAME( hxmu901 );
+ return INPUT_PORTS_NAME(hxmu901);
}
class msx_nms1160_device : public device_t, public msx_audio_kb_port_interface
{
public:
- msx_nms1160_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ msx_nms1160_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: device_t(mconfig, MSX_AUDIO_KB_NMS1160, tag, owner, clock)
, msx_audio_kb_port_interface(mconfig, *this)
, m_row(0)
@@ -190,9 +190,9 @@ public:
virtual ioport_constructor device_input_ports() const override;
- virtual uint8_t read() override
+ virtual u8 read() override
{
- uint8_t result = 0xff;
+ u8 result = 0xff;
for (int i = 0; i < 8; i++)
{
@@ -204,7 +204,7 @@ public:
return result;
}
- virtual void write(uint8_t data) override
+ virtual void write(u8 data) override
{
logerror("msx_nms1160::write %02x\n", data);
m_row = data;
@@ -219,7 +219,7 @@ private:
};
-static INPUT_PORTS_START( nms1160 )
+static INPUT_PORTS_START(nms1160)
PORT_START("KEY.0")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C1")
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C#1")
@@ -302,7 +302,7 @@ INPUT_PORTS_END
ioport_constructor msx_nms1160_device::device_input_ports() const
{
- return INPUT_PORTS_NAME( nms1160 );
+ return INPUT_PORTS_NAME(nms1160);
}
diff --git a/src/devices/bus/msx_cart/msx_audio_kb.h b/src/devices/bus/msx/cart/msx_audio_kb.h
index ecab5732c98..13cf19fb70a 100644
--- a/src/devices/bus/msx_cart/msx_audio_kb.h
+++ b/src/devices/bus/msx/cart/msx_audio_kb.h
@@ -25,21 +25,21 @@ public:
// construction/destruction
template <typename T>
msx_audio_kbdc_port_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts, char const *dflt)
- : msx_audio_kbdc_port_device(mconfig, tag, owner, (uint32_t)0)
+ : msx_audio_kbdc_port_device(mconfig, tag, owner, u32(0))
{
option_reset();
opts(*this);
set_default_option(dflt);
set_fixed(false);
}
- msx_audio_kbdc_port_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ msx_audio_kbdc_port_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
// Physical connection simply consists of 8 input and 8 output lines split across 2 connectors
- void write(uint8_t data);
- uint8_t read();
+ void write(u8 data);
+ u8 read();
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
msx_audio_kb_port_interface *m_keyboard;
diff --git a/src/devices/bus/msx/cart/msxdos2.cpp b/src/devices/bus/msx/cart/msxdos2.cpp
new file mode 100644
index 00000000000..d502b422352
--- /dev/null
+++ b/src/devices/bus/msx/cart/msxdos2.cpp
@@ -0,0 +1,226 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#include "emu.h"
+#include "msxdos2.h"
+
+#include "bus/generic/slot.h"
+
+
+/*
+Emulation of MSX-DOS2 cartridges.
+
+Japanese MSX-DOS2 uses an expanded slot model:
+- Subslot 1 - Memory mapper with no, 128KB, or 256KB RAM
+- Subslot 2 - Kanji Basic ROM
+- Subslot 3 - MSX-DOS2 banked ROM
+
+European MSX-DOS2 releases only contain MSX-DOS2 banked ROM.
+
+The rom banking address is either $6000 or $7ffe depending on the
+version of the hardware.
+
+*/
+
+namespace {
+
+class msx_cart_msxdos2_base_device : public device_t, public msx_cart_interface
+{
+protected:
+ msx_cart_msxdos2_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, type, tag, owner, clock)
+ , msx_cart_interface(mconfig, *this)
+ , m_rombank(*this, "rombank")
+ , m_bank_address(0)
+ { }
+
+ virtual void device_start() override { }
+ virtual void device_reset() override;
+ virtual std::error_condition initialize_cartridge(std::string &message) override;
+
+ void bank_w(u8 data);
+
+ static inline constexpr unsigned PAGE_SIZE = 0x4000;
+
+ memory_bank_creator m_rombank;
+ u16 m_bank_address;
+};
+
+void msx_cart_msxdos2_base_device::device_reset()
+{
+ m_rombank->set_entry(0);
+}
+
+std::error_condition msx_cart_msxdos2_base_device::initialize_cartridge(std::string &message)
+{
+ if (!cart_rom_region())
+ {
+ message = "msx_cart_msxdos2: Required region 'rom' was not found.";
+ return image_error::INTERNAL;
+ }
+
+ if (cart_rom_region()->bytes() != 0x10000)
+ {
+ message = "msx_cart_msxdos2: Region 'rom' has unsupported size.";
+ return image_error::INVALIDLENGTH;
+ }
+
+ const char *bank_address_str = get_feature("bank_address");
+ if (!bank_address_str)
+ {
+ message = "msx_cart_msxdos2: Feature 'bank_address' was not found.";
+ return image_error::BADSOFTWARE;
+ }
+ m_bank_address = strtol(bank_address_str, nullptr, 0);
+ if (m_bank_address < 0x4000 || m_bank_address > 0x7fff)
+ {
+ message = "msx_cart_msxdos2: bank_address must be between 0x4000 and 0x7fff.";
+ return image_error::BADSOFTWARE;
+ }
+
+ m_rombank->configure_entries(0, 4, cart_rom_region()->base(), PAGE_SIZE);
+
+ return std::error_condition();
+}
+
+void msx_cart_msxdos2_base_device::bank_w(u8 data)
+{
+ m_rombank->set_entry(data & 0x03);
+}
+
+
+
+class msx_cart_msxdos2j_device : public msx_cart_msxdos2_base_device
+{
+public:
+ msx_cart_msxdos2j_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : msx_cart_msxdos2_base_device(mconfig, MSX_CART_MSXDOS2J, tag, owner, clock)
+ , m_rambank(*this, "rambank%u", 0)
+ , m_view_page{ {*this, "view_page0"}, {*this, "view_page1"}, {*this, "view_page2"}, {*this, "view_page3"} }
+ , m_secondary_slot(0)
+ , m_bank_mask(0)
+ { }
+
+ virtual std::error_condition initialize_cartridge(std::string &message) override;
+
+protected:
+ virtual void device_start() override;
+
+private:
+ u8 secondary_slot_r();
+ void secondary_slot_w(u8 data);
+ template <int Bank> void mm_bank_w(u8 data);
+
+ memory_bank_array_creator<4> m_rambank;
+ memory_view m_view_page[4];
+ u8 m_secondary_slot;
+ u8 m_bank_mask;
+};
+
+
+void msx_cart_msxdos2j_device::device_start()
+{
+ msx_cart_msxdos2_base_device::device_start();
+ save_item(NAME(m_secondary_slot));
+}
+
+std::error_condition msx_cart_msxdos2j_device::initialize_cartridge(std::string &message)
+{
+ std::error_condition result = msx_cart_msxdos2_base_device::initialize_cartridge(message);
+ if (result)
+ return result;
+
+ u32 ram_size = cart_ram_region() ? cart_ram_region()->bytes() : 0;
+ if (ram_size > 256 * PAGE_SIZE || (ram_size & (PAGE_SIZE - 1)) != 0)
+ {
+ message = "msx_cart_msxdos2: Region 'ram' size must be a multiple of 0x4000 and at most 0x400000.";
+ return image_error::BADSOFTWARE;
+ }
+
+ for (int pg = 0; pg < 4; pg++)
+ page(pg)->install_view(0x4000 * pg, 0x4000 * pg + 0x3fff, m_view_page[pg]);
+ page(3)->install_readwrite_handler(0xffff, 0xffff, emu::rw_delegate(*this, FUNC(msx_cart_msxdos2j_device::secondary_slot_r)), emu::rw_delegate(*this, FUNC(msx_cart_msxdos2j_device::secondary_slot_w)));
+
+ // Make sure all views we can select do exist.
+ for (int subslot = 0; subslot < 4; subslot++)
+ {
+ for (int page = 0; page < 4; page++)
+ m_view_page[page][subslot];
+ }
+
+ // Kanji driver
+ m_view_page[1][2].install_rom(0x4000, 0x7fff, cart_rom_region()->base() + 0xc000);
+
+ // MSX-DOS2 rom
+ m_view_page[1][3].install_read_bank(0x4000, 0x7fff, m_rombank);
+ m_view_page[1][3].install_write_handler(m_bank_address, m_bank_address, emu::rw_delegate(*this, FUNC(msx_cart_msxdos2j_device::bank_w)));
+
+ // On-cartridge memory mapper RAM
+ if (ram_size)
+ {
+ m_bank_mask = device_generic_cart_interface::map_non_power_of_two(
+ unsigned(ram_size / PAGE_SIZE),
+ [this] (unsigned entry, unsigned page)
+ {
+ for (int i = 0; i < 4; i++)
+ m_rambank[i]->configure_entry(entry, cart_ram_region()->base() + PAGE_SIZE * page);
+ }
+ );
+
+ for (int pg = 0; pg < 4; pg++)
+ m_view_page[pg][1].install_readwrite_bank(0x4000 * pg, 0x4000 * pg + 0x3fff, m_rambank[pg]);
+
+ io_space().install_write_tap(0xfc, 0xfc, "bank0", [this] (offs_t, u8& data, u8){ this->mm_bank_w<0>(data); });
+ io_space().install_write_tap(0xfd, 0xfd, "bank1", [this] (offs_t, u8& data, u8){ this->mm_bank_w<1>(data); });
+ io_space().install_write_tap(0xfe, 0xfe, "bank2", [this] (offs_t, u8& data, u8){ this->mm_bank_w<2>(data); });
+ io_space().install_write_tap(0xff, 0xff, "bank3", [this] (offs_t, u8& data, u8){ this->mm_bank_w<3>(data); });
+ }
+
+ return std::error_condition();
+}
+
+u8 msx_cart_msxdos2j_device::secondary_slot_r()
+{
+ return ~m_secondary_slot;
+}
+
+void msx_cart_msxdos2j_device::secondary_slot_w(u8 data)
+{
+ for (int page = 0; page < 4; page++)
+ m_view_page[page].select((data >> (2 * page)) & 0x03);
+ m_secondary_slot = data;
+}
+
+template <int Bank>
+void msx_cart_msxdos2j_device::mm_bank_w(u8 data)
+{
+ m_rambank[Bank]->set_entry(data & m_bank_mask);
+}
+
+
+
+class msx_cart_msxdos2e_device : public msx_cart_msxdos2_base_device
+{
+public:
+ msx_cart_msxdos2e_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : msx_cart_msxdos2_base_device(mconfig, MSX_CART_MSXDOS2E, tag, owner, clock)
+ { }
+
+ virtual std::error_condition initialize_cartridge(std::string &message) override;
+};
+
+std::error_condition msx_cart_msxdos2e_device::initialize_cartridge(std::string &message)
+{
+ std::error_condition result = msx_cart_msxdos2_base_device::initialize_cartridge(message);
+ if (result)
+ return result;
+
+ page(1)->install_read_bank(0x4000, 0x7fff, m_rombank);
+ page(1)->install_write_handler(m_bank_address, m_bank_address, emu::rw_delegate(*this, FUNC(msx_cart_msxdos2e_device::bank_w)));
+
+ return std::error_condition();
+}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_MSXDOS2J, msx_cart_interface, msx_cart_msxdos2j_device, "msx_cart_msxdos2j", "MSX Cartridge - MSXDOS2 Japan")
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_MSXDOS2E, msx_cart_interface, msx_cart_msxdos2e_device, "msx_cart_msxdos2e", "MSX Cartridge - MSXDOS2 Europe")
diff --git a/src/devices/bus/msx/cart/msxdos2.h b/src/devices/bus/msx/cart/msxdos2.h
new file mode 100644
index 00000000000..55245c0f312
--- /dev/null
+++ b/src/devices/bus/msx/cart/msxdos2.h
@@ -0,0 +1,14 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#ifndef MAME_BUS_MSX_CART_MSXDOS2_H
+#define MAME_BUS_MSX_CART_MSXDOS2_H
+
+#pragma once
+
+#include "bus/msx/slot/cartridge.h"
+
+
+DECLARE_DEVICE_TYPE(MSX_CART_MSXDOS2J, msx_cart_interface)
+DECLARE_DEVICE_TYPE(MSX_CART_MSXDOS2E, msx_cart_interface)
+
+#endif // MAME_BUS_MSX_CART_MSXDOS2_H
diff --git a/src/devices/bus/msx/cart/nomapper.cpp b/src/devices/bus/msx/cart/nomapper.cpp
new file mode 100644
index 00000000000..20e62654960
--- /dev/null
+++ b/src/devices/bus/msx/cart/nomapper.cpp
@@ -0,0 +1,152 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+
+#include "emu.h"
+#include "nomapper.h"
+
+namespace {
+
+class msx_cart_nomapper_device : public device_t, public msx_cart_interface
+{
+public:
+ msx_cart_nomapper_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, MSX_CART_NOMAPPER, tag, owner, clock)
+ , msx_cart_interface(mconfig, *this)
+ , m_start_address(0)
+ , m_end_address(0)
+ { }
+
+ // device_t implementation
+ virtual void device_start() override { }
+
+ virtual std::error_condition initialize_cartridge(std::string &message) override;
+
+private:
+ uint32_t m_start_address;
+ uint32_t m_end_address;
+
+ void install_memory();
+};
+
+void msx_cart_nomapper_device::install_memory()
+{
+ u32 start_address = m_start_address;
+ u32 rom_offset = 0;
+
+ if (m_start_address != 0x0000 && m_start_address != 0x4000 && m_start_address != 0x8000 && m_start_address != 0xc000)
+ {
+ fatalerror("nomapper: Unsupported start address %04x\n", m_start_address);
+ }
+
+ for (int i = 0; i < 4; i++)
+ {
+ if (start_address < (i + 1) * 0x4000 && start_address < m_end_address)
+ {
+ if (page(i))
+ {
+ page(i)->install_rom(start_address, std::min<uint32_t>(start_address + 0x3fff, m_end_address - 1), cart_rom_region()->base() + rom_offset);
+ }
+ rom_offset += 0x4000;
+ start_address += 0x4000;
+ }
+ }
+}
+
+std::error_condition msx_cart_nomapper_device::initialize_cartridge(std::string &message)
+{
+ if (!cart_rom_region())
+ {
+ message = "msx_cart_nomapper_device: Required region 'rom' was not found.";
+ return image_error::INTERNAL;
+ }
+
+ const u32 size = cart_rom_region()->bytes();
+ u8 *rom = cart_rom_region()->base();
+
+ // 64KB images fill all pages.
+ if (size == 0x10000)
+ {
+ m_start_address = 0;
+ }
+ else if (is_loaded_through_softlist())
+ {
+ const char *start_page_str = get_feature("start_page");
+ if (!start_page_str)
+ {
+ message = "msx_cart_nomapper_device: Feature 'start_page' was not found.";
+ return image_error::BADSOFTWARE;
+ }
+ u32 start_page = strtol(start_page_str, nullptr, 0);
+ if (start_page > 2)
+ {
+ message = "msx_cart_nomapper_device: Invalid value for 'start_page', allowed values are 0, 1, and 2";
+ return image_error::BADSOFTWARE;
+ }
+
+ m_start_address = start_page * 0x4000;
+ }
+ else
+ {
+ // Try to guess the start address from the rom contents.
+ // determine start address, default to 0x4000
+ m_start_address = 0x4000;
+
+ switch (size)
+ {
+ // 8KB/16KB
+ case 0x2000: case 0x4000:
+ {
+ uint16_t start = rom[3] << 8 | rom[2];
+
+ // start address of $0000: call address in the $4000 region: $4000, else $8000
+ if (start == 0)
+ {
+ if ((rom[5] & 0xc0) == 0x40)
+ m_start_address = 0x4000;
+ else
+ m_start_address = 0x8000;
+ }
+
+ // start address in the $8000 region: $8000, else default
+ else if ((start & 0xc000) == 0x8000)
+ m_start_address = 0x8000;
+
+ break;
+ }
+
+ // 32KB
+ case 0x8000:
+ // take default, check when no "AB" at $0000, but "AB" at $4000
+ if (rom[0] != 'A' && rom[1] != 'B' && rom[0x4000] == 'A' && rom[0x4001] == 'B')
+ {
+ uint16_t start = rom[0x4003] << 8 | rom[0x4002];
+
+ // start address of $0000 and call address in the $4000 region, or start address outside the $8000 region: $0000, else default
+ if ((start == 0 && (rom[0x4005] & 0xc0) == 0x40) || start < 0x8000 || start >= 0xc000)
+ m_start_address = 0;
+ }
+
+ break;
+
+ // 48KB
+ case 0xc000:
+ // "AB" at $0000, but no "AB" at $4000, not "AB": $0000
+ if (rom[0] == 'A' && rom[1] == 'B' && rom[0x4000] != 'A' && rom[0x4001] != 'B')
+ m_start_address = 0x4000;
+ else
+ m_start_address = 0;
+
+ break;
+ }
+ }
+
+ m_end_address = std::min<u32>(m_start_address + size, 0x10000);
+
+ install_memory();
+
+ return std::error_condition();
+}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_NOMAPPER, msx_cart_interface, msx_cart_nomapper_device, "msx_cart_nomapper", "MSX Cartridge - ROM")
diff --git a/src/devices/bus/msx/cart/nomapper.h b/src/devices/bus/msx/cart/nomapper.h
new file mode 100644
index 00000000000..ac86741c621
--- /dev/null
+++ b/src/devices/bus/msx/cart/nomapper.h
@@ -0,0 +1,13 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#ifndef MAME_BUS_MSX_CART_NOMAPPER_H
+#define MAME_BUS_MSX_CART_NOMAPPER_H
+
+#pragma once
+
+#include "bus/msx/slot/cartridge.h"
+
+
+DECLARE_DEVICE_TYPE(MSX_CART_NOMAPPER, msx_cart_interface)
+
+#endif // MAME_BUS_MSX_CART_NOMAPPER_H
diff --git a/src/devices/bus/msx/cart/quickdisk.cpp b/src/devices/bus/msx/cart/quickdisk.cpp
new file mode 100644
index 00000000000..6fca9a8274b
--- /dev/null
+++ b/src/devices/bus/msx/cart/quickdisk.cpp
@@ -0,0 +1,124 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#include "emu.h"
+#include "quickdisk.h"
+#include "machine/z80sio.h"
+/**********************************************************************************
+
+Emulation of MSX QuickDisk interfaces.
+
+All known MSX QuickDisk interfaces contain 8KB ROM, 2KB RAM, and are connected
+to a Mitsumi QuickDisk drive.
+
+TODO:
+- Implement a quick disk drive and connect it to the SIO.
+- Dumps of MSX QuickDisks.
+
+**********************************************************************************/
+
+//#define VERBOSE (1)
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+namespace
+{
+
+class msx_cart_quickdisk_device : public device_t, public msx_cart_interface
+{
+public:
+ msx_cart_quickdisk_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MSX_CART_QUICKDISK, tag, owner, clock)
+ , msx_cart_interface(mconfig, *this)
+ , m_sio(*this, "sio")
+ { }
+
+ virtual std::error_condition initialize_cartridge(std::string &message) override;
+
+ static constexpr feature_type unemulated_features() { return feature::DISK; }
+
+protected:
+ virtual void device_start() override { }
+ virtual void device_add_mconfig(machine_config &config) override;
+
+private:
+ required_device<z80sio_device> m_sio;
+
+ void rtsa_w(int state);
+ void rtsb_w(int state);
+ void dtra_w(int state);
+ void dtrb_w(int state);
+};
+
+
+void msx_cart_quickdisk_device::device_add_mconfig(machine_config &config)
+{
+ Z80SIO(config, m_sio, 6.5_MHz_XTAL);
+ m_sio->out_int_callback().set(*this, FUNC(msx_cart_quickdisk_device::irq_out));
+ m_sio->out_rtsa_callback().set(*this, FUNC(msx_cart_quickdisk_device::rtsa_w)); // RTSA - write enable
+ m_sio->out_rtsb_callback().set(*this, FUNC(msx_cart_quickdisk_device::rtsb_w)); // RTSB - mfm demodulator?
+ m_sio->out_dtra_callback().set(*this, FUNC(msx_cart_quickdisk_device::dtra_w)); // DTRA - not used
+ m_sio->out_dtrb_callback().set(*this, FUNC(msx_cart_quickdisk_device::dtrb_w)); // DTRB - motor on
+ // CTSA - media write protected
+ // CTSB - not used
+ // DCDA - media inserted
+ // DCDB - ready
+}
+
+
+std::error_condition msx_cart_quickdisk_device::initialize_cartridge(std::string &message)
+{
+ if (!cart_rom_region())
+ {
+ message = "msx_cart_quickdisk_device: Required region 'rom' was not found.";
+ return image_error::INTERNAL;
+ }
+
+ if (cart_rom_region()->bytes() != 0x2000)
+ {
+ message = "msx_cart_quickdisk_device: Region 'rom' has unsupported size.";
+ return image_error::INVALIDLENGTH;
+ }
+
+ if (!cart_ram_region())
+ {
+ message = "msx_cart_quickdisk_device: Required region 'ram' was not found.";
+ return image_error::INTERNAL;
+ }
+
+ if (cart_ram_region()->bytes() != 0x800)
+ {
+ message = "msx_cart_quickdisk_device: Region 'ram' has unsupported size.";
+ return image_error::INVALIDLENGTH;
+ }
+
+ page(1)->install_rom(0x4000, 0x5fff, cart_rom_region()->base());
+ page(1)->install_read_handler(0x6000, 0x6003, emu::rw_delegate(m_sio, FUNC(z80sio_device::cd_ba_r)));
+ page(1)->install_write_handler(0x6000, 0x6003, emu::rw_delegate(m_sio, FUNC(z80sio_device::cd_ba_w)));
+ page(1)->install_ram(0x7000, 0x77ff, cart_ram_region()->base());
+
+ return std::error_condition();
+}
+
+void msx_cart_quickdisk_device::rtsa_w(int state)
+{
+ LOG("RTSA / write enable: %d\n", state);
+}
+
+void msx_cart_quickdisk_device::rtsb_w(int state)
+{
+ LOG("RTSB / mfm demodulator: %d\n", state);
+}
+
+void msx_cart_quickdisk_device::dtra_w(int state)
+{
+ LOG("DTRA / not used: %d\n", state);
+}
+
+void msx_cart_quickdisk_device::dtrb_w(int state)
+{
+ LOG("DTRB / motor on: %d\n", state);
+}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_QUICKDISK, msx_cart_interface, msx_cart_quickdisk_device, "msx_cart_quickdisk", "Quickdisk Interface")
diff --git a/src/devices/bus/msx/cart/quickdisk.h b/src/devices/bus/msx/cart/quickdisk.h
new file mode 100644
index 00000000000..433d5a2347d
--- /dev/null
+++ b/src/devices/bus/msx/cart/quickdisk.h
@@ -0,0 +1,13 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#ifndef MAME_BUS_MSX_CART_QUICKDISK_H
+#define MAME_BUS_MSX_CART_QUICKDISK_H
+
+#pragma once
+
+#include "bus/msx/slot/cartridge.h"
+
+
+DECLARE_DEVICE_TYPE(MSX_CART_QUICKDISK, msx_cart_interface)
+
+#endif // MAME_BUS_MSX_CART_QUICKDISK_H
diff --git a/src/devices/bus/msx/cart/ram.cpp b/src/devices/bus/msx/cart/ram.cpp
new file mode 100644
index 00000000000..9b98460df50
--- /dev/null
+++ b/src/devices/bus/msx/cart/ram.cpp
@@ -0,0 +1,349 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+/*
+Emulation of memory expansions for the MSX system.
+
+Standard 16K RAM expansions:
+- Addcom ADMSM 301
+- Casio OR-216
+- General RJ-102
+- Hitachi MP-RA01H
+- Mitsubishi ML-16RAM
+- National CF-2131
+- Philips VU 0031
+- Sanyo MRP-16
+- Sony HBM-16
+- Toshiba HX-M250
+
+Standard 32K RAM expansions:
+- Addcom ADMSM 302
+- Pioneer PX-RA32
+- Yamaha URM-01
+
+Standard 48K RAM expansions:
+- Addcom ADMSM 303
+- Neos RM-48
+
+Standard 64K RAM expansions:
+- Casio OR-264
+- Philips VU 0034
+- Sanyo Memoire Ram 64Ko
+- Sanyo MRP-64
+- Sharp-Epcom HB-4100
+- Sony HBM-64
+- Spectravideo SVI-747
+- Toshiba HX-M251
+- Walther Miller WM 0587
+
+Not supported:
+- Fujitsu MB22451 - Fujitsu FM-X only, adds 16K memory and a printer port
+- Yamaha SRE-01 - 60pin 32K memory expansion
+- Yamaha SRM-01 - 60pin 32K memory expansion and slot expander
+
+
+
+256KB Memmory Mapper expansions
+- R. & J.Jansen Memory Mapper 256
+
+512KB Memory Mapper expansions
+- Green MSX WBM512
+- Hardware Partners TM 512KB
+- HSH RE-512 MM
+- Padial LPE-512KBSRAM-V3
+- R. & J.Jansen Memory Mapper 512
+- Sony HBM-512
+
+768KB Memory Mapper expansions
+- ASCII MEM-768
+
+1MB Memory Mapper expansions
+- 8bits4ever MEGA-MAPPER 1024KB
+- Digital KC MSX Memory Mapper 1024KB
+- Hardware Partners TM 1M
+- MK MSX Memory Mapper 1024KB
+- MSX Club Gouda Memory Mapper 1MB
+- Popolon MSX Memory Mapper
+
+2MB Memory Mapper expansions
+- 8bits4ever MEGA-MAPPER 2048KB
+- Digital KC MSX Memory Mapper 2048KB
+- MFP Extended Memory-2048K
+- MK MSX Memory Mapper 2048KB
+- MSX Club Gouda Memory Mapper 2MB
+
+4MB Memory Mapper expansions
+- 8bits4ever MEGA-MAPPER 4096KB
+- Digital KC MSX Memory Mapper 4096KB
+- MK MSX Memory Mapper 4096KB
+- MSX Club Gouda Memory Mapper 4MB
+- Padial LPE-4MB-V42KP
+- T.N.S. Addram
+- Tecnobytes Double RAM (MegaRam not supported)
+
+Not supported memory mappers:
+- 8bits4ever SD-512
+- RBSC Carnivore2
+- Classic PC 16MB Expansion Memory - 4 x 4MB memory mapper
+- GR8NET
+- MSX Cartridge Shop MegaFlashROM SCC+ SD
+- Padial LPE-4FMB-V8SKP - 4MB memory mapper + MegaRam mode
+- Playsonic - 4MB memory mapper, up to 16MB through extra register
+- Popolon Musical Memory Mapper - 1MB memory mapper + SN76489AN
+- Stichting CODE MCR-025 - 256KB memory mapper + RAM Disk + Printer buffer
+- Stichting CODE MCR-051 - 512KB memory mapper + RAM Disk + Printer buffer
+- Stichting CODE MCR-076 - 768KB memory mapper + RAM Disk + Printer buffer
+- Stichting CODE MCR-102 - 1MB memory mapper + RAM Disk + Printer buffer
+- Stichting CODE MCR-204 - 2MB memory mapper + RAM Disk + Printer buffer
+*/
+#include "emu.h"
+#include "ram.h"
+#include "slotoptions.h"
+
+#include "bus/msx/slot/cartridge.h"
+
+#include "bus/generic/slot.h"
+
+
+
+DECLARE_DEVICE_TYPE(MSX_CART_16K_RAM, msx_cart_interface)
+DECLARE_DEVICE_TYPE(MSX_CART_32K_RAM, msx_cart_interface)
+DECLARE_DEVICE_TYPE(MSX_CART_48K_RAM, msx_cart_interface)
+DECLARE_DEVICE_TYPE(MSX_CART_64K_RAM, msx_cart_interface)
+DECLARE_DEVICE_TYPE(MSX_CART_256K_MM_RAM, msx_cart_interface)
+DECLARE_DEVICE_TYPE(MSX_CART_512K_MM_RAM, msx_cart_interface)
+DECLARE_DEVICE_TYPE(MSX_CART_768K_MM_RAM, msx_cart_interface)
+DECLARE_DEVICE_TYPE(MSX_CART_1024K_MM_RAM, msx_cart_interface)
+DECLARE_DEVICE_TYPE(MSX_CART_2048K_MM_RAM, msx_cart_interface)
+DECLARE_DEVICE_TYPE(MSX_CART_4096K_MM_RAM, msx_cart_interface)
+
+void msx_cart_ram_register_options(device_slot_interface &device)
+{
+ using namespace bus::msx::cart;
+ device.option_add(slotoptions::RAM16K, MSX_CART_16K_RAM);
+ device.option_add(slotoptions::RAM32K, MSX_CART_32K_RAM);
+ device.option_add(slotoptions::RAM48K, MSX_CART_48K_RAM);
+ device.option_add(slotoptions::RAM64K, MSX_CART_64K_RAM);
+ device.option_add(slotoptions::MM256K, MSX_CART_256K_MM_RAM);
+ device.option_add(slotoptions::MM512K, MSX_CART_512K_MM_RAM);
+ device.option_add(slotoptions::MM768K, MSX_CART_768K_MM_RAM);
+ device.option_add(slotoptions::MM1024K, MSX_CART_1024K_MM_RAM);
+ device.option_add(slotoptions::MM2048K, MSX_CART_2048K_MM_RAM);
+ device.option_add(slotoptions::MM4096K, MSX_CART_4096K_MM_RAM);
+}
+
+namespace {
+
+class msx_cart_base_ram_device : public device_t, public msx_cart_interface
+{
+protected:
+ msx_cart_base_ram_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u32 ram_size)
+ : device_t(mconfig, type, tag, owner, clock)
+ , msx_cart_interface(mconfig, *this)
+ , m_ram_size(ram_size)
+ { }
+
+ virtual void device_start() override
+ {
+ m_ram = std::make_unique<u8[]>(m_ram_size);
+ save_pointer(NAME(m_ram), m_ram_size);
+ }
+
+ u8 *ram_data()
+ {
+ return m_ram.get();
+ }
+
+ u32 get_ram_size() const
+ {
+ return m_ram_size;
+ }
+
+private:
+ std::unique_ptr<u8[]> m_ram;
+ const u32 m_ram_size;
+};
+
+
+class msx_cart_16k_ram_device : public msx_cart_base_ram_device
+{
+public:
+ msx_cart_16k_ram_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : msx_cart_base_ram_device(mconfig, MSX_CART_16K_RAM, tag, owner, clock, 16 * 1024)
+ { }
+
+protected:
+ virtual void device_start() override
+ {
+ msx_cart_base_ram_device::device_start();
+ page(2)->install_ram(0x8000, 0xbfff, ram_data());
+ }
+};
+
+class msx_cart_32k_ram_device : public msx_cart_base_ram_device
+{
+public:
+ msx_cart_32k_ram_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : msx_cart_base_ram_device(mconfig, MSX_CART_32K_RAM, tag, owner, clock, 32 * 1024)
+ { }
+
+protected:
+ virtual void device_start() override
+ {
+ msx_cart_base_ram_device::device_start();
+ page(0)->install_ram(0x0000, 0x3fff, ram_data());
+ page(1)->install_ram(0x4000, 0x7fff, ram_data() + 0x4000);
+ }
+};
+
+class msx_cart_48k_ram_device : public msx_cart_base_ram_device
+{
+public:
+ msx_cart_48k_ram_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : msx_cart_base_ram_device(mconfig, MSX_CART_48K_RAM, tag, owner, clock, 48 * 1024)
+ { }
+
+protected:
+ virtual void device_start() override
+ {
+ msx_cart_base_ram_device::device_start();
+ page(0)->install_ram(0x0000, 0x3fff, ram_data());
+ page(1)->install_ram(0x4000, 0x7fff, ram_data() + 0x4000);
+ page(2)->install_ram(0x8000, 0xbfff, ram_data() + 0x8000);
+ }
+};
+
+class msx_cart_64k_ram_device : public msx_cart_base_ram_device
+{
+public:
+ msx_cart_64k_ram_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : msx_cart_base_ram_device(mconfig, MSX_CART_64K_RAM, tag, owner, clock, 64 * 1024)
+ { }
+
+protected:
+ virtual void device_start() override
+ {
+ msx_cart_base_ram_device::device_start();
+ page(0)->install_ram(0x0000, 0x3fff, ram_data());
+ page(1)->install_ram(0x4000, 0x7fff, ram_data() + 0x4000);
+ page(2)->install_ram(0x8000, 0xbfff, ram_data() + 0x8000);
+ page(3)->install_ram(0xc000, 0xffff, ram_data() + 0xc000);
+ }
+};
+
+
+class msx_cart_base_mm_ram_device : public msx_cart_base_ram_device
+{
+protected:
+ msx_cart_base_mm_ram_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u32 ram_size)
+ : msx_cart_base_ram_device(mconfig, type, tag, owner, clock, ram_size)
+ , m_rambank(*this, "rambank%u", 0U)
+ , m_bank_mask(0)
+ { }
+
+ virtual void device_start() override;
+
+ template <int Bank> void bank_w(u8 data);
+
+private:
+ memory_bank_array_creator<4> m_rambank;
+ u8 m_bank_mask;
+};
+
+void msx_cart_base_mm_ram_device::device_start()
+{
+ msx_cart_base_ram_device::device_start();
+
+ m_bank_mask = device_generic_cart_interface::map_non_power_of_two(
+ unsigned(get_ram_size() / 0x4000),
+ [this] (unsigned entry, unsigned page)
+ {
+ for (int i = 0; i < 4; i++)
+ m_rambank[i]->configure_entry(entry, ram_data() + 0x4000 * page);
+ }
+ );
+
+ // The MSX system allows multiple devices to react to I/O, so we use taps.
+ io_space().install_write_tap(0xfc, 0xfc, "bank0", [this] (offs_t, u8& data, u8){ this->bank_w<0>(data); });
+ io_space().install_write_tap(0xfd, 0xfd, "bank1", [this] (offs_t, u8& data, u8){ this->bank_w<1>(data); });
+ io_space().install_write_tap(0xfe, 0xfe, "bank2", [this] (offs_t, u8& data, u8){ this->bank_w<2>(data); });
+ io_space().install_write_tap(0xff, 0xff, "bank3", [this] (offs_t, u8& data, u8){ this->bank_w<3>(data); });
+
+ page(0)->install_readwrite_bank(0x0000, 0x3fff, m_rambank[0]);
+ page(1)->install_readwrite_bank(0x4000, 0x7fff, m_rambank[1]);
+ page(2)->install_readwrite_bank(0x8000, 0xbfff, m_rambank[2]);
+ page(3)->install_readwrite_bank(0xc000, 0xffff, m_rambank[3]);
+
+ m_rambank[0]->set_entry(3);
+ m_rambank[1]->set_entry(2);
+ m_rambank[2]->set_entry(1);
+ m_rambank[3]->set_entry(0);
+}
+
+template <int Bank>
+void msx_cart_base_mm_ram_device::bank_w(u8 data)
+{
+ m_rambank[Bank]->set_entry(data & m_bank_mask);
+}
+
+
+class msx_cart_256k_mm_ram_device : public msx_cart_base_mm_ram_device
+{
+public:
+ msx_cart_256k_mm_ram_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : msx_cart_base_mm_ram_device(mconfig, MSX_CART_256K_MM_RAM, tag, owner, clock, 256 * 1024)
+ { }
+};
+
+class msx_cart_512k_mm_ram_device : public msx_cart_base_mm_ram_device
+{
+public:
+ msx_cart_512k_mm_ram_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : msx_cart_base_mm_ram_device(mconfig, MSX_CART_512K_MM_RAM, tag, owner, clock, 512 * 1024)
+ { }
+};
+
+class msx_cart_768k_mm_ram_device : public msx_cart_base_mm_ram_device
+{
+public:
+ msx_cart_768k_mm_ram_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : msx_cart_base_mm_ram_device(mconfig, MSX_CART_768K_MM_RAM, tag, owner, clock, 768 * 1024)
+ { }
+};
+
+class msx_cart_1024k_mm_ram_device : public msx_cart_base_mm_ram_device
+{
+public:
+ msx_cart_1024k_mm_ram_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : msx_cart_base_mm_ram_device(mconfig, MSX_CART_1024K_MM_RAM, tag, owner, clock, 1024 * 1024)
+ { }
+};
+
+class msx_cart_2048k_mm_ram_device : public msx_cart_base_mm_ram_device
+{
+public:
+ msx_cart_2048k_mm_ram_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : msx_cart_base_mm_ram_device(mconfig, MSX_CART_2048K_MM_RAM, tag, owner, clock, 2048 * 1024)
+ { }
+};
+
+class msx_cart_4096k_mm_ram_device : public msx_cart_base_mm_ram_device
+{
+public:
+ msx_cart_4096k_mm_ram_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : msx_cart_base_mm_ram_device(mconfig, MSX_CART_4096K_MM_RAM, tag, owner, clock, 4096 * 1024)
+ { }
+};
+
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_16K_RAM, msx_cart_interface, msx_cart_16k_ram_device, "msx_cart_16k_ram", "Generic MSX 16K RAM Expansion")
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_32K_RAM, msx_cart_interface, msx_cart_32k_ram_device, "msx_cart_32k_ram", "Generic MSX 32K RAM Expansion")
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_48K_RAM, msx_cart_interface, msx_cart_48k_ram_device, "msx_cart_48k_ram", "Generic MSX 48K RAM Expansion")
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_64K_RAM, msx_cart_interface, msx_cart_64k_ram_device, "msx_cart_64k_ram", "Generic MSX 64K RAM Expansion")
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_256K_MM_RAM, msx_cart_interface, msx_cart_256k_mm_ram_device, "msx_cart_256k_mm_ram", "Generic MSX 256K MM RAM Expansion")
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_512K_MM_RAM, msx_cart_interface, msx_cart_512k_mm_ram_device, "msx_cart_512k_mm_ram", "Generic MSX 512K MM RAM Expansion")
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_768K_MM_RAM, msx_cart_interface, msx_cart_768k_mm_ram_device, "msx_cart_768k_mm_ram", "Generic MSX 768K MM RAM Expansion")
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_1024K_MM_RAM, msx_cart_interface, msx_cart_1024k_mm_ram_device, "msx_cart_1024k_mm_ram", "Generic MSX 1024K MM RAM Expansion")
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_2048K_MM_RAM, msx_cart_interface, msx_cart_2048k_mm_ram_device, "msx_cart_2048k_mm_ram", "Generic MSX 2048K MM RAM Expansion")
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_4096K_MM_RAM, msx_cart_interface, msx_cart_4096k_mm_ram_device, "msx_cart_4096k_mm_ram", "Generic MSX 4096K MM RAM Expansion")
diff --git a/src/devices/bus/msx/cart/ram.h b/src/devices/bus/msx/cart/ram.h
new file mode 100644
index 00000000000..48faec13873
--- /dev/null
+++ b/src/devices/bus/msx/cart/ram.h
@@ -0,0 +1,11 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#ifndef MAME_BUS_MSX_CART_RAM_H
+#define MAME_BUS_MSX_CART_RAM_H
+
+#pragma once
+
+
+void msx_cart_ram_register_options(device_slot_interface &device);
+
+#endif // MAME_BUS_MSX_CART_RAM_H
diff --git a/src/devices/bus/msx/cart/rtype.cpp b/src/devices/bus/msx/cart/rtype.cpp
new file mode 100644
index 00000000000..d2f527b2c82
--- /dev/null
+++ b/src/devices/bus/msx/cart/rtype.cpp
@@ -0,0 +1,62 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#include "emu.h"
+#include "rtype.h"
+
+namespace {
+
+class msx_cart_rtype_device : public device_t, public msx_cart_interface
+{
+public:
+ msx_cart_rtype_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MSX_CART_RTYPE, tag, owner, clock)
+ , msx_cart_interface(mconfig, *this)
+ , m_rombank(*this, "rombank")
+ { }
+
+ virtual std::error_condition initialize_cartridge(std::string &message) override;
+
+protected:
+ // device_t implementation
+ virtual void device_start() override { }
+
+private:
+ void bank_w(u8 data);
+
+ memory_bank_creator m_rombank;
+};
+
+std::error_condition msx_cart_rtype_device::initialize_cartridge(std::string &message)
+{
+ if (!cart_rom_region())
+ {
+ message = "msx_cart_rtype_device: Required region 'rom' was not found.";
+ return image_error::INTERNAL;
+ }
+
+ if (cart_rom_region()->bytes() != 0x80000 && cart_rom_region()->bytes() != 0x60000)
+ {
+ message = "msx_cart_rtype_device: Region 'rom' has unsupported size.";
+ return image_error::INVALIDLENGTH;
+ }
+
+ m_rombank->configure_entries(0, 24, cart_rom_region()->base(), 0x4000);
+
+ page(1)->install_rom(0x4000, 0x7fff, cart_rom_region()->base() + 15 * 0x4000);
+ page(1)->install_write_handler(0x7000, 0x7fff, emu::rw_delegate(*this, FUNC(msx_cart_rtype_device::bank_w)));
+ page(2)->install_read_bank(0x8000, 0xbfff, m_rombank);
+
+ return std::error_condition();
+}
+
+void msx_cart_rtype_device::bank_w(u8 data)
+{
+ data &= 0x1f;
+ if (data & 0x10)
+ data &= 0x17;
+ m_rombank->set_entry(data);
+}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_RTYPE, msx_cart_interface, msx_cart_rtype_device, "msx_cart_rtype", "MSX Cartridge - R-Type")
diff --git a/src/devices/bus/msx/cart/rtype.h b/src/devices/bus/msx/cart/rtype.h
new file mode 100644
index 00000000000..cacc247d4b6
--- /dev/null
+++ b/src/devices/bus/msx/cart/rtype.h
@@ -0,0 +1,13 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#ifndef MAME_BUS_MSX_CART_RTYPE_H
+#define MAME_BUS_MSX_CART_RTYPE_H
+
+#pragma once
+
+#include "bus/msx/slot/cartridge.h"
+
+
+DECLARE_DEVICE_TYPE(MSX_CART_RTYPE, msx_cart_interface)
+
+#endif // MAME_BUS_MSX_CART_RTYPE_H
diff --git a/src/devices/bus/msx/cart/scsi.cpp b/src/devices/bus/msx/cart/scsi.cpp
new file mode 100644
index 00000000000..9b049a89ec2
--- /dev/null
+++ b/src/devices/bus/msx/cart/scsi.cpp
@@ -0,0 +1,229 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#include "emu.h"
+#include "scsi.h"
+
+#include "bus/nscsi/devices.h"
+#include "machine/mb87030.h"
+#include "machine/nscsi_bus.h"
+#include "machine/wd33c9x.h"
+
+/*
+
+Implementation of SCSI interface as it appeared in:
+- MSX Computer Club Gouda MSX-SCSI Interface
+- ESE MegaSCSI
+ - Came with SRAM on the cartridge (128/256/512/1024KB SRAM)
+
+
+Other known SCSI(-ish) interfaces:
+
+ASCII HD Interface (SASI Interface)
+B.E.R.T.
+HSH SCSI Interface
+MAK/Green/Sparrowsoft SCSI Interface
+MK SCSI Interface
+- Evolved into B.E.R.T. SCSI Interface.
+
+TODO:
+- Fix MegaSCSI mb89352 write operation at 8MHz.
+
+*/
+
+namespace
+{
+
+class msx_cart_gouda_scsi_device : public device_t, public msx_cart_interface
+{
+public:
+ msx_cart_gouda_scsi_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MSX_CART_GOUDA_SCSI, tag, owner, clock)
+ , msx_cart_interface(mconfig, *this)
+ , m_wd33c93a(*this, "scsi:6:wd33c93a")
+ { }
+
+ virtual std::error_condition initialize_cartridge(std::string &message) override;
+
+protected:
+ virtual void device_start() override { }
+ virtual void device_add_mconfig(machine_config &config) override;
+
+private:
+ required_device<wd33c93a_device> m_wd33c93a;
+
+ void reset_w(u8 data);
+};
+
+void msx_cart_gouda_scsi_device::device_add_mconfig(machine_config &config)
+{
+ NSCSI_BUS(config, "scsi", 0);
+ NSCSI_CONNECTOR(config, "scsi:0", default_scsi_devices, "harddisk", false);
+ NSCSI_CONNECTOR(config, "scsi:1", default_scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi:2", default_scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi:3", default_scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi:4", default_scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi:5", default_scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi:6").option_set("wd33c93a", WD33C93A).clock(10_MHz_XTAL);
+}
+
+std::error_condition msx_cart_gouda_scsi_device::initialize_cartridge(std::string &message)
+{
+ if (!cart_rom_region())
+ {
+ message = "msx_cart_gouda_scsi_device: Required region 'rom' was not found.";
+ return image_error::INTERNAL;
+ }
+
+ if (cart_rom_region()->bytes() < 0x4000)
+ {
+ message = "msx_cart_gouda_scsi_device: Region 'rom' has unsupported size.";
+ return image_error::INVALIDLENGTH;
+ }
+
+ page(1)->install_rom(0x4000, 0x7fff, cart_rom_region()->base());
+
+ io_space().install_write_handler(0x34, 0x35, emu::rw_delegate(*m_wd33c93a, FUNC(wd33c93a_device::indir_w)));
+ io_space().install_read_handler(0x34, 0x35, emu::rw_delegate(*m_wd33c93a, FUNC(wd33c93a_device::indir_r)));
+ io_space().install_write_handler(0x36, 0x36, emu::rw_delegate(*this, FUNC(msx_cart_gouda_scsi_device::reset_w)));
+
+ return std::error_condition();
+}
+
+void msx_cart_gouda_scsi_device::reset_w(u8 data)
+{
+ m_wd33c93a->reset_w(data);
+}
+
+
+
+class msx_cart_mega_scsi_device : public device_t, public msx_cart_interface
+{
+public:
+ msx_cart_mega_scsi_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MSX_CART_MEGA_SCSI, tag, owner, clock)
+ , msx_cart_interface(mconfig, *this)
+ , m_mb89352a(*this, "scsi:7:mb89352a")
+ , m_srambank(*this, "srambank%u", 0U)
+ , m_view{ {*this, "view0"}, {*this, "view1"}, {*this, "view2"}, {*this, "view3"} }
+ , m_bank_mask(0)
+ { }
+
+ virtual std::error_condition initialize_cartridge(std::string &message) override;
+
+ static constexpr feature_type imperfect_features() { return feature::TIMING; }
+
+protected:
+ virtual void device_start() override { }
+ virtual void device_reset() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+
+private:
+ static constexpr size_t BANK_SIZE = 0x2000;
+
+ required_device<mb89352_device> m_mb89352a;
+ memory_bank_array_creator<4> m_srambank;
+ memory_view m_view[4];
+ u8 m_bank_mask;
+
+ template <int Bank> void bank_w(u8 data);
+};
+
+void msx_cart_mega_scsi_device::device_add_mconfig(machine_config &config)
+{
+ NSCSI_BUS(config, "scsi", 0);
+ NSCSI_CONNECTOR(config, "scsi:0", default_scsi_devices, "harddisk", false);
+ NSCSI_CONNECTOR(config, "scsi:1", default_scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi:2", default_scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi:3", default_scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi:4", default_scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi:5", default_scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi:6", default_scsi_devices, nullptr, false);
+ // Input clock is 8MHz according to the schematic. However, clocks below 11MHz cause writes to fail. Reads are fine at 8MHz.
+ //NSCSI_CONNECTOR(config, "scsi:7").option_set("mb89352a", MB89352).clock(16_MHz_XTAL/2);
+ NSCSI_CONNECTOR(config, "scsi:7").option_set("mb89352a", MB89352).clock(11'000'000);
+}
+
+void msx_cart_mega_scsi_device::device_reset()
+{
+ for (int i = 0; i < 4; i++)
+ {
+ if (i != 1)
+ m_view[i].select(0);
+ m_srambank[i]->set_entry(0);
+ }
+}
+
+std::error_condition msx_cart_mega_scsi_device::initialize_cartridge(std::string &message)
+{
+ if (!cart_sram_region())
+ {
+ message = "msx_cart_mega_scsi_device: Required region 'sram' was not found.";
+ return image_error::INTERNAL;
+ }
+
+ const u32 sram_size = cart_sram_region()->bytes();
+
+ if (sram_size != 0x20000 && sram_size != 0x40000 && sram_size != 0x80000 && sram_size != 0x100000)
+ {
+ message = "msx_cart_mega_scsi_device: Region 'sram' has unsupported size.";
+ return image_error::INVALIDLENGTH;
+ }
+
+ const u16 sram_banks = sram_size / BANK_SIZE;
+ m_bank_mask = sram_banks - 1;
+
+ for (int i = 0; i < 4; i++)
+ m_srambank[i]->configure_entries(0, sram_banks, cart_sram_region()->base(), BANK_SIZE);
+
+ page(1)->install_view(0x4000, 0x5fff, m_view[0]);
+ m_view[0][0].install_read_bank(0x4000, 0x5fff, m_srambank[0]);
+ m_view[0][1].install_readwrite_bank(0x4000, 0x5fff, m_srambank[0]);
+ m_view[0][2].install_read_handler(0x4000, 0x4fff, emu::rw_delegate(*m_mb89352a, FUNC(mb89352_device::dma_r)));
+ m_view[0][2].install_write_handler(0x4000, 0x4fff, emu::rw_delegate(*m_mb89352a, FUNC(mb89352_device::dma_w)));
+ // mb89352 is mirrored at 5000 - 5fff
+ for (int addr = 0x5000; addr < 0x6000; addr += 0x10)
+ m_view[0][2].install_device(addr, addr + 0x0f, *m_mb89352a, &mb89352_device::map);
+ page(1)->install_read_bank(0x6000, 0x7fff, m_srambank[1]);
+ page(2)->install_view(0x8000, 0x9fff, m_view[2]);
+ m_view[2][0].install_read_bank(0x8000, 0x9fff, m_srambank[2]);
+ m_view[2][1].install_readwrite_bank(0x8000, 0x9fff, m_srambank[2]);
+ m_view[2][2].install_read_handler(0x8000, 0x8fff, emu::rw_delegate(*m_mb89352a, FUNC(mb89352_device::dma_r)));
+ m_view[2][2].install_write_handler(0x8000, 0x8fff, emu::rw_delegate(*m_mb89352a, FUNC(mb89352_device::dma_w)));
+ // mb89352 is mirrored at 9000 - 9fff
+ for (int addr = 0x9000; addr < 0xa000; addr += 0x10)
+ m_view[2][2].install_device(addr, addr + 0x0f, *m_mb89352a, &mb89352_device::map);
+ page(2)->install_view(0xa000, 0xbfff, m_view[3]);
+ m_view[3][0].install_read_bank(0xa000, 0xbfff, m_srambank[3]);
+ m_view[3][1].install_readwrite_bank(0xa000, 0xbfff, m_srambank[3]);
+ m_view[3][2].install_read_handler(0xa000, 0xafff, emu::rw_delegate(*m_mb89352a, FUNC(mb89352_device::dma_r)));
+ m_view[3][2].install_write_handler(0xa000, 0xafff, emu::rw_delegate(*m_mb89352a, FUNC(mb89352_device::dma_w)));
+ // mb89352 is mirrored at b000 - bfff
+ for (int addr = 0xb000; addr < 0xc000; addr += 0x10)
+ m_view[3][2].install_device(addr, addr + 0x0f, *m_mb89352a, &mb89352_device::map);
+
+ page(1)->install_write_handler(0x6000, 0x67ff, emu::rw_delegate(*this, FUNC(msx_cart_mega_scsi_device::bank_w<0>)));
+ page(1)->install_write_handler(0x6800, 0x6fff, emu::rw_delegate(*this, FUNC(msx_cart_mega_scsi_device::bank_w<1>)));
+ page(1)->install_write_handler(0x7000, 0x77ff, emu::rw_delegate(*this, FUNC(msx_cart_mega_scsi_device::bank_w<2>)));
+ page(1)->install_write_handler(0x7800, 0x7fff, emu::rw_delegate(*this, FUNC(msx_cart_mega_scsi_device::bank_w<3>)));
+
+ return std::error_condition();
+}
+
+template <int Bank>
+void msx_cart_mega_scsi_device::bank_w(u8 data)
+{
+ // Also writes of $00 and $10 to 7ffe are seen before banking; some kind of banking enable?
+ m_srambank[Bank]->set_entry(data & m_bank_mask);
+ if (Bank != 1)
+ {
+ int view_to_select = BIT(data, 7) ? 1 : (BIT(data, 6) ? 2 : 0);
+
+ m_view[Bank].select(view_to_select);
+ }
+}
+
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_GOUDA_SCSI, msx_cart_interface, msx_cart_gouda_scsi_device, "msx_cart_gouda_scsi", "MSX Computer Club Gouda MSX-SCSI Interface")
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_MEGA_SCSI, msx_cart_interface, msx_cart_mega_scsi_device, "msx_cart_mega_scsi", "ESE MEGA-SCSI")
diff --git a/src/devices/bus/msx/cart/scsi.h b/src/devices/bus/msx/cart/scsi.h
new file mode 100644
index 00000000000..5e371f436c6
--- /dev/null
+++ b/src/devices/bus/msx/cart/scsi.h
@@ -0,0 +1,13 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#ifndef MAME_BUS_MSX_CART_SCSI_H
+#define MAME_BUS_MSX_CART_SCSI_H
+
+#pragma once
+
+#include "bus/msx/slot/cartridge.h"
+
+DECLARE_DEVICE_TYPE(MSX_CART_GOUDA_SCSI, msx_cart_interface)
+DECLARE_DEVICE_TYPE(MSX_CART_MEGA_SCSI, msx_cart_interface)
+
+#endif // MAME_BUS_MSX_CART_SCSI_H
diff --git a/src/devices/bus/msx/cart/slotexpander.cpp b/src/devices/bus/msx/cart/slotexpander.cpp
new file mode 100644
index 00000000000..cf3a78ce733
--- /dev/null
+++ b/src/devices/bus/msx/cart/slotexpander.cpp
@@ -0,0 +1,147 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#include "emu.h"
+#include "slotexpander.h"
+#include "bus/msx/cart/cartridge.h"
+#include "machine/input_merger.h"
+
+/*
+Emulation of a 4 slot expander for the MSX system.
+
+Some slot expanders have the ability to enable/disable subslots through
+jumpers/switches, or adjustable volume per slot. None of that is emulated.
+
+Known slot expanders:
+- 8bits4ever Slot x4 - audio mixer with adjustable volume per slot not emulated.
+- CIEL Mini Slot Expander - Jumpers and switches not emulated.
+- Digital Design Expansor de slots DDX
+- ECC Expansion Computer Case - 8 slot version not emulated
+- Front Line Slot Expander
+- G.DOS Slotexpander
+- Hans Oranje slotexpander - Switches not emulated
+- Incompel Expansor de slots
+- MAD Expander Slot Box MXE-MAIN-A / MXE-MAIN4-A - Switches not emulated
+- MK Slotexpander - Switches not emulated
+- MSX Club Gouda Slotexpander - Switches not emulated
+- Mitsubishi ML-20EB
+- Neos EX-4
+- Padial LPE-4EXP-V3SC
+- Padial LPE-4EXP-V4SC
+- Repro Factory My Super Expander 4X
+- Sinfox Slotexpander
+- Sony HBI-50 - Only expands to 2 slots
+- Sunrise 8x SlotExpander - only 4 slots emulated
+- Supersoniqs Modulon
+- Toshiba HX-E601
+- Victor HC-A703E - Only expands to 2 slots?
+- Zemina Expansion slot - Only expands to 2 slots
+
+*/
+
+namespace {
+
+class msx_cart_slotexpander_device : public device_t, public msx_cart_interface
+{
+public:
+ msx_cart_slotexpander_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MSX_CART_SLOTEXPANDER, tag, owner, clock)
+ , msx_cart_interface(mconfig, *this)
+ , m_cartslot(*this, "cartslot%u", 1)
+ , m_irq_out(*this, "irq_out")
+ , m_view{ {*this, "view0"}, {*this, "view1"}, {*this, "view2"}, {*this, "view3"} }
+ , m_secondary_slot(0)
+ { }
+
+protected:
+ virtual void device_start() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_resolve_objects() override;
+ virtual void device_config_complete() override;
+
+private:
+ template<int Slot> void add_cartslot(machine_config &mconfig);
+ u8 secondary_slot_r();
+ void secondary_slot_w(u8 data);
+
+ required_device_array<msx_slot_cartridge_device, 4> m_cartslot;
+ required_device<input_merger_any_high_device> m_irq_out;
+ memory_view m_view[4];
+ u8 m_secondary_slot;
+};
+
+template<int Slot>
+void msx_cart_slotexpander_device::add_cartslot(machine_config &mconfig)
+{
+ MSX_SLOT_CARTRIDGE(mconfig, m_cartslot[Slot], DERIVED_CLOCK(1, 1));
+ m_cartslot[Slot]->option_reset();
+ msx_cart(*m_cartslot[Slot], true);
+ m_cartslot[Slot]->set_default_option(nullptr);
+ m_cartslot[Slot]->set_fixed(false);
+ m_cartslot[Slot]->irq_handler().set(m_irq_out, FUNC(input_merger_device::in_w<Slot>));
+ if (parent_slot())
+ {
+ m_cartslot[Slot]->add_route(ALL_OUTPUTS, soundin(), 1.0);
+ }
+}
+
+void msx_cart_slotexpander_device::device_add_mconfig(machine_config &mconfig)
+{
+ add_cartslot<0>(mconfig);
+ add_cartslot<1>(mconfig);
+ add_cartslot<2>(mconfig);
+ add_cartslot<3>(mconfig);
+
+ INPUT_MERGER_ANY_HIGH(mconfig, m_irq_out).output_handler().set(*this, FUNC(msx_cart_slotexpander_device::irq_out));
+}
+
+void msx_cart_slotexpander_device::device_config_complete()
+{
+ if (parent_slot())
+ {
+ for (auto &subslot : m_cartslot)
+ {
+ auto target = subslot.finder_target();
+ parent_slot()->configure_subslot(*target.first.subdevice<msx_slot_cartridge_device>(target.second));
+ }
+ }
+}
+
+void msx_cart_slotexpander_device::device_resolve_objects()
+{
+ for (int pg = 0; pg < 4; pg++)
+ page(pg)->install_view(0x4000 * pg, 0x04000 * pg + 0x3fff, m_view[pg]);
+ page(3)->install_readwrite_handler(0xffff, 0xffff, emu::rw_delegate(*this, FUNC(msx_cart_slotexpander_device::secondary_slot_r)), emu::rw_delegate(*this, FUNC(msx_cart_slotexpander_device::secondary_slot_w)));
+
+ for (int subslot = 0; subslot < 4; subslot++)
+ for (int page = 0; page < 4; page++)
+ m_view[page][subslot];
+
+ for (int subslot = 0; subslot < 4; subslot++)
+ m_cartslot[subslot]->install(&m_view[0][subslot], &m_view[1][subslot], &m_view[2][subslot], &m_view[3][subslot]);
+}
+
+void msx_cart_slotexpander_device::device_start()
+{
+ save_item(NAME(m_secondary_slot));
+ m_secondary_slot = 0;
+
+ for (int page = 0; page < 4; page++)
+ m_view[page].select(0);
+}
+
+u8 msx_cart_slotexpander_device::secondary_slot_r()
+{
+ return ~m_secondary_slot;
+}
+
+void msx_cart_slotexpander_device::secondary_slot_w(u8 data)
+{
+ for (int page = 0; page < 4; page++)
+ m_view[page].select((data >> (2 * page)) & 0x03);
+ m_secondary_slot = data;
+}
+
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_SLOTEXPANDER, msx_cart_interface, msx_cart_slotexpander_device, "msx_cart_slotexpander", "MSX Slot Expander")
diff --git a/src/devices/bus/msx/cart/slotexpander.h b/src/devices/bus/msx/cart/slotexpander.h
new file mode 100644
index 00000000000..d21dfc03b9c
--- /dev/null
+++ b/src/devices/bus/msx/cart/slotexpander.h
@@ -0,0 +1,13 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#ifndef MAME_BUS_MSX_CART_SLOTEXPANDER_H
+#define MAME_BUS_MSX_CART_SLOTEXPANDER_H
+
+#pragma once
+
+#include "bus/msx/slot/cartridge.h"
+
+
+DECLARE_DEVICE_TYPE(MSX_CART_SLOTEXPANDER, msx_cart_interface)
+
+#endif // MAME_BUS_MSX_CART_SLOTEXPANDER_H
diff --git a/src/devices/bus/msx/cart/slotoptions.cpp b/src/devices/bus/msx/cart/slotoptions.cpp
new file mode 100644
index 00000000000..493f1d13ca3
--- /dev/null
+++ b/src/devices/bus/msx/cart/slotoptions.cpp
@@ -0,0 +1,90 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#include "emu.h"
+#include "slotoptions.h"
+
+namespace bus::msx::cart::slotoptions {
+char const *const ARC = "arc";
+char const *const ASCII8 = "ascii8";
+char const *const ASCII8_SRAM = "ascii8_sram";
+char const *const ASCII16 = "ascii16";
+char const *const ASCII16_SRAM = "ascii16_sram";
+char const *const BEEPACK = "beepack";
+char const *const BM_012 = "bm_012";
+char const *const CROSS_BLAIM = "cross_blaim";
+char const *const DISK_AVDPF550 = "disk_avdpf550";
+char const *const DISK_CDX2 = "disk_cdx2";
+char const *const DISK_DDX3 = "disk_ddx3";
+char const *const DISK_FD03 = "disk_fd03";
+char const *const DISK_FD051 = "disk_fd051";
+char const *const DISK_FSCF351 = "disk_fscf351";
+char const *const DISK_FSFD1 = "disk_fsfd1";
+char const *const DISK_FSFD1A = "disk_fsfd1a";
+char const *const DISK_HB3600 = "disk_hb3600";
+char const *const DISK_HBD20W = "disk_hbd20w";
+char const *const DISK_HBD50 = "disk_hbd50";
+char const *const DISK_HBDF1 = "disk_hbdf1";
+char const *const DISK_HXF101PE = "disk_hxf101pe";
+char const *const DISK_MFD001 = "disk_mfd001";
+char const *const DISK_ML30DC = "disk_ml30dc";
+char const *const DISK_NMS1200 = "disk_nms1200";
+char const *const DISK_TADPF550 = "disk_tadpf550";
+char const *const DISK_VY0010 = "disk_vy0010";
+char const *const DOOLY = "dooly";
+char const *const EASISPEECH = "easispeech";
+char const *const EC701 = "ec701";
+char const *const FMPAC = "fmpac";
+char const *const FS_SR021 = "fs_sr021";
+char const *const FS_SR022 = "fs_sr022";
+char const *const GAMEMASTER2 = "gamemaster2";
+char const *const GOUDA_SCSI = "gouda_scsi";
+char const *const HALNOTE = "halnote";
+char const *const HBI55 = "hbi55";
+char const *const HFOX = "hfox";
+char const *const HOLY_QURAN = "holy_quran";
+char const *const INK = "ink";
+char const *const KANJI = "kanji";
+char const *const KEYBOARD_MASTER = "keyboard_master";
+char const *const KONAMI = "konami";
+char const *const KONAMI_SCC = "konami_scc";
+char const *const KOREAN_25IN1 = "korean_25in1";
+char const *const KOREAN_80IN1 = "korean_80in1";
+char const *const KOREAN_90IN1 = "korean_90in1";
+char const *const KOREAN_126IN1 = "korean_126in1";
+char const *const KOREAN_HYDLIDE2 = "korean_hydlide2";
+char const *const LOVEPLUS = "loveplus";
+char const *const MAJUSTUSHI = "majutsushi";
+char const *const MATRA_COMP = "matra_comp";
+char const *const MEGA_SCSI = "mega_scsi";
+char const *const MM256K = "mm256k";
+char const *const MM512K = "mm512k";
+char const *const MM768K = "mm768k";
+char const *const MM1024K = "mm1024k";
+char const *const MM2048K = "mm2048k";
+char const *const MM4096K = "mm4096k";
+char const *const MOONSOUND = "moonsound";
+char const *const MSXAUD_FSCA1 = "msxaud_fsca1";
+char const *const MSXAUD_HXMU900 = "msxaud_hxmu900";
+char const *const MSXAUD_NMS1205 = "msxaud_nms1205";
+char const *const MSXDOS2J = "msxdos2j";
+char const *const MSXDOS2E = "msxdos2e";
+char const *const MSXWRITE = "msxwrite";
+char const *const NOMAPPER = "nomapper";
+char const *const QUICKDISK = "quickdisk";
+char const *const RAM16K = "ram16k";
+char const *const RAM32K = "ram32k";
+char const *const RAM48K = "ram48k";
+char const *const RAM64K = "ram64k";
+char const *const RTYPE = "rtype";
+char const *const SLOTEXP = "slotexp";
+char const *const SOFTCARD = "softcard";
+char const *const SOUND_SNATCHER = "sound_snatcher";
+char const *const SOUND_SDSNATCH = "sound_sdsnatch";
+char const *const SUNRISE_SCC = "sunrise_scc";
+char const *const SUPER_SWANGI = "super_swangi";
+char const *const SUPERLODERUNNER = "superloderunner";
+char const *const SYNTHESIZER = "synthesizer";
+char const *const UCN01 = "ucn01";
+
+} // namespace bus::msx::cart::slotoptions
+
diff --git a/src/devices/bus/msx/cart/slotoptions.h b/src/devices/bus/msx/cart/slotoptions.h
new file mode 100644
index 00000000000..c2f96a782d6
--- /dev/null
+++ b/src/devices/bus/msx/cart/slotoptions.h
@@ -0,0 +1,94 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#ifndef MAME_BUS_MSX_CART_SLOTOPTIONS_H
+#define MAME_BUS_MSX_CART_SLOTOPTIONS_H
+
+#pragma once
+
+namespace bus::msx::cart::slotoptions {
+
+extern char const *const ARC;
+extern char const *const ASCII8;
+extern char const *const ASCII8_SRAM;
+extern char const *const ASCII16;
+extern char const *const ASCII16_SRAM;
+extern char const *const BEEPACK;
+extern char const *const BM_012;
+extern char const *const CROSS_BLAIM;
+extern char const *const DISK_AVDPF550;
+extern char const *const DISK_CDX2;
+extern char const *const DISK_DDX3;
+extern char const *const DISK_FD03;
+extern char const *const DISK_FD051;
+extern char const *const DISK_FSCF351;
+extern char const *const DISK_FSFD1;
+extern char const *const DISK_FSFD1A;
+extern char const *const DISK_HB3600;
+extern char const *const DISK_HBD20W;
+extern char const *const DISK_HBD50;
+extern char const *const DISK_HBDF1;
+extern char const *const DISK_HXF101PE;
+extern char const *const DISK_MFD001;
+extern char const *const DISK_ML30DC;
+extern char const *const DISK_NMS1200;
+extern char const *const DISK_TADPF550;
+extern char const *const DISK_VY0010;
+extern char const *const DOOLY;
+extern char const *const EASISPEECH;
+extern char const *const EC701;
+extern char const *const FMPAC;
+extern char const *const FS_SR021;
+extern char const *const FS_SR022;
+extern char const *const GAMEMASTER2;
+extern char const *const GOUDA_SCSI;
+extern char const *const HALNOTE;
+extern char const *const HBI55;
+extern char const *const HFOX;
+extern char const *const HOLY_QURAN;
+extern char const *const INK;
+extern char const *const KANJI;
+extern char const *const KEYBOARD_MASTER;
+extern char const *const KONAMI;
+extern char const *const KONAMI_SCC;
+extern char const *const KOREAN_25IN1;
+extern char const *const KOREAN_80IN1;
+extern char const *const KOREAN_90IN1;
+extern char const *const KOREAN_126IN1;
+extern char const *const KOREAN_HYDLIDE2;
+extern char const *const LOVEPLUS;
+extern char const *const MAJUSTUSHI;
+extern char const *const MATRA_COMP;
+extern char const *const MEGA_SCSI;
+extern char const *const MM256K;
+extern char const *const MM512K;
+extern char const *const MM768K;
+extern char const *const MM1024K;
+extern char const *const MM2048K ;
+extern char const *const MM4096K;
+extern char const *const MOONSOUND;
+extern char const *const MSXAUD_FSCA1;
+extern char const *const MSXAUD_HXMU900;
+extern char const *const MSXAUD_NMS1205;
+extern char const *const MSXDOS2J;
+extern char const *const MSXDOS2E;
+extern char const *const MSXWRITE;
+extern char const *const NOMAPPER;
+extern char const *const QUICKDISK;
+extern char const *const RAM16K;
+extern char const *const RAM32K;
+extern char const *const RAM48K;
+extern char const *const RAM64K;
+extern char const *const RTYPE;
+extern char const *const SLOTEXP;
+extern char const *const SOFTCARD;
+extern char const *const SOUND_SNATCHER;
+extern char const *const SOUND_SDSNATCH;
+extern char const *const SUNRISE_SCC;
+extern char const *const SUPER_SWANGI;
+extern char const *const SUPERLODERUNNER;
+extern char const *const SYNTHESIZER;
+extern char const *const UCN01;
+
+} // namespace bus::msx::cart::slotoptions
+
+#endif // MAME_BUS_MSX_CART_SLOTOPTIONS_H
diff --git a/src/devices/bus/msx/cart/softcard.cpp b/src/devices/bus/msx/cart/softcard.cpp
new file mode 100644
index 00000000000..5a42f004ead
--- /dev/null
+++ b/src/devices/bus/msx/cart/softcard.cpp
@@ -0,0 +1,92 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+/***********************************************************************************
+
+Emulation for the Electric Software Astron SoftCard Adaptor cartridge.
+
+This cartridge allows SoftCards to be used on an MSX system.
+
+***********************************************************************************/
+
+#include "emu.h"
+#include "softcard.h"
+#include "bus/msx/softcard/softcard.h"
+#include "softlist_dev.h"
+
+
+DEFINE_DEVICE_TYPE(MSX_CART_SOFTCARD, msx_cart_softcard_device, "msx_cart_softcard", "Electric Software Astron SoftCard Adaptor")
+
+
+msx_cart_softcard_device::msx_cart_softcard_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MSX_CART_SOFTCARD, tag, owner, clock)
+ , device_cartrom_image_interface(mconfig, *this)
+ , device_single_card_slot_interface<softcard_interface>(mconfig, *this)
+ , msx_cart_interface(mconfig, *this)
+{
+}
+
+void msx_cart_softcard_device::device_resolve_objects()
+{
+ m_softcard = get_card_device();
+ if (m_softcard)
+ {
+ m_softcard->set_views(page(0), page(1), page(2), page(3));
+ }
+}
+
+void msx_cart_softcard_device::device_add_mconfig(machine_config &config)
+{
+ softcard(*this);
+ SOFTWARE_LIST(config, "softcard_list").set_original("msx_softcard");
+}
+
+std::pair<std::error_condition, std::string> msx_cart_softcard_device::call_load()
+{
+ if (m_softcard)
+ {
+ if (loaded_through_softlist())
+ {
+ u32 const length = get_software_region_length("rom");
+ // Only 32KB images are supported
+ if (length != 0x8000)
+ return std::pair(image_error::BADSOFTWARE, "Invalid file size for a softcard (must be 32K)");
+ }
+ else
+ {
+ u32 const length = this->length();
+ // Only 32KB images are supported
+ if (length != 0x8000)
+ return std::pair(image_error::BADSOFTWARE, "Invalid file size for a softcard (must be 32K)");
+
+ memory_region *const romregion = machine().memory().region_alloc(subtag("rom"), length, 1, ENDIANNESS_LITTLE);
+ if (fread(romregion->base(), length) != length)
+ return std::make_pair(image_error::UNSPECIFIED, "Unable to fully read file");
+ }
+
+ std::string message;
+ std::error_condition result = m_softcard->initialize_cartridge(message);
+ return std::make_pair(result, message);
+ }
+ return std::make_pair(std::error_condition(), std::string());
+}
+
+std::string msx_cart_softcard_device::get_default_card_software(get_default_card_software_hook &hook) const
+{
+ return software_get_default_slot("nomapper");
+}
+
+
+softcard_interface::softcard_interface(const machine_config &mconfig, device_t &device)
+ : device_interface(device, "softcard")
+ , m_page{nullptr, nullptr, nullptr, nullptr}
+ , m_slot(dynamic_cast<msx_cart_softcard_device *>(device.owner()))
+{
+}
+
+void softcard_interface::set_views(memory_view::memory_view_entry *page0, memory_view::memory_view_entry *page1, memory_view::memory_view_entry *page2, memory_view::memory_view_entry *page3)
+{
+ m_page[0] = page0;
+ m_page[1] = page1;
+ m_page[2] = page2;
+ m_page[3] = page3;
+}
diff --git a/src/devices/bus/msx/cart/softcard.h b/src/devices/bus/msx/cart/softcard.h
new file mode 100644
index 00000000000..122d7cec7e1
--- /dev/null
+++ b/src/devices/bus/msx/cart/softcard.h
@@ -0,0 +1,58 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#ifndef MAME_BUS_MSX_CART_SOFTCARD_H
+#define MAME_BUS_MSX_CART_SOFTCARD_H
+
+#pragma once
+
+#include "bus/msx/slot/cartridge.h"
+#include "imagedev/cartrom.h"
+
+
+DECLARE_DEVICE_TYPE(MSX_CART_SOFTCARD, msx_cart_softcard_device)
+
+class softcard_interface;
+
+
+class msx_cart_softcard_device : public device_t
+ , public device_cartrom_image_interface
+ , public device_single_card_slot_interface<softcard_interface>
+ , public msx_cart_interface
+{
+public:
+ msx_cart_softcard_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
+ virtual bool is_reset_on_load() const noexcept override { return true; }
+ virtual const char *image_interface() const noexcept override { return "softcard"; }
+ virtual const char *file_extensions() const noexcept override { return "bin,rom"; }
+
+protected:
+ virtual void device_resolve_objects() override;
+ virtual void device_start() override { }
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
+
+ softcard_interface *m_softcard;
+};
+
+
+class softcard_interface : public device_interface
+{
+public:
+ virtual std::error_condition initialize_cartridge(std::string &message) { return std::error_condition(); }
+ void set_views(memory_view::memory_view_entry *page0, memory_view::memory_view_entry *page1, memory_view::memory_view_entry *page2, memory_view::memory_view_entry *page3);
+
+protected:
+ softcard_interface(const machine_config &mconfig, device_t &device);
+ memory_region *cart_rom_region() { return m_slot ? m_slot->memregion("rom") : nullptr; }
+ memory_view::memory_view_entry *page(int i) { return m_page[i]; }
+
+private:
+ memory_view::memory_view_entry *m_page[4];
+ msx_cart_softcard_device *const m_slot;
+};
+
+
+#endif // MAME_BUS_MSX_CART_SOFTCARD_H
diff --git a/src/devices/bus/msx/cart/super_swangi.cpp b/src/devices/bus/msx/cart/super_swangi.cpp
new file mode 100644
index 00000000000..cd17e6db0d8
--- /dev/null
+++ b/src/devices/bus/msx/cart/super_swangi.cpp
@@ -0,0 +1,59 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#include "emu.h"
+#include "super_swangi.h"
+
+namespace {
+
+class msx_cart_super_swangi_device : public device_t, public msx_cart_interface
+{
+public:
+ msx_cart_super_swangi_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MSX_CART_SUPER_SWANGI, tag, owner, clock)
+ , msx_cart_interface(mconfig, *this)
+ , m_rombank(*this, "rombank")
+ { }
+
+ virtual std::error_condition initialize_cartridge(std::string &message) override;
+
+protected:
+ // device_t implementation
+ virtual void device_start() override { }
+
+private:
+ void bank_w(u8 data);
+
+ memory_bank_creator m_rombank;
+};
+
+std::error_condition msx_cart_super_swangi_device::initialize_cartridge(std::string &message)
+{
+ if (!cart_rom_region())
+ {
+ message = "msx_cart_super_swangi_device: Required region 'rom' was not found.";
+ return image_error::INTERNAL;
+ }
+
+ if (cart_rom_region()->bytes() < 0x10000)
+ {
+ message = "msx_cart_super_swangi_device: Region 'rom' has unsupported size.";
+ return image_error::INVALIDLENGTH;
+ }
+
+ m_rombank->configure_entries(0, 4, cart_rom_region()->base(), 0x4000);
+
+ page(1)->install_rom(0x4000, 0x7fff, cart_rom_region()->base());
+ page(2)->install_read_bank(0x8000, 0xbfff, m_rombank);
+ page(2)->install_write_handler(0x8000, 0x8000, emu::rw_delegate(*this, FUNC(msx_cart_super_swangi_device::bank_w)));
+
+ return std::error_condition();
+}
+
+void msx_cart_super_swangi_device::bank_w(u8 data)
+{
+ m_rombank->set_entry((data >> 1) & 0x03);
+}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_SUPER_SWANGI, msx_cart_interface, msx_cart_super_swangi_device, "msx_cart_super_swangi", "MSX Cartridge - Super Swangi")
diff --git a/src/devices/bus/msx/cart/super_swangi.h b/src/devices/bus/msx/cart/super_swangi.h
new file mode 100644
index 00000000000..e43c0953ee5
--- /dev/null
+++ b/src/devices/bus/msx/cart/super_swangi.h
@@ -0,0 +1,13 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#ifndef MAME_BUS_MSX_CART_SUPER_SWANGI_H
+#define MAME_BUS_MSX_CART_SUPER_SWANGI_H
+
+#pragma once
+
+#include "bus/msx/slot/cartridge.h"
+
+
+DECLARE_DEVICE_TYPE(MSX_CART_SUPER_SWANGI, msx_cart_interface)
+
+#endif // MAME_BUS_MSX_CART_SUPER_SWANGI_H
diff --git a/src/devices/bus/msx/cart/superloderunner.cpp b/src/devices/bus/msx/cart/superloderunner.cpp
new file mode 100644
index 00000000000..4a4813cf9bd
--- /dev/null
+++ b/src/devices/bus/msx/cart/superloderunner.cpp
@@ -0,0 +1,63 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#include "emu.h"
+#include "superloderunner.h"
+
+namespace {
+
+class msx_cart_superloderunner_device : public device_t, public msx_cart_interface
+{
+public:
+ msx_cart_superloderunner_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MSX_CART_SUPERLODERUNNER, tag, owner, clock)
+ , msx_cart_interface(mconfig, *this)
+ , m_rombank(*this, "rombank")
+ { }
+
+ virtual std::error_condition initialize_cartridge(std::string &message) override;
+
+protected:
+ // device_t implementation
+ virtual void device_start() override;
+
+private:
+ void bank_w(u8 data);
+
+ memory_bank_creator m_rombank;
+};
+
+void msx_cart_superloderunner_device::device_start()
+{
+ // Install evil system wide memory write handler
+ memory_space().install_write_handler(0x0000, 0x0000, emu::rw_delegate(*this, FUNC(msx_cart_superloderunner_device::bank_w)));
+}
+
+std::error_condition msx_cart_superloderunner_device::initialize_cartridge(std::string &message)
+{
+ if (!cart_rom_region())
+ {
+ message = "msx_cart_superloderunner_device: Required region 'rom' was not found.";
+ return image_error::INTERNAL;
+ }
+
+ if (cart_rom_region()->bytes() != 0x20000)
+ {
+ message = "msx_cart_superloderunner_device: Region 'rom' has unsupported size.";
+ return image_error::INVALIDLENGTH;
+ }
+
+ m_rombank->configure_entries(0, 8, cart_rom_region()->base(), 0x4000);
+
+ page(2)->install_read_bank(0x8000, 0xbfff, m_rombank);
+
+ return std::error_condition();
+}
+
+void msx_cart_superloderunner_device::bank_w(u8 data)
+{
+ m_rombank->set_entry(data & 0x07);
+}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_SUPERLODERUNNER, msx_cart_interface, msx_cart_superloderunner_device, "msx_cart_superloderunner", "MSX Cartridge - Super Lode Runner")
diff --git a/src/devices/bus/msx/cart/superloderunner.h b/src/devices/bus/msx/cart/superloderunner.h
new file mode 100644
index 00000000000..9457d43e695
--- /dev/null
+++ b/src/devices/bus/msx/cart/superloderunner.h
@@ -0,0 +1,13 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#ifndef MAME_BUS_MSX_CART_SUPERLODERUNNER_H
+#define MAME_BUS_MSX_CART_SUPERLODERUNNER_H
+
+#pragma once
+
+#include "bus/msx/slot/cartridge.h"
+
+
+DECLARE_DEVICE_TYPE(MSX_CART_SUPERLODERUNNER, msx_cart_interface)
+
+#endif // MAME_BUS_MSX_CART_SUPERLODERUNNER_H
diff --git a/src/devices/bus/msx/cart/yamaha_ucn01.cpp b/src/devices/bus/msx/cart/yamaha_ucn01.cpp
new file mode 100644
index 00000000000..ebf9d87bf9b
--- /dev/null
+++ b/src/devices/bus/msx/cart/yamaha_ucn01.cpp
@@ -0,0 +1,65 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#include "emu.h"
+#include "yamaha_ucn01.h"
+#include "bus/msx/module/module.h"
+
+/*
+Emulation of Yamaha UCN-01.
+
+Converts a regular MSX cartridge slot into a Yamaha module slot.
+
+The extra pins are not connected so modules that make use of the
+video out or sound out pins would not work. This limitation is
+currently not emulated.
+
+*/
+
+namespace {
+
+class msx_cart_ucn01_device : public device_t, public msx_cart_interface
+{
+public:
+ msx_cart_ucn01_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MSX_CART_UCN01, tag, owner, clock)
+ , msx_cart_interface(mconfig, *this)
+ , m_module(*this, "module")
+ { }
+
+protected:
+ virtual void device_start() override { }
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_resolve_objects() override;
+ virtual void device_config_complete() override;
+
+private:
+ required_device<msx_slot_yamaha_expansion_device> m_module;
+};
+
+void msx_cart_ucn01_device::device_add_mconfig(machine_config &mconfig)
+{
+ MSX_SLOT_YAMAHA_EXPANSION(mconfig, m_module, DERIVED_CLOCK(1, 1));
+ m_module->option_reset();
+ msx_yamaha_60pin(*m_module, false);
+ m_module->set_default_option(nullptr);
+ m_module->set_fixed(false);
+ m_module->irq_handler().set(*this, FUNC(msx_cart_ucn01_device::irq_out));
+}
+
+void msx_cart_ucn01_device::device_config_complete()
+{
+ if (parent_slot())
+ {
+ auto target = m_module.finder_target();
+ parent_slot()->configure_subslot(*target.first.subdevice<msx_slot_yamaha_expansion_device>(target.second));
+ }
+}
+
+void msx_cart_ucn01_device::device_resolve_objects()
+{
+ m_module->install(page(0), page(1), page(2), page(3));
+}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_UCN01, msx_cart_interface, msx_cart_ucn01_device, "msx_cart_ucn01", "Yamaha UCN-01")
diff --git a/src/devices/bus/msx/cart/yamaha_ucn01.h b/src/devices/bus/msx/cart/yamaha_ucn01.h
new file mode 100644
index 00000000000..537e7b2c56a
--- /dev/null
+++ b/src/devices/bus/msx/cart/yamaha_ucn01.h
@@ -0,0 +1,13 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#ifndef MAME_BUS_MSX_CART_YAMAHA_UCN01_H
+#define MAME_BUS_MSX_CART_YAMAHA_UCN01_H
+
+#pragma once
+
+#include "bus/msx/slot/cartridge.h"
+
+
+DECLARE_DEVICE_TYPE(MSX_CART_UCN01, msx_cart_interface)
+
+#endif // MAME_BUS_MSX_CART_YAMAHA_UCN01_H
diff --git a/src/devices/bus/msx/ctrl/ctrl.cpp b/src/devices/bus/msx/ctrl/ctrl.cpp
new file mode 100644
index 00000000000..f26c175c449
--- /dev/null
+++ b/src/devices/bus/msx/ctrl/ctrl.cpp
@@ -0,0 +1,61 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+/**********************************************************************
+
+ MSX General Purpose port emulation
+
+**********************************************************************/
+
+#include "emu.h"
+#include "ctrl.h"
+
+#include "hypershot.h"
+#include "joystick.h"
+#include "libbler.h"
+#include "magickey.h"
+#include "mouse.h"
+#include "sgadapt.h"
+#include "towns6b.h"
+#include "townspad.h"
+#include "vaus.h"
+#include "xe1ap.h"
+
+
+DEFINE_DEVICE_TYPE(MSX_GENERAL_PURPOSE_PORT, msx_general_purpose_port_device, "msx_general_purpose_port", "MSX General Purpose port")
+
+
+device_msx_general_purpose_port_interface::device_msx_general_purpose_port_interface(const machine_config &mconfig, device_t &device)
+ : device_interface(device, "msxctrl")
+ , m_port(dynamic_cast<msx_general_purpose_port_device *>(device.owner()))
+{
+}
+
+
+msx_general_purpose_port_device::msx_general_purpose_port_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MSX_GENERAL_PURPOSE_PORT, tag, owner, clock)
+ , device_single_card_slot_interface<device_msx_general_purpose_port_interface>(mconfig, *this)
+ , m_device(nullptr)
+{
+}
+
+
+void msx_general_purpose_port_device::device_start()
+{
+ m_device = get_card_device();
+}
+
+
+void msx_general_purpose_port_devices(device_slot_interface &device)
+{
+ device.option_add("hypershot", MSX_HYPERSHOT);
+ device.option_add("joystick", MSX_JOYSTICK);
+ device.option_add("libbler", MSX_LIBBLERPAD);
+ device.option_add("magickey", MSX_MAGICKEY);
+ device.option_add("martypad", MSX_MARTYPAD);
+ device.option_add("mouse", MSX_MOUSE);
+ device.option_add("sega", MSX_SEGACTRL);
+ device.option_add("towns6b", MSX_TOWNS6B);
+ device.option_add("townspad", MSX_TOWNSPAD);
+ device.option_add("vaus", MSX_VAUS);
+ device.option_add("xe1ap", MSX_XE1AP);
+}
diff --git a/src/devices/bus/msx/ctrl/ctrl.h b/src/devices/bus/msx/ctrl/ctrl.h
new file mode 100644
index 00000000000..bc827c31e7e
--- /dev/null
+++ b/src/devices/bus/msx/ctrl/ctrl.h
@@ -0,0 +1,85 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+/**********************************************************************
+
+ MSX General Purpose port emulation
+
+The MSX General Purpose port uses a DE-9 connector; the pin assignment
+is similar to but slightly different from the Atari VCS controller port.
+
+**********************************************************************/
+
+#ifndef MAME_BUS_MSX_CTRL_CTRL_H
+#define MAME_BUS_MSX_CTRL_CTRL_H
+
+#pragma once
+
+
+class msx_general_purpose_port_device;
+
+
+class device_msx_general_purpose_port_interface : public device_interface
+{
+public:
+ virtual ~device_msx_general_purpose_port_interface() { }
+
+ virtual u8 read() { return 0xff; }
+ virtual void pin_6_w(int state) { }
+ virtual void pin_7_w(int state) { }
+ virtual void pin_8_w(int state) { }
+
+protected:
+ device_msx_general_purpose_port_interface(const machine_config &mconfig, device_t &device);
+
+ msx_general_purpose_port_device *m_port;
+};
+
+
+class msx_general_purpose_port_device : public device_t
+ , public device_single_card_slot_interface<device_msx_general_purpose_port_interface>
+{
+public:
+ template <typename T>
+ msx_general_purpose_port_device(const machine_config &mconfig, const char *tag, device_t *owner, T &&opts, char const* dflt)
+ : msx_general_purpose_port_device(mconfig, tag, owner)
+ {
+ option_reset();
+ opts(*this);
+ set_default_option(dflt);
+ set_fixed(false);
+ }
+ msx_general_purpose_port_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);
+
+ // computer interface
+ //
+ // Data returned by the read method:
+ // bit 0 - pin 1 - Up (I)
+ // bit 1 - pin 2 - Down (I)
+ // bit 2 - pin 3 - Left (I)
+ // bit 3 - pin 4 - Right (I)
+ // pin 5 - +5V
+ // bit 4 - pin 6 - Button 1 (I/O)
+ // bit 5 - pin 7 - Button 2 (I/O)
+ // bit 6 - pin 8 - Strobe (O for MSX, I/O for FM Towns)
+ // pin 9 - GND
+ //
+ u8 read() { return exists() ? m_device->read() : 0xff; }
+
+ void pin_6_w(int state) { if (exists()) m_device->pin_6_w(state); }
+ void pin_7_w(int state) { if (exists()) m_device->pin_7_w(state); }
+ void pin_8_w(int state) { if (exists()) m_device->pin_8_w(state); }
+
+ bool exists() const { return m_device != nullptr; }
+
+protected:
+ virtual void device_start() override;
+
+ device_msx_general_purpose_port_interface *m_device;
+};
+
+
+DECLARE_DEVICE_TYPE(MSX_GENERAL_PURPOSE_PORT, msx_general_purpose_port_device)
+
+void msx_general_purpose_port_devices(device_slot_interface &device);
+
+#endif // MAME_BUS_MSX_CTRL_CTRL_H
diff --git a/src/devices/bus/msx/ctrl/hypershot.cpp b/src/devices/bus/msx/ctrl/hypershot.cpp
new file mode 100644
index 00000000000..f70418a7f99
--- /dev/null
+++ b/src/devices/bus/msx/ctrl/hypershot.cpp
@@ -0,0 +1,85 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/**********************************************************************
+
+ Konami JE 502/JE 503 Hyper Shot emulation
+
+ Very simple controller with two buttons. RUN is connected to
+ both right and down, and JUMP is connected to TL. Symmetrical
+ case allows use with either button to the left. Pin 8 is used
+ as the common pin so it will work with Sega and Atari consoles.
+ It will work with MSX computers provided pin 8 is pulled low.
+
+ Known versions:
+ * JE 502 original Japanese version, metal case
+ * JE 503 cost-reduced Japanese version, plastic case
+ * JE 503-X02 cost-reduced export version, plastic case
+
+**********************************************************************/
+
+#include "emu.h"
+#include "hypershot.h"
+
+
+namespace {
+
+INPUT_PORTS_START(hypershot)
+ PORT_START("BUTTONS")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_BUTTON2) PORT_NAME("%p Run")
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_NAME("%p Jump")
+INPUT_PORTS_END
+
+
+class hypershot_device : public device_t, public device_msx_general_purpose_port_interface
+{
+public:
+ hypershot_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+ virtual u8 read() override;
+ virtual void pin_8_w(int state) override;
+
+protected:
+ virtual void device_start() override;
+ virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(hypershot); }
+
+private:
+ required_ioport m_buttons;
+
+ u8 m_pin8_in;
+};
+
+hypershot_device::hypershot_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MSX_HYPERSHOT, tag, owner, clock)
+ , device_msx_general_purpose_port_interface(mconfig, *this)
+ , m_buttons(*this, "BUTTONS")
+ , m_pin8_in(1)
+{
+}
+
+u8 hypershot_device::read()
+{
+ if (m_pin8_in)
+ {
+ return 0xff;
+ }
+ else
+ {
+ u8 const inputs = m_buttons->read();
+ return 0xe5 | (BIT(inputs, 1) << 4) | (BIT(inputs, 0) ? 0x0a : 0x00);
+ }
+}
+
+void hypershot_device::pin_8_w(int state)
+{
+ m_pin8_in = state ? 1 : 0;
+}
+
+void hypershot_device::device_start()
+{
+ save_item(NAME(m_pin8_in));
+}
+
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_HYPERSHOT, device_msx_general_purpose_port_interface, hypershot_device, "msx_hypershot", "Konami Hyper Shot (JE 502/JE 503, MSX)")
diff --git a/src/devices/bus/msx/ctrl/hypershot.h b/src/devices/bus/msx/ctrl/hypershot.h
new file mode 100644
index 00000000000..dad0ef8891c
--- /dev/null
+++ b/src/devices/bus/msx/ctrl/hypershot.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/**********************************************************************
+
+ Konami JE 502/JE 503 Hyper Shot emulation
+
+**********************************************************************/
+
+#ifndef MAME_BUS_MSX_CTRL_HYPERSHOT_H
+#define MAME_BUS_MSX_CTRL_HYPERSHOT_H
+
+#pragma once
+
+#include "ctrl.h"
+
+
+DECLARE_DEVICE_TYPE(MSX_HYPERSHOT, device_msx_general_purpose_port_interface)
+
+#endif // MAME_BUS_MSX_CTRL_HYPERSHOT_H
diff --git a/src/devices/bus/msx/ctrl/joystick.cpp b/src/devices/bus/msx/ctrl/joystick.cpp
new file mode 100644
index 00000000000..e5d792c8590
--- /dev/null
+++ b/src/devices/bus/msx/ctrl/joystick.cpp
@@ -0,0 +1,53 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+/**********************************************************************
+
+ MSX Digital Joystick emulation
+
+**********************************************************************/
+
+#include "emu.h"
+#include "joystick.h"
+
+
+namespace {
+
+INPUT_PORTS_START(msx_joystick)
+ PORT_START("JOY")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP) PORT_8WAY
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN) PORT_8WAY
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT) PORT_8WAY
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT) PORT_8WAY
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_BUTTON1)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_BUTTON2)
+ PORT_BIT(0xc0, IP_ACTIVE_LOW, IPT_UNUSED)
+INPUT_PORTS_END
+
+
+class msx_joystick_device : public device_t, public device_msx_general_purpose_port_interface
+{
+public:
+ msx_joystick_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual u8 read() override { return m_joy->read(); }
+
+protected:
+ virtual void device_start() override { }
+ virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(msx_joystick); }
+
+private:
+ required_ioport m_joy;
+};
+
+
+msx_joystick_device::msx_joystick_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MSX_JOYSTICK, tag, owner, clock)
+ , device_msx_general_purpose_port_interface(mconfig, *this)
+ , m_joy(*this, "JOY")
+{
+}
+
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_JOYSTICK, device_msx_general_purpose_port_interface, msx_joystick_device, "msx_joystick", "MSX Digital Joystick")
diff --git a/src/devices/bus/msx/ctrl/joystick.h b/src/devices/bus/msx/ctrl/joystick.h
new file mode 100644
index 00000000000..e0c533fd7e8
--- /dev/null
+++ b/src/devices/bus/msx/ctrl/joystick.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+/**********************************************************************
+
+ MSX Digital Joystick emulation
+
+**********************************************************************/
+
+#ifndef MAME_BUS_MSX_CTRL_JOYSTICK_H
+#define MAME_BUS_MSX_CTRL_JOYSTICK_H
+
+#pragma once
+
+#include "ctrl.h"
+
+
+DECLARE_DEVICE_TYPE(MSX_JOYSTICK, device_msx_general_purpose_port_interface)
+
+#endif // MAME_BUS_MSX_CTRL_JOYSTICK_H
diff --git a/src/devices/bus/msx/ctrl/libbler.cpp b/src/devices/bus/msx/ctrl/libbler.cpp
new file mode 100644
index 00000000000..3e51b5024ca
--- /dev/null
+++ b/src/devices/bus/msx/ctrl/libbler.cpp
@@ -0,0 +1,79 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/**********************************************************************
+
+ Micomsoft Libble Rabble Joypad (XPD-1LR) emulation
+
+ Bundled with the following games:
+ - Crazy Climber Video Game Anthology Vol.5 (Sharp X68000)
+ - Libble Rabble (Sharp X68000)
+ - Libble Rabble (Fujitsu FM Towns)
+
+**********************************************************************/
+
+#include "emu.h"
+#include "libbler.h"
+
+
+namespace {
+
+INPUT_PORTS_START(xpd_1lr)
+ PORT_START("PAD1")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_JOYSTICKLEFT_UP) PORT_8WAY
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_JOYSTICKLEFT_DOWN) PORT_8WAY
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_JOYSTICKLEFT_LEFT) PORT_8WAY
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_JOYSTICKLEFT_RIGHT) PORT_8WAY
+ PORT_BIT(0xf0, IP_ACTIVE_HIGH, IPT_UNUSED)
+
+ PORT_START("PAD2")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_JOYSTICKRIGHT_UP) PORT_8WAY
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_JOYSTICKRIGHT_DOWN) PORT_8WAY
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_JOYSTICKRIGHT_LEFT) PORT_8WAY
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_JOYSTICKRIGHT_RIGHT) PORT_8WAY
+ PORT_BIT(0xf0, IP_ACTIVE_HIGH, IPT_UNUSED)
+
+ PORT_START("BUTTONS")
+ PORT_BIT(0x0f, IP_ACTIVE_HIGH, IPT_UNUSED)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_NAME("%p A") // used to add credits
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_BUTTON2) PORT_NAME("%p B") // used to pause
+ PORT_BIT(0xc0, IP_ACTIVE_LOW, IPT_UNUSED)
+INPUT_PORTS_END
+
+
+class xpd_1lr_device : public device_t, public device_msx_general_purpose_port_interface
+{
+public:
+ xpd_1lr_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual u8 read() override { return m_pad[m_pin8]->read() | m_buttons->read(); }
+ virtual void pin_8_w(int state) override { m_pin8 = state ? 1 : 0; }
+
+protected:
+ virtual void device_start() override;
+ virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(xpd_1lr); }
+
+private:
+ required_ioport_array<2> m_pad;
+ required_ioport m_buttons;
+ u8 m_pin8;
+};
+
+
+xpd_1lr_device::xpd_1lr_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MSX_LIBBLERPAD, tag, owner, clock)
+ , device_msx_general_purpose_port_interface(mconfig, *this)
+ , m_pad(*this, "PAD%u", 1U)
+ , m_buttons(*this, "BUTTONS")
+ , m_pin8(0)
+{
+}
+
+void xpd_1lr_device::device_start()
+{
+ save_item(NAME(m_pin8));
+}
+
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_LIBBLERPAD, device_msx_general_purpose_port_interface, xpd_1lr_device, "msx_libblerpad", "Micomsoft Libble Rabble Joypad (XPD-1LR)")
diff --git a/src/devices/bus/msx/ctrl/libbler.h b/src/devices/bus/msx/ctrl/libbler.h
new file mode 100644
index 00000000000..b1d89a42abb
--- /dev/null
+++ b/src/devices/bus/msx/ctrl/libbler.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/**********************************************************************
+
+ Micomsoft Libble Rabble Joypad (XPD-1LR) emulation
+
+**********************************************************************/
+
+#ifndef MAME_BUS_MSX_CTRL_LIBBLER_H
+#define MAME_BUS_MSX_CTRL_LIBBLER_H
+
+#pragma once
+
+#include "ctrl.h"
+
+
+DECLARE_DEVICE_TYPE(MSX_LIBBLERPAD, device_msx_general_purpose_port_interface)
+
+#endif // MAME_BUS_MSX_CTRL_LIBBLER_H
diff --git a/src/devices/bus/msx/ctrl/magickey.cpp b/src/devices/bus/msx/ctrl/magickey.cpp
new file mode 100644
index 00000000000..f515b2f39b7
--- /dev/null
+++ b/src/devices/bus/msx/ctrl/magickey.cpp
@@ -0,0 +1,53 @@
+// license:BSD-3-Clause
+// copyright-holders:hap
+/**********************************************************************
+
+Sony Magic Key emulation
+
+It's a dongle that enables a cheat menu on some games published by Sony
+when inserted into port B. It was a lottery prize from a Japanese MSX
+magazine, not sold separately.
+
+The dongle ties pin 1/2 (up/down) to pin 8 (strobe).
+
+Note that this cheat menu can also be accessed with an FM Towns pad.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "magickey.h"
+
+
+namespace {
+
+class msx_magickey_device : public device_t, public device_msx_general_purpose_port_interface
+{
+public:
+ msx_magickey_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual u8 read() override { return m_pin8_state ? 0xff : 0xfc; }
+ virtual void pin_8_w(int state) override { m_pin8_state = state; }
+
+protected:
+ virtual void device_start() override;
+
+private:
+ u8 m_pin8_state = 0;
+};
+
+
+msx_magickey_device::msx_magickey_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MSX_MAGICKEY, tag, owner, clock)
+ , device_msx_general_purpose_port_interface(mconfig, *this)
+{
+}
+
+void msx_magickey_device::device_start()
+{
+ save_item(NAME(m_pin8_state));
+}
+
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_MAGICKEY, device_msx_general_purpose_port_interface, msx_magickey_device, "msx_magickey", "Sony Magic Key Dongle")
diff --git a/src/devices/bus/msx/ctrl/magickey.h b/src/devices/bus/msx/ctrl/magickey.h
new file mode 100644
index 00000000000..031a554ce7c
--- /dev/null
+++ b/src/devices/bus/msx/ctrl/magickey.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:hap
+/**********************************************************************
+
+ Sony Magic Key emulation
+
+**********************************************************************/
+
+#ifndef MAME_BUS_MSX_CTRL_MAGICKEY_H
+#define MAME_BUS_MSX_CTRL_MAGICKEY_H
+
+#pragma once
+
+#include "ctrl.h"
+
+
+DECLARE_DEVICE_TYPE(MSX_MAGICKEY, device_msx_general_purpose_port_interface)
+
+#endif // MAME_BUS_MSX_CTRL_MAGICKEY_H
diff --git a/src/devices/bus/msx/ctrl/mouse.cpp b/src/devices/bus/msx/ctrl/mouse.cpp
new file mode 100644
index 00000000000..f8182903d71
--- /dev/null
+++ b/src/devices/bus/msx/ctrl/mouse.cpp
@@ -0,0 +1,120 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+/**********************************************************************
+
+ MSX Mouse emulation
+
+**********************************************************************/
+
+#include "emu.h"
+#include "mouse.h"
+
+
+namespace {
+
+INPUT_PORTS_START(msx_mouse)
+ PORT_START("BUTTONS")
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_BUTTON1)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_BUTTON2)
+ PORT_BIT(0xcf, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("MOUSE_X")
+ PORT_BIT(0xffff, 0, IPT_MOUSE_X) PORT_SENSITIVITY(50)
+
+ PORT_START("MOUSE_Y")
+ PORT_BIT(0xffff, 0, IPT_MOUSE_Y) PORT_SENSITIVITY(50)
+INPUT_PORTS_END
+
+
+class msx_mouse_device : public device_t, public device_msx_general_purpose_port_interface
+{
+public:
+ msx_mouse_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual u8 read() override;
+ virtual void pin_8_w(int state) override;
+
+protected:
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(msx_mouse); }
+
+private:
+ required_ioport m_buttons;
+ required_ioport m_port_mouse_x;
+ required_ioport m_port_mouse_y;
+ u16 m_data;
+ u8 m_stat;
+ u8 m_old_pin8;
+ s16 m_mouse_x;
+ s16 m_mouse_y;
+ attotime m_last_pin8_change;
+ attotime m_timeout;
+};
+
+msx_mouse_device::msx_mouse_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MSX_MOUSE, tag, owner, clock)
+ , device_msx_general_purpose_port_interface(mconfig, *this)
+ , m_buttons(*this, "BUTTONS")
+ , m_port_mouse_x(*this, "MOUSE_X")
+ , m_port_mouse_y(*this, "MOUSE_Y")
+{
+}
+
+void msx_mouse_device::device_start()
+{
+ save_item(NAME(m_data));
+ save_item(NAME(m_stat));
+ save_item(NAME(m_old_pin8));
+ save_item(NAME(m_last_pin8_change));
+ save_item(NAME(m_mouse_x));
+ save_item(NAME(m_mouse_y));
+ m_timeout = attotime::from_msec(3);
+}
+
+void msx_mouse_device::device_reset()
+{
+ m_data = 0;
+ m_stat = 3;
+ m_old_pin8 = 0;
+ m_last_pin8_change = attotime::zero;
+ m_mouse_x = 0;
+ m_mouse_y = 0;
+}
+
+u8 msx_mouse_device::read()
+{
+ return (m_buttons->read() & 0xf0) | ((m_data >> (4 * (3 - m_stat))) & 0x0f);
+}
+
+void msx_mouse_device::pin_8_w(int state)
+{
+ if (m_old_pin8 != state)
+ {
+ attotime now = machine().scheduler().time();
+ if (now - m_last_pin8_change > m_timeout)
+ {
+ // force restart
+ m_stat = 3;
+ }
+ m_last_pin8_change = now;
+ m_stat = (m_stat + 1) & 0x03;
+
+ if (m_stat == 0)
+ {
+ s16 mouse_x = m_port_mouse_x->read();
+ s16 mouse_y = m_port_mouse_y->read();
+
+ m_data = (u8(m_mouse_x - mouse_x) << 8) | u8(m_mouse_y - mouse_y);
+ m_mouse_x = mouse_x;
+ m_mouse_y = mouse_y;
+ }
+ }
+ m_old_pin8 = state;
+}
+
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_MOUSE, device_msx_general_purpose_port_interface, msx_mouse_device, "msx_mouse", "MSX Mouse")
diff --git a/src/devices/bus/msx/ctrl/mouse.h b/src/devices/bus/msx/ctrl/mouse.h
new file mode 100644
index 00000000000..10b6fdedf3c
--- /dev/null
+++ b/src/devices/bus/msx/ctrl/mouse.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+/**********************************************************************
+
+ MSX Mouse emulation
+
+**********************************************************************/
+
+#ifndef MAME_BUS_MSX_CTRL_MOUSE_H
+#define MAME_BUS_MSX_CTRL_MOUSE_H
+
+#pragma once
+
+#include "ctrl.h"
+
+
+DECLARE_DEVICE_TYPE(MSX_MOUSE, device_msx_general_purpose_port_interface)
+
+#endif // MAME_BUS_MSX_CTRL_MOUSE_H
diff --git a/src/devices/bus/msx/ctrl/sgadapt.cpp b/src/devices/bus/msx/ctrl/sgadapt.cpp
new file mode 100644
index 00000000000..76101f4a3aa
--- /dev/null
+++ b/src/devices/bus/msx/ctrl/sgadapt.cpp
@@ -0,0 +1,131 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/**********************************************************************
+
+ Sega controller adapter emulation
+
+ Simple wired adapter:
+
+ PC Pin Sega pin
+ Up 1 1 Up
+ Down 2 2 Down
+ Left 3 3 Left
+ Right 4 4 Right
+ +5V 5 5 +5V
+ Trigger 1 6 6 TL
+ Trigger 2 7 9 TR
+ Strobe 8 7 TH
+ GND 9 8 GND
+
+ An adapter with this wiring was included with the game Chelnov
+ for Sharp X68000, to be used with a 3-button Sega Mega Drive
+ Control Pad. The same adapters were supported by Super Street
+ Figher II for Sharp X68000 for use with 6-button Sega Mega
+ Drive controllers.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "sgadapt.h"
+
+#include "bus/sms_ctrl/controllers.h"
+#include "bus/sms_ctrl/smsctrl.h"
+
+//#define VERBOSE 1
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+
+namespace {
+
+class sega_adapter_device : public device_t, public device_msx_general_purpose_port_interface
+{
+public:
+ sega_adapter_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual u8 read() override;
+ virtual void pin_6_w(int state) override;
+ virtual void pin_7_w(int state) override;
+ virtual void pin_8_w(int state) override;
+
+protected:
+ virtual void device_start() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+
+private:
+ required_device<sms_control_port_device> m_port;
+
+ u8 m_out;
+ u8 m_th_in;
+};
+
+
+sega_adapter_device::sega_adapter_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MSX_SEGACTRL, tag, owner, clock)
+ , device_msx_general_purpose_port_interface(mconfig, *this)
+ , m_port(*this, "ctrl")
+ , m_out(0x7f)
+ , m_th_in(0x40)
+{
+}
+
+u8 sega_adapter_device::read()
+{
+ return (m_port->in_r() & 0x3f) | m_th_in;
+}
+
+void sega_adapter_device::pin_6_w(int state)
+{
+ if (u8(state ? 1 : 0) != BIT(m_out, 4))
+ {
+ if (state)
+ m_out |= 0x10;
+ else
+ m_out &= ~0x10;
+ LOG("TL %u -> %u (out 0x%02X)\n", BIT(~m_out, 4), BIT(m_out, 4), m_out);
+ m_port->out_w(m_out, m_out ^ 0x7f);
+ }
+}
+
+void sega_adapter_device::pin_7_w(int state)
+{
+ if (u8(state ? 1 : 0) != BIT(m_out, 5))
+ {
+ if (state)
+ m_out |= 0x20;
+ else
+ m_out &= ~0x20;
+ LOG("TR %u -> %u (out 0x%02X)\n", BIT(~m_out, 5), BIT(m_out, 5), m_out);
+ m_port->out_w(m_out, m_out ^ 0x7f);
+ }
+}
+
+void sega_adapter_device::pin_8_w(int state)
+{
+ if (u8(state ? 1 : 0) != BIT(m_out, 6))
+ {
+ if (state)
+ m_out |= 0x40;
+ else
+ m_out &= ~0x40;
+ LOG("TH %u -> %u (out 0x%02X)\n", BIT(~m_out, 6), BIT(m_out, 6), m_out);
+ m_port->out_w(m_out, m_out ^ 0x7f);
+ }
+}
+
+void sega_adapter_device::device_start()
+{
+ save_item(NAME(m_out));
+ save_item(NAME(m_th_in));
+}
+
+void sega_adapter_device::device_add_mconfig(machine_config &config)
+{
+ SMS_CONTROL_PORT(config, m_port, sms_control_port_devices, SMS_CTRL_OPTION_MD_6BUTTON);
+ m_port->th_handler().set([this] (int state) { m_th_in = state ? 0x40 : 0x00; });
+}
+
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_SEGACTRL, device_msx_general_purpose_port_interface, sega_adapter_device, "msx_segactrl", "X68000 Sega Controller Adapter")
diff --git a/src/devices/bus/msx/ctrl/sgadapt.h b/src/devices/bus/msx/ctrl/sgadapt.h
new file mode 100644
index 00000000000..f0b2ad63ac6
--- /dev/null
+++ b/src/devices/bus/msx/ctrl/sgadapt.h
@@ -0,0 +1,20 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/**********************************************************************
+
+ Sega controller adapter emulation
+
+**********************************************************************/
+
+#ifndef MAME_BUS_MSX_CTRL_SGADAPT_H
+#define MAME_BUS_MSX_CTRL_SGADAPT_H
+
+#pragma once
+
+#include "ctrl.h"
+
+
+DECLARE_DEVICE_TYPE(MSX_SEGACTRL, device_msx_general_purpose_port_interface)
+DECLARE_DEVICE_TYPE(MSX_SEGACTRL, device_msx_general_purpose_port_interface)
+
+#endif // MAME_BUS_MSX_CTRL_SGADAPT_H
diff --git a/src/devices/bus/msx/ctrl/towns6b.cpp b/src/devices/bus/msx/ctrl/towns6b.cpp
new file mode 100644
index 00000000000..08bab6a4ac8
--- /dev/null
+++ b/src/devices/bus/msx/ctrl/towns6b.cpp
@@ -0,0 +1,90 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/**********************************************************************
+
+ FM Towns 6-button Pad emulation
+
+**********************************************************************/
+
+#include "emu.h"
+#include "towns6b.h"
+
+
+namespace {
+
+INPUT_PORTS_START(fm_towns_6b)
+ PORT_START("PAD")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP) PORT_8WAY
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN) PORT_8WAY
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT) PORT_8WAY
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT) PORT_8WAY
+ PORT_BIT(0x30, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_START) PORT_NAME("%p Run")
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_SELECT)
+
+ PORT_START("BUTTONS")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_BUTTON6) PORT_NAME("%p Z")
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_BUTTON5) PORT_NAME("%p Y")
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_BUTTON4) PORT_NAME("%p X")
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_BUTTON3) PORT_NAME("%p C")
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_NAME("%p A")
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_BUTTON2) PORT_NAME("%p B")
+ PORT_BIT(0xc0, IP_ACTIVE_LOW, IPT_UNUSED)
+INPUT_PORTS_END
+
+
+class fm_towns_6b_device : public device_t, public device_msx_general_purpose_port_interface
+{
+public:
+ fm_towns_6b_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual u8 read() override;
+ virtual void pin_8_w(int state) override { m_pin8 = state; }
+
+protected:
+ virtual void device_start() override;
+ virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(fm_towns_6b); }
+
+private:
+ required_ioport m_pad;
+ required_ioport m_buttons;
+ u8 m_pin8;
+};
+
+
+fm_towns_6b_device::fm_towns_6b_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MSX_TOWNS6B, tag, owner, clock)
+ , device_msx_general_purpose_port_interface(mconfig, *this)
+ , m_pad(*this, "PAD")
+ , m_buttons(*this, "BUTTONS")
+ , m_pin8(0)
+{
+}
+
+u8 fm_towns_6b_device::read()
+{
+ const u8 buttons = m_buttons->read();
+ if (m_pin8)
+ {
+ return buttons;
+ }
+ else
+ {
+ u8 pad = m_pad->read();
+ if (!BIT(pad, 6)) // RUN activates RIGHT+LEFT
+ pad &= 0xf3;
+ if (!BIT(pad, 7)) // SELECT activates BACK+FWD
+ pad &= 0xfc;
+ return (buttons & 0xf0) | (pad & 0x0f);
+ }
+}
+
+void fm_towns_6b_device::device_start()
+{
+ save_item(NAME(m_pin8));
+}
+
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_TOWNS6B, device_msx_general_purpose_port_interface, fm_towns_6b_device, "msx_towns6b", "FM Towns 6-button Pad")
diff --git a/src/devices/bus/msx/ctrl/towns6b.h b/src/devices/bus/msx/ctrl/towns6b.h
new file mode 100644
index 00000000000..df738978c4c
--- /dev/null
+++ b/src/devices/bus/msx/ctrl/towns6b.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/**********************************************************************
+
+ FM Towns 6-button Pad emulation
+
+**********************************************************************/
+
+#ifndef MAME_BUS_MSX_CTRL_TOWNS6B_H
+#define MAME_BUS_MSX_CTRL_TOWNS6B_H
+
+#pragma once
+
+#include "ctrl.h"
+
+
+DECLARE_DEVICE_TYPE(MSX_TOWNS6B, device_msx_general_purpose_port_interface)
+
+#endif // MAME_BUS_MSX_CTRL_TOWNS6B_H
diff --git a/src/devices/bus/msx/ctrl/townspad.cpp b/src/devices/bus/msx/ctrl/townspad.cpp
new file mode 100644
index 00000000000..2a77cf94ed9
--- /dev/null
+++ b/src/devices/bus/msx/ctrl/townspad.cpp
@@ -0,0 +1,96 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/**********************************************************************
+
+ FM Towns Pad emulation
+
+**********************************************************************/
+
+#include "emu.h"
+#include "townspad.h"
+
+
+namespace {
+
+INPUT_PORTS_START(fm_towns_pad)
+ PORT_START("PAD")
+ PORT_BIT(0x001, IP_ACTIVE_LOW, IPT_JOYSTICK_UP) PORT_8WAY
+ PORT_BIT(0x002, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN) PORT_8WAY
+ PORT_BIT(0x004, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT) PORT_8WAY
+ PORT_BIT(0x008, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT) PORT_8WAY
+ PORT_BIT(0x010, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_NAME("%p A")
+ PORT_BIT(0x020, IP_ACTIVE_LOW, IPT_BUTTON2) PORT_NAME("%p B")
+ PORT_BIT(0x0c0, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x100, IP_ACTIVE_LOW, IPT_START) PORT_NAME("%p Run")
+ PORT_BIT(0x200, IP_ACTIVE_LOW, IPT_SELECT)
+INPUT_PORTS_END
+
+INPUT_PORTS_START(marty_pad)
+ PORT_INCLUDE(fm_towns_pad)
+
+ PORT_MODIFY("PAD")
+ PORT_BIT(0x040, IP_ACTIVE_LOW, IPT_BUTTON3) PORT_NAME("%p Zoom") // shoulder button
+INPUT_PORTS_END
+
+
+class fm_towns_pad_device : public device_t, public device_msx_general_purpose_port_interface
+{
+public:
+ fm_towns_pad_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual u8 read() override;
+
+protected:
+ fm_towns_pad_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
+ virtual void device_start() override { }
+ virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(fm_towns_pad); }
+
+private:
+ required_ioport m_pad;
+};
+
+
+fm_towns_pad_device::fm_towns_pad_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : fm_towns_pad_device(mconfig, MSX_TOWNSPAD, tag, owner, clock)
+{
+}
+
+fm_towns_pad_device::fm_towns_pad_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, type, tag, owner, clock)
+ , device_msx_general_purpose_port_interface(mconfig, *this)
+ , m_pad(*this, "PAD")
+{
+}
+
+u8 fm_towns_pad_device::read()
+{
+ auto pad = m_pad->read();
+ if (!BIT(pad, 8)) // RUN activates RIGHT+LEFT
+ pad &= ~0x0c;
+ if (!BIT(pad, 9)) // SELECT activates BACK+FWD
+ pad &= ~0x03;
+ return u8(pad & 0xff);
+}
+
+
+class marty_pad_device : public fm_towns_pad_device
+{
+public:
+ marty_pad_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(marty_pad); }
+};
+
+
+marty_pad_device::marty_pad_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : fm_towns_pad_device(mconfig, MSX_MARTYPAD, tag, owner, clock)
+{
+}
+
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_TOWNSPAD, device_msx_general_purpose_port_interface, fm_towns_pad_device, "msx_townspad", "FM Towns 2-button Pad")
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_MARTYPAD, device_msx_general_purpose_port_interface, marty_pad_device, "msx_martypad", "FM Towns Marty Pad")
diff --git a/src/devices/bus/msx/ctrl/townspad.h b/src/devices/bus/msx/ctrl/townspad.h
new file mode 100644
index 00000000000..c6070526be6
--- /dev/null
+++ b/src/devices/bus/msx/ctrl/townspad.h
@@ -0,0 +1,20 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/**********************************************************************
+
+ FM Towns Pad emulation
+
+**********************************************************************/
+
+#ifndef MAME_BUS_MSX_CTRL_TOWNSPAD_H
+#define MAME_BUS_MSX_CTRL_TOWNSPAD_H
+
+#pragma once
+
+#include "ctrl.h"
+
+
+DECLARE_DEVICE_TYPE(MSX_TOWNSPAD, device_msx_general_purpose_port_interface)
+DECLARE_DEVICE_TYPE(MSX_MARTYPAD, device_msx_general_purpose_port_interface)
+
+#endif // MAME_BUS_MSX_CTRL_TOWNSPAD_H
diff --git a/src/devices/bus/msx/ctrl/vaus.cpp b/src/devices/bus/msx/ctrl/vaus.cpp
new file mode 100644
index 00000000000..6d3e1878e96
--- /dev/null
+++ b/src/devices/bus/msx/ctrl/vaus.cpp
@@ -0,0 +1,115 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+/**********************************************************************
+
+ MSX Arkanoid Vaus controller emulation
+
+**********************************************************************/
+
+#include "emu.h"
+#include "vaus.h"
+
+
+namespace {
+
+INPUT_PORTS_START(msx_vaus)
+ PORT_START("BUTTON")
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_BUTTON1)
+
+ PORT_START("POT")
+ PORT_BIT(0x1ff, 0x100, IPT_PADDLE) PORT_MINMAX(110, 380) PORT_SENSITIVITY(30) PORT_KEYDELTA(20)
+INPUT_PORTS_END
+
+
+class msx_vaus_device : public device_t, public device_msx_general_purpose_port_interface
+{
+public:
+ msx_vaus_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual u8 read() override;
+ virtual void pin_6_w(int state) override;
+ virtual void pin_8_w(int state) override;
+
+protected:
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(msx_vaus); }
+ TIMER_CALLBACK_MEMBER(copy_counter);
+
+private:
+ required_ioport m_button;
+ required_ioport m_pot;
+ emu_timer *m_timer;
+ u8 m_old_pin6;
+ u8 m_old_pin8;
+ u16 m_counter;
+ u16 m_shift_reg;
+};
+
+msx_vaus_device::msx_vaus_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MSX_VAUS, tag, owner, clock)
+ , device_msx_general_purpose_port_interface(mconfig, *this)
+ , m_button(*this, "BUTTON")
+ , m_pot(*this, "POT")
+ , m_timer(nullptr)
+{
+}
+
+void msx_vaus_device::device_start()
+{
+ m_timer = timer_alloc(FUNC(msx_vaus_device::copy_counter), this);
+ save_item(NAME(m_old_pin6));
+ save_item(NAME(m_old_pin8));
+ save_item(NAME(m_counter));
+ save_item(NAME(m_shift_reg));
+}
+
+void msx_vaus_device::device_reset()
+{
+ m_old_pin8 = 0;
+ m_counter = 0;
+ m_shift_reg = 0;
+}
+
+u8 msx_vaus_device::read()
+{
+ // bit 0/pin 1 - shift register output
+ // bit 1/pin 2 - button
+ return (m_button->read() & 0x02) | (BIT(m_shift_reg, 8) ? 0x01 : 0x00) | 0xfc;
+}
+
+void msx_vaus_device::pin_6_w(int state)
+{
+ if (!m_old_pin6 && state)
+ {
+ m_shift_reg <<= 1;
+ }
+ m_old_pin6 = state;
+}
+
+void msx_vaus_device::pin_8_w(int state)
+{
+ if (!state)
+ {
+ m_counter = 0;
+ m_timer->adjust(attotime::never);
+ }
+ else if (!m_old_pin8)
+ {
+ // start counting; the counter is incremented on a ~96k2 clock
+ m_counter = m_pot->read();
+ m_timer->adjust(attotime::from_ticks(m_counter, 96200));
+ }
+ m_old_pin8 = state;
+}
+
+TIMER_CALLBACK_MEMBER(msx_vaus_device::copy_counter)
+{
+ m_shift_reg = m_counter;
+}
+
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_VAUS, device_msx_general_purpose_port_interface, msx_vaus_device, "msx_vaus", "Taito Arkanoid Vaus Controller (MSX)")
diff --git a/src/devices/bus/msx/ctrl/vaus.h b/src/devices/bus/msx/ctrl/vaus.h
new file mode 100644
index 00000000000..1b6d713a9a3
--- /dev/null
+++ b/src/devices/bus/msx/ctrl/vaus.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+/**********************************************************************
+
+ MSX Arkanoid Vaus controller emulation
+
+**********************************************************************/
+
+#ifndef MAME_BUS_MSX_CTRL_VAUS_H
+#define MAME_BUS_MSX_CTRL_VAUS_H
+
+#pragma once
+
+#include "ctrl.h"
+
+
+DECLARE_DEVICE_TYPE(MSX_VAUS, device_msx_general_purpose_port_interface)
+
+#endif // MAME_BUS_MSX_CTRL_VAUS_H
diff --git a/src/devices/bus/msx/ctrl/xe1ap.cpp b/src/devices/bus/msx/ctrl/xe1ap.cpp
new file mode 100644
index 00000000000..4d38d378666
--- /dev/null
+++ b/src/devices/bus/msx/ctrl/xe1ap.cpp
@@ -0,0 +1,101 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/**********************************************************************
+
+ Dempa Micom Soft Analog/Digital Controller XE-1AP emulation
+
+**********************************************************************/
+
+#include "emu.h"
+#include "xe1ap.h"
+
+#include "machine/micomxe1a.h"
+
+
+namespace {
+
+INPUT_PORTS_START(xe1ap)
+ PORT_START("BUTTONS")
+ PORT_BIT(0x0001, IP_ACTIVE_LOW, IPT_BUTTON4) PORT_NAME("%p D") // left shoulder lower
+ PORT_BIT(0x0002, IP_ACTIVE_LOW, IPT_BUTTON3) PORT_NAME("%p C") // left shoulder upper
+ PORT_BIT(0x0004, IP_ACTIVE_LOW, IPT_BUTTON2) PORT_NAME("%p B") // right shoulder lower
+ PORT_BIT(0x0008, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_NAME("%p A") // right shoulder upper
+ PORT_BIT(0x0010, IP_ACTIVE_LOW, IPT_SELECT) // left face bottom
+ PORT_BIT(0x0020, IP_ACTIVE_LOW, IPT_START) // right face bottom
+ PORT_BIT(0x0040, IP_ACTIVE_LOW, IPT_BUTTON6) PORT_NAME("%p E2") // left face top inner
+ PORT_BIT(0x0080, IP_ACTIVE_LOW, IPT_BUTTON5) PORT_NAME("%p E1") // left face top outer
+ PORT_BIT(0x0100, IP_ACTIVE_LOW, IPT_BUTTON8) PORT_NAME("%p B'") // right face top inner
+ PORT_BIT(0x0200, IP_ACTIVE_LOW, IPT_BUTTON7) PORT_NAME("%p A'") // right face top outer
+ PORT_BIT(0xfc00, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("CH0")
+ PORT_BIT(0xff, 0x80, IPT_AD_STICK_Y) PORT_SENSITIVITY(50) PORT_KEYDELTA(50)
+
+ PORT_START("CH1")
+ PORT_BIT(0xff, 0x80, IPT_AD_STICK_X) PORT_SENSITIVITY(50) PORT_KEYDELTA(50)
+
+ PORT_START("CH2")
+ PORT_BIT(0xff, 0x80, IPT_AD_STICK_Z) PORT_SENSITIVITY(50) PORT_KEYDELTA(50) PORT_NAME("%p Throttle")
+
+ PORT_START("CH3")
+ PORT_BIT(0xff, 0x00, IPT_UNUSED)
+
+ PORT_START("MODE")
+ PORT_CONFNAME(0x01, 0x01, "Mode") PORT_WRITE_LINE_DEVICE_MEMBER("xe1", micom_xe_1a_device, mode_w)
+ PORT_CONFSETTING( 0x00, "Digital")
+ PORT_CONFSETTING( 0x01, "Analog")
+ PORT_CONFNAME(0x02, 0x00, "Interface") PORT_WRITE_LINE_DEVICE_MEMBER("xe1", micom_xe_1a_device, interface_w)
+ PORT_CONFSETTING( 0x00, "Personal Computer")
+ PORT_CONFSETTING( 0x02, "MD")
+INPUT_PORTS_END
+
+
+class xe1ap_device : public device_t, public device_msx_general_purpose_port_interface
+{
+public:
+ xe1ap_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) ATTR_COLD;
+
+ virtual u8 read() override { return m_xe1->out_r() | 0xc0; }
+ virtual void pin_8_w(int state) override { m_xe1->req_w(state); }
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD { return INPUT_PORTS_NAME(xe1ap); }
+ virtual void device_start() override ATTR_COLD { }
+ virtual void device_reset() override ATTR_COLD;
+
+private:
+ u8 read_channel(offs_t offset) { return m_axes[offset]->read(); }
+
+ required_device<micom_xe_1a_device> m_xe1;
+ required_ioport_array<4> m_axes;
+ required_ioport m_mode;
+};
+
+xe1ap_device::xe1ap_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) :
+ device_t(mconfig, MSX_XE1AP, tag, owner, clock),
+ device_msx_general_purpose_port_interface(mconfig, *this),
+ m_xe1(*this, "xe1"),
+ m_axes(*this, "CH%u", 0U),
+ m_mode(*this, "MODE")
+{
+}
+
+void xe1ap_device::device_add_mconfig(machine_config &config)
+{
+ MICOM_XE_1A(config, m_xe1);
+ m_xe1->buttons_handler().set_ioport("BUTTONS");
+ m_xe1->analog_handler().set(FUNC(xe1ap_device::read_channel));
+}
+
+void xe1ap_device::device_reset()
+{
+ auto const mode = m_mode->read();
+ m_xe1->mode_w(BIT(mode, 0));
+ m_xe1->interface_w(BIT(mode, 1));
+}
+
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_XE1AP, device_msx_general_purpose_port_interface, xe1ap_device, "msx_xe1ap", "Dempa Micom Soft Analog Controller (XE-1AP, PC)")
diff --git a/src/devices/bus/msx/ctrl/xe1ap.h b/src/devices/bus/msx/ctrl/xe1ap.h
new file mode 100644
index 00000000000..515394b71fa
--- /dev/null
+++ b/src/devices/bus/msx/ctrl/xe1ap.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/**********************************************************************
+
+ Dempa Micom Soft Analog/Digital Controller XE-1AP emulation
+
+**********************************************************************/
+
+#ifndef MAME_BUS_MSX_CTRL_XE1AP_H
+#define MAME_BUS_MSX_CTRL_XE1AP_H
+
+#pragma once
+
+#include "ctrl.h"
+
+
+DECLARE_DEVICE_TYPE(MSX_XE1AP, device_msx_general_purpose_port_interface)
+
+#endif // MAME_BUS_MSX_CTRL_XE1AP_H
diff --git a/src/devices/bus/msx/minicart/minicart.cpp b/src/devices/bus/msx/minicart/minicart.cpp
new file mode 100644
index 00000000000..3f7c8bf53e6
--- /dev/null
+++ b/src/devices/bus/msx/minicart/minicart.cpp
@@ -0,0 +1,35 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#include "emu.h"
+#include "minicart.h"
+#include "bus/msx/cart/nomapper.h"
+
+
+namespace bus::msx::minicart::slotoptions {
+char const *const NOMAPPER = "nomapper";
+}
+
+void msx_yamaha_minicart(device_slot_interface &device, bool is_in_subslot)
+{
+ using namespace bus::msx::minicart::slotoptions;
+ device.option_add_internal(NOMAPPER, MSX_CART_NOMAPPER);
+}
+
+
+DEFINE_DEVICE_TYPE(MSX_SLOT_YAMAHA_MINICART, msx_slot_yamaha_minicart_device, "msx_slot_yamaha_minicart", "MSX Yamaha Minicart slot")
+
+
+msx_slot_yamaha_minicart_device::msx_slot_yamaha_minicart_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : msx_slot_cartridge_base_device(mconfig, MSX_SLOT_YAMAHA_MINICART, tag, owner, clock)
+{
+}
+
+void msx_slot_yamaha_minicart_device::device_start()
+{
+}
+
+std::string msx_slot_yamaha_minicart_device::get_default_card_software(get_default_card_software_hook &hook) const
+{
+ using namespace bus::msx::minicart::slotoptions;
+ return software_get_default_slot(NOMAPPER);
+}
diff --git a/src/devices/bus/msx/minicart/minicart.h b/src/devices/bus/msx/minicart/minicart.h
new file mode 100644
index 00000000000..9da07418c0d
--- /dev/null
+++ b/src/devices/bus/msx/minicart/minicart.h
@@ -0,0 +1,38 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+/***************************************************************************
+
+ MSX Yamaha minicart slot
+
+Pinout of the 30 pin connector is unknown.
+
+ ***************************************************************************/
+#ifndef MAME_BUS_MSX_MINICART_MINICART_H
+#define MAME_BUS_MSX_MINICART_MINICART_H
+
+#pragma once
+
+#include "bus/msx/slot/cartridge.h"
+
+
+void msx_yamaha_minicart(device_slot_interface &device, bool is_in_subslot); // 30 pin mini cartridge slot as found in some yamaha machines
+
+
+DECLARE_DEVICE_TYPE(MSX_SLOT_YAMAHA_MINICART, msx_slot_yamaha_minicart_device)
+
+
+class msx_slot_yamaha_minicart_device : public msx_slot_cartridge_base_device
+{
+public:
+ msx_slot_yamaha_minicart_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual const char *image_interface() const noexcept override { return "msx_yamaha_minicart"; }
+ virtual const char *image_type_name() const noexcept override { return "yamahaminicart"; }
+ virtual const char *image_brief_type_name() const noexcept override { return "mini"; }
+ virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
+
+protected:
+ virtual void device_start() override;
+};
+
+#endif // MAME_BUS_MSX_MINICART_MINICART_H
diff --git a/src/devices/bus/msx/module/module.cpp b/src/devices/bus/msx/module/module.cpp
new file mode 100644
index 00000000000..b716d5478e5
--- /dev/null
+++ b/src/devices/bus/msx/module/module.cpp
@@ -0,0 +1,41 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#include "emu.h"
+#include "module.h"
+#include "sfg.h"
+#include "skw01.h"
+
+
+namespace bus::msx::module::slotoptions {
+char const *const SFG01 = "sfg01";
+char const *const SFG05 = "sfg05";
+char const *const SKW01 = "skw01";
+}
+
+
+void msx_yamaha_60pin(device_slot_interface &device, bool is_in_subslot)
+{
+ using namespace bus::msx::module;
+ device.option_add(slotoptions::SFG01, MSX_CART_SFG01);
+ device.option_add(slotoptions::SFG05, MSX_CART_SFG05);
+ device.option_add(slotoptions::SKW01, MSX_CART_SKW01);
+}
+
+
+DEFINE_DEVICE_TYPE(MSX_SLOT_YAMAHA_EXPANSION, msx_slot_yamaha_expansion_device, "msx_slot_yamaha_expansion", "MSX Yamaha Expansion slot")
+
+
+msx_slot_yamaha_expansion_device::msx_slot_yamaha_expansion_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : msx_slot_cartridge_base_device(mconfig, MSX_SLOT_YAMAHA_EXPANSION, tag, owner, clock)
+{
+}
+
+void msx_slot_yamaha_expansion_device::device_start()
+{
+}
+
+std::string msx_slot_yamaha_expansion_device::get_default_card_software(get_default_card_software_hook &hook) const
+{
+ using namespace bus::msx::module;
+ return software_get_default_slot(slotoptions::SFG01);
+}
diff --git a/src/devices/bus/msx/module/module.h b/src/devices/bus/msx/module/module.h
new file mode 100644
index 00000000000..4bd91b74c33
--- /dev/null
+++ b/src/devices/bus/msx/module/module.h
@@ -0,0 +1,66 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+/***************************************************************************
+
+ MSX Yamaha module slot
+
+ Cartridge edge connector (double-sided):
+ GND - 2 1 - SOUND OUT
+Phase control - 4 3 - GND
+ B-Y - 6 5 - Y
+ R-Y - 8 7 - C VIDEO
+CLOCK INT/EXT - 10 9 - EXT CLOCK
+ /CS2 - 12 11 - /CS1
+ /SLTSL - 14 13 - /CS12
+ /RFSH - 16 15 - reserved
+ /INT - 18 17 - /WAIT
+ /BUSDIR - 20 19 - /M1
+ /MREQ - 22 21 - /IORQ
+ /RD - 24 23 - /WR
+ reserved - 26 25 - /RESET
+ A15 - 28 27 - A9
+ A10 - 30 29 - A11
+ A6 - 32 31 - A7
+ A8 - 34 33 - A12
+ A13 - 36 35 - A14
+ A0 - 38 37 - A1
+ A2 - 40 39 - A3
+ A4 - 42 41 - A5
+ D0 - 44 43 - D1
+ D2 - 46 45 - D3
+ D4 - 48 47 - D5
+ D6 - 50 49 - D7
+ CLOCK - 52 51 - GND
+ SW1 - 54 53 - GND
+ SW2 - 56 55 - +5V
+ +12V - 58 57 - +5V
+ -12V - 60 59 - SOUNDIN
+
+ ***************************************************************************/
+#ifndef MAME_BUS_MSX_MODULE_MODULE_H
+#define MAME_BUS_MSX_MODULE_MODULE_H
+
+#pragma once
+
+#include "bus/msx/slot/cartridge.h"
+
+
+void msx_yamaha_60pin(device_slot_interface &device, bool is_in_subslot); // 60 pin expansion slots as found in yamaha machines
+DECLARE_DEVICE_TYPE(MSX_SLOT_YAMAHA_EXPANSION, msx_slot_yamaha_expansion_device)
+
+
+class msx_slot_yamaha_expansion_device : public msx_slot_cartridge_base_device
+{
+public:
+ msx_slot_yamaha_expansion_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual const char *image_interface() const noexcept override { return "msx_yamaha_60pin"; }
+ virtual const char *image_type_name() const noexcept override { return "cartridge60pin"; }
+ virtual const char *image_brief_type_name() const noexcept override { return "cart60p"; }
+ virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
+
+protected:
+ virtual void device_start() override;
+};
+
+#endif // MAME_BUS_MSX_MODULE_MODULE_H
diff --git a/src/devices/bus/msx/module/sfg.cpp b/src/devices/bus/msx/module/sfg.cpp
new file mode 100644
index 00000000000..ac7ad33493e
--- /dev/null
+++ b/src/devices/bus/msx/module/sfg.cpp
@@ -0,0 +1,212 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+/**************************************************************************
+
+Yamaha SFG01/SFG05 emulation
+
+**************************************************************************/
+
+#include "emu.h"
+#include "sfg.h"
+
+#include "bus/midi/midi.h"
+#include "bus/msx/cart/msx_audio_kb.h"
+#include "machine/ym2148.h"
+#include "sound/ymopm.h"
+
+#include "speaker.h"
+
+
+namespace {
+
+class msx_cart_sfg_device : public device_t, public msx_cart_interface
+{
+protected:
+ msx_cart_sfg_device(const machine_config &mconfig, const device_type type, const char *tag, device_t *owner, u32 clock);
+
+ // device_t implementation
+ virtual void device_start() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+
+ IRQ_CALLBACK_MEMBER(irq_callback);
+
+ void ym2151_irq_w(int state);
+ void ym2148_irq_w(int state);
+
+ void check_irq();
+
+ required_memory_region m_region_sfg;
+ required_device<ym_generic_device> m_ym2151;
+ required_device<msx_audio_kbdc_port_device> m_kbdc;
+ required_device<ym2148_device> m_ym2148;
+ int m_ym2151_irq_state;
+ int m_ym2148_irq_state;
+ u32 m_rom_mask;
+};
+
+msx_cart_sfg_device::msx_cart_sfg_device(const machine_config &mconfig, const device_type type, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, type, tag, owner, clock)
+ , msx_cart_interface(mconfig, *this)
+ , m_region_sfg(*this, "sfg")
+ , m_ym2151(*this, "ym2151")
+ , m_kbdc(*this, "kbdc")
+ , m_ym2148(*this, "ym2148")
+ , m_ym2151_irq_state(CLEAR_LINE)
+ , m_ym2148_irq_state(CLEAR_LINE)
+ , m_rom_mask(0)
+{
+}
+
+void msx_cart_sfg_device::device_add_mconfig(machine_config &config)
+{
+ // YM2151 (OPM)
+ // YM3012 (DAC)
+ // YM2148 (MKS)
+
+ SPEAKER(config, "lspeaker").front_left();
+ SPEAKER(config, "rspeaker").front_right();
+ ym2151_device &ym2151(YM2151(config, m_ym2151, DERIVED_CLOCK(1, 1))); // The SFG01 uses a YM2151, the SFG05 uses a YM2164, input clock comes from the main cpu frequency
+ ym2151.irq_handler().set(FUNC(msx_cart_sfg_device::ym2151_irq_w));
+ ym2151.add_route(0, "lspeaker", 0.80);
+ ym2151.add_route(1, "rspeaker", 0.80);
+
+ YM2148(config, m_ym2148, XTAL(4'000'000));
+ m_ym2148->txd_handler().set("mdout", FUNC(midi_port_device::write_txd));
+ m_ym2148->port_write_handler().set("kbdc", FUNC(msx_audio_kbdc_port_device::write));
+ m_ym2148->port_read_handler().set("kbdc", FUNC(msx_audio_kbdc_port_device::read));
+ m_ym2148->irq_handler().set(FUNC(msx_cart_sfg_device::ym2148_irq_w));
+
+ MSX_AUDIO_KBDC_PORT(config, m_kbdc, msx_audio_keyboards, nullptr);
+
+ MIDI_PORT(config, "mdout", midiout_slot, "midiout");
+ MIDI_PORT(config, "mdin", midiin_slot, "midiin").rxd_handler().set("ym2148", FUNC(ym2148_device::write_rxd));
+}
+
+void msx_cart_sfg_device::device_start()
+{
+ // Set rom mask
+ m_rom_mask = m_region_sfg->bytes() - 1;
+
+ maincpu().set_irq_acknowledge_callback(*this, FUNC(msx_cart_sfg_device::irq_callback));
+
+ page(0)->install_rom(0x0000, 0x3fff, m_region_sfg->base());
+ if (m_region_sfg->bytes() == 0x8000)
+ {
+ page(1)->install_rom(0x4000, 0x7fff, m_region_sfg->base() + 0x4000);
+ }
+ else
+ {
+ page(1)->install_rom(0x4000, 0x7fff, m_region_sfg->base());
+ }
+
+ for (int i = 0; i < 4; i++)
+ {
+ // These addresses deliberately overlap
+ page(i)->install_read_handler(0x4000 * i + 0x3ff0, 0x4000 * i + 0x3ff6, emu::rw_delegate(*m_ym2148, FUNC(ym2148_device::read)));
+ page(i)->install_read_handler(0x4000 * i + 0x3ff0, 0x4000 * i + 0x3ff1, emu::rw_delegate(*m_ym2151, FUNC(ym_generic_device::read)));
+ page(i)->install_write_handler(0x4000 * i + 0x3ff0, 0x4000 * i + 0x3ff6, emu::rw_delegate(*m_ym2148, FUNC(ym2148_device::write)));
+ page(i)->install_write_handler(0x4000 * i + 0x3ff0, 0x4000 * i + 0x3ff1, emu::rw_delegate(*m_ym2151, FUNC(ym_generic_device::write)));
+ }
+}
+
+IRQ_CALLBACK_MEMBER(msx_cart_sfg_device::irq_callback)
+{
+ return m_ym2148->get_irq_vector();
+}
+
+void msx_cart_sfg_device::ym2151_irq_w(int state)
+{
+ m_ym2151_irq_state = state ? ASSERT_LINE : CLEAR_LINE;
+ check_irq();
+}
+
+void msx_cart_sfg_device::ym2148_irq_w(int state)
+{
+ m_ym2148_irq_state = state ? ASSERT_LINE : CLEAR_LINE;
+ check_irq();
+}
+
+void msx_cart_sfg_device::check_irq()
+{
+ if (m_ym2151_irq_state != CLEAR_LINE || m_ym2148_irq_state != CLEAR_LINE)
+ {
+ irq_out(ASSERT_LINE);
+ }
+ else
+ {
+ irq_out(CLEAR_LINE);
+ }
+}
+
+
+class msx_cart_sfg01_device : public msx_cart_sfg_device
+{
+public:
+ msx_cart_sfg01_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual const tiny_rom_entry *device_rom_region() const override;
+};
+
+msx_cart_sfg01_device::msx_cart_sfg01_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : msx_cart_sfg_device(mconfig, MSX_CART_SFG01, tag, owner, clock)
+{
+}
+
+ROM_START(msx_sfg01)
+ ROM_REGION(0x4000, "sfg", 0)
+ ROM_LOAD("sfg01.rom", 0x0, 0x4000, CRC(0995fb36) SHA1(434651305f92aa770a89e40b81125fb22d91603d)) // correct label is almost certainly "yamaha__ym2211-22702__48_18_89_b.ic104" though the datecode portion may vary between late 1983 and mid 1984
+ROM_END
+
+const tiny_rom_entry *msx_cart_sfg01_device::device_rom_region() const
+{
+ return ROM_NAME(msx_sfg01);
+}
+
+
+
+class msx_cart_sfg05_device : public msx_cart_sfg_device
+{
+public:
+ msx_cart_sfg05_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+};
+
+msx_cart_sfg05_device::msx_cart_sfg05_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : msx_cart_sfg_device(mconfig, MSX_CART_SFG05, tag, owner, clock)
+{
+}
+
+void msx_cart_sfg05_device::device_add_mconfig(machine_config &config)
+{
+ msx_cart_sfg_device::device_add_mconfig(config);
+
+ ym2164_device &ym2164(YM2164(config.replace(), m_ym2151, DERIVED_CLOCK(1, 1)));
+ ym2164.irq_handler().set(FUNC(msx_cart_sfg05_device::ym2151_irq_w));
+ ym2164.add_route(0, "lspeaker", 0.80);
+ ym2164.add_route(1, "rspeaker", 0.80);
+}
+
+ROM_START(msx_sfg05)
+ ROM_REGION(0x8000, "sfg", 0)
+ // Version string starts at $02BD
+ ROM_SYSTEM_BIOS(0, "m5.01.011", "SFG05 (original) M5.01.011")
+ ROMX_LOAD( "sfg05.rom", 0x0, 0x8000, CRC(2425c279) SHA1(d956167e234f60ad916120437120f86fc8c3c321), ROM_BIOS(0)) // correct label MIGHT be "yamaha__ym2301-23959.ic104" but this needs redump/verification
+ ROM_SYSTEM_BIOS(1, "m5.00.013", "SFG05 (SFG01 upgrade) M5.00.013") // SFG01 PCB, Yamaha official upgrade, has YM2151 instead of YM2164
+ ROMX_LOAD( "sfg05a.rom", 0x0, 0x8000, CRC(5bc237f8) SHA1(930338f45c08228108c0831cc4a26014c2674718), ROM_BIOS(1)) // this came on a single eprom on a daughterboard on an SFG01 board which had been factory upgraded to SFG05
+ ROM_SYSTEM_BIOS(2, "m5.00.011", "SFG05 M5.00.011") // Found in Sakhr AX-200M
+ ROMX_LOAD("sfg05_m5_00_011.rom", 0x0, 0x8000, BAD_DUMP CRC(9d5e20c9) SHA1(fcc385b90c65575e29fc009aa00b5120fc4c251a), ROM_BIOS(2)) // Still seems to have I/O reads at $7ff0 - $7fff
+ROM_END
+
+const tiny_rom_entry *msx_cart_sfg05_device::device_rom_region() const
+{
+ return ROM_NAME(msx_sfg05);
+}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_SFG01, msx_cart_interface, msx_cart_sfg01_device, "msx_cart_sfg01", "MSX Cartridge - SFG01")
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_SFG05, msx_cart_interface, msx_cart_sfg05_device, "msx_cart_sfg05", "MSX Cartridge - SFG05")
diff --git a/src/devices/bus/msx/module/sfg.h b/src/devices/bus/msx/module/sfg.h
new file mode 100644
index 00000000000..663b7b87a5a
--- /dev/null
+++ b/src/devices/bus/msx/module/sfg.h
@@ -0,0 +1,14 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#ifndef MAME_BUS_MSX_MODULE_SFG_H
+#define MAME_BUS_MSX_MODULE_SFG_H
+
+#pragma once
+
+#include "bus/msx/slot/cartridge.h"
+
+
+DECLARE_DEVICE_TYPE(MSX_CART_SFG01, msx_cart_interface)
+DECLARE_DEVICE_TYPE(MSX_CART_SFG05, msx_cart_interface)
+
+#endif // MAME_BUS_MSX_MODULE_SFG_H
diff --git a/src/devices/bus/msx/module/skw01.cpp b/src/devices/bus/msx/module/skw01.cpp
new file mode 100644
index 00000000000..0fef9c1de6b
--- /dev/null
+++ b/src/devices/bus/msx/module/skw01.cpp
@@ -0,0 +1,176 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+/**************************************************************************
+
+Yamaha SKW-01 emulation
+
+Word processor side slot module with Kanij ROM, 2KB SRAM, and a
+printer port.
+The PCB is labeled YMX-YWP.
+
+The software can be started from Basic by entering the command "CALL JWP"
+or "_JWP".
+
+**************************************************************************/
+
+#include "emu.h"
+#include "skw01.h"
+#include "bus/centronics/ctronics.h"
+#include "machine/buffer.h"
+#include "machine/nvram.h"
+
+namespace {
+
+class msx_cart_skw01_device : public device_t, public msx_cart_interface
+{
+public:
+ msx_cart_skw01_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+protected:
+ virtual void device_start() override;
+
+ virtual void device_add_mconfig(machine_config &config) override;
+
+private:
+ static constexpr u16 SRAM_SIZE = 2048;
+
+ required_device<nvram_device> m_nvram;
+ required_memory_region m_region_rom;
+ required_memory_region m_region_dict;
+ required_memory_region m_region_kanji;
+ u16 m_bank_address[5];
+ std::unique_ptr<u8[]> m_sram;
+ required_device<input_buffer_device> m_cent_status_in;
+ required_device<output_latch_device> m_cent_ctrl_out;
+ required_device<output_latch_device> m_cent_data_out;
+ required_device<centronics_device> m_centronics;
+
+ template<int Bank> void addr_lo_w(u8 data);
+ template<int Bank> void addr_hi_w(u8 data);
+ template<int Bank> u8 ready_r() const;
+ template<int Bank> u8 data_r() const;
+ void dictsram_w(u8 data);
+ u8 dictsram_r() const;
+};
+
+
+msx_cart_skw01_device::msx_cart_skw01_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MSX_CART_SKW01, tag, owner, clock)
+ , msx_cart_interface(mconfig, *this)
+ , m_nvram(*this, "nvram")
+ , m_region_rom(*this, "rom")
+ , m_region_dict(*this, "dict")
+ , m_region_kanji(*this, "kanji")
+ , m_bank_address{0}
+ , m_cent_status_in(*this, "cent_status_in")
+ , m_cent_ctrl_out(*this, "cent_ctrl_out")
+ , m_cent_data_out(*this, "cent_data_out")
+ , m_centronics(*this, "centronics")
+{
+}
+
+void msx_cart_skw01_device::device_add_mconfig(machine_config &config)
+{
+ NVRAM(config, m_nvram, nvram_device::DEFAULT_ALL_0);
+
+ // printer port
+ CENTRONICS(config, m_centronics, centronics_devices, "printer");
+ m_centronics->busy_handler().set(m_cent_status_in, FUNC(input_buffer_device::write_bit1));
+
+ OUTPUT_LATCH(config, m_cent_data_out);
+ m_centronics->set_output_latch(*m_cent_data_out);
+ INPUT_BUFFER(config, m_cent_status_in);
+
+ OUTPUT_LATCH(config, m_cent_ctrl_out);
+ m_cent_ctrl_out->bit_handler<1>().set(m_centronics, FUNC(centronics_device::write_strobe));
+}
+
+ROM_START(msx_skw01)
+ ROM_REGION(0x8000, "rom", 0)
+ ROM_LOAD("skw-01.rom", 0x0000, 0x8000, CRC(9a7c9a26) SHA1(6a7f41d89f9d50f4ff648233670660cfb07a41ee))
+ ROM_REGION(0x8000, "dict", 0)
+ ROM_LOAD("skw-01p4.rom", 0x0000, 0x8000, CRC(41779e03) SHA1(82f2ecd9f3135a8602d54cc6322216b3b15ae8b3))
+ ROM_REGION(0x20000, "kanji", 0)
+ ROM_LOAD("skw-01kf.rom", 0x00000, 0x20000, CRC(9de1dc10) SHA1(f0901a63de6c95a42ce6ad82dd5e6bfba4bcf180))
+ROM_END
+
+const tiny_rom_entry *msx_cart_skw01_device::device_rom_region() const
+{
+ return ROM_NAME(msx_skw01);
+}
+
+void msx_cart_skw01_device::device_start()
+{
+ m_sram = std::make_unique<u8[]>(SRAM_SIZE);
+ m_nvram->set_base(m_sram.get(), SRAM_SIZE);
+ save_pointer(NAME(m_sram), SRAM_SIZE);
+ save_item(NAME(m_bank_address));
+
+ page(0)->install_rom(0x0000, 0x3fff, m_region_rom->base());
+ page(1)->install_rom(0x4000, 0x7fff, m_region_rom->base() + 0x4000);
+ page(1)->install_readwrite_handler(0x7fc0, 0x7fc0, emu::rw_delegate(*this, FUNC(msx_cart_skw01_device::ready_r<0>)), emu::rw_delegate(*this, FUNC(msx_cart_skw01_device::addr_lo_w<0>)));
+ page(1)->install_readwrite_handler(0x7fc1, 0x7fc1, emu::rw_delegate(*this, FUNC(msx_cart_skw01_device::data_r<0>)), emu::rw_delegate(*this, FUNC(msx_cart_skw01_device::addr_hi_w<0>)));
+ page(1)->install_readwrite_handler(0x7fc2, 0x7fc2, emu::rw_delegate(*this, FUNC(msx_cart_skw01_device::ready_r<1>)), emu::rw_delegate(*this, FUNC(msx_cart_skw01_device::addr_lo_w<1>)));
+ page(1)->install_readwrite_handler(0x7fc3, 0x7fc3, emu::rw_delegate(*this, FUNC(msx_cart_skw01_device::data_r<1>)), emu::rw_delegate(*this, FUNC(msx_cart_skw01_device::addr_hi_w<1>)));
+ page(1)->install_readwrite_handler(0x7fc4, 0x7fc4, emu::rw_delegate(*this, FUNC(msx_cart_skw01_device::ready_r<2>)), emu::rw_delegate(*this, FUNC(msx_cart_skw01_device::addr_lo_w<2>)));
+ page(1)->install_readwrite_handler(0x7fc5, 0x7fc5, emu::rw_delegate(*this, FUNC(msx_cart_skw01_device::data_r<2>)), emu::rw_delegate(*this, FUNC(msx_cart_skw01_device::addr_hi_w<2>)));
+ page(1)->install_readwrite_handler(0x7fc6, 0x7fc6, emu::rw_delegate(*this, FUNC(msx_cart_skw01_device::ready_r<3>)), emu::rw_delegate(*this, FUNC(msx_cart_skw01_device::addr_lo_w<3>)));
+ page(1)->install_readwrite_handler(0x7fc7, 0x7fc7, emu::rw_delegate(*this, FUNC(msx_cart_skw01_device::data_r<3>)), emu::rw_delegate(*this, FUNC(msx_cart_skw01_device::addr_hi_w<3>)));
+ page(1)->install_write_handler(0x7fc8, 0x7fc8, emu::rw_delegate(*this, FUNC(msx_cart_skw01_device::addr_lo_w<4>)));
+ page(1)->install_write_handler(0x7fc9, 0x7fc9, emu::rw_delegate(*this, FUNC(msx_cart_skw01_device::addr_hi_w<4>)));
+ page(1)->install_readwrite_handler(0x7fca, 0x7fcb, emu::rw_delegate(*this, FUNC(msx_cart_skw01_device::dictsram_r)), emu::rw_delegate(*this, FUNC(msx_cart_skw01_device::dictsram_w)));
+ page(1)->install_readwrite_handler(0x7fcc, 0x7fcc, emu::rw_delegate(*m_cent_status_in, FUNC(input_buffer_device::read)), emu::rw_delegate(*m_cent_ctrl_out, FUNC(output_latch_device::write)));
+ page(1)->install_write_handler(0x7fce, 0x7fce, emu::rw_delegate(*m_cent_data_out, FUNC(output_latch_device::write)));
+}
+
+template<int Bank>
+void msx_cart_skw01_device::addr_lo_w(u8 data)
+{
+ m_bank_address[Bank] = (m_bank_address[Bank] & 0xff00) | data;
+}
+
+template<int Bank>
+void msx_cart_skw01_device::addr_hi_w(u8 data)
+{
+ m_bank_address[Bank] = (m_bank_address[Bank] & 0x00ff) | (u16(data) << 8);
+}
+
+template<int Bank>
+u8 msx_cart_skw01_device::ready_r() const
+{
+ // Unknown what the delay should be
+ // 0 - Not ready
+ // 1 - Data ready to read
+ return 1;
+}
+
+template<int Bank>
+u8 msx_cart_skw01_device::data_r() const
+{
+ return m_region_kanji->as_u8((Bank * 0x8000) | (m_bank_address[Bank] & 0x7fff));
+}
+
+void msx_cart_skw01_device::dictsram_w(u8 data)
+{
+ if (BIT(m_bank_address[4], 15))
+ {
+ m_sram[m_bank_address[4] & (SRAM_SIZE - 1)] = data;
+ }
+}
+
+u8 msx_cart_skw01_device::dictsram_r() const
+{
+ if (BIT(m_bank_address[4], 15))
+ {
+ return m_sram[m_bank_address[4] & (SRAM_SIZE - 1)];
+ }
+
+ return m_region_dict->as_u8(m_bank_address[4]);
+}
+
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_SKW01, msx_cart_interface, msx_cart_skw01_device, "msx_cart_skw01", "Yamaha SKW-01")
diff --git a/src/devices/bus/msx/module/skw01.h b/src/devices/bus/msx/module/skw01.h
new file mode 100644
index 00000000000..eeccf3fea47
--- /dev/null
+++ b/src/devices/bus/msx/module/skw01.h
@@ -0,0 +1,12 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#ifndef MAME_BUS_MSX_MODULE_SKW01_H
+#define MAME_BUS_MSX_MODULE_SKW01_H
+
+#pragma once
+
+#include "bus/msx/slot/cartridge.h"
+
+DECLARE_DEVICE_TYPE(MSX_CART_SKW01, msx_cart_interface)
+
+#endif // MAME_BUS_MSX_MODULE_SKW01_H
diff --git a/src/devices/bus/msx/slot/ax230.cpp b/src/devices/bus/msx/slot/ax230.cpp
new file mode 100644
index 00000000000..a60b67273c6
--- /dev/null
+++ b/src/devices/bus/msx/slot/ax230.cpp
@@ -0,0 +1,53 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+/*
+
+ Emulation of the games mapper as found in AX-230 machines.
+
+*/
+
+#include "emu.h"
+#include "ax230.h"
+
+
+DEFINE_DEVICE_TYPE(MSX_SLOT_AX230, msx_slot_ax230_device, "msx_slot_ax230", "MSX Internal AX230")
+
+
+msx_slot_ax230_device::msx_slot_ax230_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MSX_SLOT_AX230, tag, owner, clock)
+ , msx_internal_slot_interface(mconfig, *this)
+ , m_rom_region(*this, finder_base::DUMMY_TAG)
+ , m_rombank(*this, "rombank%u", 0U)
+ , m_region_offset(0)
+{
+}
+
+void msx_slot_ax230_device::device_start()
+{
+ // Sanity checks
+ if (m_rom_region->bytes() < m_region_offset + 0x100000)
+ {
+ fatalerror("Memory region '%s' is too small for the AX230 firmware\n", m_rom_region.finder_tag());
+ }
+
+ for (int i = 0; i < 4; i++)
+ {
+ m_rombank[i]->configure_entries(0, BANKS, m_rom_region->base() + m_region_offset, 0x2000);
+ }
+ page(1)->install_read_bank(0x4000, 0x5fff, m_rombank[0]);
+ page(1)->install_read_bank(0x6000, 0x7fff, m_rombank[1]);
+ page(1)->install_write_handler(0x6000, 0x7fff, emu::rw_delegate(*this, FUNC(msx_slot_ax230_device::mapper_write)));
+ page(2)->install_read_bank(0x8000, 0x9fff, m_rombank[2]);
+ page(2)->install_read_bank(0xa000, 0xbfff, m_rombank[3]);
+}
+
+void msx_slot_ax230_device::device_reset()
+{
+ for (int i = 0; i < 4; i++)
+ m_rombank[i]->set_entry(0);
+}
+
+void msx_slot_ax230_device::mapper_write(offs_t offset, u8 data)
+{
+ m_rombank[(offset / 0x800) & 0x03]->set_entry(data & BANK_MASK);
+}
diff --git a/src/devices/bus/msx/slot/ax230.h b/src/devices/bus/msx/slot/ax230.h
new file mode 100644
index 00000000000..31f5fa3df8d
--- /dev/null
+++ b/src/devices/bus/msx/slot/ax230.h
@@ -0,0 +1,38 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#ifndef MAME_BUS_MSX_SLOT_AX230_H
+#define MAME_BUS_MSX_SLOT_AX230_H
+
+#pragma once
+
+#include "slot.h"
+
+
+DECLARE_DEVICE_TYPE(MSX_SLOT_AX230, msx_slot_ax230_device)
+
+
+class msx_slot_ax230_device : public device_t, public msx_internal_slot_interface
+{
+public:
+ msx_slot_ax230_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ // configuration helpers
+ void set_rom_start(const char *region, u32 offset) { m_rom_region.set_tag(region); m_region_offset = offset; }
+
+protected:
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+private:
+ static constexpr u8 BANKS = 0x80;
+ static constexpr u8 BANK_MASK = BANKS - 1;
+
+ void mapper_write(offs_t offset, uint8_t data);
+
+ required_memory_region m_rom_region;
+ memory_bank_array_creator<4> m_rombank;
+ u32 m_region_offset;
+};
+
+
+#endif // MAME_BUS_MSX_SLOT_AX230_H
diff --git a/src/devices/bus/msx/slot/bruc100.cpp b/src/devices/bus/msx/slot/bruc100.cpp
new file mode 100644
index 00000000000..b5b8af39c26
--- /dev/null
+++ b/src/devices/bus/msx/slot/bruc100.cpp
@@ -0,0 +1,50 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+/*
+
+ Emulation of the firmware mapper as found in Frael Bruc 100 machines.
+
+*/
+
+#include "emu.h"
+#include "bruc100.h"
+
+
+DEFINE_DEVICE_TYPE(MSX_SLOT_BRUC100, msx_slot_bruc100_device, "msx_slot_bruc100", "MSX Internal BRUC100")
+
+
+msx_slot_bruc100_device::msx_slot_bruc100_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MSX_SLOT_BRUC100, tag, owner, clock)
+ , msx_internal_slot_interface(mconfig, *this)
+ , m_rom_region(*this, finder_base::DUMMY_TAG)
+ , m_rombank(*this, "rombank%u", 0U)
+ , m_region_offset(0)
+{
+}
+
+void msx_slot_bruc100_device::device_start()
+{
+ // Sanity checks
+ if (m_rom_region->bytes() < m_region_offset + 0x10000)
+ {
+ fatalerror("Memory region '%s' is too small for the BRUC100 firmware\n", m_rom_region.finder_tag());
+ }
+
+ m_rombank[0]->configure_entries(0, 2, m_rom_region->base() + m_region_offset, 0x8000);
+ m_rombank[1]->configure_entries(0, 2, m_rom_region->base() + m_region_offset + 0x4000, 0x8000);
+
+ page(0)->install_read_bank(0x0000, 0x3fff, m_rombank[0]);
+ page(1)->install_read_bank(0x4000, 0x7fff, m_rombank[1]);
+}
+
+void msx_slot_bruc100_device::device_reset()
+{
+ m_rombank[0]->set_entry(0);
+ m_rombank[1]->set_entry(0);
+}
+
+void msx_slot_bruc100_device::select_bank(u8 bank)
+{
+ m_rombank[0]->set_entry(bank);
+ m_rombank[1]->set_entry(bank);
+}
diff --git a/src/devices/bus/msx/slot/bruc100.h b/src/devices/bus/msx/slot/bruc100.h
new file mode 100644
index 00000000000..cf37efc7779
--- /dev/null
+++ b/src/devices/bus/msx/slot/bruc100.h
@@ -0,0 +1,35 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#ifndef MAME_BUS_MSX_SLOT_BRUC100_H
+#define MAME_BUS_MSX_SLOT_BRUC100_H
+
+#pragma once
+
+#include "slot.h"
+
+
+DECLARE_DEVICE_TYPE(MSX_SLOT_BRUC100, msx_slot_bruc100_device)
+
+
+class msx_slot_bruc100_device : public device_t, public msx_internal_slot_interface
+{
+public:
+ msx_slot_bruc100_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ // configuration helpers
+ void set_rom_start(const char *region, u32 offset) { m_rom_region.set_tag(region); m_region_offset = offset; }
+
+ void select_bank(u8 bank);
+
+protected:
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+private:
+ required_memory_region m_rom_region;
+ memory_bank_array_creator<2> m_rombank;
+ u32 m_region_offset;
+};
+
+
+#endif // MAME_BUS_MSX_SLOT_BRUC100_H
diff --git a/src/devices/bus/msx_slot/bunsetsu.cpp b/src/devices/bus/msx/slot/bunsetsu.cpp
index 9c73a37dbd8..f72c9a5c35f 100644
--- a/src/devices/bus/msx_slot/bunsetsu.cpp
+++ b/src/devices/bus/msx/slot/bunsetsu.cpp
@@ -11,43 +11,51 @@
DEFINE_DEVICE_TYPE(MSX_SLOT_BUNSETSU, msx_slot_bunsetsu_device, "msx_slot_bunsetsu", "MSX Internal BUNSETSU")
-msx_slot_bunsetsu_device::msx_slot_bunsetsu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+msx_slot_bunsetsu_device::msx_slot_bunsetsu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: msx_slot_rom_device(mconfig, MSX_SLOT_BUNSETSU, tag, owner, clock)
, m_bunsetsu_region(*this, finder_base::DUMMY_TAG)
, m_bunsetsu_address(0)
{
}
+void msx_slot_bunsetsu_device::device_start()
+{
+ msx_slot_rom_device::device_start();
+
+ save_item(NAME(m_bunsetsu_address));
+
+ page(2)->install_read_handler(0xbfff, 0xbfff, emu::rw_delegate(*this, FUNC(msx_slot_bunsetsu_device::buns_read)));
+ page(2)->install_write_handler(0xbffc, 0xbffe, emu::rw_delegate(*this, FUNC(msx_slot_bunsetsu_device::buns_write)));
+}
void msx_slot_bunsetsu_device::device_reset()
{
m_bunsetsu_address = 0;
}
-
-uint8_t msx_slot_bunsetsu_device::read(offs_t offset)
+u8 msx_slot_bunsetsu_device::buns_read()
{
- if (offset == 0xbfff)
- {
- return m_bunsetsu_region[m_bunsetsu_address++ & 0x1ffff];
- }
- return msx_slot_rom_device::read(offset);
-}
+ u8 data = m_bunsetsu_region[m_bunsetsu_address & 0x1ffff];
+ if (!machine().side_effects_disabled())
+ m_bunsetsu_address++;
+
+ return data;
+}
-void msx_slot_bunsetsu_device::write(offs_t offset, uint8_t data)
+void msx_slot_bunsetsu_device::buns_write(offs_t offset, u8 data)
{
switch (offset)
{
- case 0xbffc:
+ case 0:
m_bunsetsu_address = (m_bunsetsu_address & 0xffff00) | data;
break;
- case 0xbffd:
+ case 1:
m_bunsetsu_address = (m_bunsetsu_address & 0xff00ff) | (data << 8);
break;
- case 0xbffe:
+ case 2:
m_bunsetsu_address = (m_bunsetsu_address & 0x00ffff) | (data << 16);
break;
}
diff --git a/src/devices/bus/msx_slot/bunsetsu.h b/src/devices/bus/msx/slot/bunsetsu.h
index df0bcedb32f..f2f94dc2405 100644
--- a/src/devices/bus/msx_slot/bunsetsu.h
+++ b/src/devices/bus/msx/slot/bunsetsu.h
@@ -5,8 +5,8 @@
#pragma once
-#include "bus/msx_slot/slot.h"
-#include "bus/msx_slot/rom.h"
+#include "rom.h"
+#include "slot.h"
DECLARE_DEVICE_TYPE(MSX_SLOT_BUNSETSU, msx_slot_bunsetsu_device)
@@ -15,20 +15,21 @@ DECLARE_DEVICE_TYPE(MSX_SLOT_BUNSETSU, msx_slot_bunsetsu_device)
class msx_slot_bunsetsu_device : public msx_slot_rom_device
{
public:
- msx_slot_bunsetsu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ msx_slot_bunsetsu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
// configuration helpers
void set_bunsetsu_region_tag(const char *tag) { m_bunsetsu_region.set_tag(tag); }
- virtual uint8_t read(offs_t offset) override;
- virtual void write(offs_t offset, uint8_t data) override;
-
protected:
+ virtual void device_start() override;
virtual void device_reset() override;
private:
+ u8 buns_read();
+ void buns_write(offs_t offset, u8 data);
+
required_region_ptr<uint8_t> m_bunsetsu_region;
- uint32_t m_bunsetsu_address;
+ u32 m_bunsetsu_address;
};
diff --git a/src/devices/bus/msx/slot/cartridge.cpp b/src/devices/bus/msx/slot/cartridge.cpp
new file mode 100644
index 00000000000..13138bd3ca4
--- /dev/null
+++ b/src/devices/bus/msx/slot/cartridge.cpp
@@ -0,0 +1,130 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#include "emu.h"
+#include "cartridge.h"
+#include "hashfile.h"
+
+
+msx_slot_cartridge_base_device::msx_slot_cartridge_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, type, tag, owner, clock)
+ , device_cartrom_image_interface(mconfig, *this)
+ , device_slot_interface(mconfig, *this)
+ , device_mixer_interface(mconfig, *this)
+ , msx_internal_slot_interface(mconfig, *this)
+ , m_irq_handler(*this)
+ , m_cartridge(nullptr)
+{
+}
+
+
+void msx_slot_cartridge_base_device::device_resolve_objects()
+{
+ m_cartridge = dynamic_cast<msx_cart_interface *>(get_card_device());
+ if (m_cartridge)
+ {
+ m_cartridge->set_views(page(0), page(1), page(2), page(3));
+ }
+}
+
+
+void msx_slot_cartridge_base_device::device_start()
+{
+}
+
+
+std::pair<std::error_condition, std::string> msx_slot_cartridge_base_device::call_load()
+{
+ if (m_cartridge)
+ {
+ if (!loaded_through_softlist())
+ {
+ u32 const length = this->length();
+
+ // determine how much space to allocate
+ u32 length_aligned = 0x10000;
+
+ if (length <= 0x2000)
+ length_aligned = 0x2000;
+ else if (length <= 0x4000)
+ length_aligned = 0x4000;
+ else if (length <= 0x8000)
+ length_aligned = 0x8000;
+ else if (length <= 0xc000)
+ length_aligned = 0xc000;
+ else
+ {
+ while (length_aligned < length)
+ length_aligned *= 2;
+ }
+
+ memory_region *const romregion = machine().memory().region_alloc(subtag("rom"), length_aligned, 1, ENDIANNESS_LITTLE);
+ if (fread(romregion->base(), length) != length)
+ return std::make_pair(image_error::UNSPECIFIED, "Unable to fully read file");
+ }
+
+ std::string message;
+ std::error_condition result = m_cartridge->initialize_cartridge(message);
+ if (result)
+ return std::make_pair(result, message);
+
+ if (m_cartridge->cart_sram_region())
+ battery_load(m_cartridge->cart_sram_region()->base(), m_cartridge->cart_sram_region()->bytes(), 0x00);
+ }
+ return std::make_pair(std::error_condition(), std::string());
+}
+
+
+void msx_slot_cartridge_base_device::call_unload()
+{
+ if (m_cartridge && m_cartridge->cart_sram_region())
+ {
+ battery_save(m_cartridge->cart_sram_region()->base(), m_cartridge->cart_sram_region()->bytes());
+ }
+}
+
+void msx_slot_cartridge_base_device::irq_out(int state)
+{
+ m_irq_handler(state);
+}
+
+
+msx_cart_interface::msx_cart_interface(const machine_config &mconfig, device_t &device)
+ : device_interface(device, "msxcart")
+ , m_exp(dynamic_cast<msx_slot_cartridge_base_device *>(device.owner()))
+{
+ for (int i = 0; i < 4; i++)
+ m_page[i] = nullptr;
+}
+
+void msx_cart_interface::irq_out(int state)
+{
+ m_exp->irq_out(state);
+}
+
+address_space &msx_cart_interface::memory_space() const
+{
+ return m_exp->memory_space();
+}
+
+address_space &msx_cart_interface::io_space() const
+{
+ return m_exp->io_space();
+}
+
+cpu_device &msx_cart_interface::maincpu() const
+{
+ return m_exp->maincpu();
+}
+
+device_mixer_interface &msx_cart_interface::soundin() const
+{
+ return *m_exp;
+}
+
+void msx_cart_interface::set_views(memory_view::memory_view_entry *page0, memory_view::memory_view_entry *page1, memory_view::memory_view_entry *page2, memory_view::memory_view_entry *page3)
+{
+ m_page[0] = page0;
+ m_page[1] = page1;
+ m_page[2] = page2;
+ m_page[3] = page3;
+}
diff --git a/src/devices/bus/msx/slot/cartridge.h b/src/devices/bus/msx/slot/cartridge.h
new file mode 100644
index 00000000000..67b822774f7
--- /dev/null
+++ b/src/devices/bus/msx/slot/cartridge.h
@@ -0,0 +1,113 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+/***************************************************************************
+
+ MSX cartridge slot
+
+ Cartridge edge connector (double-sided):
+ /CS2 - 2 1 - /CS1
+ /SLTSL - 4 3 - /CS12
+ /RFSH - 6 5 - reserved
+ /INT - 8 7 - /WAIT
+ /BUSDIR - 10 9 - /M1
+ /MREQ - 12 11 - /IORQ
+ /RD - 14 13 - /WR
+reserved - 16 15 - /RESET
+ A15 - 18 17 - A9
+ A10 - 20 19 - A11
+ A6 - 22 21 - A7
+ A8 - 24 23 - A12
+ A13 - 26 25 - A14
+ A0 - 28 27 - A1
+ A2 - 30 29 - A3
+ A4 - 32 31 - A5
+ D0 - 34 33 - D1
+ D2 - 36 35 - D3
+ D4 - 38 37 - D5
+ D6 - 40 39 - D7
+ CLOCK - 42 41 - GND
+ SW1 - 44 43 - GND
+ SW2 - 46 45 - +5V
+ +12V - 48 47 - +5V
+ -12V - 50 49 - SOUNDIN
+
+ ***************************************************************************/
+#ifndef MAME_BUS_MSX_SLOT_CARTRIDGE_H
+#define MAME_BUS_MSX_SLOT_CARTRIDGE_H
+
+#pragma once
+
+#include "slot.h"
+#include "imagedev/cartrom.h"
+
+
+class msx_cart_interface;
+
+class msx_slot_cartridge_base_device : public device_t
+ , public device_cartrom_image_interface
+ , public device_slot_interface
+ , public device_mixer_interface
+ , public msx_internal_slot_interface
+{
+public:
+ auto irq_handler() { return m_irq_handler.bind(); }
+
+ virtual std::pair<std::error_condition, std::string> call_load() override;
+ virtual void call_unload() override;
+ virtual bool is_reset_on_load() const noexcept override { return true; }
+ virtual const char *image_interface() const noexcept override { return "msx_cart"; }
+ virtual const char *file_extensions() const noexcept override { return "mx1,bin,rom"; }
+
+ virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override = 0;
+
+ void irq_out(int state);
+
+protected:
+ msx_slot_cartridge_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
+ virtual void device_resolve_objects() override;
+ virtual void device_start() override;
+
+ devcb_write_line m_irq_handler;
+ msx_cart_interface *m_cartridge;
+};
+
+
+
+class msx_cart_interface : public device_interface
+{
+ friend class msx_slot_cartridge_base_device;
+
+public:
+ // This is called after loading cartridge contents and allows the cartridge
+ // implementation to perform some additional initialization based on the
+ // cartridge contents.
+ virtual std::error_condition initialize_cartridge(std::string &message) { return std::error_condition(); }
+ virtual void interface_pre_start() override { assert(m_exp != nullptr); }
+
+ void set_views(memory_view::memory_view_entry *page0, memory_view::memory_view_entry *page1, memory_view::memory_view_entry *page2, memory_view::memory_view_entry *page3);
+
+protected:
+ msx_cart_interface(const machine_config &mconfig, device_t &device);
+
+ memory_region *cart_rom_region() { return m_exp ? m_exp->memregion("rom") : nullptr; }
+ memory_region *cart_vlm5030_region() { return m_exp ? m_exp->memregion("vlm5030") : nullptr; }
+ memory_region *cart_kanji_region() { return m_exp ? m_exp->memregion("kanji") : nullptr; }
+ memory_region *cart_ram_region() { return m_exp ? m_exp->memregion("ram") : nullptr; }
+ memory_region *cart_sram_region() { return m_exp ? m_exp->memregion("sram") : nullptr; }
+ const char *get_feature(std::string_view feature_name) { return m_exp ? m_exp->get_feature(feature_name) : nullptr; }
+ bool is_loaded_through_softlist() { return m_exp ? m_exp->loaded_through_softlist() : false; }
+ void irq_out(int state);
+ msx_slot_cartridge_base_device *parent_slot() const { return m_exp; }
+ address_space &memory_space() const;
+ address_space &io_space() const;
+ cpu_device &maincpu() const;
+ device_mixer_interface &soundin() const;
+ memory_view::memory_view_entry *page(int i) { return m_page[i]; }
+
+private:
+ msx_slot_cartridge_base_device *m_exp;
+ memory_view::memory_view_entry *m_page[4];
+};
+
+#endif // MAME_BUS_MSX_SLOT_CARTRIDGE_H
diff --git a/src/devices/bus/msx/slot/disk.cpp b/src/devices/bus/msx/slot/disk.cpp
new file mode 100644
index 00000000000..0de21e7df6f
--- /dev/null
+++ b/src/devices/bus/msx/slot/disk.cpp
@@ -0,0 +1,1434 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+/*
+From: erbo@xs4all.nl (erik de boer)
+
+sony and philips have used (almost) the same design
+and this is the memory layout
+but it is not a msx standard !
+
+WD1793 or wd2793 registers
+
+address
+
+7FF8H read status register
+ write command register
+7FF9H r/w track register (r/o on NMS 8245 and Sony)
+7FFAH r/w sector register (r/o on NMS 8245 and Sony)
+7FFBH r/w data register
+
+
+hardware registers
+
+address
+
+7FFCH r/w bit 0 side select
+7FFDH r/w b7>M-on , b6>in-use , b1>ds1 , b0>ds0 (all neg. logic)
+7FFEH not used
+7FFFH read b7>drq , b6>intrq
+
+set on 7FFDH bit 2 always to 0 (some use it as disk change reset)
+
+*/
+
+#include "emu.h"
+#include "disk.h"
+#include "formats/dmk_dsk.h"
+#include "formats/msx_dsk.h"
+
+
+DEFINE_DEVICE_TYPE(MSX_SLOT_DISK1_FD1793, msx_slot_disk1_fd1793_device, "msx_slot_disk1_fd1793", "MSX Internal floppy type 1 - FD1793 - 1 DSDD Drive")
+DEFINE_DEVICE_TYPE(MSX_SLOT_DISK1_MB8877, msx_slot_disk1_mb8877_device, "msx_slot_disk1_mb8877", "MSX Internal floppy type 1 - MB8877 - 1 DSDD Drive")
+DEFINE_DEVICE_TYPE(MSX_SLOT_DISK1_WD2793_N, msx_slot_disk1_wd2793_n_device, "msx_slot_disk1_wd2793_n", "MSX Internal floppy type 1 - WD2793 no force ready - 1 DSDD Drive")
+DEFINE_DEVICE_TYPE(MSX_SLOT_DISK1_WD2793_N_2_DRIVES, msx_slot_disk1_wd2793_n_2_drives_device, "msx_slot_disk1_wd2793_n_2_drives", "MSX Internal floppy type 1 - WD2793 no force ready - 2 DSDD Drives")
+DEFINE_DEVICE_TYPE(MSX_SLOT_DISK1_WD2793, msx_slot_disk1_wd2793_device, "msx_slot_disk1_wd2793", "MSX Internal floppy type 1 - WD2793 - 1 DSDD Drive")
+DEFINE_DEVICE_TYPE(MSX_SLOT_DISK1_WD2793_0, msx_slot_disk1_wd2793_0_device, "msx_slot_disk1_wd2793_0", "MSX Internal floppy type 1 - WD2793 - No drive")
+DEFINE_DEVICE_TYPE(MSX_SLOT_DISK1_WD2793_SS, msx_slot_disk1_wd2793_ss_device, "msx_slot_disk1_wd2793_ss", "MSX Internal floppy type 1 - WD2793 - 1 SSDD Drive")
+DEFINE_DEVICE_TYPE(MSX_SLOT_DISK1_WD2793_2_DRIVES, msx_slot_disk1_wd2793_2_drives_device, "msx_slot_disk1_wd2793_2_drives", "MSX Internal floppy type 1 - WD2793 - 2 DSDD Drives")
+DEFINE_DEVICE_TYPE(MSX_SLOT_DISK2_FD1793_SS, msx_slot_disk2_fd1793_ss_device, "msx_slot_disk2_fd1793_ss", "MSX Internal floppy type 2 - FD1793 - 1 SSDD Drive")
+DEFINE_DEVICE_TYPE(MSX_SLOT_DISK2_MB8877, msx_slot_disk2_mb8877_device, "msx_slot_disk2_mb8877", "MSX Internal floppy type 2 - MB8877 - 1 DSDD Drive")
+DEFINE_DEVICE_TYPE(MSX_SLOT_DISK2_MB8877_SS, msx_slot_disk2_mb8877_ss_device, "msx_slot_disk2_mb8877_ss", "MSX Internal floppy type 2 - MB8877 - 1 SSDD Drive")
+DEFINE_DEVICE_TYPE(MSX_SLOT_DISK2_MB8877_2_DRIVES, msx_slot_disk2_mb8877_2_drives_device, "msx_slot_disk2_mb8877_2_drives", "MSX Internal floppy type 2 - MB8877 - 2 DSDD Drives")
+DEFINE_DEVICE_TYPE(MSX_SLOT_DISK2_WD2793, msx_slot_disk2_wd2793_device, "msx_slot_disk2_wd2793", "MSX Internal floppy type 2 - WD2793 - 1 DSDD Drive")
+DEFINE_DEVICE_TYPE(MSX_SLOT_DISK2_WD2793_2_DRIVES, msx_slot_disk2_wd2793_2_drives_device, "msx_slot_disk2_wd2793_2_drives", "MSX Internal floppy type 2 - WD2793 - 2 DSDD Drives")
+DEFINE_DEVICE_TYPE(MSX_SLOT_DISK3_TC8566, msx_slot_disk3_tc8566_device, "msx_slot_disk3_tc8566", "MSX Internal floppy type 3 - TC8566 - 1 DSDD Drive")
+DEFINE_DEVICE_TYPE(MSX_SLOT_DISK3_TC8566_2_DRIVES, msx_slot_disk3_tc8566_2_drives_device, "msx_slot_disk3_tc8566_2_drives", "MSX Internal floppy type 3 - TC8566 - 2 DSDD Drives")
+DEFINE_DEVICE_TYPE(MSX_SLOT_DISK4_TC8566, msx_slot_disk4_tc8566_device, "msx_slot_disk4_tc8566", "MSX Internal floppy type 4 - TC8566 - 1 DSDD Drive")
+DEFINE_DEVICE_TYPE(MSX_SLOT_DISK5_WD2793, msx_slot_disk5_wd2793_device, "msx_slot_disk5_wd2793", "MSX Internal floppy type 5 - WD2793 - 1 DSDD Drive")
+DEFINE_DEVICE_TYPE(MSX_SLOT_DISK6_WD2793_N, msx_slot_disk6_wd2793_n_device, "msx_slot_disk6_wd2793_n", "MSX Internal floppy type 6 - WD2793 no force ready - 1 DSDD Drive")
+DEFINE_DEVICE_TYPE(MSX_SLOT_DISK7_MB8877, msx_slot_disk7_mb8877_device, "msx_slot_disk7_mb8877", "MSX Internal floppy type 7 - MB8877 - 1 DSDD Drive")
+DEFINE_DEVICE_TYPE(MSX_SLOT_DISK8_MB8877, msx_slot_disk8_mb8877_device, "msx_slot_disk8_mb8877", "MSX Internal floppy type 8 - MB8877 - 1 DSDD Drive")
+DEFINE_DEVICE_TYPE(MSX_SLOT_DISK8_WD2793_2_DRIVES, msx_slot_disk8_wd2793_2_drives_device, "msx_slot_disk8_wd2793_2_drives", "MSX Internal floppy type 8 - WD2793 - 2 DSDD Drives")
+DEFINE_DEVICE_TYPE(MSX_SLOT_DISK9_WD2793_N, msx_slot_disk9_wd2793_n_device, "msx_slot_disk9_wd2793_n", "MSX Internal floppy type 9 - WD2793 no force ready - 1 DSDD Drive")
+DEFINE_DEVICE_TYPE(MSX_SLOT_DISK10_MB8877, msx_slot_disk10_mb8877_device, "msx_slot_disk10_mb8877", "MSX Internal floppy type 10 - MB8877 - 1 DSDD Drive")
+DEFINE_DEVICE_TYPE(MSX_SLOT_DISK10_MB8877_2_DRIVES, msx_slot_disk10_mb8877_2_drives_device, "msx_slot_disk10_mb8877_2_drives", "MSX Internal floppy type 10 - MB8877 - 2 DSDD Drives")
+DEFINE_DEVICE_TYPE(MSX_SLOT_DISK11_WD2793, msx_slot_disk11_wd2793_device, "msx_slot_disk11_wd2793", "MSX Internal floppy type 11 - WD2793 - 1 DSDD Drive")
+
+
+static void msx_floppies(device_slot_interface &device)
+{
+ device.option_add("35dd", FLOPPY_35_DD);
+ device.option_add("35ssdd", FLOPPY_35_SSDD);
+}
+
+void msx_slot_disk_device::floppy_formats(format_registration &fr)
+{
+ fr.add_mfm_containers();
+ fr.add(FLOPPY_MSX_FORMAT);
+ fr.add(FLOPPY_DMK_FORMAT);
+}
+
+
+msx_slot_disk_device::msx_slot_disk_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, int nr_drives)
+ : msx_slot_rom_device(mconfig, type, tag, owner, clock)
+ , m_floppy(*this, "fdc:%u", 0U)
+ , m_current_floppy(nullptr)
+ , m_internal_drive_led(*this, "internal_drive%u_led", 0U)
+ , m_nr_drives(nr_drives)
+{
+}
+
+void msx_slot_disk_device::add_drive_mconfig(machine_config &config, bool double_sided)
+{
+ for (int drive = 0; drive < m_nr_drives; drive++)
+ FLOPPY_CONNECTOR(config, m_floppy[drive], msx_floppies, double_sided ? "35dd" : "35ssdd", msx_slot_disk_device::floppy_formats).enable_sound(true);
+}
+
+void msx_slot_disk_device::device_start()
+{
+ msx_slot_rom_device::device_start();
+
+ m_internal_drive_led.resolve();
+}
+
+void msx_slot_disk_device::device_reset()
+{
+ msx_slot_rom_device::device_reset();
+ for (int i = 0; i < m_internal_drive_led.size(); i++)
+ {
+ set_drive_access_led_state(i, 0);
+ }
+}
+
+void msx_slot_disk_device::set_drive_access_led_state(int drive, int led_state)
+{
+ m_internal_drive_led[drive] = led_state;
+}
+
+
+msx_slot_wd_disk_device::msx_slot_wd_disk_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, int nr_drives)
+ : msx_slot_disk_device(mconfig, type, tag, owner, clock, nr_drives)
+ , m_fdc(*this, "fdc")
+ , m_control_led_bit(0)
+{
+}
+
+void msx_slot_wd_disk_device::device_start()
+{
+ msx_slot_disk_device::device_start();
+}
+
+template <typename FDCType>
+void msx_slot_wd_disk_device::add_mconfig(machine_config &config, FDCType &&type, bool force_ready, bool double_sided)
+{
+ std::forward<FDCType>(type)(config, m_fdc, 4_MHz_XTAL / 4);
+ m_fdc->set_force_ready(force_ready);
+ add_drive_mconfig(config, double_sided);
+}
+
+
+
+msx_slot_tc8566_disk_device::msx_slot_tc8566_disk_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, int nr_drives)
+ : msx_slot_disk_device(mconfig, type, tag, owner, clock, nr_drives)
+ , m_fdc(*this, "fdc")
+{
+}
+
+void msx_slot_tc8566_disk_device::add_mconfig(machine_config &config)
+{
+ TC8566AF(config, m_fdc, 16'000'000);
+
+ add_drive_mconfig(config, DS);
+}
+
+void msx_slot_tc8566_disk_device::dor_w(u8 data)
+{
+ // Assuming drive LEDs are connected to the motor signal
+ set_drive_access_led_state(0, BIT(data, 4));
+ set_drive_access_led_state(1, BIT(data, 5));
+ m_fdc->dor_w(data);
+}
+
+
+
+msx_slot_disk1_base_device::msx_slot_disk1_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, int nr_drives)
+ : msx_slot_wd_disk_device(mconfig, type, tag, owner, clock, nr_drives)
+ , m_side_control(0)
+ , m_control(0)
+{
+ set_control_led_bit(6);
+}
+
+void msx_slot_disk1_base_device::device_start()
+{
+ msx_slot_wd_disk_device::device_start();
+
+ save_item(NAME(m_side_control));
+ save_item(NAME(m_control));
+
+ page(1)->install_rom(0x4000, 0x7fff, rom_base());
+ page(1)->install_read_handler(0x7ff8, 0x7ff8, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::status_r)));
+ page(1)->install_read_handler(0x7ff9, 0x7ff9, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::track_r)));
+ page(1)->install_read_handler(0x7ffa, 0x7ffa, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::sector_r)));
+ page(1)->install_read_handler(0x7ffb, 0x7ffb, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::data_r)));
+ page(1)->install_read_handler(0x7ffc, 0x7ffc, emu::rw_delegate(*this, FUNC(msx_slot_disk1_base_device::side_control_r)));
+ page(1)->install_read_handler(0x7ffd, 0x7ffd, emu::rw_delegate(*this, FUNC(msx_slot_disk1_base_device::control_r)));
+ page(1)->install_read_handler(0x7fff, 0x7fff, emu::rw_delegate(*this, FUNC(msx_slot_disk1_base_device::status_r)));
+ page(1)->install_write_handler(0x7ff8, 0x7ff8, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::cmd_w)));
+ page(1)->install_write_handler(0x7ff9, 0x7ff9, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::track_w)));
+ page(1)->install_write_handler(0x7ffa, 0x7ffa, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::sector_w)));
+ page(1)->install_write_handler(0x7ffb, 0x7ffb, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::data_w)));
+ page(1)->install_write_handler(0x7ffc, 0x7ffc, emu::rw_delegate(*this, FUNC(msx_slot_disk1_base_device::set_side_control)));
+ page(1)->install_write_handler(0x7ffd, 0x7ffd, emu::rw_delegate(*this, FUNC(msx_slot_disk1_base_device::set_control)));
+
+ if (page_configured(2))
+ {
+ page(2)->install_read_handler(0xbff8, 0xbff8, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::status_r)));
+ page(2)->install_read_handler(0xbff9, 0xbff9, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::track_r)));
+ page(2)->install_read_handler(0xbffa, 0xbffa, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::sector_r)));
+ page(2)->install_read_handler(0xbffb, 0xbffb, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::data_r)));
+ page(2)->install_read_handler(0xbffc, 0xbffc, emu::rw_delegate(*this, FUNC(msx_slot_disk1_base_device::side_control_r)));
+ page(2)->install_read_handler(0xbffd, 0xbffd, emu::rw_delegate(*this, FUNC(msx_slot_disk1_base_device::control_r)));
+ page(2)->install_read_handler(0xbfff, 0xbfff, emu::rw_delegate(*this, FUNC(msx_slot_disk1_base_device::status_r)));
+ page(2)->install_write_handler(0xbff8, 0xbff8, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::cmd_w)));
+ page(2)->install_write_handler(0xbff9, 0xbff9, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::track_w)));
+ page(2)->install_write_handler(0xbffa, 0xbffa, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::sector_w)));
+ page(2)->install_write_handler(0xbffb, 0xbffb, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::data_w)));
+ page(2)->install_write_handler(0xbffc, 0xbffc, emu::rw_delegate(*this, FUNC(msx_slot_disk1_base_device::set_side_control)));
+ page(2)->install_write_handler(0xbffd, 0xbffd, emu::rw_delegate(*this, FUNC(msx_slot_disk1_base_device::set_control)));
+ }
+}
+
+void msx_slot_disk1_base_device::device_reset()
+{
+ msx_slot_disk_device::device_reset();
+ m_fdc->dden_w(false);
+}
+
+void msx_slot_disk1_base_device::device_post_load()
+{
+ set_control(m_control);
+}
+
+void msx_slot_disk1_base_device::set_side_control(u8 data)
+{
+ m_side_control = data;
+
+ if (m_current_floppy)
+ {
+ m_current_floppy->ss_w(BIT(m_side_control, 0));
+ }
+}
+
+void msx_slot_disk1_base_device::set_control(u8 data)
+{
+ // 7------- motor on (0 = on)
+ // -6------ in-use / LED (0 = on)
+ // --5432-- unused
+ // ------1- drive 1 select (0 = selected)
+ // -------0 drive 0 select (0 = selected)
+
+ m_control = data;
+
+ switch (m_control & 0x03)
+ {
+ case 0:
+ case 2:
+ m_current_floppy = m_floppy[0] ? m_floppy[0]->get_device() : nullptr;
+ set_drive_access_led_state(0, BIT(m_control, get_control_led_bit()));
+ set_drive_access_led_state(1, 0);
+ break;
+
+ case 1:
+ m_current_floppy = m_floppy[1] ? m_floppy[1]->get_device() : nullptr;
+ set_drive_access_led_state(0, 0);
+ set_drive_access_led_state(1, BIT(m_control, get_control_led_bit()));
+ break;
+
+ default:
+ m_current_floppy = nullptr;
+ set_drive_access_led_state(0, 0);
+ set_drive_access_led_state(1, 0);
+ break;
+ }
+
+ if (m_current_floppy)
+ {
+ m_current_floppy->mon_w(BIT(m_control, 7) ? 0 : 1);
+ m_current_floppy->ss_w(BIT(m_side_control, 0));
+ }
+
+ m_fdc->set_floppy(m_current_floppy);
+}
+
+u8 msx_slot_disk1_base_device::side_control_r()
+{
+ return 0xfe | (m_side_control & 0x01);
+}
+
+u8 msx_slot_disk1_base_device::control_r()
+{
+ return (m_control & 0x83) | 0x78;
+}
+
+u8 msx_slot_disk1_base_device::status_r()
+{
+ return 0x3f | (m_fdc->intrq_r() ? 0 : 0x40) | (m_fdc->drq_r() ? 0 : 0x80);
+}
+
+
+msx_slot_disk1_fd1793_device::msx_slot_disk1_fd1793_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : msx_slot_disk1_base_device(mconfig, MSX_SLOT_DISK1_FD1793, tag, owner, clock, DRIVES_1)
+{
+}
+
+void msx_slot_disk1_fd1793_device::device_add_mconfig(machine_config &config)
+{
+ add_mconfig(config, FD1793, NO_FORCE_READY, DS);
+}
+
+
+msx_slot_disk1_mb8877_device::msx_slot_disk1_mb8877_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : msx_slot_disk1_base_device(mconfig, MSX_SLOT_DISK1_MB8877, tag, owner, clock, DRIVES_1)
+{
+}
+
+void msx_slot_disk1_mb8877_device::device_add_mconfig(machine_config &config)
+{
+ add_mconfig(config, MB8877, FORCE_READY, DS);
+}
+
+
+msx_slot_disk1_wd2793_n_device::msx_slot_disk1_wd2793_n_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : msx_slot_disk1_base_device(mconfig, MSX_SLOT_DISK1_WD2793_N, tag, owner, clock, DRIVES_1)
+{
+}
+
+void msx_slot_disk1_wd2793_n_device::device_add_mconfig(machine_config &config)
+{
+ add_mconfig(config, WD2793, NO_FORCE_READY, DS);
+}
+
+
+msx_slot_disk1_wd2793_n_2_drives_device::msx_slot_disk1_wd2793_n_2_drives_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : msx_slot_disk1_base_device(mconfig, MSX_SLOT_DISK1_WD2793_N_2_DRIVES, tag, owner, clock, DRIVES_2)
+{
+}
+
+void msx_slot_disk1_wd2793_n_2_drives_device::device_add_mconfig(machine_config &config)
+{
+ add_mconfig(config, WD2793, NO_FORCE_READY, DS);
+}
+
+
+msx_slot_disk1_wd2793_device::msx_slot_disk1_wd2793_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : msx_slot_disk1_base_device(mconfig, MSX_SLOT_DISK1_WD2793, tag, owner, clock, DRIVES_1)
+{
+}
+
+void msx_slot_disk1_wd2793_device::device_add_mconfig(machine_config &config)
+{
+ add_mconfig(config, WD2793, FORCE_READY, DS);
+}
+
+
+msx_slot_disk1_wd2793_0_device::msx_slot_disk1_wd2793_0_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : msx_slot_disk1_base_device(mconfig, MSX_SLOT_DISK1_WD2793_0, tag, owner, clock, NO_DRIVES)
+{
+}
+
+void msx_slot_disk1_wd2793_0_device::device_add_mconfig(machine_config &config)
+{
+ add_mconfig(config, WD2793, FORCE_READY, DS);
+}
+
+
+msx_slot_disk1_wd2793_ss_device::msx_slot_disk1_wd2793_ss_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : msx_slot_disk1_base_device(mconfig, MSX_SLOT_DISK1_WD2793_SS, tag, owner, clock, DRIVES_1)
+{
+}
+
+void msx_slot_disk1_wd2793_ss_device::device_add_mconfig(machine_config &config)
+{
+ add_mconfig(config, WD2793, FORCE_READY, SS);
+}
+
+
+msx_slot_disk1_wd2793_2_drives_device::msx_slot_disk1_wd2793_2_drives_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : msx_slot_disk1_base_device(mconfig, MSX_SLOT_DISK1_WD2793_2_DRIVES, tag, owner, clock, DRIVES_2)
+{
+}
+
+void msx_slot_disk1_wd2793_2_drives_device::device_add_mconfig(machine_config &config)
+{
+ add_mconfig(config, WD2793, FORCE_READY, DS);
+}
+
+
+
+
+msx_slot_disk2_base_device::msx_slot_disk2_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, int nr_drives)
+ : msx_slot_wd_disk_device(mconfig, type, tag, owner, clock, nr_drives)
+ , m_control(0)
+{
+ set_control_led_bit(6);
+}
+
+void msx_slot_disk2_base_device::device_start()
+{
+ msx_slot_wd_disk_device::device_start();
+
+ save_item(NAME(m_control));
+
+ page(1)->install_rom(0x4000, 0x7fff, rom_base());
+ page(1)->install_read_handler(0x7fb8, 0x7fb8, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::status_r)));
+ page(1)->install_read_handler(0x7fb9, 0x7fb9, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::track_r)));
+ page(1)->install_read_handler(0x7fba, 0x7fba, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::sector_r)));
+ page(1)->install_read_handler(0x7fbb, 0x7fbb, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::data_r)));
+ page(1)->install_read_handler(0x7fbc, 0x7fbc, emu::rw_delegate(*this, FUNC(msx_slot_disk2_base_device::status_r)));
+ page(1)->install_write_handler(0x7fb8, 0x7fb8, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::cmd_w)));
+ page(1)->install_write_handler(0x7fb9, 0x7fb9, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::track_w)));
+ page(1)->install_write_handler(0x7fba, 0x7fba, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::sector_w)));
+ page(1)->install_write_handler(0x7fbb, 0x7fbb, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::data_w)));
+ page(1)->install_write_handler(0x7fbc, 0x7fbc, emu::rw_delegate(*this, FUNC(msx_slot_disk2_base_device::set_control)));
+
+ page(2)->install_read_handler(0xbfb8, 0xbfb8, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::status_r)));
+ page(2)->install_read_handler(0xbfb9, 0xbfb9, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::track_r)));
+ page(2)->install_read_handler(0xbfba, 0xbfba, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::sector_r)));
+ page(2)->install_read_handler(0xbfbb, 0xbfbb, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::data_r)));
+ page(2)->install_read_handler(0xbfbc, 0xbfbc, emu::rw_delegate(*this, FUNC(msx_slot_disk2_base_device::status_r)));
+ page(2)->install_write_handler(0xbfb8, 0xbfb8, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::cmd_w)));
+ page(2)->install_write_handler(0xbfb9, 0xbfb9, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::track_w)));
+ page(2)->install_write_handler(0xbfba, 0xbfba, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::sector_w)));
+ page(2)->install_write_handler(0xbfbb, 0xbfbb, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::data_w)));
+ page(2)->install_write_handler(0xbfbc, 0xbfbc, emu::rw_delegate(*this, FUNC(msx_slot_disk2_base_device::set_control)));
+}
+
+void msx_slot_disk2_base_device::device_reset()
+{
+ msx_slot_disk_device::device_reset();
+ m_fdc->dden_w(false);
+}
+
+void msx_slot_disk2_base_device::device_post_load()
+{
+ set_control(m_control);
+}
+
+void msx_slot_disk2_base_device::set_control(u8 data)
+{
+ m_control = data;
+
+ switch (m_control & 3)
+ {
+ case 1:
+ m_current_floppy = m_floppy[0] ? m_floppy[0]->get_device() : nullptr;
+ set_drive_access_led_state(0, BIT(m_control, get_control_led_bit()));
+ set_drive_access_led_state(1, 0);
+ break;
+
+ case 2:
+ m_current_floppy = m_floppy[1] ? m_floppy[1]->get_device() : nullptr;
+ set_drive_access_led_state(0, 0);
+ set_drive_access_led_state(1, BIT(m_control, get_control_led_bit()));
+ break;
+
+ default:
+ m_current_floppy = nullptr;
+ set_drive_access_led_state(0, 0);
+ set_drive_access_led_state(1, 0);
+ break;
+ }
+
+ if (m_current_floppy)
+ {
+ m_current_floppy->mon_w(BIT(m_control, 3) ? 0 : 1);
+ m_current_floppy->ss_w(BIT(m_control, 2) ? 1 : 0);
+ }
+
+ m_fdc->set_floppy(m_current_floppy);
+}
+
+u8 msx_slot_disk2_base_device::status_r()
+{
+ return 0x3f | (m_fdc->drq_r() ? 0 : 0x40) | (m_fdc->intrq_r() ? 0x80 : 0);
+}
+
+
+msx_slot_disk2_fd1793_ss_device::msx_slot_disk2_fd1793_ss_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : msx_slot_disk2_base_device(mconfig, MSX_SLOT_DISK2_FD1793_SS, tag, owner, clock, DRIVES_1)
+{
+}
+
+void msx_slot_disk2_fd1793_ss_device::device_add_mconfig(machine_config &config)
+{
+ add_mconfig(config, FD1793, FORCE_READY, SS);
+}
+
+
+msx_slot_disk2_mb8877_device::msx_slot_disk2_mb8877_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : msx_slot_disk2_base_device(mconfig, MSX_SLOT_DISK2_MB8877, tag, owner, clock, DRIVES_1)
+{
+}
+
+void msx_slot_disk2_mb8877_device::device_add_mconfig(machine_config &config)
+{
+ add_mconfig(config, MB8877, FORCE_READY, DS);
+}
+
+
+msx_slot_disk2_mb8877_ss_device::msx_slot_disk2_mb8877_ss_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : msx_slot_disk2_base_device(mconfig, MSX_SLOT_DISK2_MB8877_SS, tag, owner, clock, DRIVES_1)
+{
+}
+
+void msx_slot_disk2_mb8877_ss_device::device_add_mconfig(machine_config &config)
+{
+ add_mconfig(config, MB8877, FORCE_READY, SS);
+}
+
+
+msx_slot_disk2_mb8877_2_drives_device::msx_slot_disk2_mb8877_2_drives_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : msx_slot_disk2_base_device(mconfig, MSX_SLOT_DISK2_MB8877_2_DRIVES, tag, owner, clock, DRIVES_2)
+{
+}
+
+void msx_slot_disk2_mb8877_2_drives_device::device_add_mconfig(machine_config &config)
+{
+ add_mconfig(config, MB8877, FORCE_READY, DS);
+}
+
+
+msx_slot_disk2_wd2793_device::msx_slot_disk2_wd2793_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : msx_slot_disk2_base_device(mconfig, MSX_SLOT_DISK2_WD2793, tag, owner, clock, DRIVES_1)
+{
+}
+
+void msx_slot_disk2_wd2793_device::device_add_mconfig(machine_config &config)
+{
+ add_mconfig(config, WD2793, FORCE_READY, DS);
+}
+
+
+msx_slot_disk2_wd2793_2_drives_device::msx_slot_disk2_wd2793_2_drives_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : msx_slot_disk2_base_device(mconfig, MSX_SLOT_DISK2_WD2793_2_DRIVES, tag, owner, clock, DRIVES_2)
+{
+}
+
+void msx_slot_disk2_wd2793_2_drives_device::device_add_mconfig(machine_config &config)
+{
+ add_mconfig(config, WD2793, FORCE_READY, DS);
+}
+
+
+
+
+
+
+msx_slot_disk3_tc8566_device::msx_slot_disk3_tc8566_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : msx_slot_disk3_tc8566_device(mconfig, MSX_SLOT_DISK3_TC8566, tag, owner, clock, DRIVES_1)
+{
+}
+
+msx_slot_disk3_tc8566_device::msx_slot_disk3_tc8566_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, int nr_drives)
+ : msx_slot_tc8566_disk_device(mconfig, type, tag, owner, clock, nr_drives)
+{
+}
+
+void msx_slot_disk3_tc8566_device::device_add_mconfig(machine_config &config)
+{
+ add_mconfig(config);
+}
+
+void msx_slot_disk3_tc8566_device::device_start()
+{
+ msx_slot_tc8566_disk_device::device_start();
+
+ page(1)->install_rom(0x4000, 0x7fff, rom_base());
+ page(1)->install_read_handler(0x7ffa, 0x7ffa, emu::rw_delegate(*m_fdc, FUNC(tc8566af_device::msr_r)));
+ page(1)->install_read_handler(0x7ffb, 0x7ffb, emu::rw_delegate(*m_fdc, FUNC(tc8566af_device::fifo_r)));
+ page(1)->install_write_handler(0x7ff8, 0x7ff8, emu::rw_delegate(*this, FUNC(msx_slot_disk3_tc8566_device::dor_w)));
+ page(1)->install_write_handler(0x7ff9, 0x7ff9, emu::rw_delegate(*m_fdc, FUNC(tc8566af_device::cr1_w)));
+ page(1)->install_write_handler(0x7ffb, 0x7ffb, emu::rw_delegate(*m_fdc, FUNC(tc8566af_device::fifo_w)));
+
+ page(2)->install_read_handler(0xbffa, 0xbffa, emu::rw_delegate(*m_fdc, FUNC(tc8566af_device::msr_r)));
+ page(2)->install_read_handler(0xbffb, 0xbffb, emu::rw_delegate(*m_fdc, FUNC(tc8566af_device::fifo_r)));
+ page(2)->install_write_handler(0xbff8, 0xbff8, emu::rw_delegate(*this, FUNC(msx_slot_disk3_tc8566_device::dor_w)));
+ page(2)->install_write_handler(0xbff9, 0xbff9, emu::rw_delegate(*m_fdc, FUNC(tc8566af_device::cr1_w)));
+ page(2)->install_write_handler(0xbffb, 0xbffb, emu::rw_delegate(*m_fdc, FUNC(tc8566af_device::fifo_w)));
+}
+
+
+msx_slot_disk3_tc8566_2_drives_device::msx_slot_disk3_tc8566_2_drives_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : msx_slot_disk3_tc8566_device(mconfig, MSX_SLOT_DISK3_TC8566_2_DRIVES, tag, owner, clock, DRIVES_2)
+{
+}
+
+void msx_slot_disk3_tc8566_2_drives_device::device_add_mconfig(machine_config &config)
+{
+ add_mconfig(config);
+}
+
+
+
+
+
+
+msx_slot_disk4_tc8566_device::msx_slot_disk4_tc8566_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : msx_slot_tc8566_disk_device(mconfig, MSX_SLOT_DISK4_TC8566, tag, owner, clock, DRIVES_1)
+ , m_rombank(*this, "rombank")
+{
+}
+
+void msx_slot_disk4_tc8566_device::device_start()
+{
+ msx_slot_tc8566_disk_device::device_start();
+
+ m_rombank->configure_entries(0, 4, rom_base(), 0x4000);
+ m_rombank->set_entry(0);
+
+ page(1)->install_read_bank(0x4000, 0x7fff, m_rombank);
+ page(1)->install_read_handler(0x7ff0, 0x7ff0, emu::rw_delegate(*this, FUNC(msx_slot_disk4_tc8566_device::bank_r)));
+ page(1)->install_write_handler(0x7ff0, 0x7ff0, emu::rw_delegate(*this, FUNC(msx_slot_disk4_tc8566_device::bank_w)));
+ page(1)->install_read_handler(0x7ff1, 0x7ff1, emu::rw_delegate(*this, FUNC(msx_slot_disk4_tc8566_device::media_change_r)));
+ page(1)->install_write_handler(0x7ff2, 0x7ff2, emu::rw_delegate(*this, FUNC(msx_slot_disk4_tc8566_device::dor_w)));
+ page(1)->install_write_handler(0x7ff3, 0x7ff3, emu::rw_delegate(*m_fdc, FUNC(tc8566af_device::cr1_w)));
+ page(1)->install_read_handler(0x7ff4, 0x7ff4, emu::rw_delegate(*m_fdc, FUNC(tc8566af_device::msr_r)));
+ page(1)->install_read_handler(0x7ff5, 0x7ff5, emu::rw_delegate(*m_fdc, FUNC(tc8566af_device::fifo_r)));
+ page(1)->install_write_handler(0x7ff5, 0x7ff5, emu::rw_delegate(*m_fdc, FUNC(tc8566af_device::fifo_w)));
+ page(1)->install_read_handler(0x7ffc, 0x7ffc, emu::rw_delegate(*this, FUNC(msx_slot_disk4_tc8566_device::unk_7ffc_r)));
+ page(1)->install_read_handler(0x7ffd, 0x7ffd, emu::rw_delegate(*this, FUNC(msx_slot_disk4_tc8566_device::unk_7ffd_r)));
+ page(1)->install_read_handler(0x7fff, 0x7fff, emu::rw_delegate(*this, FUNC(msx_slot_disk4_tc8566_device::unk_7fff_r)));
+ // TODO: Investigate on real unit
+ // Some or all register reads are mirrored? Register writes also?
+ // At least msr_r must be mirrored otherwise Microcabin software will not boot (on FS-A1ST).
+ page(2)->install_read_handler(0xbff0, 0xbff0, emu::rw_delegate(*this, FUNC(msx_slot_disk4_tc8566_device::bank_r)));
+ page(2)->install_read_handler(0xbff1, 0xbff1, emu::rw_delegate(*this, FUNC(msx_slot_disk4_tc8566_device::media_change_r)));
+ page(2)->install_read_handler(0xbff4, 0xbff4, emu::rw_delegate(*m_fdc, FUNC(tc8566af_device::msr_r)));
+ page(2)->install_read_handler(0xbff5, 0xbff5, emu::rw_delegate(*m_fdc, FUNC(tc8566af_device::fifo_r)));
+ page(2)->install_read_handler(0xbffc, 0xbffc, emu::rw_delegate(*this, FUNC(msx_slot_disk4_tc8566_device::unk_7ffc_r)));
+ page(2)->install_read_handler(0xbffd, 0xbffd, emu::rw_delegate(*this, FUNC(msx_slot_disk4_tc8566_device::unk_7ffd_r)));
+ page(2)->install_read_handler(0xbfff, 0xbfff, emu::rw_delegate(*this, FUNC(msx_slot_disk4_tc8566_device::unk_7fff_r)));
+}
+
+void msx_slot_disk4_tc8566_device::device_add_mconfig(machine_config &config)
+{
+ add_mconfig(config);
+}
+
+u8 msx_slot_disk4_tc8566_device::bank_r()
+{
+ return m_rombank->entry();
+}
+
+void msx_slot_disk4_tc8566_device::bank_w(u8 data)
+{
+ m_rombank->set_entry(data & 0x03);
+}
+
+u8 msx_slot_disk4_tc8566_device::media_change_r()
+{
+ return (m_floppy[0] && m_floppy[0]->get_device()->dskchg_r() ? 0x10 : 0x00) |
+ (m_floppy[1] && m_floppy[1]->get_device()->dskchg_r() ? 0x20 : 0x00) |
+ 0x03;
+}
+
+u8 msx_slot_disk4_tc8566_device::unk_7ffc_r()
+{
+ // Unknown
+ return 0xfc;
+}
+
+u8 msx_slot_disk4_tc8566_device::unk_7ffd_r()
+{
+ // Unknown
+ return 0xfc;
+}
+
+u8 msx_slot_disk4_tc8566_device::unk_7fff_r()
+{
+ // Unknown
+ return 0x3f;
+}
+
+
+
+msx_slot_disk5_wd2793_device::msx_slot_disk5_wd2793_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : msx_slot_wd_disk_device(mconfig, MSX_SLOT_DISK5_WD2793, tag, owner, clock, DRIVES_1)
+ , m_control(0)
+{
+}
+
+void msx_slot_disk5_wd2793_device::device_add_mconfig(machine_config &config)
+{
+ add_mconfig(config, WD2793, FORCE_READY, DS);
+}
+
+void msx_slot_disk5_wd2793_device::device_start()
+{
+ msx_slot_wd_disk_device::device_start();
+
+ save_item(NAME(m_control));
+
+ page(1)->install_rom(0x4000, 0x7fff, rom_base());
+
+ // Install IO read/write handlers
+ io_space().install_write_handler(0xd0, 0xd0, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::cmd_w)));
+ io_space().install_write_handler(0xd1, 0xd1, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::track_w)));
+ io_space().install_write_handler(0xd2, 0xd2, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::sector_w)));
+ io_space().install_write_handler(0xd3, 0xd3, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::data_w)));
+ io_space().install_write_handler(0xd4, 0xd4, emu::rw_delegate(*this, FUNC(msx_slot_disk5_wd2793_device::control_w)));
+ io_space().install_read_handler(0xd0, 0xd0, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::status_r)));
+ io_space().install_read_handler(0xd1, 0xd1, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::track_r)));
+ io_space().install_read_handler(0xd2, 0xd2, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::sector_r)));
+ io_space().install_read_handler(0xd3, 0xd3, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::data_r)));
+ io_space().install_read_handler(0xd4, 0xd4, emu::rw_delegate(*this, FUNC(msx_slot_disk5_wd2793_device::status_r)));
+}
+
+void msx_slot_disk5_wd2793_device::device_reset()
+{
+ msx_slot_disk_device::device_reset();
+ m_fdc->dden_w(false);
+}
+
+void msx_slot_disk5_wd2793_device::device_post_load()
+{
+ control_w(m_control);
+}
+
+void msx_slot_disk5_wd2793_device::control_w(u8 control)
+{
+ m_control = control;
+
+ switch (m_control & 0x0f)
+ {
+ case 0x01:
+ m_current_floppy = m_floppy[0] ? m_floppy[0]->get_device() : nullptr;
+ set_drive_access_led_state(0, BIT(m_control, 6));
+ set_drive_access_led_state(1, 0);
+ set_drive_access_led_state(2, 0);
+ set_drive_access_led_state(3, 0);
+ break;
+
+ case 0x02:
+ m_current_floppy = m_floppy[1] ? m_floppy[1]->get_device() : nullptr;
+ set_drive_access_led_state(0, 0);
+ set_drive_access_led_state(1, BIT(m_control, 6));
+ set_drive_access_led_state(2, 0);
+ set_drive_access_led_state(3, 0);
+ break;
+
+ case 0x04:
+ m_current_floppy = m_floppy[2] ? m_floppy[2]->get_device() : nullptr;
+ set_drive_access_led_state(0, 0);
+ set_drive_access_led_state(1, 0);
+ set_drive_access_led_state(2, BIT(m_control, 6));
+ set_drive_access_led_state(3, 0);
+ break;
+
+ case 0x08:
+ m_current_floppy = m_floppy[3] ? m_floppy[3]->get_device() : nullptr;
+ set_drive_access_led_state(0, 0);
+ set_drive_access_led_state(1, 0);
+ set_drive_access_led_state(2, 0);
+ set_drive_access_led_state(3, BIT(m_control, 6));
+ break;
+
+ default:
+ m_current_floppy = nullptr;
+ set_drive_access_led_state(0, 0);
+ set_drive_access_led_state(1, 0);
+ set_drive_access_led_state(2, 0);
+ set_drive_access_led_state(3, 0);
+ break;
+ }
+
+ if (m_current_floppy)
+ {
+ m_current_floppy->mon_w(BIT(m_control, 5) ? 0 : 1);
+ m_current_floppy->ss_w(BIT(m_control, 4) ? 1 : 0);
+ }
+
+ m_fdc->set_floppy(m_current_floppy);
+}
+
+u8 msx_slot_disk5_wd2793_device::status_r()
+{
+ return 0x3f | (m_fdc->drq_r() ? 0 : 0x40) | (m_fdc->intrq_r() ? 0x80 : 0);
+}
+
+
+
+msx_slot_disk6_wd2793_n_device::msx_slot_disk6_wd2793_n_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : msx_slot_wd_disk_device(mconfig, MSX_SLOT_DISK6_WD2793_N, tag, owner, clock, DRIVES_1)
+ , m_side_motor(0)
+ , m_drive_select(0)
+ , m_drive_present(false)
+ , m_unknown(0)
+{
+}
+
+void msx_slot_disk6_wd2793_n_device::device_add_mconfig(machine_config &config)
+{
+ add_mconfig(config, WD2793, NO_FORCE_READY, DS);
+}
+
+void msx_slot_disk6_wd2793_n_device::device_start()
+{
+ msx_slot_wd_disk_device::device_start();
+
+ save_item(NAME(m_side_motor));
+ save_item(NAME(m_drive_select));
+ save_item(NAME(m_drive_present));
+ save_item(NAME(m_unknown));
+
+ page(1)->install_rom(0x4000, 0x7fff, rom_base());
+ page(1)->install_read_handler(0x7ff0, 0x7ff0, 0, 0x0008, 0, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::status_r)));
+ page(1)->install_read_handler(0x7ff1, 0x7ff1, 0, 0x0008, 0, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::track_r)));
+ page(1)->install_read_handler(0x7ff2, 0x7ff2, 0, 0x0008, 0, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::sector_r)));
+ page(1)->install_read_handler(0x7ff3, 0x7ff3, 0, 0x0008, 0, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::data_r)));
+ page(1)->install_read_handler(0x7ff4, 0x7ff4, 0, 0x0008, 0, emu::rw_delegate(*this, FUNC(msx_slot_disk6_wd2793_n_device::side_motor_r)));
+ page(1)->install_read_handler(0x7ff5, 0x7ff5, 0, 0x0008, 0, emu::rw_delegate(*this, FUNC(msx_slot_disk6_wd2793_n_device::select0_r)));
+ page(1)->install_read_handler(0x7ff6, 0x7ff6, 0, 0x0008, 0, emu::rw_delegate(*this, FUNC(msx_slot_disk6_wd2793_n_device::dskchg_r)));
+ page(1)->install_read_handler(0x7ff7, 0x7ff7, 0, 0x0008, 0, emu::rw_delegate(*this, FUNC(msx_slot_disk6_wd2793_n_device::status_r)));
+ page(1)->install_write_handler(0x7ff0, 0x7ff0, 0, 0x0008, 0, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::cmd_w)));
+ page(1)->install_write_handler(0x7ff1, 0x7ff1, 0, 0x0008, 0, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::track_w)));
+ page(1)->install_write_handler(0x7ff2, 0x7ff2, 0, 0x0008, 0, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::sector_w)));
+ page(1)->install_write_handler(0x7ff3, 0x7ff3, 0, 0x0008, 0, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::data_w)));
+ page(1)->install_write_handler(0x7ff4, 0x7ff4, 0, 0x0008, 0, emu::rw_delegate(*this, FUNC(msx_slot_disk6_wd2793_n_device::side_motor_w)));
+ page(1)->install_write_handler(0x7ff5, 0x7ff5, 0, 0x0008, 0, emu::rw_delegate(*this, FUNC(msx_slot_disk6_wd2793_n_device::select_w)));
+ page(1)->install_write_handler(0x7ff6, 0x7ff6, 0, 0x0008, 0, emu::rw_delegate(*this, FUNC(msx_slot_disk6_wd2793_n_device::unknown_w)));
+}
+
+void msx_slot_disk6_wd2793_n_device::device_reset()
+{
+ msx_slot_disk_device::device_reset();
+ m_fdc->dden_w(false);
+ m_drive_select = 0;
+ m_drive_present = false;
+ m_unknown = 0;
+}
+
+void msx_slot_disk6_wd2793_n_device::device_post_load()
+{
+ select_drive();
+}
+
+void msx_slot_disk6_wd2793_n_device::select_drive()
+{
+ if (BIT(m_drive_select, 0))
+ {
+ m_current_floppy = m_floppy[1] ? m_floppy[1]->get_device() : nullptr;
+ m_drive_present = m_current_floppy;
+ }
+ else
+ {
+ m_current_floppy = m_floppy[0] ? m_floppy[0]->get_device() : nullptr;
+ m_drive_present = m_current_floppy;
+ }
+
+ m_fdc->set_floppy(m_current_floppy);
+
+ set_side_motor();
+}
+
+void msx_slot_disk6_wd2793_n_device::set_side_motor()
+{
+ if (m_current_floppy)
+ {
+ m_current_floppy->mon_w(BIT(m_side_motor, 1) ? 0 : 1);
+ m_current_floppy->ss_w(BIT(m_side_motor, 0));
+ }
+ if (BIT(m_drive_select, 0))
+ {
+ set_drive_access_led_state(0, 0);
+ set_drive_access_led_state(1, BIT(m_side_motor, 1));
+ }
+ else
+ {
+ set_drive_access_led_state(0, BIT(m_side_motor, 1));
+ set_drive_access_led_state(1, 0);
+ }
+}
+
+u8 msx_slot_disk6_wd2793_n_device::side_motor_r()
+{
+ // bit 0 = side control
+ // bit 1 = motor control
+ return 0xfc | m_side_motor;
+}
+
+u8 msx_slot_disk6_wd2793_n_device::select0_r()
+{
+ // This reads back a 0 in bit 0 if selected drive is present
+ return 0xfe | (m_drive_present ? 0 : 1);
+}
+
+u8 msx_slot_disk6_wd2793_n_device::dskchg_r()
+{
+ // Disk change status for selected drive
+ return 0xfe | (m_current_floppy && m_current_floppy->dskchg_r() ? 0 : 1);
+}
+
+u8 msx_slot_disk6_wd2793_n_device::status_r()
+{
+ return 0x3f | (m_fdc->intrq_r() ? 0 : 0x40) | (m_fdc->drq_r() ? 0 : 0x80);
+}
+
+void msx_slot_disk6_wd2793_n_device::side_motor_w(u8 data)
+{
+ // Side and motor control
+ // bit 0 = side select
+ // bit 1 = motor on/off
+ m_side_motor = data;
+ set_side_motor();
+}
+
+void msx_slot_disk6_wd2793_n_device::select_w(u8 data)
+{
+ // bit 0 - select drive 0/1
+ m_drive_select = data;
+ select_drive();
+}
+
+void msx_slot_disk6_wd2793_n_device::unknown_w(u8 data)
+{
+ // bit 0 - ? inverse of what is written to drive select.
+ m_unknown = data;
+}
+
+
+
+msx_slot_disk7_mb8877_device::msx_slot_disk7_mb8877_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : msx_slot_wd_disk_device(mconfig, MSX_SLOT_DISK7_MB8877, tag, owner, clock, DRIVES_1)
+ , m_drive_side_motor(0)
+{
+}
+
+void msx_slot_disk7_mb8877_device::device_add_mconfig(machine_config &config)
+{
+ add_mconfig(config, MB8877, FORCE_READY, DS);
+}
+
+void msx_slot_disk7_mb8877_device::device_start()
+{
+ msx_slot_wd_disk_device::device_start();
+
+ save_item(NAME(m_drive_side_motor));
+
+ page(1)->install_rom(0x4000, 0x7fff, rom_base());
+ page(1)->install_read_handler(0x7ff8, 0x7ff8, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::status_r)));
+ page(1)->install_read_handler(0x7ff9, 0x7ff9, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::track_r)));
+ page(1)->install_read_handler(0x7ffa, 0x7ffa, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::sector_r)));
+ page(1)->install_read_handler(0x7ffb, 0x7ffb, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::data_r)));
+ page(1)->install_read_handler(0x7ffc, 0x7ffc, emu::rw_delegate(*this, FUNC(msx_slot_disk7_mb8877_device::status_r)));
+ page(1)->install_write_handler(0x7ff8, 0x7ff8, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::cmd_w)));
+ page(1)->install_write_handler(0x7ff9, 0x7ff9, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::track_w)));
+ page(1)->install_write_handler(0x7ffa, 0x7ffa, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::sector_w)));
+ page(1)->install_write_handler(0x7ffb, 0x7ffb, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::data_w)));
+ page(1)->install_write_handler(0x7ffc, 0x7ffc, emu::rw_delegate(*this, FUNC(msx_slot_disk7_mb8877_device::side_motor_w)));
+
+ page(2)->install_read_handler(0xbff8, 0xbff8, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::status_r)));
+ page(2)->install_read_handler(0xbff9, 0xbff9, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::track_r)));
+ page(2)->install_read_handler(0xbffa, 0xbffa, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::sector_r)));
+ page(2)->install_read_handler(0xbffb, 0xbffb, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::data_r)));
+ page(2)->install_read_handler(0xbffc, 0xbffc, emu::rw_delegate(*this, FUNC(msx_slot_disk7_mb8877_device::status_r)));
+ page(2)->install_write_handler(0xbff8, 0xbff8, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::cmd_w)));
+ page(2)->install_write_handler(0xbff9, 0xbff9, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::track_w)));
+ page(2)->install_write_handler(0xbffa, 0xbffa, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::sector_w)));
+ page(2)->install_write_handler(0xbffb, 0xbffb, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::data_w)));
+ page(2)->install_write_handler(0xbffc, 0xbffc, emu::rw_delegate(*this, FUNC(msx_slot_disk7_mb8877_device::side_motor_w)));
+}
+
+void msx_slot_disk7_mb8877_device::device_reset()
+{
+ msx_slot_disk_device::device_reset();
+ m_fdc->dden_w(false);
+}
+
+void msx_slot_disk7_mb8877_device::device_post_load()
+{
+ select_drive();
+}
+
+void msx_slot_disk7_mb8877_device::select_drive()
+{
+ // No separate bit for the drive LEDs? Assuming LEDs are triggered by the motor on signal.
+ m_current_floppy = nullptr;
+
+ switch (m_drive_side_motor & 0x03)
+ {
+ case 0:
+ m_current_floppy = m_floppy[0] ? m_floppy[0]->get_device() : nullptr;
+ set_drive_access_led_state(0, BIT(~m_drive_side_motor, 3));
+ set_drive_access_led_state(1, 0);
+ break;
+ case 1:
+ m_current_floppy = m_floppy[1] ? m_floppy[1]->get_device() : nullptr;
+ set_drive_access_led_state(0, 0);
+ set_drive_access_led_state(1, BIT(~m_drive_side_motor, 3));
+ break;
+ default:
+ set_drive_access_led_state(0, 0);
+ set_drive_access_led_state(1, 0);
+ break;
+ }
+
+ m_fdc->set_floppy(m_current_floppy);
+}
+
+void msx_slot_disk7_mb8877_device::set_drive_side_motor()
+{
+ select_drive();
+
+ if (m_current_floppy)
+ {
+ m_current_floppy->mon_w(BIT(m_drive_side_motor, 3) ? 0 : 1);
+ m_current_floppy->ss_w(BIT(m_drive_side_motor, 2));
+ }
+}
+
+void msx_slot_disk7_mb8877_device::side_motor_w(u8 data)
+{
+ // Drive, side and motor control
+ // bit 0,1 = drive select
+ // bit 2 = side select
+ // bit 3 = motor on/off
+ m_drive_side_motor = data;
+ set_drive_side_motor();
+}
+
+u8 msx_slot_disk7_mb8877_device::status_r()
+{
+ return (m_drive_side_motor & 0x0f)
+ | (m_current_floppy && m_current_floppy->dskchg_r() ? 0x00 : 0x10)
+ | (m_current_floppy && m_current_floppy->ready_r() ? 0x00 : 0x20)
+ | (m_fdc->intrq_r() ? 0x40 : 0x00)
+ | (m_fdc->drq_r() ? 0x80 : 0x00);
+}
+
+
+
+msx_slot_disk8_mb8877_device::msx_slot_disk8_mb8877_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : msx_slot_disk8_mb8877_device(mconfig, MSX_SLOT_DISK8_MB8877, tag, owner, clock, DRIVES_1)
+{
+}
+
+msx_slot_disk8_mb8877_device::msx_slot_disk8_mb8877_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, int nr_drives)
+ : msx_slot_wd_disk_device(mconfig, type, tag, owner, clock, nr_drives)
+ , m_control(0)
+{
+}
+
+void msx_slot_disk8_mb8877_device::device_add_mconfig(machine_config &config)
+{
+ add_mconfig(config, MB8877, FORCE_READY, DS);
+}
+
+void msx_slot_disk8_mb8877_device::device_start()
+{
+ msx_slot_wd_disk_device::device_start();
+
+ save_item(NAME(m_control));
+
+ page(1)->install_rom(0x4000, 0x7fff, rom_base());
+ page(1)->install_read_handler(0x7f80, 0x7f80, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::status_r)));
+ page(1)->install_read_handler(0x7f81, 0x7f81, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::track_r)));
+ page(1)->install_read_handler(0x7f82, 0x7f82, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::sector_r)));
+ page(1)->install_read_handler(0x7f83, 0x7f83, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::data_r)));
+ page(1)->install_read_handler(0x7f84, 0x7f84, emu::rw_delegate(*this, FUNC(msx_slot_disk8_mb8877_device::status_r)));
+ page(1)->install_write_handler(0x7f80, 0x7f80, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::cmd_w)));
+ page(1)->install_write_handler(0x7f81, 0x7f81, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::track_w)));
+ page(1)->install_write_handler(0x7f82, 0x7f82, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::sector_w)));
+ page(1)->install_write_handler(0x7f83, 0x7f83, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::data_w)));
+ page(1)->install_write_handler(0x7f84, 0x7f84, emu::rw_delegate(*this, FUNC(msx_slot_disk8_mb8877_device::set_control)));
+
+ page(2)->install_read_handler(0xbf80, 0xbf80, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::status_r)));
+ page(2)->install_read_handler(0xbf81, 0xbf81, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::track_r)));
+ page(2)->install_read_handler(0xbf82, 0xbf82, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::sector_r)));
+ page(2)->install_read_handler(0xbf83, 0xbf83, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::data_r)));
+ page(2)->install_read_handler(0xbf84, 0xbf84, emu::rw_delegate(*this, FUNC(msx_slot_disk8_mb8877_device::status_r)));
+ page(2)->install_write_handler(0xbf80, 0xbf80, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::cmd_w)));
+ page(2)->install_write_handler(0xbf81, 0xbf81, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::track_w)));
+ page(2)->install_write_handler(0xbf82, 0xbf82, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::sector_w)));
+ page(2)->install_write_handler(0xbf83, 0xbf83, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::data_w)));
+ page(2)->install_write_handler(0xbf84, 0xbf84, emu::rw_delegate(*this, FUNC(msx_slot_disk8_mb8877_device::set_control)));
+}
+
+
+void msx_slot_disk8_mb8877_device::device_reset()
+{
+ msx_slot_disk_device::device_reset();
+ m_fdc->dden_w(false);
+}
+
+
+void msx_slot_disk8_mb8877_device::device_post_load()
+{
+ set_control(m_control);
+}
+
+
+void msx_slot_disk8_mb8877_device::set_control(u8 data)
+{
+ m_control = data;
+
+ switch (m_control & 3)
+ {
+ case 1:
+ m_current_floppy = m_floppy[0] ? m_floppy[0]->get_device() : nullptr;
+ set_drive_access_led_state(0, BIT(m_control, 6));
+ set_drive_access_led_state(1, 0);
+ break;
+
+ case 2:
+ m_current_floppy = m_floppy[1] ? m_floppy[1]->get_device() : nullptr;
+ set_drive_access_led_state(0, 0);
+ set_drive_access_led_state(1, BIT(m_control, 6));
+ break;
+
+ default:
+ m_current_floppy = nullptr;
+ set_drive_access_led_state(0, 0);
+ set_drive_access_led_state(1, 0);
+ break;
+ }
+
+ if (m_current_floppy)
+ {
+ m_current_floppy->mon_w(BIT(m_control, 3) ? 0 : 1);
+ m_current_floppy->ss_w(BIT(m_control, 2) ? 1 : 0);
+ }
+
+ m_fdc->set_floppy(m_current_floppy);
+}
+
+u8 msx_slot_disk8_mb8877_device::status_r()
+{
+ return 0x3f | (m_fdc->drq_r() ? 0 : 0x40) | (m_fdc->intrq_r() ? 0x80 : 0);
+}
+
+
+msx_slot_disk8_wd2793_2_drives_device::msx_slot_disk8_wd2793_2_drives_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : msx_slot_disk8_mb8877_device(mconfig, MSX_SLOT_DISK8_WD2793_2_DRIVES, tag, owner, clock, DRIVES_2)
+{
+}
+
+void msx_slot_disk8_wd2793_2_drives_device::device_add_mconfig(machine_config &config)
+{
+ add_mconfig(config, WD2793, FORCE_READY, DS);
+}
+
+
+
+
+msx_slot_disk9_wd2793_n_device::msx_slot_disk9_wd2793_n_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : msx_slot_wd_disk_device(mconfig, MSX_SLOT_DISK9_WD2793_N, tag, owner, clock, DRIVES_1)
+ , m_control(0)
+{
+}
+
+void msx_slot_disk9_wd2793_n_device::device_add_mconfig(machine_config &config)
+{
+ add_mconfig(config, WD2793, NO_FORCE_READY, DS);
+}
+
+void msx_slot_disk9_wd2793_n_device::device_start()
+{
+ msx_slot_wd_disk_device::device_start();
+
+ save_item(NAME(m_control));
+
+ page(1)->install_rom(0x4000, 0x7fff, rom_base());
+ page(1)->install_read_handler(0x7ff8, 0x7ff8, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::status_r)));
+ page(1)->install_read_handler(0x7ff9, 0x7ff9, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::track_r)));
+ page(1)->install_read_handler(0x7ffa, 0x7ffa, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::sector_r)));
+ page(1)->install_read_handler(0x7ffb, 0x7ffb, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::data_r)));
+ page(1)->install_read_handler(0x7ffc, 0x7ffc, emu::rw_delegate(*this, FUNC(msx_slot_disk9_wd2793_n_device::status_r)));
+ page(1)->install_write_handler(0x7ff8, 0x7ff8, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::cmd_w)));
+ page(1)->install_write_handler(0x7ff9, 0x7ff9, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::track_w)));
+ page(1)->install_write_handler(0x7ffa, 0x7ffa, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::sector_w)));
+ page(1)->install_write_handler(0x7ffb, 0x7ffb, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::data_w)));
+ page(1)->install_write_handler(0x7ffc, 0x7ffc, emu::rw_delegate(*this, FUNC(msx_slot_disk9_wd2793_n_device::control_w)));
+}
+
+void msx_slot_disk9_wd2793_n_device::device_reset()
+{
+ msx_slot_disk_device::device_reset();
+ m_fdc->dden_w(false);
+}
+
+void msx_slot_disk9_wd2793_n_device::device_post_load()
+{
+ control_w(m_control);
+}
+
+void msx_slot_disk9_wd2793_n_device::control_w(u8 data)
+{
+ m_control = data;
+
+ switch (m_control & 0x03)
+ {
+ case 1:
+ m_current_floppy = m_floppy[0] ? m_floppy[0]->get_device() : nullptr;
+ set_drive_access_led_state(0, BIT(m_control, 6));
+ set_drive_access_led_state(1, 0);
+ break;
+
+ case 2:
+ m_current_floppy = m_floppy[1] ? m_floppy[1]->get_device() : nullptr;
+ set_drive_access_led_state(0, 0);
+ set_drive_access_led_state(1, BIT(m_control, 6));
+ break;
+
+ default:
+ m_current_floppy = nullptr;
+ set_drive_access_led_state(0, 0);
+ set_drive_access_led_state(1, 0);
+ break;
+ }
+
+ if (m_current_floppy)
+ {
+ m_current_floppy->mon_w(BIT(m_control, 3) ? 0 : 1);
+ m_current_floppy->ss_w(BIT(m_control, 2));
+ }
+
+ m_fdc->set_floppy(m_current_floppy);
+}
+
+u8 msx_slot_disk9_wd2793_n_device::status_r()
+{
+ return 0x3f | (m_fdc->intrq_r() ? 0x80 : 0) | (m_fdc->drq_r() ? 0x40 : 0);
+}
+
+
+
+
+msx_slot_disk10_mb8877_device::msx_slot_disk10_mb8877_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : msx_slot_disk10_mb8877_device(mconfig, MSX_SLOT_DISK10_MB8877, tag, owner, clock, DRIVES_1)
+{
+}
+
+msx_slot_disk10_mb8877_device::msx_slot_disk10_mb8877_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, int nr_drives)
+ : msx_slot_wd_disk_device(mconfig, type, tag, owner, clock, nr_drives)
+ , m_control(0)
+{
+}
+
+void msx_slot_disk10_mb8877_device::device_add_mconfig(machine_config &config)
+{
+ add_mconfig(config, MB8877, FORCE_READY, DS);
+}
+
+void msx_slot_disk10_mb8877_device::device_start()
+{
+ msx_slot_wd_disk_device::device_start();
+
+ save_item(NAME(m_control));
+
+ page(1)->install_rom(0x4000, 0x7fff, rom_base());
+ page(1)->install_read_handler(0x7ff8, 0x7ff8, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::status_r)));
+ page(1)->install_read_handler(0x7ff9, 0x7ff9, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::track_r)));
+ page(1)->install_read_handler(0x7ffa, 0x7ffa, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::sector_r)));
+ page(1)->install_read_handler(0x7ffb, 0x7ffb, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::data_r)));
+ page(1)->install_read_handler(0x7ffc, 0x7ffc, emu::rw_delegate(*this, FUNC(msx_slot_disk10_mb8877_device::status_r)));
+ // TODO 0x7ffd return system control/status
+ page(1)->install_write_handler(0x7ff8, 0x7ff8, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::cmd_w)));
+ page(1)->install_write_handler(0x7ff9, 0x7ff9, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::track_w)));
+ page(1)->install_write_handler(0x7ffa, 0x7ffa, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::sector_w)));
+ page(1)->install_write_handler(0x7ffb, 0x7ffb, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::data_w)));
+ page(1)->install_write_handler(0x7ffc, 0x7ffc, emu::rw_delegate(*this, FUNC(msx_slot_disk10_mb8877_device::control_w)));
+}
+
+void msx_slot_disk10_mb8877_device::device_reset()
+{
+ msx_slot_disk_device::device_reset();
+ m_fdc->dden_w(false);
+}
+
+void msx_slot_disk10_mb8877_device::device_post_load()
+{
+ control_w(m_control);
+}
+
+void msx_slot_disk10_mb8877_device::control_w(u8 data)
+{
+ m_control = data;
+
+ // Assuming drive LEDs are connected to the motor signals
+ if (BIT(m_control, 2))
+ {
+ m_current_floppy = m_floppy[1] ? m_floppy[1]->get_device() : nullptr;
+ set_drive_access_led_state(0, 0);
+ set_drive_access_led_state(1, BIT(m_control, 1));
+ }
+ else
+ {
+ m_current_floppy = m_floppy[0] ? m_floppy[0]->get_device() : nullptr;
+ set_drive_access_led_state(0, BIT(m_control, 0));
+ set_drive_access_led_state(1, 0);
+ }
+
+ if (m_current_floppy && !BIT(m_control, 2))
+ m_current_floppy->mon_w(BIT(m_control, 0) ? 0 : 1);
+
+ if (m_current_floppy && BIT(m_control, 2))
+ m_current_floppy->mon_w(BIT(m_control, 1) ? 0 : 1);
+
+ if (m_current_floppy)
+ m_current_floppy->ss_w(BIT(m_control, 3));
+
+ m_fdc->set_floppy(m_current_floppy);
+}
+
+u8 msx_slot_disk10_mb8877_device::status_r()
+{
+ return 0x23
+ | (m_control & 0x04)
+ | ((m_control & 0x08) ^ 0x08)
+ | ((m_current_floppy && m_current_floppy->mon_r()) ? 0 : 0x10)
+ | (m_fdc->drq_r() ? 0x40 : 0)
+ | (m_fdc->intrq_r() ? 0x80 : 0);
+}
+
+
+msx_slot_disk10_mb8877_2_drives_device::msx_slot_disk10_mb8877_2_drives_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : msx_slot_disk10_mb8877_device(mconfig, MSX_SLOT_DISK10_MB8877_2_DRIVES, tag, owner, clock, DRIVES_2)
+{
+}
+
+void msx_slot_disk10_mb8877_2_drives_device::device_add_mconfig(machine_config &config)
+{
+ add_mconfig(config, MB8877, FORCE_READY, DS);
+}
+
+
+
+msx_slot_disk11_wd2793_device::msx_slot_disk11_wd2793_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : msx_slot_wd_disk_device(mconfig, MSX_SLOT_DISK11_WD2793, tag, owner, clock, DRIVES_1)
+ , m_side_control(0)
+ , m_control(0)
+{
+}
+
+void msx_slot_disk11_wd2793_device::device_add_mconfig(machine_config &config)
+{
+ add_mconfig(config, WD2793, FORCE_READY, DS);
+}
+
+void msx_slot_disk11_wd2793_device::device_start()
+{
+ msx_slot_wd_disk_device::device_start();
+
+ save_item(NAME(m_side_control));
+ save_item(NAME(m_control));
+
+ page(1)->install_rom(0x4000, 0x7fff, rom_base());
+ page(1)->install_read_handler(0x7ff8, 0x7ff8, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::status_r)));
+ page(1)->install_read_handler(0x7ff9, 0x7ff9, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::track_r)));
+ page(1)->install_read_handler(0x7ffa, 0x7ffa, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::sector_r)));
+ page(1)->install_read_handler(0x7ffb, 0x7ffb, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::data_r)));
+ page(1)->install_read_handler(0x7ffc, 0x7ffc, emu::rw_delegate(*this, FUNC(msx_slot_disk11_wd2793_device::side_control_r)));
+ page(1)->install_read_handler(0x7ffd, 0x7ffd, emu::rw_delegate(*this, FUNC(msx_slot_disk11_wd2793_device::control_r)));
+ page(1)->install_read_handler(0x7fff, 0x7fff, emu::rw_delegate(*this, FUNC(msx_slot_disk11_wd2793_device::status_r)));
+ page(1)->install_write_handler(0x7ff8, 0x7ff8, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::cmd_w)));
+ page(1)->install_write_handler(0x7ff9, 0x7ff9, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::track_w)));
+ page(1)->install_write_handler(0x7ffa, 0x7ffa, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::sector_w)));
+ page(1)->install_write_handler(0x7ffb, 0x7ffb, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::data_w)));
+ page(1)->install_write_handler(0x7ffc, 0x7ffc, emu::rw_delegate(*this, FUNC(msx_slot_disk11_wd2793_device::side_control_w)));
+ page(1)->install_write_handler(0x7ffd, 0x7ffd, emu::rw_delegate(*this, FUNC(msx_slot_disk11_wd2793_device::control_w)));
+
+ page(2)->install_read_handler(0xbff8, 0xbff8, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::status_r)));
+ page(2)->install_read_handler(0xbff9, 0xbff9, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::track_r)));
+ page(2)->install_read_handler(0xbffa, 0xbffa, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::sector_r)));
+ page(2)->install_read_handler(0xbffb, 0xbffb, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::data_r)));
+ page(2)->install_read_handler(0xbffc, 0xbffc, emu::rw_delegate(*this, FUNC(msx_slot_disk11_wd2793_device::side_control_r)));
+ page(2)->install_read_handler(0xbffd, 0xbffd, emu::rw_delegate(*this, FUNC(msx_slot_disk11_wd2793_device::control_r)));
+ page(2)->install_read_handler(0xbfff, 0xbfff, emu::rw_delegate(*this, FUNC(msx_slot_disk11_wd2793_device::status_r)));
+ page(2)->install_write_handler(0xbff8, 0xbff8, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::cmd_w)));
+ page(2)->install_write_handler(0xbff9, 0xbff9, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::track_w)));
+ page(2)->install_write_handler(0xbffa, 0xbffa, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::sector_w)));
+ page(2)->install_write_handler(0xbffb, 0xbffb, emu::rw_delegate(*m_fdc, FUNC(wd_fdc_analog_device_base::data_w)));
+ page(2)->install_write_handler(0xbffc, 0xbffc, emu::rw_delegate(*this, FUNC(msx_slot_disk11_wd2793_device::side_control_w)));
+ page(2)->install_write_handler(0xbffd, 0xbffd, emu::rw_delegate(*this, FUNC(msx_slot_disk11_wd2793_device::control_w)));
+}
+
+void msx_slot_disk11_wd2793_device::device_reset()
+{
+ msx_slot_disk_device::device_reset();
+ m_fdc->dden_w(false);
+}
+
+void msx_slot_disk11_wd2793_device::device_post_load()
+{
+ control_w(m_control);
+}
+
+void msx_slot_disk11_wd2793_device::side_control_w(u8 data)
+{
+ m_side_control = data;
+
+ if (m_current_floppy)
+ m_current_floppy->ss_w(BIT(m_side_control, 0));
+}
+
+void msx_slot_disk11_wd2793_device::control_w(u8 data)
+{
+ m_control = data;
+
+ switch (m_control & 0x03)
+ {
+ case 0:
+ m_current_floppy = m_floppy[0] ? m_floppy[0]->get_device() : nullptr;
+ set_drive_access_led_state(0, BIT(m_control, 6)); // Wild guess based on other floppy interfaces
+ set_drive_access_led_state(1, 0);
+ break;
+
+ case 1:
+ m_current_floppy = m_floppy[1] ? m_floppy[1]->get_device() : nullptr;
+ set_drive_access_led_state(0, 0);
+ set_drive_access_led_state(1, BIT(m_control, 6)); // Wild guess based on other floppy interfaces
+ break;
+
+ default:
+ m_current_floppy = nullptr;
+ set_drive_access_led_state(0, 0);
+ set_drive_access_led_state(1, 0);
+ break;
+ }
+
+ if (m_current_floppy)
+ {
+ m_current_floppy->mon_w(BIT(m_control, 7) ? 0 : 1);
+ m_current_floppy->ss_w(BIT(m_side_control, 0));
+ }
+
+ m_fdc->set_floppy(m_current_floppy);
+}
+
+u8 msx_slot_disk11_wd2793_device::side_control_r()
+{
+ return 0xfe | (m_side_control & 0x01);
+}
+
+u8 msx_slot_disk11_wd2793_device::control_r()
+{
+ return (m_control & 0x83) | 0x78;
+}
+
+u8 msx_slot_disk11_wd2793_device::status_r()
+{
+ // bit 4 is checked during reading (ready check?)
+ return 0x3f | (m_fdc->intrq_r() ? 0 : 0x40) | (m_fdc->drq_r() ? 0 : 0x80);
+}
diff --git a/src/devices/bus/msx/slot/disk.h b/src/devices/bus/msx/slot/disk.h
new file mode 100644
index 00000000000..9b5c3eea82c
--- /dev/null
+++ b/src/devices/bus/msx/slot/disk.h
@@ -0,0 +1,499 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#ifndef MAME_BUS_MSX_SLOT_DISK_H
+#define MAME_BUS_MSX_SLOT_DISK_H
+
+#pragma once
+
+#include "slot.h"
+#include "rom.h"
+#include "machine/wd_fdc.h"
+#include "machine/upd765.h"
+#include "imagedev/floppy.h"
+
+
+// WD FDC accessed through 7ffx
+DECLARE_DEVICE_TYPE(MSX_SLOT_DISK1_FD1793, msx_slot_disk1_fd1793_device)
+DECLARE_DEVICE_TYPE(MSX_SLOT_DISK1_MB8877, msx_slot_disk1_mb8877_device)
+DECLARE_DEVICE_TYPE(MSX_SLOT_DISK1_WD2793_N, msx_slot_disk1_wd2793_n_device)
+DECLARE_DEVICE_TYPE(MSX_SLOT_DISK1_WD2793_N_2_DRIVES, msx_slot_disk1_wd2793_n_2_drives_device)
+DECLARE_DEVICE_TYPE(MSX_SLOT_DISK1_WD2793, msx_slot_disk1_wd2793_device)
+DECLARE_DEVICE_TYPE(MSX_SLOT_DISK1_WD2793_0, msx_slot_disk1_wd2793_0_device) // No drives, for nms8260
+DECLARE_DEVICE_TYPE(MSX_SLOT_DISK1_WD2793_SS, msx_slot_disk1_wd2793_ss_device)
+DECLARE_DEVICE_TYPE(MSX_SLOT_DISK1_WD2793_2_DRIVES, msx_slot_disk1_wd2793_2_drives_device)
+// WD FDC accessed through 7fbx
+DECLARE_DEVICE_TYPE(MSX_SLOT_DISK2_FD1793_SS, msx_slot_disk2_fd1793_ss_device)
+DECLARE_DEVICE_TYPE(MSX_SLOT_DISK2_MB8877, msx_slot_disk2_mb8877_device)
+DECLARE_DEVICE_TYPE(MSX_SLOT_DISK2_MB8877_SS, msx_slot_disk2_mb8877_ss_device)
+DECLARE_DEVICE_TYPE(MSX_SLOT_DISK2_MB8877_2_DRIVES, msx_slot_disk2_mb8877_2_drives_device)
+DECLARE_DEVICE_TYPE(MSX_SLOT_DISK2_WD2793, msx_slot_disk2_wd2793_device)
+DECLARE_DEVICE_TYPE(MSX_SLOT_DISK2_WD2793_2_DRIVES, msx_slot_disk2_wd2793_2_drives_device)
+// TC8566 accessed through 7ff8-7fff
+DECLARE_DEVICE_TYPE(MSX_SLOT_DISK3_TC8566, msx_slot_disk3_tc8566_device)
+DECLARE_DEVICE_TYPE(MSX_SLOT_DISK3_TC8566_2_DRIVES, msx_slot_disk3_tc8566_2_drives_device)
+// TC8566 accessed through 7ff0-7ff7 (used in Turob-R, untested)
+DECLARE_DEVICE_TYPE(MSX_SLOT_DISK4_TC8566, msx_slot_disk4_tc8566_device)
+// WD FDC accessed through i/o ports 0xd0-0xd4
+DECLARE_DEVICE_TYPE(MSX_SLOT_DISK5_WD2793, msx_slot_disk5_wd2793_device)
+// WD FDC accessed through 7ff0-7ff? (used in Toshiba HX34)
+DECLARE_DEVICE_TYPE(MSX_SLOT_DISK6_WD2793_N, msx_slot_disk6_wd2793_n_device)
+// MB FDC accessed through 7ff8-7ffc (used in Canon V-30F)
+DECLARE_DEVICE_TYPE(MSX_SLOT_DISK7_MB8877, msx_slot_disk7_mb8877_device)
+// WD FDC accessed through 7f8x
+DECLARE_DEVICE_TYPE(MSX_SLOT_DISK8_MB8877, msx_slot_disk8_mb8877_device)
+DECLARE_DEVICE_TYPE(MSX_SLOT_DISK8_WD2793_2_DRIVES, msx_slot_disk8_wd2793_2_drives_device)
+// WD FDC accessed through 7ffx, slightly different from DISK1 (used in PHC-77)
+DECLARE_DEVICE_TYPE(MSX_SLOT_DISK9_WD2793_N, msx_slot_disk9_wd2793_n_device)
+// WD FDC accessed through 7ffx, slightly different from DISK1 (used in Victor HC-90 / HC-95)
+DECLARE_DEVICE_TYPE(MSX_SLOT_DISK10_MB8877, msx_slot_disk10_mb8877_device)
+DECLARE_DEVICE_TYPE(MSX_SLOT_DISK10_MB8877_2_DRIVES, msx_slot_disk10_mb8877_2_drives_device)
+// WD FDC accessed through 7ffx, slightly different from DISK1 (used in Yamaha YIS-805)
+DECLARE_DEVICE_TYPE(MSX_SLOT_DISK11_WD2793, msx_slot_disk11_wd2793_device)
+
+
+class msx_slot_disk_device : public msx_slot_rom_device
+{
+protected:
+ static constexpr int NO_DRIVES = 0;
+ static constexpr int DRIVES_1 = 1;
+ static constexpr int DRIVES_2 = 2;
+ static constexpr int DRIVES_3 = 3;
+ static constexpr int DRIVES_4 = 4;
+ static constexpr bool DS = true;
+ static constexpr bool SS = false;
+
+ msx_slot_disk_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, int nr_drives);
+
+ static void floppy_formats(format_registration &fr);
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ void add_drive_mconfig(machine_config &config, bool double_sided);
+ void set_drive_access_led_state(int drive, int led_state);
+
+ optional_device_array<floppy_connector, 4> m_floppy;
+ floppy_image_device *m_current_floppy;
+
+private:
+ output_finder<4> m_internal_drive_led;
+ int m_nr_drives;
+};
+
+
+class msx_slot_wd_disk_device : public msx_slot_disk_device
+{
+public:
+ virtual void use_motor_for_led() { }
+
+protected:
+ static constexpr bool FORCE_READY = true;
+ static constexpr bool NO_FORCE_READY = false;
+
+ msx_slot_wd_disk_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, int nr_drives);
+
+ virtual void device_start() override;
+ template <typename FDCType> void add_mconfig(machine_config &config, FDCType &&type, bool force_ready, bool double_sided);
+ void set_control_led_bit(u8 control_led_bit) { m_control_led_bit = control_led_bit; }
+ u8 get_control_led_bit() const { return m_control_led_bit; }
+
+ required_device<wd_fdc_analog_device_base> m_fdc;
+
+private:
+ u8 m_control_led_bit; // For the implementations that need it, which bit of a control write controls the LED bit.
+};
+
+
+class msx_slot_tc8566_disk_device : public msx_slot_disk_device
+{
+protected:
+ msx_slot_tc8566_disk_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, int nr_drives);
+
+ void add_mconfig(machine_config &config);
+ void dor_w(u8 data);
+
+ required_device<tc8566af_device> m_fdc;
+};
+
+
+class msx_slot_disk1_base_device : public msx_slot_wd_disk_device
+{
+public:
+ virtual void use_motor_for_led() override { set_control_led_bit(7); }
+
+protected:
+ msx_slot_disk1_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, int nr_drives);
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void device_post_load() override;
+
+private:
+ void set_control(u8 data);
+ void set_side_control(u8 data);
+ u8 side_control_r();
+ u8 control_r();
+ u8 status_r();
+
+ u8 m_side_control;
+ u8 m_control;
+};
+
+class msx_slot_disk1_fd1793_device : public msx_slot_disk1_base_device
+{
+public:
+ msx_slot_disk1_fd1793_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override;
+};
+
+class msx_slot_disk1_mb8877_device : public msx_slot_disk1_base_device
+{
+public:
+ msx_slot_disk1_mb8877_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override;
+};
+
+class msx_slot_disk1_wd2793_n_device : public msx_slot_disk1_base_device
+{
+public:
+ msx_slot_disk1_wd2793_n_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override;
+};
+
+class msx_slot_disk1_wd2793_n_2_drives_device : public msx_slot_disk1_base_device
+{
+public:
+ msx_slot_disk1_wd2793_n_2_drives_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override;
+};
+
+class msx_slot_disk1_wd2793_device : public msx_slot_disk1_base_device
+{
+public:
+ msx_slot_disk1_wd2793_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override;
+};
+
+class msx_slot_disk1_wd2793_0_device : public msx_slot_disk1_base_device
+{
+public:
+ msx_slot_disk1_wd2793_0_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override;
+};
+
+class msx_slot_disk1_wd2793_ss_device : public msx_slot_disk1_base_device
+{
+public:
+ msx_slot_disk1_wd2793_ss_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override;
+};
+
+class msx_slot_disk1_wd2793_2_drives_device : public msx_slot_disk1_base_device
+{
+public:
+ msx_slot_disk1_wd2793_2_drives_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override;
+};
+
+
+class msx_slot_disk2_base_device : public msx_slot_wd_disk_device
+{
+public:
+ virtual void use_motor_for_led() override { set_control_led_bit(3); }
+
+protected:
+ msx_slot_disk2_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, int nr_drives);
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void device_post_load() override;
+
+private:
+ void set_control(u8 data);
+ u8 status_r();
+
+ u8 m_control;
+};
+
+class msx_slot_disk2_fd1793_ss_device : public msx_slot_disk2_base_device
+{
+public:
+ msx_slot_disk2_fd1793_ss_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override;
+};
+
+class msx_slot_disk2_mb8877_device : public msx_slot_disk2_base_device
+{
+public:
+ msx_slot_disk2_mb8877_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override;
+};
+
+class msx_slot_disk2_mb8877_ss_device : public msx_slot_disk2_base_device
+{
+public:
+ msx_slot_disk2_mb8877_ss_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override;
+};
+
+class msx_slot_disk2_mb8877_2_drives_device : public msx_slot_disk2_base_device
+{
+public:
+ msx_slot_disk2_mb8877_2_drives_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override;
+};
+
+class msx_slot_disk2_wd2793_device : public msx_slot_disk2_base_device
+{
+public:
+ msx_slot_disk2_wd2793_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override;
+};
+
+class msx_slot_disk2_wd2793_2_drives_device : public msx_slot_disk2_base_device
+{
+public:
+ msx_slot_disk2_wd2793_2_drives_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override;
+};
+
+
+
+class msx_slot_disk3_tc8566_device : public msx_slot_tc8566_disk_device
+{
+public:
+ msx_slot_disk3_tc8566_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ msx_slot_disk3_tc8566_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, int nr_drives);
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_start() override;
+};
+
+
+class msx_slot_disk3_tc8566_2_drives_device : public msx_slot_disk3_tc8566_device
+{
+public:
+ msx_slot_disk3_tc8566_2_drives_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override;
+};
+
+
+class msx_slot_disk4_tc8566_device : public msx_slot_tc8566_disk_device
+{
+public:
+ msx_slot_disk4_tc8566_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_start() override;
+
+private:
+ u8 bank_r();
+ void bank_w(u8 bank);
+ u8 media_change_r();
+ u8 unk_7ffc_r();
+ u8 unk_7ffd_r();
+ u8 unk_7fff_r();
+
+ memory_bank_creator m_rombank;
+};
+
+
+class msx_slot_disk5_wd2793_device : public msx_slot_wd_disk_device
+{
+public:
+ msx_slot_disk5_wd2793_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void device_post_load() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+
+private:
+ void control_w(u8 control);
+ u8 status_r();
+
+ u8 m_control;
+};
+
+
+class msx_slot_disk6_wd2793_n_device : public msx_slot_wd_disk_device
+{
+public:
+ msx_slot_disk6_wd2793_n_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void device_post_load() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+
+private:
+ void set_side_motor();
+ void select_drive();
+ u8 side_motor_r();
+ u8 select0_r();
+ u8 dskchg_r();
+ u8 status_r();
+ void side_motor_w(u8 data);
+ void select_w(u8 data);
+ void unknown_w(u8 data);
+
+ u8 m_side_motor;
+ u8 m_drive_select;
+ bool m_drive_present;
+ u8 m_unknown;
+};
+
+
+class msx_slot_disk7_mb8877_device : public msx_slot_wd_disk_device
+{
+public:
+ msx_slot_disk7_mb8877_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void device_post_load() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+
+private:
+ void set_drive_side_motor();
+ void select_drive();
+ void side_motor_w(u8 data);
+ u8 status_r();
+
+ u8 m_drive_side_motor;
+};
+
+
+class msx_slot_disk8_mb8877_device : public msx_slot_wd_disk_device
+{
+public:
+ msx_slot_disk8_mb8877_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ msx_slot_disk8_mb8877_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, int nr_drives);
+
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void device_post_load() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+
+private:
+ void set_control(u8 data);
+ u8 status_r();
+
+ u8 m_control;
+};
+
+class msx_slot_disk8_wd2793_2_drives_device : public msx_slot_disk8_mb8877_device
+{
+public:
+ msx_slot_disk8_wd2793_2_drives_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override;
+};
+
+
+class msx_slot_disk9_wd2793_n_device : public msx_slot_wd_disk_device
+{
+public:
+ msx_slot_disk9_wd2793_n_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void device_post_load() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+
+private:
+ void control_w(u8 data);
+ u8 status_r();
+
+ u8 m_control;
+};
+
+
+class msx_slot_disk10_mb8877_device : public msx_slot_wd_disk_device
+{
+public:
+ msx_slot_disk10_mb8877_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ msx_slot_disk10_mb8877_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, int nr_drives);
+
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void device_post_load() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+
+private:
+ void control_w(u8 data);
+ u8 status_r();
+
+ u8 m_control;
+};
+
+class msx_slot_disk10_mb8877_2_drives_device : public msx_slot_disk10_mb8877_device
+{
+public:
+ msx_slot_disk10_mb8877_2_drives_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override;
+};
+
+
+class msx_slot_disk11_wd2793_device : public msx_slot_wd_disk_device
+{
+public:
+ msx_slot_disk11_wd2793_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void device_post_load() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+
+private:
+ void control_w(u8 data);
+ void side_control_w(u8 data);
+ u8 side_control_r();
+ u8 control_r();
+ u8 status_r();
+
+ u8 m_side_control;
+ u8 m_control;
+};
+
+#endif // MAME_BUS_MSX_SLOT_DISK_H
diff --git a/src/devices/bus/msx/slot/fs4600.cpp b/src/devices/bus/msx/slot/fs4600.cpp
new file mode 100644
index 00000000000..7f947b5b7fd
--- /dev/null
+++ b/src/devices/bus/msx/slot/fs4600.cpp
@@ -0,0 +1,135 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+/*
+ Emulation for the internal firmware mapper in the National FS-4600.
+*/
+
+#include "emu.h"
+#include "fs4600.h"
+
+
+DEFINE_DEVICE_TYPE(MSX_SLOT_FS4600, msx_slot_fs4600_device, "msx_slot_fs4600", "MSX Internal FS4600 Firmware")
+
+
+msx_slot_fs4600_device::msx_slot_fs4600_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MSX_SLOT_FS4600, tag, owner, clock)
+ , msx_internal_slot_interface(mconfig, *this)
+ , m_nvram(*this, "nvram")
+ , m_rom_region(*this, finder_base::DUMMY_TAG)
+ , m_rombank(*this, "rombank%u", 0U)
+ , m_view{ {*this, "view0"}, {*this, "view1"}, {*this, "view2"} }
+ , m_region_offset(0)
+ , m_sram_address(0)
+{
+}
+
+void msx_slot_fs4600_device::device_add_mconfig(machine_config &config)
+{
+ NVRAM(config, m_nvram, nvram_device::DEFAULT_ALL_0);
+}
+
+void msx_slot_fs4600_device::device_start()
+{
+ // Sanity checks
+ if (m_rom_region->bytes() < m_region_offset + 0x100000)
+ {
+ fatalerror("Memory region '%s' is too small for the FS4600 firmware\n", m_rom_region.finder_tag());
+ }
+
+ m_sram.resize(SRAM_SIZE);
+ m_nvram->set_base(m_sram.data(), SRAM_SIZE);
+
+ save_item(NAME(m_sram_address));
+
+ for (int i = 0; i < 3; i++)
+ m_rombank[i]->configure_entries(0, 0x40, m_rom_region->base() + m_region_offset, 0x4000);
+
+ page(0)->install_view(0x0000, 0x3fff, m_view[0]);
+ m_view[0][0].install_read_bank(0x0000, 0x3fff, m_rombank[0]);
+ m_view[0][1].install_read_bank(0x0000, 0x3fff, m_rombank[0]);
+ m_view[0][1].install_write_handler(0x3ffa, 0x3ffd, emu::rw_delegate(*this, FUNC(msx_slot_fs4600_device::sram_w)));
+ m_view[0][1].install_read_handler(0x3ffd, 0x3ffd, emu::rw_delegate(*this, FUNC(msx_slot_fs4600_device::sram_r)));
+
+ page(1)->install_view(0x4000, 0x7fff, m_view[1]);
+ m_view[1][0].install_read_bank(0x4000, 0x7fff, m_rombank[1]);
+ m_view[1][0].install_write_handler(0x6000, 0x6000, emu::rw_delegate(*this, FUNC(msx_slot_fs4600_device::bank_w<1>)));
+ m_view[1][0].install_write_handler(0x6400, 0x6400, emu::rw_delegate(*this, FUNC(msx_slot_fs4600_device::bank_w<0>)));
+ m_view[1][0].install_write_handler(0x7000, 0x7000, emu::rw_delegate(*this, FUNC(msx_slot_fs4600_device::bank_w<2>)));
+ m_view[1][1].install_read_bank(0x4000, 0x7fff, m_rombank[1]);
+ m_view[1][1].install_write_handler(0x7ffa, 0x7ffd, emu::rw_delegate(*this, FUNC(msx_slot_fs4600_device::sram_w)));
+ m_view[1][1].install_read_handler(0x7ffd, 0x7ffd, emu::rw_delegate(*this, FUNC(msx_slot_fs4600_device::sram_r)));
+ m_view[1][2].install_read_bank(0x4000, 0x7fff, m_rombank[1]);
+ m_view[1][2].install_write_handler(0x6000, 0x6000, emu::rw_delegate(*this, FUNC(msx_slot_fs4600_device::bank_w<1>)));
+ m_view[1][2].install_write_handler(0x6400, 0x6400, emu::rw_delegate(*this, FUNC(msx_slot_fs4600_device::bank_w<0>)));
+ m_view[1][2].install_write_handler(0x7000, 0x7000, emu::rw_delegate(*this, FUNC(msx_slot_fs4600_device::bank_w<2>)));
+ m_view[1][2].install_read_handler(0x7ff0, 0x7ff5, emu::rw_delegate(*this, FUNC(msx_slot_fs4600_device::bank_r)));
+ m_view[1][3].install_read_bank(0x4000, 0x7fff, m_rombank[1]);
+ m_view[1][3].install_read_handler(0x7ff0, 0x7ff5, emu::rw_delegate(*this, FUNC(msx_slot_fs4600_device::bank_r)));
+ m_view[1][3].install_write_handler(0x7ffa, 0x7ffd, emu::rw_delegate(*this, FUNC(msx_slot_fs4600_device::sram_w)));
+ m_view[1][3].install_read_handler(0x7ffd, 0x7ffd, emu::rw_delegate(*this, FUNC(msx_slot_fs4600_device::sram_r)));
+
+ page(1)->install_write_handler(0x7ff9, 0x7ff9, emu::rw_delegate(*this, FUNC(msx_slot_fs4600_device::control_w)));
+
+ page(2)->install_view(0x8000, 0xbfff, m_view[2]);
+ m_view[2][0].install_read_bank(0x8000, 0xbfff, m_rombank[2]);
+ m_view[2][1].install_read_bank(0x8000, 0xbfff, m_rombank[2]);
+ m_view[2][1].install_write_handler(0xbffa, 0xbffd, emu::rw_delegate(*this, FUNC(msx_slot_fs4600_device::sram_w)));
+ m_view[2][1].install_read_handler(0xbffd, 0xbffd, emu::rw_delegate(*this, FUNC(msx_slot_fs4600_device::sram_r)));
+}
+
+void msx_slot_fs4600_device::device_reset()
+{
+ for (int i = 0; i < 3; i++)
+ {
+ m_view[i].select(0);
+ m_rombank[i]->set_entry(0);
+ }
+}
+
+u8 msx_slot_fs4600_device::sram_r()
+{
+ u8 data = m_sram[m_sram_address & (SRAM_SIZE - 1)];
+ if (!machine().side_effects_disabled())
+ m_sram_address++;
+ return data;
+}
+
+void msx_slot_fs4600_device::sram_w(offs_t offset, u8 data)
+{
+ switch (offset)
+ {
+ case 0:
+ m_sram_address = (m_sram_address & 0x00ffff) | (data << 16);
+ break;
+
+ case 1:
+ m_sram_address = (m_sram_address & 0xff00ff) | (data << 8);
+ break;
+
+ case 2:
+ m_sram_address = (m_sram_address & 0xffff00) | data;
+ break;
+
+ case 3:
+ m_sram[m_sram_address++ & (SRAM_SIZE - 1)] = data;
+ break;
+ }
+}
+
+u8 msx_slot_fs4600_device::bank_r(offs_t offset)
+{
+ return m_rombank[offset >> 1]->entry();
+}
+
+template <int Bank>
+void msx_slot_fs4600_device::bank_w(u8 data)
+{
+ m_rombank[Bank]->set_entry(data & 0x3f);
+}
+
+void msx_slot_fs4600_device::control_w(u8 data)
+{
+ m_view[0].select((data >> 1) & 0x01);
+ m_view[1].select((data >> 1) & 0x03);
+ m_view[2].select((data >> 1) & 0x01);
+}
diff --git a/src/devices/bus/msx_slot/fs4600.h b/src/devices/bus/msx/slot/fs4600.h
index 4b571c2ef56..5061e9186bf 100644
--- a/src/devices/bus/msx_slot/fs4600.h
+++ b/src/devices/bus/msx/slot/fs4600.h
@@ -15,32 +15,33 @@ DECLARE_DEVICE_TYPE(MSX_SLOT_FS4600, msx_slot_fs4600_device)
class msx_slot_fs4600_device : public device_t, public msx_internal_slot_interface
{
public:
- msx_slot_fs4600_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ msx_slot_fs4600_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
// configuration helpers
- void set_rom_start(const char *region, uint32_t offset) { m_rom_region.set_tag(region); m_region_offset = offset; }
-
- virtual uint8_t read(offs_t offset) override;
- virtual void write(offs_t offset, uint8_t data) override;
+ void set_rom_start(const char *region, u32 offset) { m_rom_region.set_tag(region); m_region_offset = offset; }
protected:
virtual void device_start() override;
- virtual void device_post_load() override;
+ virtual void device_reset() override;
virtual void device_add_mconfig(machine_config &config) override;
- void restore_banks();
-
private:
+ static constexpr size_t SRAM_SIZE = 0x1000;
+
+ void control_w(u8 data);
+ u8 sram_r();
+ void sram_w(offs_t offset, u8 data);
+ template <int Bank> void bank_w(u8 data);
+ u8 bank_r(offs_t offset);
+
required_device<nvram_device> m_nvram;
required_memory_region m_rom_region;
- uint32_t m_region_offset;
- const uint8_t *m_rom;
- uint8_t m_selected_bank[4];
- const uint8_t *m_bank_base[4];
- uint32_t m_sram_address;
- uint8_t m_sram[0x1000];
- uint8_t m_control;
+ memory_bank_array_creator<3> m_rombank;
+ memory_view m_view[3];
+ u32 m_region_offset;
+ u32 m_sram_address;
+ std::vector<u8> m_sram;
};
diff --git a/src/devices/bus/msx/slot/fsa1fm.cpp b/src/devices/bus/msx/slot/fsa1fm.cpp
new file mode 100644
index 00000000000..93e55d5b78d
--- /dev/null
+++ b/src/devices/bus/msx/slot/fsa1fm.cpp
@@ -0,0 +1,221 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+/*
+
+ Emulation of the firmware mapper in the Panasonic FS-A1FM.
+
+*/
+
+#include "emu.h"
+#include "fsa1fm.h"
+
+
+DEFINE_DEVICE_TYPE(MSX_SLOT_FSA1FM, msx_slot_fsa1fm_device, "msx_slot_fs1afm", "MSX Internal FS-A1FM")
+DEFINE_DEVICE_TYPE(MSX_SLOT_FSA1FM2, msx_slot_fsa1fm2_device, "msx_slot_fs1afm2", "MSX Internal FS-A1FM part 2")
+
+
+msx_slot_fsa1fm2_device::msx_slot_fsa1fm2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, MSX_SLOT_FSA1FM2, tag, owner, clock)
+ , msx_internal_slot_interface(mconfig, *this)
+ , m_rom_region(*this, finder_base::DUMMY_TAG)
+ , m_bank(*this, "bank%u", 0U)
+ , m_view{ {*this, "view0"}, {*this, "view1"}, {*this, "view2"}, {*this, "view3"}, {*this, "view4"}, {*this, "view5"} }
+ , m_region_offset(0)
+{
+}
+
+void msx_slot_fsa1fm2_device::device_start()
+{
+ // Sanity checks
+ if (m_rom_region->bytes() != 0x100000)
+ {
+ fatalerror("Memory region '%s' is not the correct size for the FS-A1FM firmware\n", m_rom_region.finder_tag());
+ }
+
+ m_ram.resize(RAM_SIZE);
+ m_empty_bank.resize(8 * 1024);
+ for (int i = 0; i < 8 * 1024; i++)
+ m_empty_bank[i] = 0xff;
+
+ save_item(NAME(m_selected_bank));
+ save_item(NAME(m_control));
+ save_item(NAME(m_ram_active));
+ save_pointer(m_ram.data(), "ram", RAM_SIZE);
+
+ for (int i = 0; i < 6; i++)
+ {
+ m_bank[i]->configure_entries(0, 0x80, m_rom_region->base() + m_region_offset, 0x2000);
+ m_bank[i]->configure_entries(0x80, 0x80, m_rom_region->base() + m_region_offset, 0x2000);
+ for (int j = 0; j < 4; j++)
+ {
+ m_bank[i]->configure_entry(0x80 + j, m_empty_bank.data()); // 0x80-0x83 empty
+ m_bank[i]->configure_entry(0x84 + j, m_ram.data()); // 0x84-0x87 ram
+ m_bank[i]->configure_entry(0x88 + j, m_empty_bank.data()); // 0x88-0x8b empty
+ m_bank[i]->configure_entry(0x8c + j, m_ram.data()); // 0x8c-0x8f ram
+ }
+ }
+
+ page(0)->install_view(0x0000, 0x1fff, m_view[0]);
+ m_view[0][0].install_read_bank(0x0000, 0x1fff, m_bank[0]);
+ m_view[0][1].install_readwrite_bank(0x0000, 0x1fff, m_bank[0]);
+
+ page(0)->install_view(0x2000, 0x3fff, m_view[1]);
+ m_view[1][0].install_read_bank(0x2000, 0x3fff, m_bank[1]);
+ m_view[1][1].install_readwrite_bank(0x2000, 0x3fff, m_bank[1]);
+
+ page(1)->install_view(0x4000, 0x5fff, m_view[2]);
+ m_view[2][0].install_read_bank(0x4000, 0x5fff, m_bank[2]);
+ m_view[2][1].install_readwrite_bank(0x4000, 0x5fff, m_bank[2]);
+
+ page(1)->install_view(0x6000, 0x7fff, m_view[3]);
+ m_view[3][0].install_read_bank(0x6000, 0x7fff, m_bank[3]);
+ m_view[3][1].install_readwrite_bank(0x6000, 0x7fff, m_bank[3]);
+ m_view[3][2].install_read_bank(0x6000, 0x7fff, m_bank[3]);
+ m_view[3][2].install_read_handler(0x7ff0, 0x7ff7, emu::rw_delegate(*this, FUNC(msx_slot_fsa1fm2_device::bank_r)));
+ m_view[3][3].install_readwrite_bank(0x6000, 0x7fff, m_bank[3]);
+ m_view[3][3].install_read_handler(0x7ff0, 0x7ff7, emu::rw_delegate(*this, FUNC(msx_slot_fsa1fm2_device::bank_r)));
+ page(1)->install_write_handler(0x6000, 0x6000, emu::rw_delegate(*this, FUNC(msx_slot_fsa1fm2_device::bank_w<2>)));
+ page(1)->install_write_handler(0x6400, 0x6400, emu::rw_delegate(*this, FUNC(msx_slot_fsa1fm2_device::bank_w<0>)));
+ page(1)->install_write_handler(0x6800, 0x6800, emu::rw_delegate(*this, FUNC(msx_slot_fsa1fm2_device::bank_w<3>)));
+ page(1)->install_write_handler(0x6c00, 0x6c00, emu::rw_delegate(*this, FUNC(msx_slot_fsa1fm2_device::bank_w<1>)));
+ page(1)->install_write_handler(0x7000, 0x7000, emu::rw_delegate(*this, FUNC(msx_slot_fsa1fm2_device::bank_w<4>)));
+ page(1)->install_write_handler(0x7800, 0x7800, emu::rw_delegate(*this, FUNC(msx_slot_fsa1fm2_device::bank_w<5>)));
+ page(1)->install_write_handler(0x7ff9, 0x7ff9, emu::rw_delegate(*this, FUNC(msx_slot_fsa1fm2_device::control_w)));
+
+ page(2)->install_view(0x8000, 0x9fff, m_view[4]);
+ m_view[4][0].install_read_bank(0x8000, 0x9fff, m_bank[4]);
+ m_view[4][1].install_readwrite_bank(0x8000, 0x9fff, m_bank[4]);
+
+ page(2)->install_view(0xa000, 0xbfff, m_view[5]);
+ m_view[5][0].install_read_bank(0xa000, 0xbfff, m_bank[5]);
+ m_view[5][1].install_readwrite_bank(0xa000, 0xbfff, m_bank[5]);
+}
+
+void msx_slot_fsa1fm2_device::device_reset()
+{
+ m_control = 0;
+
+ for (int i = 0; i < 6 ; i++)
+ {
+ m_view[i].select(0);
+ m_selected_bank[i] = 0xa8;
+ m_bank[i]->set_entry(0x28);
+ }
+}
+
+template <int Bank>
+void msx_slot_fsa1fm2_device::set_view()
+{
+ bool ram_active = (m_selected_bank[Bank] & 0xf4) == 0x84;
+ if (Bank == 3)
+ m_view[3].select((ram_active ? 1 : 0) | (BIT(m_control, 2) ? 2 : 0));
+ else if (Bank != 2)
+ m_view[Bank].select(ram_active ? 1 : 0);
+}
+
+template <int Bank>
+void msx_slot_fsa1fm2_device::bank_w(u8 data)
+{
+ m_selected_bank[Bank] = data;
+ m_bank[Bank]->set_entry(data);
+ set_view<Bank>();
+}
+
+u8 msx_slot_fsa1fm2_device::bank_r(offs_t offset)
+{
+ return (offset < 6) ? m_selected_bank[offset] : 0;
+}
+
+void msx_slot_fsa1fm2_device::control_w(u8 data)
+{
+ // writing $04 enables read back of banking registers at 7ff0-7ff5
+ m_control = data;
+ set_view<3>();
+}
+
+
+
+
+msx_slot_fsa1fm_device::msx_slot_fsa1fm_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MSX_SLOT_FSA1FM, tag, owner, clock)
+ , msx_internal_slot_interface(mconfig, *this)
+ , m_nvram(*this, "nvram")
+ , m_i8251(*this, "i8251")
+ , m_i8255(*this, "i8255")
+ , m_switch_port(*this, "SWITCH")
+ , m_rom_region(*this, finder_base::DUMMY_TAG)
+ , m_rombank(*this, "rombank")
+ , m_region_offset(0)
+{
+}
+
+static INPUT_PORTS_START(fsa1fm)
+ PORT_START("SWITCH")
+ PORT_CONFNAME(0x04, 0x00, "Enable Firmware")
+ PORT_CONFSETTING(0x04, DEF_STR(No))
+ PORT_CONFSETTING(0x00, DEF_STR(Yes))
+INPUT_PORTS_END
+
+ioport_constructor msx_slot_fsa1fm_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(fsa1fm);
+}
+
+void msx_slot_fsa1fm_device::device_add_mconfig(machine_config &config)
+{
+ NVRAM(config, m_nvram, nvram_device::DEFAULT_ALL_0);
+
+ // Unknown how these are connected
+ I8251(config, m_i8251, 0);
+
+ I8255(config, m_i8255);
+ m_i8255->out_pa_callback().set(FUNC(msx_slot_fsa1fm_device::i8255_port_a_w));
+ m_i8255->out_pb_callback().set(FUNC(msx_slot_fsa1fm_device::i8255_port_b_w));
+ m_i8255->in_pc_callback().set(FUNC(msx_slot_fsa1fm_device::i8255_port_c_r));
+}
+
+void msx_slot_fsa1fm_device::device_start()
+{
+ // Sanity checks
+ if (m_rom_region->bytes() != 0x100000)
+ {
+ fatalerror("Memory region '%s' is not the correct size for the FS-A1FM firmware\n", m_rom_region.finder_tag());
+ }
+
+ m_sram.resize(SRAM_SIZE);
+ m_nvram->set_base(m_sram.data(), SRAM_SIZE);
+
+ m_rombank->configure_entries(0, 16, m_rom_region->base(), 0x2000);
+
+ page(1)->install_read_bank(0x4000, 0x5fff, m_rombank);
+ // SRAM is always visible?
+ page(1)->install_ram(0x6000, 0x7fff, m_sram.data());
+ page(1)->install_write_handler(0x7fc0, 0x7fc0, emu::rw_delegate(*m_i8251, FUNC(i8251_device::data_w)));
+ page(1)->install_read_handler(0x7fc0, 0x7fc0, emu::rw_delegate(*m_i8251, FUNC(i8251_device::data_r)));
+ page(1)->install_write_handler(0x7fc1, 0x7fc1, emu::rw_delegate(*m_i8251, FUNC(i8251_device::control_w)));
+ page(1)->install_write_handler(0x7fc4, 0x7fc7, emu::rw_delegate(*m_i8255, FUNC(i8255_device::write)));
+ page(1)->install_read_handler(0x7fc4, 0x7fc7, emu::rw_delegate(*m_i8255, FUNC(i8255_device::read)));
+}
+
+void msx_slot_fsa1fm_device::device_reset()
+{
+ m_rombank->set_entry(0);
+}
+
+void msx_slot_fsa1fm_device::i8255_port_a_w(u8 data)
+{
+ // 0xc0 enables sram?
+ logerror("port A write %02x\n", data);
+ m_rombank->set_entry(data & 0x0f);
+}
+
+void msx_slot_fsa1fm_device::i8255_port_b_w(u8 data)
+{
+ logerror("port B write %02x\n", data);
+}
+
+u8 msx_slot_fsa1fm_device::i8255_port_c_r()
+{
+ logerror("port C read\n");
+ return m_switch_port->read();
+}
diff --git a/src/devices/bus/msx/slot/fsa1fm.h b/src/devices/bus/msx/slot/fsa1fm.h
new file mode 100644
index 00000000000..660baa43e99
--- /dev/null
+++ b/src/devices/bus/msx/slot/fsa1fm.h
@@ -0,0 +1,83 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#ifndef MAME_BUS_MSX_SLOT_FSA1FM_H
+#define MAME_BUS_MSX_SLOT_FSA1FM_H
+
+#pragma once
+
+#include "slot.h"
+#include "machine/i8251.h"
+#include "machine/i8255.h"
+#include "machine/nvram.h"
+
+
+DECLARE_DEVICE_TYPE(MSX_SLOT_FSA1FM, msx_slot_fsa1fm_device)
+DECLARE_DEVICE_TYPE(MSX_SLOT_FSA1FM2, msx_slot_fsa1fm2_device)
+
+
+class msx_slot_fsa1fm2_device : public device_t, public msx_internal_slot_interface
+{
+public:
+ msx_slot_fsa1fm2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ // configuration helpers
+ void set_rom_start(const char *region, uint32_t offset) { m_rom_region.set_tag(region); m_region_offset = offset; }
+
+protected:
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+private:
+ static constexpr size_t RAM_SIZE = 0x2000;
+
+ template <int Bank> void set_view();
+ template <int Bank> void bank_w(u8 data);
+ u8 bank_r(offs_t offset);
+ void control_w(u8 data);
+
+ required_memory_region m_rom_region;
+ memory_bank_array_creator<6> m_bank;
+ memory_view m_view[6];
+ uint32_t m_region_offset;
+ uint8_t m_selected_bank[6];
+ bool m_ram_active[6];
+ uint8_t m_control;
+ std::vector<uint8_t> m_ram;
+ std::vector<uint8_t> m_empty_bank;
+};
+
+
+class msx_slot_fsa1fm_device : public device_t, public msx_internal_slot_interface
+{
+public:
+ msx_slot_fsa1fm_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ // configuration helpers
+ void set_rom_start(const char *region, uint32_t offset) { m_rom_region.set_tag(region); m_region_offset = offset; }
+
+protected:
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual ioport_constructor device_input_ports() const override;
+
+private:
+ static constexpr size_t SRAM_SIZE = 0x2000;
+
+ void map_bank();
+ void i8255_port_a_w(u8 data);
+ void i8255_port_b_w(u8 data);
+ u8 i8255_port_c_r();
+
+ required_device<nvram_device> m_nvram;
+ required_device<i8251_device> m_i8251;
+ required_device<i8255_device> m_i8255;
+ required_ioport m_switch_port;
+ required_memory_region m_rom_region;
+ memory_bank_creator m_rombank;
+ u32 m_region_offset;
+ std::vector<u8> m_sram;
+};
+
+
+#endif // MAME_BUS_MSX_SLOT_FSA1FM_H
diff --git a/src/devices/bus/msx/slot/msx_rs232.cpp b/src/devices/bus/msx/slot/msx_rs232.cpp
new file mode 100644
index 00000000000..0750abf7c9a
--- /dev/null
+++ b/src/devices/bus/msx/slot/msx_rs232.cpp
@@ -0,0 +1,526 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+
+/*
+Emulation of MSX internal RS-232 modules
+
+TODO:
+- What does the Mitsubishi RS232 switch do? Disable the entire RS-232 unit?
+*/
+
+#include "emu.h"
+#include "msx_rs232.h"
+
+
+DEFINE_DEVICE_TYPE(MSX_SLOT_RS232, msx_slot_rs232_device, "msx_slot_rs232", "MSX Internal RS-232C")
+DEFINE_DEVICE_TYPE(MSX_SLOT_RS232_MITSUBISHI, msx_slot_rs232_mitsubishi_device, "msx_slot_rs232_mitsubishi", "Mitsubishi Internal RS-232C")
+DEFINE_DEVICE_TYPE(MSX_SLOT_RS232_SONY, msx_slot_rs232_sony_device, "msx_slot_rs232_sony", "Sony Internal RS-232C")
+DEFINE_DEVICE_TYPE(MSX_SLOT_RS232_SVI738, msx_slot_rs232_svi738_device, "msx_slot_rs232_svi738", "SVI-738 Internal RS-232C")
+DEFINE_DEVICE_TYPE(MSX_SLOT_RS232_TOSHIBA, msx_slot_rs232_toshiba_device, "msx_slot_rs232_toshiba", "Toshiba Internal RS-232C")
+DEFINE_DEVICE_TYPE(MSX_SLOT_RS232_TOSHIBA_HX3X, msx_slot_rs232_toshiba_hx3x_device, "msx_slot_rs232_toshiba_hx3x", "Toshiba HX-33/HX-34 Internal RS-232C and firmware")
+
+
+
+static INPUT_PORTS_START(msx_rs232_enable_switch)
+ PORT_START("SWITCH")
+ PORT_CONFNAME(0x01, 0x01, "RS-232C is")
+ PORT_CONFSETTING(0x00, "disabled")
+ PORT_CONFSETTING(0x01, "enabled")
+INPUT_PORTS_END
+
+
+msx_slot_rs232_base_device::msx_slot_rs232_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
+ : msx_slot_rom_device(mconfig, type, tag, owner, clock)
+ , m_i8251(*this, "i8251")
+ , m_i8253(*this, "i8253")
+ , m_rs232(*this, "rs232")
+ , m_irq_handler(*this)
+ , m_irq_mask(0xff)
+ , m_out2(false)
+ , m_cts(false)
+ , m_dcd(false)
+ , m_ri(false)
+ , m_rxrdy(false)
+{
+}
+
+void msx_slot_rs232_base_device::device_add_mconfig(machine_config &config)
+{
+ // Config based on svi738 schematics, are they the same for other machines?
+
+ I8251(config, m_i8251, 1.8432_MHz_XTAL);
+ m_i8251->txd_handler().set(m_rs232, FUNC(rs232_port_device::write_txd));
+ m_i8251->dtr_handler().set(m_rs232, FUNC(rs232_port_device::write_dtr));
+ m_i8251->rts_handler().set(m_rs232, FUNC(rs232_port_device::write_rts));
+ m_i8251->rxrdy_handler().set(*this, FUNC(msx_slot_rs232_base_device::rxrdy_w));
+ m_i8251->txrdy_handler().set(*this, FUNC(msx_slot_rs232_base_device::txrdy_w));
+
+ PIT8253(config, m_i8253);
+ m_i8253->set_clk<0>(1.8432_MHz_XTAL);
+ m_i8253->set_clk<1>(1.8432_MHz_XTAL);
+ m_i8253->set_clk<2>(1.8432_MHz_XTAL);
+ m_i8253->out_handler<0>().set(m_i8251, FUNC(i8251_device::write_rxc));
+ m_i8253->out_handler<1>().set(m_i8251, FUNC(i8251_device::write_txc));
+ m_i8253->out_handler<2>().set(*this, FUNC(msx_slot_rs232_base_device::out2_w));
+
+ RS232_PORT(config, m_rs232, default_rs232_devices, nullptr);
+ m_rs232->rxd_handler().set(m_i8251, FUNC(i8251_device::write_rxd));
+ m_rs232->dcd_handler().set(*this, FUNC(msx_slot_rs232_base_device::dcd_w));
+ m_rs232->ri_handler().set(*this, FUNC(msx_slot_rs232_base_device::ri_w));
+ m_rs232->cts_handler().set(*this, FUNC(msx_slot_rs232_base_device::cts_w));
+ m_rs232->dsr_handler().set(m_i8251, FUNC(i8251_device::write_dsr));
+}
+
+void msx_slot_rs232_base_device::device_start()
+{
+ msx_slot_rom_device::device_start();
+
+ save_item(NAME(m_irq_mask));
+ save_item(NAME(m_out2));
+ save_item(NAME(m_cts));
+ save_item(NAME(m_dcd));
+ save_item(NAME(m_ri));
+ save_item(NAME(m_rxrdy));
+ save_item(NAME(m_txrdy));
+}
+
+void msx_slot_rs232_base_device::device_reset()
+{
+ m_irq_mask = 0xff;
+ m_out2 = false;
+ m_cts = false;
+ m_dcd = false;
+ m_ri =false;
+ m_rxrdy = false;
+}
+
+void msx_slot_rs232_base_device::irq_mask_w(offs_t offset, u8 data)
+{
+ // According to MSX datapack:
+ // 7654---- unused
+ // ----3--- timer interrupt from i8352 channel 2
+ // -----2-- sync character detect / break detect
+ // ------1- transmit data ready
+ // -------0 receive data ready
+ // but most rs232 interface only seem to support receive data ready irq
+ m_irq_mask = data;
+}
+
+void msx_slot_rs232_base_device::out2_w(int state)
+{
+ m_out2 = state;
+ update_irq_state();
+}
+
+void msx_slot_rs232_base_device::cts_w(int state)
+{
+ m_cts = state;
+ m_i8251->write_cts(state);
+}
+
+void msx_slot_rs232_base_device::dcd_w(int state)
+{
+ m_dcd = state;
+ update_irq_state();
+}
+
+void msx_slot_rs232_base_device::ri_w(int state)
+{
+ m_ri = state;
+}
+
+void msx_slot_rs232_base_device::rxrdy_w(int state)
+{
+ m_rxrdy = state;
+ update_irq_state();
+}
+
+void msx_slot_rs232_base_device::txrdy_w(int state)
+{
+ m_txrdy = state;
+ update_irq_state();
+}
+
+
+
+msx_slot_rs232_device::msx_slot_rs232_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : msx_slot_rs232_base_device(mconfig, MSX_SLOT_RS232, tag, owner, clock)
+{
+}
+
+void msx_slot_rs232_device::device_start()
+{
+ msx_slot_rs232_base_device::device_start();
+
+ // Install IO read/write handlers
+ io_space().install_readwrite_handler(0x80, 0x81, emu::rw_delegate(*m_i8251, FUNC(i8251_device::read)), emu::rw_delegate(*m_i8251, FUNC(i8251_device::write)));
+ io_space().install_readwrite_handler(0x82, 0x82, emu::rw_delegate(*this, FUNC(msx_slot_rs232_device::status_r)), emu::rw_delegate(*this, FUNC(msx_slot_rs232_device::irq_mask_w)));
+ io_space().install_readwrite_handler(0x84, 0x87, emu::rw_delegate(*m_i8253, FUNC(pit8253_device::read)), emu::rw_delegate(*m_i8253, FUNC(pit8253_device::write)));
+}
+
+u8 msx_slot_rs232_device::status_r(offs_t offset)
+{
+ // 7------- CTS
+ // -6------ 8253 channel 2 output
+ // --5432-- unused
+ // ------1- ring indicator
+ // -------0 carrier detect
+
+ u8 result = 0x00;
+
+ if (m_cts)
+ result |= 0x80;
+
+ if (m_out2)
+ result |= 0x40;
+
+ if (m_ri)
+ result |= 0x02;
+
+ if (m_dcd)
+ result |= 0x01;
+
+ return result;
+}
+
+void msx_slot_rs232_device::update_irq_state()
+{
+ m_irq_handler(m_rxrdy);
+}
+
+
+
+msx_slot_rs232_mitsubishi_device::msx_slot_rs232_mitsubishi_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : msx_slot_rs232_base_device(mconfig, MSX_SLOT_RS232_MITSUBISHI, tag, owner, clock)
+ , m_switch_port(*this, "SWITCH")
+{
+}
+
+ioport_constructor msx_slot_rs232_mitsubishi_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(msx_rs232_enable_switch);
+}
+
+void msx_slot_rs232_mitsubishi_device::device_start()
+{
+ msx_slot_rs232_base_device::device_start();
+
+ // Install IO read/write handlers
+ io_space().install_readwrite_handler(0x80, 0x81, emu::rw_delegate(*m_i8251, FUNC(i8251_device::read)), emu::rw_delegate(*m_i8251, FUNC(i8251_device::write)));
+ io_space().install_readwrite_handler(0x82, 0x82, emu::rw_delegate(*this, FUNC(msx_slot_rs232_mitsubishi_device::status_r)), emu::rw_delegate(*this, FUNC(msx_slot_rs232_mitsubishi_device::irq_mask_w)));
+ io_space().install_readwrite_handler(0x84, 0x87, emu::rw_delegate(*m_i8253, FUNC(pit8253_device::read)), emu::rw_delegate(*m_i8253, FUNC(pit8253_device::write)));
+}
+
+u8 msx_slot_rs232_mitsubishi_device::status_r(offs_t offset)
+{
+ // 7------- CTS
+ // -6------ 8253 channel 2 output
+ // --54321- unused
+ // -------0 carrier detect
+
+ uint8_t result = 0x00;
+
+ if (m_cts)
+ result |= 0x80;
+
+ if (m_out2)
+ result |= 0x40;
+
+ if (m_dcd)
+ result |= 0x01;
+
+ return result;
+}
+
+void msx_slot_rs232_mitsubishi_device::update_irq_state()
+{
+ if (!BIT(m_irq_mask, 0))
+ m_irq_handler(m_rxrdy);
+}
+
+
+
+msx_slot_rs232_sony_device::msx_slot_rs232_sony_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : msx_slot_rs232_base_device(mconfig, MSX_SLOT_RS232_SONY, tag, owner, clock)
+ , m_switch_port(*this, "SWITCH")
+{
+}
+
+ioport_constructor msx_slot_rs232_sony_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(msx_rs232_enable_switch);
+}
+
+void msx_slot_rs232_sony_device::device_start()
+{
+ msx_slot_rs232_base_device::device_start();
+
+ m_ram.resize(RAM_SIZE);
+ save_item(NAME(m_ram));
+
+ // TODO unmap rom from page 0
+ page(0)->install_ram(0x2000, 0x27ff, m_ram.data());
+ page(1)->install_rom(0x4000, 0x5fff, m_rom_region->base() + m_region_offset);
+ page(1)->install_ram(0x6000, 0x67ff, m_ram.data());
+ page(2)->install_ram(0xa000, 0xa7ff, m_ram.data());
+ page(2)->install_read_handler(0xbff8, 0xbff9, emu::rw_delegate(*m_i8251, FUNC(i8251_device::read)));
+ page(2)->install_write_handler(0xbff8, 0xbff9, emu::rw_delegate(*m_i8251, FUNC(i8251_device::write)));
+ page(2)->install_read_handler(0xbffa, 0xbffa, emu::rw_delegate(*this, FUNC(msx_slot_rs232_sony_device::status_r)));
+ page(2)->install_write_handler(0xbffa, 0xbffa, emu::rw_delegate(*this, FUNC(msx_slot_rs232_sony_device::irq_mask_w)));
+ page(2)->install_read_handler(0xbffc, 0xbfff, emu::rw_delegate(*m_i8253, FUNC(pit8253_device::read)));
+ page(2)->install_write_handler(0xbffc, 0xbfff, emu::rw_delegate(*m_i8253, FUNC(pit8253_device::write)));
+ page(3)->install_ram(0xe000, 0xe7ff, m_ram.data());
+}
+
+u8 msx_slot_rs232_sony_device::status_r(offs_t offset)
+{
+ // 7------- CTS
+ // -6------ 8253 channel 2 output
+ // --5----- unused
+ // ---4---- ??
+ // ----32-- unused
+ // ------1- ring indicator
+ // -------0 carrier detect
+
+ u8 result = 0x00;
+
+ if (m_cts)
+ result |= 0x80;
+
+ if (m_out2)
+ result |= 0x40;
+
+ if (m_ri)
+ result |= 0x02;
+
+ if (m_dcd)
+ result |= 0x01;
+
+ return result;
+}
+
+void msx_slot_rs232_sony_device::update_irq_state()
+{
+ if (!BIT(m_irq_mask, 0))
+ m_irq_handler(m_rxrdy);
+}
+
+
+
+msx_slot_rs232_svi738_device::msx_slot_rs232_svi738_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : msx_slot_rs232_base_device(mconfig, MSX_SLOT_RS232_SVI738, tag, owner, clock)
+{
+}
+
+void msx_slot_rs232_svi738_device::device_start()
+{
+ msx_slot_rs232_base_device::device_start();
+
+ // Install IO read/write handlers
+ io_space().install_readwrite_handler(0x80, 0x81, emu::rw_delegate(*m_i8251, FUNC(i8251_device::read)), emu::rw_delegate(*m_i8251, FUNC(i8251_device::write)));
+ io_space().install_read_handler(0x82, 0x82, emu::rw_delegate(*this, FUNC(msx_slot_rs232_svi738_device::status_r)));
+ io_space().install_readwrite_handler(0x84, 0x87, emu::rw_delegate(*m_i8253, FUNC(pit8253_device::read)), emu::rw_delegate(*m_i8253, FUNC(pit8253_device::write)));
+}
+
+u8 msx_slot_rs232_svi738_device::status_r(offs_t offset)
+{
+ // 7------- CTS
+ // -6------ 8253 channel 2 output
+ // --54321- unused
+ // -------0 carrier detect
+
+ u8 result = 0x00;
+
+ if (m_cts)
+ result |= 0x80;
+
+ if (m_out2)
+ result |= 0x40;
+
+ if (m_dcd)
+ result |= 0x01;
+
+ return result;
+}
+
+void msx_slot_rs232_svi738_device::update_irq_state()
+{
+ m_irq_handler(m_rxrdy);
+}
+
+
+
+msx_slot_rs232_toshiba_device::msx_slot_rs232_toshiba_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : msx_slot_rs232_base_device(mconfig, MSX_SLOT_RS232_TOSHIBA, tag, owner, clock)
+ , m_switch_port(*this, "SWITCH")
+{
+}
+
+ioport_constructor msx_slot_rs232_toshiba_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(msx_rs232_enable_switch);
+}
+
+void msx_slot_rs232_toshiba_device::device_start()
+{
+ msx_slot_rs232_base_device::device_start();
+
+ // Install IO read/write handlers
+ io_space().install_readwrite_handler(0x80, 0x81, emu::rw_delegate(*m_i8251, FUNC(i8251_device::read)), emu::rw_delegate(*m_i8251, FUNC(i8251_device::write)));
+ io_space().install_readwrite_handler(0x82, 0x82, emu::rw_delegate(*this, FUNC(msx_slot_rs232_toshiba_device::status_r)), emu::rw_delegate(*this, FUNC(msx_slot_rs232_toshiba_device::irq_mask_w)));
+ io_space().install_readwrite_handler(0x84, 0x87, emu::rw_delegate(*m_i8253, FUNC(pit8253_device::read)), emu::rw_delegate(*m_i8253, FUNC(pit8253_device::write)));
+}
+
+u8 msx_slot_rs232_toshiba_device::status_r(offs_t offset)
+{
+ // 7------- CTS
+ // -6------ 8253 channel 2 output
+ // --54---- unused
+ // ----3--- switch detection
+ // -----2-- unused
+ // ------1- ring indicator
+ // -------0 carrier detect
+
+ u8 result = 0x00;
+
+ if (m_cts)
+ result |= 0x80;
+
+ if (m_out2)
+ result |= 0x40;
+
+ if (BIT(m_irq_mask, 0) && m_switch_port->read())
+ result |= 0x08;
+
+ if (m_ri)
+ result |= 0x02;
+
+ if (m_dcd)
+ result |= 0x01;
+
+ return result;
+}
+
+void msx_slot_rs232_toshiba_device::update_irq_state()
+{
+ if (!BIT(m_irq_mask, 0))
+ m_irq_handler(m_rxrdy);
+}
+
+
+
+msx_slot_rs232_toshiba_hx3x_device::msx_slot_rs232_toshiba_hx3x_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : msx_slot_rs232_base_device(mconfig, MSX_SLOT_RS232_TOSHIBA_HX3X, tag, owner, clock)
+ , m_switch_port(*this, "SWITCH")
+ , m_copy_port(*this, "COPY")
+ , m_nvram(*this, "nvram")
+ , m_rombank(*this, "rombank")
+ , m_view(*this, "view")
+{
+}
+
+static INPUT_PORTS_START(msx_hx3x_ports)
+ PORT_INCLUDE(msx_rs232_enable_switch)
+
+ PORT_START("COPY")
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("Copy")
+INPUT_PORTS_END
+
+ioport_constructor msx_slot_rs232_toshiba_hx3x_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(msx_hx3x_ports);
+}
+
+void msx_slot_rs232_toshiba_hx3x_device::device_add_mconfig(machine_config &config)
+{
+ msx_slot_rs232_base_device::device_add_mconfig(config);
+
+ NVRAM(config, m_nvram, nvram_device::DEFAULT_ALL_0);
+}
+
+void msx_slot_rs232_toshiba_hx3x_device::device_start()
+{
+ msx_slot_rs232_base_device::device_start();
+
+ // Sanity checks
+ // 16KB for RS-232C rom and 4 16KB banks for firmware
+ if (m_rom_region->bytes() < m_region_offset + 0x14000)
+ {
+ fatalerror("Memory region '%s' is too small for rom slot '%s'\n", m_rom_region.finder_tag(), tag());
+ }
+
+ // Install IO read/write handlers
+ io_space().install_readwrite_handler(0x80, 0x81, emu::rw_delegate(*m_i8251, FUNC(i8251_device::read)), emu::rw_delegate(*m_i8251, FUNC(i8251_device::write)));
+ io_space().install_readwrite_handler(0x82, 0x82, emu::rw_delegate(*this, FUNC(msx_slot_rs232_toshiba_hx3x_device::status_r)), emu::rw_delegate(*this, FUNC(msx_slot_rs232_toshiba_hx3x_device::irq_mask_w)));
+ io_space().install_readwrite_handler(0x84, 0x87, emu::rw_delegate(*m_i8253, FUNC(pit8253_device::read)), emu::rw_delegate(*m_i8253, FUNC(pit8253_device::write)));
+
+ m_sram.resize(SRAM_SIZE);
+ m_nvram->set_base(m_sram.data(), SRAM_SIZE);
+
+ save_item(NAME(m_bank_reg));
+
+ m_rombank->configure_entries(0, 4, m_rom_region->base() + m_region_offset + 0x4000, 0x4000);
+
+ page(1)->install_write_handler(0x7fff, 0x7fff, emu::rw_delegate(*this, FUNC(msx_slot_rs232_toshiba_hx3x_device::bank_w)));
+ page(1)->install_read_handler(0x7fff, 0x7fff, emu::rw_delegate(*this, FUNC(msx_slot_rs232_toshiba_hx3x_device::bank_r)));
+ page(2)->install_view(0x8000, 0xbfff, m_view);
+ m_view[0].install_read_bank(0x8000, 0xbfff, m_rombank);
+ m_view[1].install_ram(0x8000, 0x87ff, 0x3800, m_sram.data());
+}
+
+void msx_slot_rs232_toshiba_hx3x_device::device_reset()
+{
+ msx_slot_rs232_base_device::device_reset();
+
+ m_bank_reg = 0;
+ m_view.select(0);
+ m_rombank->set_entry(0);
+}
+
+u8 msx_slot_rs232_toshiba_hx3x_device::status_r(offs_t offset)
+{
+ // 7------- CTS
+ // -6------ 8253 channel 2 output
+ // --54---- unused
+ // ----3--- switch detection
+ // -----2-- unused
+ // ------1- ring indicator
+ // -------0 carrier detect
+
+ u8 result = 0x00;
+
+ if (m_cts)
+ result |= 0x80;
+
+ if (m_out2)
+ result |= 0x40;
+
+ if (BIT(m_irq_mask, 0) && m_switch_port->read())
+ result |= 0x08;
+
+ if (m_ri)
+ result |= 0x02;
+
+ if (m_dcd)
+ result |= 0x01;
+
+ return result;
+}
+
+void msx_slot_rs232_toshiba_hx3x_device::update_irq_state()
+{
+ if (!BIT(m_irq_mask, 0))
+ m_irq_handler(m_rxrdy);
+}
+
+u8 msx_slot_rs232_toshiba_hx3x_device::bank_r()
+{
+ return (m_copy_port->read() & 0x80) | m_bank_reg;
+}
+
+void msx_slot_rs232_toshiba_hx3x_device::bank_w(u8 data)
+{
+ m_bank_reg = data & 0x7f;
+ m_rombank->set_entry(data & 0x03);
+ m_view.select(((data & 0x60) == 0x60) ? 1 : 0);
+}
diff --git a/src/devices/bus/msx/slot/msx_rs232.h b/src/devices/bus/msx/slot/msx_rs232.h
new file mode 100644
index 00000000000..6aa6ba52ffa
--- /dev/null
+++ b/src/devices/bus/msx/slot/msx_rs232.h
@@ -0,0 +1,168 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#ifndef MAME_BUS_MSX_SLOT_MSX_RS232_H
+#define MAME_BUS_MSX_SLOT_MSX_RS232_H
+
+#pragma once
+
+#include "rom.h"
+#include "bus/rs232/rs232.h"
+#include "machine/i8251.h"
+#include "machine/nvram.h"
+#include "machine/pit8253.h"
+
+class msx_slot_rs232_base_device : public msx_slot_rom_device
+{
+public:
+
+ // configuration helpers
+ auto irq_handler() { return m_irq_handler.bind(); }
+
+protected:
+ msx_slot_rs232_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+
+ virtual void irq_mask_w(offs_t offset, u8 data);
+ virtual u8 status_r(offs_t offset) { return 0; }
+ virtual void update_irq_state() { }
+ void out2_w(int state);
+ void cts_w(int state);
+ void dcd_w(int state);
+ void ri_w(int state);
+ void rxrdy_w(int state);
+ void txrdy_w(int state);
+
+ required_device<i8251_device> m_i8251;
+ required_device<pit8253_device> m_i8253;
+ required_device<rs232_port_device> m_rs232;
+
+ devcb_write_line m_irq_handler;
+
+ u8 m_irq_mask;
+ bool m_out2;
+ bool m_cts;
+ bool m_dcd;
+ bool m_ri;
+ bool m_rxrdy;
+ bool m_txrdy;
+};
+
+
+class msx_slot_rs232_device : public msx_slot_rs232_base_device
+{
+public:
+ msx_slot_rs232_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual void device_start() override;
+
+ virtual u8 status_r(offs_t offset) override;
+ virtual void update_irq_state() override;
+};
+
+
+class msx_slot_rs232_mitsubishi_device : public msx_slot_rs232_base_device
+{
+public:
+ msx_slot_rs232_mitsubishi_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual void device_start() override;
+ virtual ioport_constructor device_input_ports() const override;
+
+ virtual u8 status_r(offs_t offset) override;
+ virtual void update_irq_state() override;
+
+ required_ioport m_switch_port;
+};
+
+
+class msx_slot_rs232_sony_device : public msx_slot_rs232_base_device
+{
+public:
+ msx_slot_rs232_sony_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual void device_start() override;
+ virtual ioport_constructor device_input_ports() const override;
+
+ virtual uint8_t status_r(offs_t offset) override;
+ virtual void update_irq_state() override;
+
+ static constexpr size_t RAM_SIZE = 0x800;
+
+ required_ioport m_switch_port;
+ std::vector<u8> m_ram;
+};
+
+
+class msx_slot_rs232_svi738_device : public msx_slot_rs232_base_device
+{
+public:
+ msx_slot_rs232_svi738_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual void device_start() override;
+
+ virtual u8 status_r(offs_t offset) override;
+ virtual void update_irq_state() override;
+};
+
+
+class msx_slot_rs232_toshiba_device : public msx_slot_rs232_base_device
+{
+public:
+ msx_slot_rs232_toshiba_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual void device_start() override;
+ virtual ioport_constructor device_input_ports() const override;
+
+ virtual uint8_t status_r(offs_t offset) override;
+ virtual void update_irq_state() override;
+
+ required_ioport m_switch_port;
+};
+
+
+class msx_slot_rs232_toshiba_hx3x_device : public msx_slot_rs232_base_device
+{
+public:
+ msx_slot_rs232_toshiba_hx3x_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ static constexpr size_t SRAM_SIZE = 0x800;
+
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual ioport_constructor device_input_ports() const override;
+ virtual void device_add_mconfig(machine_config &config) override;
+
+ virtual uint8_t status_r(offs_t offset) override;
+ virtual void update_irq_state() override;
+
+ void bank_w(u8 data);
+ u8 bank_r();
+
+ required_ioport m_switch_port;
+ required_ioport m_copy_port;
+ required_device<nvram_device> m_nvram;
+ memory_bank_creator m_rombank;
+ memory_view m_view;
+ std::vector<u8> m_sram;
+ u8 m_bank_reg;
+};
+
+
+DECLARE_DEVICE_TYPE(MSX_SLOT_RS232, msx_slot_rs232_device)
+DECLARE_DEVICE_TYPE(MSX_SLOT_RS232_MITSUBISHI, msx_slot_rs232_mitsubishi_device)
+DECLARE_DEVICE_TYPE(MSX_SLOT_RS232_SONY, msx_slot_rs232_sony_device)
+DECLARE_DEVICE_TYPE(MSX_SLOT_RS232_SVI738, msx_slot_rs232_svi738_device)
+DECLARE_DEVICE_TYPE(MSX_SLOT_RS232_TOSHIBA, msx_slot_rs232_toshiba_device)
+DECLARE_DEVICE_TYPE(MSX_SLOT_RS232_TOSHIBA_HX3X, msx_slot_rs232_toshiba_hx3x_device)
+
+
+#endif // MAME_BUS_MSX_SLOT_MSX_RS232_H
diff --git a/src/devices/bus/msx/slot/msx_write.cpp b/src/devices/bus/msx/slot/msx_write.cpp
new file mode 100644
index 00000000000..dca08d30f10
--- /dev/null
+++ b/src/devices/bus/msx/slot/msx_write.cpp
@@ -0,0 +1,77 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+/*
+
+ Emulation of the firmware mapper in the Sanyo PHC-77.
+
+*/
+
+#include "emu.h"
+#include "msx_write.h"
+
+
+DEFINE_DEVICE_TYPE(MSX_SLOT_MSX_WRITE, msx_slot_msx_write_device, "msx_slot_msx_write", "MSX Internal MSX-Write")
+
+
+msx_slot_msx_write_device::msx_slot_msx_write_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MSX_SLOT_MSX_WRITE, tag, owner, clock)
+ , msx_internal_slot_interface(mconfig, *this)
+ , m_rom_region(*this, finder_base::DUMMY_TAG)
+ , m_switch_port(*this, "SWITCH")
+ , m_rombank(*this, "rombank%u", 0U)
+ , m_view{ {*this, "view1"}, {*this, "view2"} }
+ , m_region_offset(0)
+ , m_enabled(true)
+{
+}
+
+static INPUT_PORTS_START(msx_write)
+ PORT_START("SWITCH")
+ PORT_CONFNAME(0x01, 0x01, "Firmware is")
+ PORT_CONFSETTING(0x00, "disabled")
+ PORT_CONFSETTING(0x01, "enabled")
+INPUT_PORTS_END
+
+ioport_constructor msx_slot_msx_write_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(msx_write);
+}
+
+void msx_slot_msx_write_device::device_start()
+{
+ // Sanity checks
+ if (m_rom_region->bytes() != 0x80000)
+ {
+ fatalerror("Memory region '%s' is not the correct size for the MSX-Write firmware\n", m_rom_region.finder_tag());
+ }
+
+ m_rombank[0]->configure_entries(0, 0x20, m_rom_region->base() + m_region_offset, 0x4000);
+ m_rombank[1]->configure_entries(0, 0x20, m_rom_region->base() + m_region_offset, 0x4000);
+
+ page(1)->install_view(0x4000, 0x7fff, m_view[0]);
+ m_view[0][0].install_read_bank(0x4000, 0x7fff, m_rombank[0]);
+ m_view[0][0].install_write_handler(0x6fff, 0x6fff, emu::rw_delegate(*this, FUNC(msx_slot_msx_write_device::bank_w<0>)));
+ m_view[0][0].install_write_handler(0x7fff, 0x7fff, emu::rw_delegate(*this, FUNC(msx_slot_msx_write_device::bank_w<1>)));
+ m_view[0][1];
+
+ page(2)->install_view(0x8000, 0xbfff, m_view[1]);
+ m_view[1][0].install_read_bank(0x8000, 0xbfff, m_rombank[1]);
+ m_view[1][1];
+}
+
+void msx_slot_msx_write_device::device_reset()
+{
+ m_enabled = BIT(m_switch_port->read(), 0);
+
+ for (int i = 0; i < 2; i++)
+ {
+ m_rombank[i]->set_entry(i);
+ m_view[i].select(m_enabled ? 0 : 1);
+ }
+}
+
+template <int Bank>
+void msx_slot_msx_write_device::bank_w(u8 data)
+{
+ m_rombank[Bank]->set_entry(data & 0x1f);
+}
diff --git a/src/devices/bus/msx/slot/msx_write.h b/src/devices/bus/msx/slot/msx_write.h
new file mode 100644
index 00000000000..64c9d9f97e7
--- /dev/null
+++ b/src/devices/bus/msx/slot/msx_write.h
@@ -0,0 +1,40 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#ifndef MAME_BUS_MSX_SLOT_MSX_WRITE_H
+#define MAME_BUS_MSX_SLOT_MSX_WRITE_H
+
+#pragma once
+
+#include "slot.h"
+#include "machine/nvram.h"
+
+
+DECLARE_DEVICE_TYPE(MSX_SLOT_MSX_WRITE, msx_slot_msx_write_device)
+
+
+class msx_slot_msx_write_device : public device_t, public msx_internal_slot_interface
+{
+public:
+ msx_slot_msx_write_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ // configuration helpers
+ void set_rom_start(const char *region, u32 offset) { m_rom_region.set_tag(region); m_region_offset = offset; }
+
+protected:
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual ioport_constructor device_input_ports() const override;
+
+private:
+ template <int Bank> void bank_w(u8 data);
+
+ required_memory_region m_rom_region;
+ required_ioport m_switch_port;
+ memory_bank_array_creator<2> m_rombank;
+ memory_view m_view[2];
+ u32 m_region_offset;
+ bool m_enabled;
+};
+
+
+#endif // MAME_BUS_MSX_SLOT_MSX_WRITE_H
diff --git a/src/devices/bus/msx/slot/music.cpp b/src/devices/bus/msx/slot/music.cpp
new file mode 100644
index 00000000000..4cf305ea390
--- /dev/null
+++ b/src/devices/bus/msx/slot/music.cpp
@@ -0,0 +1,22 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#include "emu.h"
+#include "music.h"
+
+
+DEFINE_DEVICE_TYPE(MSX_SLOT_MUSIC, msx_slot_music_device, "msx_slot_music", "MSX Internal MSX-MUSIC")
+
+
+msx_slot_music_device::msx_slot_music_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : msx_slot_rom_device(mconfig, MSX_SLOT_MUSIC, tag, owner, clock)
+ , m_ym2413(*this, finder_base::DUMMY_TAG)
+{
+}
+
+void msx_slot_music_device::device_start()
+{
+ msx_slot_rom_device::device_start();
+
+ // Install IO read/write handlers
+ io_space().install_write_handler(0x7c, 0x7d, emu::rw_delegate(*m_ym2413, FUNC(ym2413_device::write)));
+}
diff --git a/src/devices/bus/msx_slot/music.h b/src/devices/bus/msx/slot/music.h
index 0d9240079ab..41c34fdc313 100644
--- a/src/devices/bus/msx_slot/music.h
+++ b/src/devices/bus/msx/slot/music.h
@@ -5,10 +5,13 @@
#pragma once
-#include "bus/msx_slot/slot.h"
-#include "bus/msx_slot/rom.h"
+#include "rom.h"
+#include "slot.h"
+
#include "sound/ymopl.h"
+#include <utility>
+
DECLARE_DEVICE_TYPE(MSX_SLOT_MUSIC, msx_slot_music_device)
@@ -16,21 +19,16 @@ DECLARE_DEVICE_TYPE(MSX_SLOT_MUSIC, msx_slot_music_device)
class msx_slot_music_device : public msx_slot_rom_device
{
public:
- msx_slot_music_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ msx_slot_music_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- // configuration helpers
- void set_ym2413_tag(const char *tag) { m_ym2413_tag = tag; }
-
- virtual uint8_t read(offs_t offset) override;
+ // configuration
+ template <typename T> void set_ym2413_tag(T &&tag) { m_ym2413.set_tag(std::forward<T>(tag)); }
protected:
virtual void device_start() override;
private:
- void write_ym2413(offs_t offset, uint8_t data);
-
- ym2413_device *m_ym2413;
- const char *m_ym2413_tag;
+ required_device<ym2413_device> m_ym2413;
};
diff --git a/src/devices/bus/msx/slot/panasonic08.cpp b/src/devices/bus/msx/slot/panasonic08.cpp
new file mode 100644
index 00000000000..5de4c1d1913
--- /dev/null
+++ b/src/devices/bus/msx/slot/panasonic08.cpp
@@ -0,0 +1,132 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+/*
+
+ Emulation of the firmware mapper as found in Panasonic FS-A1WX andFS-A1WSX machines.
+
+TODO:
+- SRAM has only 2 4KB pages
+- SRAM is not accessible at 4000-7fff?
+*/
+
+#include "emu.h"
+#include "panasonic08.h"
+
+
+DEFINE_DEVICE_TYPE(MSX_SLOT_PANASONIC08, msx_slot_panasonic08_device, "msx_slot_panasonic08", "MSX Internal Panasonic08")
+
+
+msx_slot_panasonic08_device::msx_slot_panasonic08_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MSX_SLOT_PANASONIC08, tag, owner, clock)
+ , msx_internal_slot_interface(mconfig, *this)
+ , m_nvram(*this, "nvram")
+ , m_rom_region(*this, finder_base::DUMMY_TAG)
+ , m_bank(*this, "bank%u", 0U)
+ , m_view{ {*this, "view0"}, {*this, "view1"}, {*this, "view2"}, {*this, "view3"}, {*this, "view4"}, {*this, "view5"} }
+ , m_region_offset(0)
+ , m_control(0)
+{
+}
+
+void msx_slot_panasonic08_device::device_add_mconfig(machine_config &config)
+{
+ NVRAM(config, m_nvram, nvram_device::DEFAULT_ALL_0);
+}
+
+void msx_slot_panasonic08_device::device_start()
+{
+ // Sanity checks
+ if (m_rom_region->bytes() < m_region_offset + 0x200000)
+ {
+ fatalerror("Memory region '%s' is too small for the panasonic08 firmware\n", m_rom_region.finder_tag());
+ }
+
+ m_sram.resize(SRAM_SIZE);
+
+ m_nvram->set_base(&m_sram[0], SRAM_SIZE);
+
+ save_item(NAME(m_selected_bank));
+ save_item(NAME(m_control));
+
+ for (int i = 0; i < 6; i++)
+ {
+ m_bank[i]->configure_entries(0, 0x100, m_rom_region->base() + m_region_offset, 0x2000);
+ m_bank[i]->configure_entry(0x80, m_sram.data());
+ m_bank[i]->configure_entry(0x81, m_sram.data() + 0x2000);
+ m_bank[i]->configure_entry(0x82, m_sram.data());
+ m_bank[i]->configure_entry(0x83, m_sram.data() + 0x2000);
+ }
+
+ page(0)->install_view(0x0000, 0x1fff, m_view[0]);
+ m_view[0][0].install_read_bank(0x0000, 0x1fff, m_bank[0]);
+ m_view[0][1].install_readwrite_bank(0x0000, 0x1fff, m_bank[0]);
+
+ page(0)->install_view(0x2000, 0x3fff, m_view[1]);
+ m_view[1][0].install_read_bank(0x2000, 0x3fff, m_bank[1]);
+ m_view[1][1].install_readwrite_bank(0x2000, 0x3fff, m_bank[1]);
+
+ // no sram writing in 4000-7fff?
+ page(1)->install_read_bank(0x4000, 0x5fff, m_bank[2]);
+
+ page(1)->install_view(0x6000, 0x7fff, m_view[3]);
+ m_view[3][0].install_read_bank(0x6000, 0x7fff, m_bank[3]);
+ m_view[3][1].install_read_bank(0x6000, 0x7fff, m_bank[3]);
+ m_view[3][1].install_read_handler(0x7ff0, 0x7ff7, emu::rw_delegate(*this, FUNC(msx_slot_panasonic08_device::bank_r)));
+ page(1)->install_write_handler(0x6000, 0x6000, emu::rw_delegate(*this, FUNC(msx_slot_panasonic08_device::bank_w<0>)));
+ page(1)->install_write_handler(0x6400, 0x6400, emu::rw_delegate(*this, FUNC(msx_slot_panasonic08_device::bank_w<1>)));
+ page(1)->install_write_handler(0x6800, 0x6800, emu::rw_delegate(*this, FUNC(msx_slot_panasonic08_device::bank_w<2>)));
+ page(1)->install_write_handler(0x6c00, 0x6c00, emu::rw_delegate(*this, FUNC(msx_slot_panasonic08_device::bank_w<3>)));
+ page(1)->install_write_handler(0x7000, 0x7000, emu::rw_delegate(*this, FUNC(msx_slot_panasonic08_device::bank_w<4>)));
+ page(1)->install_write_handler(0x7800, 0x7800, emu::rw_delegate(*this, FUNC(msx_slot_panasonic08_device::bank_w<5>)));
+ page(1)->install_write_handler(0x7ff9, 0x7ff9, emu::rw_delegate(*this, FUNC(msx_slot_panasonic08_device::control_w)));
+
+ page(2)->install_view(0x8000, 0x9fff, m_view[4]);
+ m_view[4][0].install_read_bank(0x8000, 0x9fff, m_bank[4]);
+ m_view[4][1].install_readwrite_bank(0x8000, 0x9fff, m_bank[4]);
+
+ page(2)->install_view(0xa000, 0xbfff, m_view[5]);
+ m_view[5][0].install_read_bank(0xa000, 0xbfff, m_bank[5]);
+ m_view[5][1].install_readwrite_bank(0xa000, 0xbfff, m_bank[5]);
+}
+
+void msx_slot_panasonic08_device::device_reset()
+{
+ m_control = 0;
+ for (int i = 0 ; i < 6; i++)
+ {
+ m_selected_bank[i] = 0;
+ m_bank[i]->set_entry(0);
+ if (i != 2)
+ m_view[i].select(0);
+ }
+}
+
+template <int Bank>
+void msx_slot_panasonic08_device::set_view()
+{
+ bool ram_active = (m_selected_bank[Bank] >= 0x80 && m_selected_bank[Bank] < 0x84);
+ if (Bank == 3)
+ m_view[3].select(BIT(m_control, 2) ? 1 : 0);
+ else if (Bank != 2)
+ m_view[Bank].select(ram_active ? 1 : 0);
+}
+
+template <int Bank>
+void msx_slot_panasonic08_device::bank_w(u8 data)
+{
+ m_selected_bank[Bank] = data;
+ m_bank[Bank]->set_entry(data);
+ set_view<Bank>();
+}
+
+u8 msx_slot_panasonic08_device::bank_r(offs_t offset)
+{
+ return (offset < 6) ? m_selected_bank[offset] : 0;
+}
+
+void msx_slot_panasonic08_device::control_w(u8 data)
+{
+ // writing $04 enables read back of banking registers at 7ff0-7ff5
+ m_control = data;
+ set_view<3>();
+}
diff --git a/src/devices/bus/msx_slot/panasonic08.h b/src/devices/bus/msx/slot/panasonic08.h
index b21a4964e3b..6fd7ace83f4 100644
--- a/src/devices/bus/msx_slot/panasonic08.h
+++ b/src/devices/bus/msx/slot/panasonic08.h
@@ -15,31 +15,32 @@ DECLARE_DEVICE_TYPE(MSX_SLOT_PANASONIC08, msx_slot_panasonic08_device)
class msx_slot_panasonic08_device : public device_t, public msx_internal_slot_interface
{
public:
- msx_slot_panasonic08_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ msx_slot_panasonic08_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
// configuration helpers
- void set_rom_start(const char *region, uint32_t offset) { m_rom_region.set_tag(region); m_region_offset = offset; }
-
- virtual uint8_t read(offs_t offset) override;
- virtual void write(offs_t offset, uint8_t data) override;
+ void set_rom_start(const char *region, u32 offset) { m_rom_region.set_tag(region); m_region_offset = offset; }
protected:
virtual void device_start() override;
- virtual void device_post_load() override;
+ virtual void device_reset() override;
virtual void device_add_mconfig(machine_config &config) override;
private:
- void restore_banks();
- void map_bank(int bank);
+ static constexpr size_t SRAM_SIZE = 0x4000;
+
+ template <int Bank> void set_view();
+ template <int Bank> void bank_w(u8 data);
+ u8 bank_r(offs_t offset);
+ void control_w(u8 data);
required_device<nvram_device> m_nvram;
required_memory_region m_rom_region;
- uint32_t m_region_offset;
- const uint8_t *m_rom;
- uint8_t m_selected_bank[8];
- const uint8_t *m_bank_base[8];
- uint8_t m_control;
+ memory_bank_array_creator<6> m_bank;
+ memory_view m_view[6];
+ u32 m_region_offset;
+ u8 m_selected_bank[6];
+ u8 m_control;
std::vector<uint8_t> m_sram;
};
diff --git a/src/devices/bus/msx_slot/ram.cpp b/src/devices/bus/msx/slot/ram.cpp
index 835a5551b92..92f9a57929d 100644
--- a/src/devices/bus/msx_slot/ram.cpp
+++ b/src/devices/bus/msx/slot/ram.cpp
@@ -6,7 +6,7 @@
DEFINE_DEVICE_TYPE(MSX_SLOT_RAM, msx_slot_ram_device, "msx_slot_ram", "MSX Internal RAM")
-msx_slot_ram_device::msx_slot_ram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+msx_slot_ram_device::msx_slot_ram_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: device_t(mconfig, MSX_SLOT_RAM, tag, owner, clock)
, msx_internal_slot_interface(mconfig, *this)
{
@@ -16,21 +16,13 @@ void msx_slot_ram_device::device_start()
{
m_ram.resize(m_size);
save_item(NAME(m_ram));
-}
-uint8_t msx_slot_ram_device::read(offs_t offset)
-{
- if ( offset >= m_start_address && offset < m_end_address )
- {
- return m_ram[ offset - m_start_address ];
- }
- return 0xFF;
-}
-
-void msx_slot_ram_device::write(offs_t offset, uint8_t data)
-{
- if ( offset >= m_start_address && offset < m_end_address )
+ u8 *ram = m_ram.data();
+ u32 start_address = m_start_address;
+ for (int i = m_start_address >> 14; i < 4 && i * 0x4000 < m_end_address; i++)
{
- m_ram[offset - m_start_address] = data;
+ page(i)->install_ram(start_address, std::min<u32>((i + 1) * 0x4000, m_end_address) - 1, ram);
+ start_address += 0x4000;
+ ram += 0x4000;
}
}
diff --git a/src/devices/bus/msx_slot/ram.h b/src/devices/bus/msx/slot/ram.h
index f96271ad066..9e8f08bc373 100644
--- a/src/devices/bus/msx_slot/ram.h
+++ b/src/devices/bus/msx/slot/ram.h
@@ -3,25 +3,24 @@
#ifndef MAME_BUS_MSX_SLOT_RAM_H
#define MAME_BUS_MSX_SLOT_RAM_H
+#pragma once
+
#include "slot.h"
class msx_slot_ram_device : public device_t,
public msx_internal_slot_interface
{
public:
- msx_slot_ram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ msx_slot_ram_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
// Set to 0xe000 for 8KB RAM
- void force_start_address(uint16_t start) { m_start_address = start; }
-
- virtual uint8_t read(offs_t offset) override;
- virtual void write(offs_t offset, uint8_t data) override;
+ void force_start_address(u16 start) { m_start_address = start; }
protected:
virtual void device_start() override;
private:
- std::vector<uint8_t> m_ram;
+ std::vector<u8> m_ram;
};
diff --git a/src/devices/bus/msx/slot/ram_mm.cpp b/src/devices/bus/msx/slot/ram_mm.cpp
new file mode 100644
index 00000000000..b32264a02eb
--- /dev/null
+++ b/src/devices/bus/msx/slot/ram_mm.cpp
@@ -0,0 +1,60 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#include "emu.h"
+#include "ram_mm.h"
+
+DEFINE_DEVICE_TYPE(MSX_SLOT_RAM_MM, msx_slot_ram_mm_device, "msx_slot_ram_mm", "MSX Internal Memory Mapped RAM")
+
+msx_slot_ram_mm_device::msx_slot_ram_mm_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MSX_SLOT_RAM_MM, tag, owner, clock)
+ , msx_internal_slot_interface(mconfig, *this)
+ , m_total_size(0)
+ , m_bank_mask(0)
+ , m_unused_bits(0)
+ , m_rambank(*this, "mmbank%u", 0U)
+{
+}
+
+void msx_slot_ram_mm_device::device_start()
+{
+ // Valid mapper sizes are 64KB, 128KB, 256KB, 512KB, 1MB, 2MB, and 4MB */
+ switch (m_total_size)
+ {
+ case 64*1024: m_bank_mask = 0x03; break;
+ case 128*1024: m_bank_mask = 0x07; break;
+ case 256*1024: m_bank_mask = 0x0f; break;
+ case 512*1024: m_bank_mask = 0x1f; break;
+ case 1024*1024: m_bank_mask = 0x3f; break;
+ case 2048*1024: m_bank_mask = 0x7f; break;
+ case 4096*1024: m_bank_mask = 0xff; break;
+ default: fatalerror("Invalid memory mapper size specified\n");
+ }
+
+ m_ram.resize(m_total_size);
+
+ save_item(NAME(m_ram));
+
+ // Install IO read/write handlers using taps to prevent overwriting taps
+ // installed by other (external) memory mapper devices.
+ io_space().install_write_tap(0xfc, 0xff, "mm", [this] (offs_t offset, u8& data, u8){ write_mapper_bank(offset, data); });
+ io_space().install_read_tap(0xfc, 0xff, "mm", [this] (offs_t offset, u8& data, u8){ if (!machine().side_effects_disabled()) data &= read_mapper_bank(offset); });
+
+ for (int i = 0; i < 4; i++)
+ {
+ m_rambank[i]->configure_entries(0, u32(m_bank_mask) + 1, m_ram.data(), 0x4000);
+ page(i)->install_readwrite_bank(0x4000 * i, (0x4000 * i) + 0x3fff, m_rambank[i]);
+ }
+}
+
+u8 msx_slot_ram_mm_device::read_mapper_bank(offs_t offset)
+{
+ if (m_unused_bits)
+ return m_rambank[offset & 3]->entry() | m_unused_bits;
+
+ return m_rambank[offset & 3]->entry() | ~m_bank_mask;
+}
+
+void msx_slot_ram_mm_device::write_mapper_bank(offs_t offset, u8 data)
+{
+ m_rambank[offset & 0x03]->set_entry(data & m_bank_mask);
+}
diff --git a/src/devices/bus/msx/slot/ram_mm.h b/src/devices/bus/msx/slot/ram_mm.h
new file mode 100644
index 00000000000..69ce5f41053
--- /dev/null
+++ b/src/devices/bus/msx/slot/ram_mm.h
@@ -0,0 +1,34 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#ifndef MAME_BUS_MSX_SLOT_RAM_MM_H
+#define MAME_BUS_MSX_SLOT_RAM_MM_H
+
+#pragma once
+
+#include "slot.h"
+
+class msx_slot_ram_mm_device : public device_t, public msx_internal_slot_interface
+{
+public:
+ msx_slot_ram_mm_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ msx_slot_ram_mm_device &set_total_size(u32 total_size) { m_total_size = total_size; return *this; }
+ msx_slot_ram_mm_device &set_unused_bits(u8 unused_bits) { m_unused_bits = unused_bits; return *this; }
+
+protected:
+ virtual void device_start() override;
+
+private:
+ u8 read_mapper_bank(offs_t offset);
+ void write_mapper_bank(offs_t offset, u8 data);
+
+ std::vector<u8> m_ram;
+ u32 m_total_size;
+ u8 m_bank_mask;
+ u8 m_unused_bits;
+ memory_bank_array_creator<4> m_rambank;
+};
+
+DECLARE_DEVICE_TYPE(MSX_SLOT_RAM_MM, msx_slot_ram_mm_device)
+
+#endif // MAME_BUS_MSX_SLOT_RAM_MM_H
diff --git a/src/devices/bus/msx_slot/rom.cpp b/src/devices/bus/msx/slot/rom.cpp
index aafc37b345b..783e4313f30 100644
--- a/src/devices/bus/msx_slot/rom.cpp
+++ b/src/devices/bus/msx/slot/rom.cpp
@@ -7,22 +7,19 @@
DEFINE_DEVICE_TYPE(MSX_SLOT_ROM, msx_slot_rom_device, "msx_slot_rom", "MSX Internal ROM")
-msx_slot_rom_device::msx_slot_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+msx_slot_rom_device::msx_slot_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: msx_slot_rom_device(mconfig, MSX_SLOT_ROM, tag, owner, clock)
{
}
-
-msx_slot_rom_device::msx_slot_rom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+msx_slot_rom_device::msx_slot_rom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
: device_t(mconfig, type, tag, owner, clock)
, msx_internal_slot_interface(mconfig, *this)
, m_rom_region(*this, finder_base::DUMMY_TAG)
, m_region_offset(0)
- , m_rom(nullptr)
{
}
-
void msx_slot_rom_device::device_start()
{
// Sanity checks
@@ -31,15 +28,10 @@ void msx_slot_rom_device::device_start()
fatalerror("Memory region '%s' is too small for rom slot '%s'\n", m_rom_region.finder_tag(), tag());
}
- m_rom = m_rom_region->base() + m_region_offset;
-}
-
-
-uint8_t msx_slot_rom_device::read(offs_t offset)
-{
- if (offset >= m_start_address && offset < m_end_address)
+ u8 *rom = m_rom_region->base() + m_region_offset;
+ for (int i = m_start_address >> 14; i < 4 && i * 0x4000 < m_end_address; i++)
{
- return m_rom[offset - m_start_address];
+ page(i)->install_rom(i * 0x4000, std::min<u32>((i + 1) * 0x4000, m_end_address) - 1, rom);
+ rom += 0x4000;
}
- return 0xFF;
}
diff --git a/src/devices/bus/msx_slot/rom.h b/src/devices/bus/msx/slot/rom.h
index 6bcd480a5a3..698487dae3f 100644
--- a/src/devices/bus/msx_slot/rom.h
+++ b/src/devices/bus/msx/slot/rom.h
@@ -11,22 +11,19 @@ class msx_slot_rom_device : public device_t,
public msx_internal_slot_interface
{
public:
- msx_slot_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ msx_slot_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
// configuration helpers
void set_rom_start(const char *region, uint32_t offset) { m_rom_region.set_tag(region); m_region_offset = offset; }
- virtual uint8_t read(offs_t offset) override;
-
protected:
- msx_slot_rom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+ msx_slot_rom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
virtual void device_start() override;
+ u8 *rom_base() { return m_rom_region->base() + m_region_offset; }
-private:
required_memory_region m_rom_region;
- uint32_t m_region_offset;
- const uint8_t *m_rom;
+ u32 m_region_offset;
};
DECLARE_DEVICE_TYPE(MSX_SLOT_ROM, msx_slot_rom_device)
diff --git a/src/devices/bus/msx_slot/slot.cpp b/src/devices/bus/msx/slot/slot.cpp
index 345cf6e0a5c..06d6c547221 100644
--- a/src/devices/bus/msx_slot/slot.cpp
+++ b/src/devices/bus/msx/slot/slot.cpp
@@ -16,9 +16,26 @@ pages; and multiple pieces of rom/ram/components can occur in a single slot.
msx_internal_slot_interface::msx_internal_slot_interface(const machine_config &mconfig, device_t &device)
: m_mem_space(device, finder_base::DUMMY_TAG, -1)
, m_io_space(device, finder_base::DUMMY_TAG, -1)
+ , m_maincpu(device, finder_base::DUMMY_TAG)
, m_start_address(0)
, m_size(0)
, m_end_address(0)
+ , m_page{nullptr, nullptr, nullptr, nullptr}
{
(void)mconfig;
}
+
+void msx_internal_slot_interface::configure_subslot(msx_internal_slot_interface &subslot)
+{
+ subslot.m_mem_space.set_tag(m_mem_space);
+ subslot.m_io_space.set_tag(m_io_space);
+ subslot.m_maincpu.set_tag(m_maincpu);
+}
+
+void msx_internal_slot_interface::install(memory_view::memory_view_entry *page0, memory_view::memory_view_entry *page1, memory_view::memory_view_entry *page2, memory_view::memory_view_entry *page3)
+{
+ m_page[0] = page0;
+ m_page[1] = page1;
+ m_page[2] = page2;
+ m_page[3] = page3;
+}
diff --git a/src/devices/bus/msx_slot/slot.h b/src/devices/bus/msx/slot/slot.h
index 3a95c7b6b75..8be6bc1938c 100644
--- a/src/devices/bus/msx_slot/slot.h
+++ b/src/devices/bus/msx/slot/slot.h
@@ -18,29 +18,44 @@ pages; and multiple pieces of rom/ram/components can occur in a single slot.
class msx_internal_slot_interface
{
public:
- msx_internal_slot_interface(const machine_config &mconfig, device_t &device);
msx_internal_slot_interface(const msx_internal_slot_interface &device) = delete;
virtual ~msx_internal_slot_interface() { }
// configuration helpers
template <typename T> void set_memory_space(T &&tag, int spacenum) { m_mem_space.set_tag(std::forward<T>(tag), spacenum); }
template <typename T> void set_io_space(T &&tag, int spacenum) { m_io_space.set_tag(std::forward<T>(tag), spacenum); }
- void set_start_address(uint32_t start_address) { m_start_address = start_address; m_end_address = m_start_address + m_size; }
- void set_size(uint32_t size) { m_size = size; m_end_address = m_start_address + m_size; }
+ template <typename T> void set_maincpu(T &&tag) { m_maincpu.set_tag(std::forward<T>(tag)); }
+ void set_start_address(u32 start_address) { m_start_address = start_address; m_end_address = m_start_address + m_size; }
+ void set_size(u32 size) { m_size = size; m_end_address = m_start_address + m_size; }
+
+ // for configuring downstream slots
+ void configure_subslot(msx_internal_slot_interface &subslot);
- virtual uint8_t read(offs_t offset) { return 0xFF; }
- virtual void write(offs_t offset, uint8_t data) { }
+ void install(memory_view::memory_view_entry *page0, memory_view::memory_view_entry *page1, memory_view::memory_view_entry *page2, memory_view::memory_view_entry *page3);
address_space &memory_space() const { return *m_mem_space; }
address_space &io_space() const { return *m_io_space; }
+ cpu_device &maincpu() const { return *m_maincpu; }
+ bool page_configured(int i) { return bool(m_page[i]); }
+ memory_view::memory_view_entry *page(int i)
+ {
+ if (!m_page[i])
+ fatalerror("page %i view not configured\n", i);
+ return m_page[i];
+ }
protected:
+ msx_internal_slot_interface(const machine_config &mconfig, device_t &device);
+
required_address_space m_mem_space;
required_address_space m_io_space;
+ required_device<cpu_device> m_maincpu;
+
+ u32 m_start_address;
+ u32 m_size;
+ u32 m_end_address;
- uint32_t m_start_address;
- uint32_t m_size;
- uint32_t m_end_address;
+ memory_view::memory_view_entry *m_page[4];
};
#endif // MAME_BUS_MSX_SLOT_SLOT_H
diff --git a/src/devices/bus/msx/slot/sony08.cpp b/src/devices/bus/msx/slot/sony08.cpp
new file mode 100644
index 00000000000..bf13f091ee1
--- /dev/null
+++ b/src/devices/bus/msx/slot/sony08.cpp
@@ -0,0 +1,87 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+/*
+
+ Emulation of the firmware mapper as found in Sony HB-F1XDJ and HB-F1XV machines.
+
+*/
+
+#include "emu.h"
+#include "sony08.h"
+
+
+DEFINE_DEVICE_TYPE(MSX_SLOT_SONY08, msx_slot_sony08_device, "msx_slot_sony08", "MSX Internal SONY08")
+
+
+msx_slot_sony08_device::msx_slot_sony08_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MSX_SLOT_SONY08, tag, owner, clock)
+ , msx_internal_slot_interface(mconfig, *this)
+ , m_nvram(*this, "nvram")
+ , m_rom_region(*this, finder_base::DUMMY_TAG)
+ , m_rombank(*this, "rombank%u", 0U)
+ , m_view{ {*this, "view0"}, {*this, "view1"} }
+ , m_region_offset(0)
+{
+}
+
+
+void msx_slot_sony08_device::device_add_mconfig(machine_config &config)
+{
+ NVRAM(config, m_nvram, nvram_device::DEFAULT_ALL_0);
+}
+
+void msx_slot_sony08_device::device_start()
+{
+ // Sanity checks
+ if (m_rom_region->bytes() < m_region_offset + 0x100000)
+ {
+ fatalerror("Memory region '%s' is too small for the SONY08 firmware\n", m_rom_region.finder_tag());
+ }
+
+ m_sram.resize(SRAM_SIZE);
+ m_nvram->set_base(m_sram.data(), SRAM_SIZE);
+
+ for (int i = 0; i < 4; i++)
+ m_rombank[i]->configure_entries(0, 0x80, m_rom_region->base() + m_region_offset, 0x2000);
+ m_rombank[4]->configure_entries(0, 0x100, m_rom_region->base() + m_region_offset + 0x80000, 0x800);
+ m_rombank[5]->configure_entries(0, 0x100, m_rom_region->base() + m_region_offset + 0x80000, 0x800);
+
+ page(0)->install_view(0x0000, 0x3fff, m_view[0]);
+ m_view[0][0];
+ m_view[0][1].install_ram(0x0000, 0x3fff, m_sram.data());
+
+ page(1)->install_read_bank(0x4000, 0x5fff, m_rombank[0]);
+ page(1)->install_write_handler(0x4fff, 0x4fff, emu::rw_delegate(*this, FUNC(msx_slot_sony08_device::bank_w<0>)));
+ page(1)->install_view(0x6000, 0x7fff, m_view[1]);
+ m_view[1][0].install_read_bank(0x6000, 0x7fff, m_rombank[1]);
+ m_view[1][1].install_read_bank(0x6000, 0x6fff, m_rombank[1]);
+ m_view[1][1].install_read_bank(0x7000, 0x77ff, m_rombank[4]);
+ m_view[1][1].install_read_bank(0x7800, 0x7fff, m_rombank[5]);
+ page(1)->install_write_handler(0x6fff, 0x6fff, emu::rw_delegate(*this, FUNC(msx_slot_sony08_device::bank_w<1>)));
+ page(1)->install_write_handler(0x77ff, 0x77ff, emu::rw_delegate(*this, FUNC(msx_slot_sony08_device::bank_w<4>)));
+ page(1)->install_write_handler(0x7fff, 0x7fff, emu::rw_delegate(*this, FUNC(msx_slot_sony08_device::bank_w<5>)));
+ page(2)->install_read_bank(0x8000, 0x9fff, m_rombank[2]);
+ page(2)->install_write_handler(0x8fff, 0x8fff, emu::rw_delegate(*this, FUNC(msx_slot_sony08_device::bank_w<2>)));
+ page(2)->install_read_bank(0xa000, 0xbfff, m_rombank[3]);
+ page(2)->install_write_handler(0xafff, 0xafff, emu::rw_delegate(*this, FUNC(msx_slot_sony08_device::bank_w<3>)));
+}
+
+void msx_slot_sony08_device::device_reset()
+{
+ for (int i = 0; i < 2; i++)
+ m_view[i].select(0);
+ for (int i = 0; i < 6; i++)
+ m_rombank[i]->set_entry(0);
+}
+
+template <int Bank>
+void msx_slot_sony08_device::bank_w(u8 data)
+{
+ if (Bank >= 4)
+ m_rombank[Bank]->set_entry(data);
+ else
+ m_rombank[Bank]->set_entry(data & 0x7f);
+
+ if (Bank < 2)
+ m_view[Bank].select(BIT(data, 7) ? 1 : 0);
+}
diff --git a/src/devices/bus/msx_slot/sony08.h b/src/devices/bus/msx/slot/sony08.h
index 74c8fd95f35..2fa9d9e89ca 100644
--- a/src/devices/bus/msx_slot/sony08.h
+++ b/src/devices/bus/msx/slot/sony08.h
@@ -15,32 +15,28 @@ DECLARE_DEVICE_TYPE(MSX_SLOT_SONY08, msx_slot_sony08_device)
class msx_slot_sony08_device : public device_t, public msx_internal_slot_interface
{
public:
- msx_slot_sony08_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ msx_slot_sony08_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
// configuration helpers
- void set_rom_start(const char *region, uint32_t offset) { m_rom_region.set_tag(region); m_region_offset = offset; }
-
- virtual uint8_t read(offs_t offset) override;
- virtual void write(offs_t offset, uint8_t data) override;
+ void set_rom_start(const char *region, u32 offset) { m_rom_region.set_tag(region); m_region_offset = offset; }
protected:
virtual void device_start() override;
- virtual void device_post_load() override;
+ virtual void device_reset() override;
virtual void device_add_mconfig(machine_config &config) override;
- void restore_banks();
-
private:
+ static constexpr size_t SRAM_SIZE = 0x4000;
+
+ template <int Bank> void bank_w(u8 data);
+
required_device<nvram_device> m_nvram;
required_memory_region m_rom_region;
- uint32_t m_region_offset;
- const uint8_t *m_rom;
- uint8_t m_selected_bank[8];
- const uint8_t *m_bank_base[8];
- uint8_t m_sram[0x4000];
-
- void map_bank(int bank);
+ memory_bank_array_creator<6> m_rombank;
+ memory_view m_view[2];
+ u32 m_region_offset;
+ std::vector<u8> m_sram;
};
diff --git a/src/devices/bus/msx/softcard/softcard.cpp b/src/devices/bus/msx/softcard/softcard.cpp
new file mode 100644
index 00000000000..bd0b5847f9d
--- /dev/null
+++ b/src/devices/bus/msx/softcard/softcard.cpp
@@ -0,0 +1,56 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+
+#include "emu.h"
+#include "bus/msx/cart/softcard.h"
+
+
+DECLARE_DEVICE_TYPE(SOFTCARD_NOMAPPER, softcard_interface)
+
+
+void softcard(device_slot_interface &device)
+{
+ device.option_add_internal("nomapper", SOFTCARD_NOMAPPER);
+}
+
+
+namespace {
+
+class softcard_nomapper_device : public device_t
+ , public softcard_interface
+{
+public:
+ softcard_nomapper_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override { }
+
+ virtual std::error_condition initialize_cartridge(std::string &message) override;
+
+};
+
+
+softcard_nomapper_device::softcard_nomapper_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, SOFTCARD_NOMAPPER, tag, owner, clock)
+ , softcard_interface(mconfig, *this)
+{
+}
+
+std::error_condition softcard_nomapper_device::initialize_cartridge(std::string &message)
+{
+ if (!cart_rom_region())
+ {
+ message = "softcard_nomapper: Required region 'rom' was not found.";
+ return image_error::INTERNAL;
+ }
+
+ page(1)->install_rom(0x4000, 0x7fff, cart_rom_region()->base());
+ page(2)->install_rom(0x8000, 0xbfff, cart_rom_region()->base() + 0x4000);
+
+ return std::error_condition();
+}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(SOFTCARD_NOMAPPER, softcard_interface, softcard_nomapper_device, "softcard_nomapper", "SoftCard ROM")
diff --git a/src/devices/bus/msx/softcard/softcard.h b/src/devices/bus/msx/softcard/softcard.h
new file mode 100644
index 00000000000..c47c5c8d6ac
--- /dev/null
+++ b/src/devices/bus/msx/softcard/softcard.h
@@ -0,0 +1,12 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#ifndef MAME_BUS_MSX_SOFTCARD_SOFTCARD_H
+#define MAME_BUS_MSX_SOFTCARD_SOFTCARD_H
+
+#pragma once
+
+
+void softcard(device_slot_interface &device);
+
+
+#endif // MAME_BUS_MSX_SOFTCARD_SOFTCARD_H
diff --git a/src/devices/bus/msx_cart/arc.cpp b/src/devices/bus/msx_cart/arc.cpp
deleted file mode 100644
index 6f5af572bd1..00000000000
--- a/src/devices/bus/msx_cart/arc.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Wilbert Pol
-#include "emu.h"
-#include "arc.h"
-
-
-DEFINE_DEVICE_TYPE(MSX_CART_ARC, msx_cart_arc_device, "msx_cart_arc", "MSX Cartridge - Arc")
-
-
-msx_cart_arc_device::msx_cart_arc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, MSX_CART_ARC, tag, owner, clock)
- , msx_cart_interface(mconfig, *this)
- , m_7f(0)
-{
-}
-
-
-void msx_cart_arc_device::device_start()
-{
- // Install IO read/write handlers
- io_space().install_write_handler(0x7f, 0x7f, write8smo_delegate(*this, FUNC(msx_cart_arc_device::io_7f_w)));
- io_space().install_read_handler(0x7f, 0x7f, read8smo_delegate(*this, FUNC(msx_cart_arc_device::io_7f_r)));
-}
-
-
-void msx_cart_arc_device::device_reset()
-{
- m_7f = 0;
-}
-
-
-void msx_cart_arc_device::initialize_cartridge()
-{
- if (get_rom_size() != 0x8000)
- {
- fatalerror("arc: Invalid ROM size\n");
- }
-}
-
-
-uint8_t msx_cart_arc_device::read_cart(offs_t offset)
-{
- if (offset >= 0x4000 && offset < 0xc000)
- {
- return get_rom_base()[offset - 0x4000];
- }
- return 0xff;
-}
-
-
-void msx_cart_arc_device::io_7f_w(uint8_t data)
-{
- if (data == 0x35)
- {
- m_7f++;
- }
-}
-
-
-uint8_t msx_cart_arc_device::io_7f_r()
-{
- return ((m_7f & 0x03) == 0x03) ? 0xda : 0xff;
-}
diff --git a/src/devices/bus/msx_cart/arc.h b/src/devices/bus/msx_cart/arc.h
deleted file mode 100644
index 69f4427a01f..00000000000
--- a/src/devices/bus/msx_cart/arc.h
+++ /dev/null
@@ -1,35 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Wilbert Pol
-#ifndef MAME_BUS_MSX_CART_ARC_H
-#define MAME_BUS_MSX_CART_ARC_H
-
-#pragma once
-
-#include "bus/msx_cart/cartridge.h"
-
-
-DECLARE_DEVICE_TYPE(MSX_CART_ARC, msx_cart_arc_device)
-
-
-class msx_cart_arc_device : public device_t, public msx_cart_interface
-{
-public:
- msx_cart_arc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void initialize_cartridge() override;
-
- virtual uint8_t read_cart(offs_t offset) override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
-
-private:
- void io_7f_w(uint8_t data);
- uint8_t io_7f_r();
-
- uint8_t m_7f;
-};
-
-#endif // MAME_BUS_MSX_CART_ARC_H
diff --git a/src/devices/bus/msx_cart/ascii.cpp b/src/devices/bus/msx_cart/ascii.cpp
deleted file mode 100644
index 7d1b354b404..00000000000
--- a/src/devices/bus/msx_cart/ascii.cpp
+++ /dev/null
@@ -1,555 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Wilbert Pol
-#include "emu.h"
-#include "ascii.h"
-
-
-DEFINE_DEVICE_TYPE(MSX_CART_ASCII8, msx_cart_ascii8_device, "msx_cart_ascii8", "MSX Cartridge - ASCII8")
-DEFINE_DEVICE_TYPE(MSX_CART_ASCII16, msx_cart_ascii16_device, "msx_cart_ascii16", "MSX Cartridge - ASCII16")
-DEFINE_DEVICE_TYPE(MSX_CART_ASCII8_SRAM, msx_cart_ascii8_sram_device, "msx_cart_ascii8_sram", "MSX Cartridge - ASCII8 w/SRAM")
-DEFINE_DEVICE_TYPE(MSX_CART_ASCII16_SRAM, msx_cart_ascii16_sram_device, "msx_cart_ascii16_sram", "MSX Cartridge - ASCII16 w/SRAM")
-DEFINE_DEVICE_TYPE(MSX_CART_MSXWRITE, msx_cart_msxwrite_device, "msx_cart_msxwrite", "MSX Cartridge - MSXWRITE")
-
-
-msx_cart_ascii8_device::msx_cart_ascii8_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, MSX_CART_ASCII8, tag, owner, clock)
- , msx_cart_interface(mconfig, *this)
- , m_bank_mask(0)
-{
- for (int i = 0; i < 4; i++)
- {
- m_selected_bank[i] = 0;
- m_bank_base[i] = nullptr;
- }
-}
-
-
-void msx_cart_ascii8_device::device_start()
-{
- save_item(NAME(m_selected_bank));
-}
-
-
-void msx_cart_ascii8_device::device_post_load()
-{
- restore_banks();
-}
-
-
-void msx_cart_ascii8_device::restore_banks()
-{
- for (int i = 0; i < 4; i++)
- {
- m_bank_base[i] = get_rom_base() + (m_selected_bank[i] & m_bank_mask ) * 0x2000;
- }
-}
-
-
-void msx_cart_ascii8_device::device_reset()
-{
- for (auto & elem : m_selected_bank)
- {
- elem = 0;
- }
-}
-
-
-void msx_cart_ascii8_device::initialize_cartridge()
-{
- uint32_t size = get_rom_size();
-
- if ( size > 256 * 0x2000 )
- {
- fatalerror("ascii8: ROM is too big\n");
- }
-
- uint16_t banks = size / 0x2000;
-
- if (size != banks * 0x2000 || (~(banks - 1) % banks))
- {
- fatalerror("ascii8: Invalid ROM size\n");
- }
-
- m_bank_mask = banks - 1;
-
- restore_banks();
-}
-
-
-uint8_t msx_cart_ascii8_device::read_cart(offs_t offset)
-{
- if ( offset >= 0x4000 && offset < 0xC000 )
- {
- return m_bank_base[(offset - 0x4000) >> 13][offset & 0x1fff];
- }
- return 0xff;
-}
-
-
-void msx_cart_ascii8_device::write_cart(offs_t offset, uint8_t data)
-{
- if (offset >= 0x6000 && offset < 0x8000)
- {
- uint8_t bank = (offset / 0x800) & 0x03;
-
- m_selected_bank[bank] = data;
- m_bank_base[bank] = get_rom_base() + (m_selected_bank[bank] & m_bank_mask ) * 0x2000;
- }
-}
-
-
-
-msx_cart_ascii16_device::msx_cart_ascii16_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, MSX_CART_ASCII16, tag, owner, clock)
- , msx_cart_interface(mconfig, *this)
- , m_bank_mask(0)
-{
- for (int i = 0; i < 2; i++)
- {
- m_selected_bank[i] = 0;
- m_bank_base[i] = nullptr;
- }
-}
-
-
-void msx_cart_ascii16_device::device_start()
-{
- save_item(NAME(m_selected_bank));
-}
-
-
-void msx_cart_ascii16_device::device_post_load()
-{
- restore_banks();
-}
-
-
-void msx_cart_ascii16_device::restore_banks()
-{
- for (int i = 0; i < 2; i++)
- {
- m_bank_base[i] = get_rom_base() + (m_selected_bank[i] & m_bank_mask) * 0x4000;
- }
-}
-
-
-void msx_cart_ascii16_device::device_reset()
-{
- for (auto & elem : m_selected_bank)
- {
- elem = 0;
- }
-}
-
-
-void msx_cart_ascii16_device::initialize_cartridge()
-{
- uint32_t size = get_rom_size();
-
- if ( size > 256 * 0x4000 )
- {
- fatalerror("ascii16: ROM is too big\n");
- }
-
- uint16_t banks = size / 0x4000;
-
- if (size != banks * 0x4000 || (~(banks - 1) % banks))
- {
- fatalerror("ascii16: Invalid ROM size\n");
- }
-
- m_bank_mask = banks - 1;
-
- restore_banks();
-}
-
-
-uint8_t msx_cart_ascii16_device::read_cart(offs_t offset)
-{
- if ( offset >= 0x4000 && offset < 0xC000 )
- {
- return m_bank_base[offset >> 15][offset & 0x3fff];
- }
- return 0xff;
-}
-
-
-void msx_cart_ascii16_device::write_cart(offs_t offset, uint8_t data)
-{
- if (offset >= 0x6000 && offset < 0x6800)
- {
- m_selected_bank[0] = data;
- m_bank_base[0] = get_rom_base() + (m_selected_bank[0] & m_bank_mask) * 0x4000;
- }
-
- if (offset >= 0x7000 && offset < 0x7800)
- {
- m_selected_bank[1] = data;
- m_bank_base[1] = get_rom_base() + (m_selected_bank[1] & m_bank_mask) * 0x4000;
- }
-}
-
-
-
-
-
-msx_cart_ascii8_sram_device::msx_cart_ascii8_sram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, MSX_CART_ASCII8_SRAM, tag, owner, clock)
- , msx_cart_interface(mconfig, *this)
- , m_bank_mask(0)
- , m_sram_select_mask(0)
-{
- for (int i = 0; i < 4; i++)
- {
- m_selected_bank[i] = 0;
- m_bank_base[i] = nullptr;
- }
-}
-
-
-void msx_cart_ascii8_sram_device::device_start()
-{
- save_item(NAME(m_selected_bank));
-}
-
-
-void msx_cart_ascii8_sram_device::device_post_load()
-{
- restore_banks();
-}
-
-
-void msx_cart_ascii8_sram_device::setup_bank(uint8_t bank)
-{
- if (m_selected_bank[bank] & ~(m_sram_select_mask | m_bank_mask))
- {
- // Nothing is mapped
- m_bank_base[bank] = nullptr;
- }
- else if (m_selected_bank[bank] & m_sram_select_mask)
- {
- // SRAM is selected
- m_bank_base[bank] = get_sram_base();
- }
- else
- {
- m_bank_base[bank] = get_rom_base() + (m_selected_bank[bank] & m_bank_mask ) * 0x2000;
- }
-}
-
-
-void msx_cart_ascii8_sram_device::restore_banks()
-{
- for (int i = 0; i < 4; i++)
- {
- setup_bank(i);
- }
-}
-
-
-void msx_cart_ascii8_sram_device::device_reset()
-{
- for (auto & elem : m_selected_bank)
- {
- elem = 0;
- }
-}
-
-
-void msx_cart_ascii8_sram_device::initialize_cartridge()
-{
- uint32_t size = get_rom_size();
-
- if ( size > 128 * 0x2000 )
- {
- fatalerror("ascii8_sram: ROM is too big\n");
- }
-
- uint16_t banks = size / 0x2000;
-
- if (size != banks * 0x2000 || (~(banks - 1) % banks))
- {
- fatalerror("ascii8_sram: Invalid ROM size\n");
- }
-
- if (get_sram_size() != 0x2000)
- {
- fatalerror("ascii8_sram: Unsupported SRAM size\n");
- }
-
- m_bank_mask = banks - 1;
- m_sram_select_mask = banks;
-
- restore_banks();
-}
-
-
-uint8_t msx_cart_ascii8_sram_device::read_cart(offs_t offset)
-{
- if ( offset >= 0x4000 && offset < 0xC000 )
- {
- uint8_t *bank_base = m_bank_base[(offset - 0x4000) >> 13];
-
- if (bank_base != nullptr)
- {
- return bank_base[offset & 0x1fff];
- }
- }
- return 0xff;
-}
-
-
-void msx_cart_ascii8_sram_device::write_cart(offs_t offset, uint8_t data)
-{
- if (offset >= 0x6000 && offset < 0x8000)
- {
- uint8_t bank = (offset / 0x800) & 0x03;
-
- m_selected_bank[bank] = data;
- setup_bank(bank);
- }
- else if (offset >= 0x8000 && offset < 0xc000)
- {
- uint8_t bank = (offset & 0x2000) ? 3 : 2;
-
- if ((m_selected_bank[bank] & m_sram_select_mask) && !(m_selected_bank[bank] & ~(m_sram_select_mask | m_bank_mask)))
- {
- // Write to SRAM
- m_bank_base[bank][offset & 0x1fff] = data;
- }
- }
-}
-
-
-
-msx_cart_ascii16_sram_device::msx_cart_ascii16_sram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, MSX_CART_ASCII16_SRAM, tag, owner, clock)
- , msx_cart_interface(mconfig, *this)
- , m_bank_mask(0)
- , m_sram_select_mask(0)
-{
- for (int i = 0; i < 2; i++)
- {
- m_selected_bank[i] = 0;
- m_bank_base[i] = nullptr;
- }
-}
-
-
-void msx_cart_ascii16_sram_device::device_start()
-{
- save_item(NAME(m_selected_bank));
-}
-
-
-void msx_cart_ascii16_sram_device::device_post_load()
-{
- restore_banks();
-}
-
-
-void msx_cart_ascii16_sram_device::setup_bank(uint8_t bank)
-{
- if (m_selected_bank[bank] & ~(m_sram_select_mask | m_bank_mask))
- {
- // Nothing is mapped
- m_bank_base[bank] = nullptr;
- }
- else if (m_selected_bank[bank] & m_sram_select_mask)
- {
- // SRAM is selected
- m_bank_base[bank] = get_sram_base();
- }
- else
- {
- m_bank_base[bank] = get_rom_base() + (m_selected_bank[bank] & m_bank_mask) * 0x4000;
- }
-}
-
-
-void msx_cart_ascii16_sram_device::restore_banks()
-{
- for (int i = 0; i < 2; i++)
- {
- setup_bank(i);
- }
-}
-
-
-void msx_cart_ascii16_sram_device::device_reset()
-{
- for (auto & elem : m_selected_bank)
- {
- elem = 0;
- }
-}
-
-
-void msx_cart_ascii16_sram_device::initialize_cartridge()
-{
- uint32_t size = get_rom_size();
-
- if ( size > 128 * 0x4000 )
- {
- fatalerror("ascii16_sram: ROM is too big\n");
- }
-
- uint16_t banks = size / 0x4000;
-
- if (size != banks * 0x4000 || (~(banks - 1) % banks))
- {
- fatalerror("ascii16_sram: Invalid ROM size\n");
- }
-
- if (get_sram_size() != 0x800)
- {
- fatalerror("ascii16_sram: Unsupported SRAM size\n");
- }
-
- m_bank_mask = banks - 1;
- m_sram_select_mask = banks;
-
- restore_banks();
-}
-
-
-uint8_t msx_cart_ascii16_sram_device::read_cart(offs_t offset)
-{
- if ( offset >= 0x4000 && offset < 0xC000 )
- {
- uint8_t bank = offset >> 15;
-
- if (m_bank_base[bank] != nullptr)
- {
- if (m_selected_bank[bank] & m_sram_select_mask)
- {
- return m_bank_base[bank][offset & 0x7ff];
- }
- else
- {
- return m_bank_base[bank][offset & 0x3fff];
- }
- }
- }
- return 0xff;
-}
-
-
-void msx_cart_ascii16_sram_device::write_cart(offs_t offset, uint8_t data)
-{
- if (offset >= 0x6000 && offset < 0x6800)
- {
- m_selected_bank[0] = data;
- setup_bank(0);
- }
-
- if (offset >= 0x7000 && offset < 0x7800)
- {
- m_selected_bank[1] = data;
- setup_bank(1);
- }
-
- if (offset >= 0x8000 && offset < 0xc000)
- {
- if ((m_selected_bank[1] & m_sram_select_mask) && !(m_selected_bank[1] & ~(m_sram_select_mask | m_bank_mask)))
- {
- // Write to SRAM
- m_bank_base[1][offset & 0x7ff] = data;
- }
- }
-}
-
-
-
-msx_cart_msxwrite_device::msx_cart_msxwrite_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, MSX_CART_MSXWRITE, tag, owner, clock)
- , msx_cart_interface(mconfig, *this)
- , m_bank_mask(0)
-{
- for (int i = 0; i < 2; i++)
- {
- m_selected_bank[i] = 0;
- m_bank_base[i] = nullptr;
- }
-}
-
-
-void msx_cart_msxwrite_device::device_start()
-{
- save_item(NAME(m_selected_bank));
-}
-
-
-void msx_cart_msxwrite_device::device_post_load()
-{
- restore_banks();
-}
-
-
-void msx_cart_msxwrite_device::restore_banks()
-{
- for (int i = 0; i < 2; i++)
- {
- m_bank_base[i] = get_rom_base() + (m_selected_bank[i] & m_bank_mask) * 0x4000;
- }
-}
-
-
-void msx_cart_msxwrite_device::device_reset()
-{
- for (auto & elem : m_selected_bank)
- {
- elem = 0;
- }
-}
-
-
-void msx_cart_msxwrite_device::initialize_cartridge()
-{
- uint32_t size = get_rom_size();
-
- if ( size > 256 * 0x4000 )
- {
- fatalerror("msxwrite: ROM is too big\n");
- }
-
- uint16_t banks = size / 0x4000;
-
- if (size != banks * 0x4000 || (~(banks - 1) % banks))
- {
- fatalerror("msxwrite: Invalid ROM size\n");
- }
-
- m_bank_mask = banks - 1;
-
- restore_banks();
-}
-
-
-uint8_t msx_cart_msxwrite_device::read_cart(offs_t offset)
-{
- if ( offset >= 0x4000 && offset < 0xC000 )
- {
- return m_bank_base[offset >> 15][offset & 0x3fff];
- }
- return 0xff;
-}
-
-
-void msx_cart_msxwrite_device::write_cart(offs_t offset, uint8_t data)
-{
- // The rom writes to 6fff and 7fff for banking, unknown whether
- // other locations also trigger banking.
- switch (offset)
- {
- case 0x6fff:
- m_selected_bank[0] = data;
- m_bank_base[0] = get_rom_base() + (m_selected_bank[0] & m_bank_mask) * 0x4000;
- break;
-
- case 0x7fff:
- m_selected_bank[1] = data;
- m_bank_base[1] = get_rom_base() + (m_selected_bank[1] & m_bank_mask) * 0x4000;
- break;
- }
-}
diff --git a/src/devices/bus/msx_cart/ascii.h b/src/devices/bus/msx_cart/ascii.h
deleted file mode 100644
index 0c5898fed40..00000000000
--- a/src/devices/bus/msx_cart/ascii.h
+++ /dev/null
@@ -1,148 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Wilbert Pol
-#ifndef MAME_BUS_MSX_CART_ASCII_H
-#define MAME_BUS_MSX_CART_ASCII_H
-
-#pragma once
-
-#include "bus/msx_cart/cartridge.h"
-
-
-DECLARE_DEVICE_TYPE(MSX_CART_ASCII8, msx_cart_ascii8_device)
-DECLARE_DEVICE_TYPE(MSX_CART_ASCII16, msx_cart_ascii16_device)
-DECLARE_DEVICE_TYPE(MSX_CART_ASCII8_SRAM, msx_cart_ascii8_sram_device)
-DECLARE_DEVICE_TYPE(MSX_CART_ASCII16_SRAM, msx_cart_ascii16_sram_device)
-DECLARE_DEVICE_TYPE(MSX_CART_MSXWRITE, msx_cart_msxwrite_device)
-
-
-class msx_cart_ascii8_device : public device_t, public msx_cart_interface
-{
-public:
- msx_cart_ascii8_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void initialize_cartridge() override;
-
- virtual uint8_t read_cart(offs_t offset) override;
- virtual void write_cart(offs_t offset, uint8_t data) override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_post_load() override;
-
- void restore_banks();
-
-private:
- uint8_t m_bank_mask;
- uint8_t m_selected_bank[4];
- uint8_t *m_bank_base[4];
-};
-
-
-class msx_cart_ascii16_device : public device_t, public msx_cart_interface
-{
-public:
- msx_cart_ascii16_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void initialize_cartridge() override;
-
- virtual uint8_t read_cart(offs_t offset) override;
- virtual void write_cart(offs_t offset, uint8_t data) override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_post_load() override;
-
- void restore_banks();
-
-private:
- uint8_t m_bank_mask;
- uint8_t m_selected_bank[2];
- uint8_t *m_bank_base[2];
-};
-
-
-class msx_cart_ascii8_sram_device : public device_t, public msx_cart_interface
-{
-public:
- msx_cart_ascii8_sram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void initialize_cartridge() override;
-
- virtual uint8_t read_cart(offs_t offset) override;
- virtual void write_cart(offs_t offset, uint8_t data) override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_post_load() override;
-
- void restore_banks();
-
-private:
- uint8_t m_bank_mask;
- uint8_t m_selected_bank[4];
- uint8_t *m_bank_base[4];
- uint8_t m_sram_select_mask;
-
- void setup_bank(uint8_t bank);
-};
-
-
-class msx_cart_ascii16_sram_device : public device_t, public msx_cart_interface
-{
-public:
- msx_cart_ascii16_sram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void initialize_cartridge() override;
-
- virtual uint8_t read_cart(offs_t offset) override;
- virtual void write_cart(offs_t offset, uint8_t data) override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_post_load() override;
-
- void restore_banks();
-
-private:
- uint8_t m_bank_mask;
- uint8_t m_selected_bank[2];
- uint8_t *m_bank_base[2];
- uint8_t m_sram_select_mask;
-
- void setup_bank(uint8_t bank);
-};
-
-
-class msx_cart_msxwrite_device : public device_t, public msx_cart_interface
-{
-public:
- msx_cart_msxwrite_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void initialize_cartridge() override;
-
- virtual uint8_t read_cart(offs_t offset) override;
- virtual void write_cart(offs_t offset, uint8_t data) override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_post_load() override;
-
- void restore_banks();
-
-private:
- uint8_t m_bank_mask;
- uint8_t m_selected_bank[2];
- uint8_t *m_bank_base[2];
-};
-
-#endif // MAME_BUS_MSX_CART_ASCII_H
diff --git a/src/devices/bus/msx_cart/bm_012.h b/src/devices/bus/msx_cart/bm_012.h
deleted file mode 100644
index e54213e8e75..00000000000
--- a/src/devices/bus/msx_cart/bm_012.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Wilbert Pol
-#ifndef MAME_BUS_MSX_CART_BM_012_H
-#define MAME_BUS_MSX_CART_BM_012_H
-
-#pragma once
-
-#include "bus/msx_cart/cartridge.h"
-#include "cpu/z80/tmpz84c015.h"
-#include "bus/midi/midi.h"
-
-
-DECLARE_DEVICE_TYPE(MSX_CART_BM_012, msx_cart_bm_012_device)
-
-
-class msx_cart_bm_012_device : public device_t, public msx_cart_interface
-{
-public:
- msx_cart_bm_012_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- virtual void device_start() override;
-
- // device-level overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
-
-private:
- DECLARE_WRITE_LINE_MEMBER(midi_in);
-
- void bm_012_memory_map(address_map &map);
-
- required_device<tmpz84c015_device> m_tmpz84c015af;
- required_device<z80pio_device> m_bm012_pio;
- required_device<midi_port_device> m_mdthru;
-};
-
-
-#endif // MAME_BUS_MSX_CART_BM_012_H
diff --git a/src/devices/bus/msx_cart/cartridge.cpp b/src/devices/bus/msx_cart/cartridge.cpp
deleted file mode 100644
index 4bda712eabe..00000000000
--- a/src/devices/bus/msx_cart/cartridge.cpp
+++ /dev/null
@@ -1,132 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Wilbert Pol
-
-#include "emu.h"
-#include "cartridge.h"
-#include "arc.h"
-#include "ascii.h"
-#include "bm_012.h"
-#include "crossblaim.h"
-#include "disk.h"
-#include "dooly.h"
-#include "easi_speech.h"
-#include "fmpac.h"
-#include "fs_sr022.h"
-#include "halnote.h"
-#include "hfox.h"
-#include "holy_quran.h"
-#include "ink.h"
-#include "konami.h"
-#include "korean.h"
-#include "majutsushi.h"
-#include "moonsound.h"
-#include "msx_audio.h"
-#include "msxdos2.h"
-#include "nomapper.h"
-#include "rtype.h"
-#include "superloderunner.h"
-#include "super_swangi.h"
-#include "yamaha.h"
-
-#include "bus/msx_slot/cartridge.h"
-
-
-void msx_cart(device_slot_interface &device)
-{
- device.option_add_internal("nomapper", MSX_CART_NOMAPPER);
- device.option_add_internal("msxdos2", MSX_CART_MSXDOS2);
- device.option_add_internal("konami_scc", MSX_CART_KONAMI_SCC);
- device.option_add_internal("konami", MSX_CART_KONAMI);
- device.option_add_internal("ascii8", MSX_CART_ASCII8);
- device.option_add_internal("ascii16", MSX_CART_ASCII16);
- device.option_add_internal("gamemaster2", MSX_CART_GAMEMASTER2);
- device.option_add_internal("ascii8_sram", MSX_CART_ASCII8_SRAM);
- device.option_add_internal("ascii16_sram", MSX_CART_ASCII16_SRAM);
- device.option_add_internal("rtype", MSX_CART_RTYPE);
- device.option_add_internal("majutsushi", MSX_CART_MAJUTSUSHI);
- device.option_add_internal("fmpac", MSX_CART_FMPAC);
- device.option_add_internal("fs_sr022", MSX_CART_FS_SR022);
- device.option_add_internal("superloderunner", MSX_CART_SUPERLODERUNNER);
- device.option_add_internal("synthesizer", MSX_CART_SYNTHESIZER);
- device.option_add_internal("easispeech", MSX_CART_EASISPEECH);
- device.option_add_internal("cross_blaim", MSX_CART_CROSSBLAIM);
- device.option_add_internal("korean_80in1", MSX_CART_KOREAN_80IN1);
- device.option_add_internal("korean_90in1", MSX_CART_KOREAN_90IN1);
- device.option_add_internal("korean_126in1", MSX_CART_KOREAN_126IN1);
- device.option_add_internal("msxwrite", MSX_CART_MSXWRITE);
- device.option_add_internal("sound_snatcher", MSX_CART_SOUND_SNATCHER);
- device.option_add_internal("sound_sdsnatch", MSX_CART_SOUND_SDSNATCHER);
- device.option_add_internal("msxaud_hxmu900", MSX_CART_MSX_AUDIO_HXMU900);
- device.option_add_internal("msxaud_fsca1", MSX_CART_MSX_AUDIO_FSCA1);
- device.option_add_internal("msxaud_nms1205", MSX_CART_MSX_AUDIO_NMS1205);
- device.option_add_internal("super_swangi", MSX_CART_SUPER_SWANGI);
- device.option_add_internal("hfox", MSX_CART_HFOX);
- device.option_add_internal("ink", MSX_CART_INK);
- device.option_add_internal("keyboard_master", MSX_CART_KEYBOARD_MASTER);
- device.option_add_internal("holy_quran", MSX_CART_HOLY_QURAN);
- device.option_add_internal("dooly", MSX_CART_DOOLY);
- device.option_add_internal("halnote", MSX_CART_HALNOTE);
- device.option_add_internal("arc", MSX_CART_ARC);
- device.option_add_internal("disk_vy0010", MSX_CART_VY0010);
- device.option_add_internal("disk_fsfd1", MSX_CART_FSFD1);
- device.option_add_internal("disk_fsfd1a", MSX_CART_FSFD1A);
- device.option_add_internal("disk_fscf351", MSX_CART_FSCF351);
- device.option_add("bm_012", MSX_CART_BM_012);
- device.option_add("moonsound", MSX_CART_MOONSOUND);
-}
-
-
-msx_cart_interface::msx_cart_interface(const machine_config &mconfig, device_t &device)
- : device_interface(device, "msxcart")
- , m_exp(nullptr)
-{
-}
-
-void msx_cart_interface::rom_alloc(uint32_t size)
-{
- m_rom.resize(size);
- std::fill_n(m_rom.begin(), size, 0xff);
-}
-
-void msx_cart_interface::rom_vlm5030_alloc(uint32_t size)
-{
- m_rom_vlm5030.resize(size);
- std::fill_n(m_rom_vlm5030.begin(), size, 0xff);
-}
-
-void msx_cart_interface::ram_alloc(uint32_t size)
-{
- m_ram.resize(size);
- std::fill_n(m_ram.begin(), size, 0x00);
-}
-
-void msx_cart_interface::sram_alloc(uint32_t size)
-{
- m_sram.resize(size);
- std::fill_n(m_sram.begin(), size, 0x00);
-}
-
-WRITE_LINE_MEMBER(msx_cart_interface::irq_out)
-{
- m_exp->irq_out(state);
-}
-
-address_space &msx_cart_interface::memory_space() const
-{
- return m_exp->memory_space();
-}
-
-address_space &msx_cart_interface::io_space() const
-{
- return m_exp->io_space();
-}
-
-
-// Several yamaha machines had 60 pin expansion slots. The pinouts of these slots was
-// exactly the same as the regular 50 pin cartridge slots. The lowest 10 pins are simply
-// not connected.
-void msx_yamaha_60pin(device_slot_interface &device)
-{
- device.option_add("sfg01", MSX_CART_SFG01);
- device.option_add("sfg05", MSX_CART_SFG05);
-}
diff --git a/src/devices/bus/msx_cart/cartridge.h b/src/devices/bus/msx_cart/cartridge.h
deleted file mode 100644
index 73759baf544..00000000000
--- a/src/devices/bus/msx_cart/cartridge.h
+++ /dev/null
@@ -1,63 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Wilbert Pol
-#ifndef MAME_BUS_MSX_CART_CARTRIDGE_H
-#define MAME_BUS_MSX_CART_CARTRIDGE_H
-
-#pragma once
-
-
-void msx_cart(device_slot_interface &device);
-void msx_yamaha_60pin(device_slot_interface &device); // 60 pin expansion slots as found in yamaha machines
-
-
-class msx_slot_cartridge_device;
-
-class msx_cart_interface : public device_interface
-{
- friend class msx_slot_cartridge_device;
-
-public:
- // This is called after loading cartridge contents and allows the cartridge
- // implementation to perform some additional initialization based on the
- // cartridge contents.
- virtual void initialize_cartridge() { }
- virtual void interface_pre_start() override { assert(m_exp != nullptr); }
-
- // reading and writing
- virtual uint8_t read_cart(offs_t offset) { return 0xff; }
- virtual void write_cart(offs_t offset, uint8_t data) { }
-
- DECLARE_WRITE_LINE_MEMBER(irq_out);
- address_space &memory_space() const;
- address_space &io_space() const;
-
- // ROM/RAM/SRAM management
- // Mainly used by the cartridge slot when loading images
- void rom_alloc(uint32_t size);
- void ram_alloc(uint32_t size);
- void rom_vlm5030_alloc(uint32_t size);
- void sram_alloc(uint32_t size);
-
- uint8_t* get_rom_base() { return &m_rom[0]; }
- uint8_t* get_rom_vlm5030_base() { return &m_rom_vlm5030[0]; }
- uint8_t* get_ram_base() { return &m_ram[0]; }
- uint8_t* get_sram_base() { return &m_sram[0]; }
- uint32_t get_rom_size() { return m_rom.size(); }
- uint32_t get_rom_vlm5030_size() { return m_rom_vlm5030.size(); }
- uint32_t get_ram_size() { return m_ram.size(); }
- uint32_t get_sram_size() { return m_sram.size(); }
-
-protected:
- msx_cart_interface(const machine_config &mconfig, device_t &device);
-
- std::vector<uint8_t> m_rom;
- std::vector<uint8_t> m_ram;
- std::vector<uint8_t> m_rom_vlm5030;
- std::vector<uint8_t> m_sram;
-
-private:
- msx_slot_cartridge_device *m_exp;
-};
-
-
-#endif // MAME_BUS_MSX_CART_CARTRIDGE_H
diff --git a/src/devices/bus/msx_cart/crossblaim.cpp b/src/devices/bus/msx_cart/crossblaim.cpp
deleted file mode 100644
index 6494e492f5b..00000000000
--- a/src/devices/bus/msx_cart/crossblaim.cpp
+++ /dev/null
@@ -1,86 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Wilbert Pol
-#include "emu.h"
-#include "crossblaim.h"
-
-DEFINE_DEVICE_TYPE(MSX_CART_CROSSBLAIM, msx_cart_crossblaim_device, "msx_cart_crossblaim", "MSX Cartridge Cross Blaim")
-
-
-msx_cart_crossblaim_device::msx_cart_crossblaim_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, MSX_CART_CROSSBLAIM, tag, owner, clock)
- , msx_cart_interface(mconfig, *this)
- , m_selected_bank(1)
-{
- for (auto & elem : m_bank_base)
- {
- elem = nullptr;
- }
-}
-
-
-void msx_cart_crossblaim_device::device_start()
-{
- save_item(NAME(m_selected_bank));
-}
-
-
-void msx_cart_crossblaim_device::device_post_load()
-{
- restore_banks();
-}
-
-
-void msx_cart_crossblaim_device::setup_bank()
-{
- m_bank_base[0] = ( m_selected_bank & 2 ) ? nullptr : get_rom_base() + ( m_selected_bank & 0x03 ) * 0x4000;
- m_bank_base[2] = get_rom_base() + ( m_selected_bank & 0x03 ) * 0x4000;
- m_bank_base[3] = ( m_selected_bank & 2 ) ? nullptr : get_rom_base() + ( m_selected_bank & 0x03 ) * 0x4000;
-}
-
-
-void msx_cart_crossblaim_device::restore_banks()
-{
- m_bank_base[1] = get_rom_base();
- setup_bank();
-}
-
-
-void msx_cart_crossblaim_device::device_reset()
-{
- m_selected_bank = 1;
-}
-
-
-void msx_cart_crossblaim_device::initialize_cartridge()
-{
- if (get_rom_size() != 0x10000)
- {
- fatalerror("crossblaim: Invalid ROM size\n");
- }
-
- restore_banks();
-}
-
-
-uint8_t msx_cart_crossblaim_device::read_cart(offs_t offset)
-{
- uint8_t *bank_base = m_bank_base[offset >> 14];
-
- if (bank_base != nullptr)
- {
- return bank_base[offset & 0x3fff];
- }
-
- return 0xff;
-}
-
-
-void msx_cart_crossblaim_device::write_cart(offs_t offset, uint8_t data)
-{
- m_selected_bank = data & 3;
- if (m_selected_bank == 0)
- {
- m_selected_bank = 1;
- }
- setup_bank();
-}
diff --git a/src/devices/bus/msx_cart/crossblaim.h b/src/devices/bus/msx_cart/crossblaim.h
deleted file mode 100644
index 04a44c1d905..00000000000
--- a/src/devices/bus/msx_cart/crossblaim.h
+++ /dev/null
@@ -1,40 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Wilbert Pol
-#ifndef MAME_BUS_MSX_CART_CROSSBLAIM_H
-#define MAME_BUS_MSX_CART_CROSSBLAIM_H
-
-#pragma once
-
-#include "bus/msx_cart/cartridge.h"
-
-
-DECLARE_DEVICE_TYPE(MSX_CART_CROSSBLAIM, msx_cart_crossblaim_device)
-
-
-class msx_cart_crossblaim_device : public device_t, public msx_cart_interface
-{
-public:
- msx_cart_crossblaim_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void initialize_cartridge() override;
-
- virtual uint8_t read_cart(offs_t offset) override;
- virtual void write_cart(offs_t offset, uint8_t data) override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_post_load() override;
-
- void restore_banks();
-
-private:
- uint8_t m_selected_bank;
- uint8_t *m_bank_base[4];
-
- void setup_bank();
-};
-
-
-#endif // MAME_BUS_MSX_CART_CROSSBLAIM_H
diff --git a/src/devices/bus/msx_cart/disk.cpp b/src/devices/bus/msx_cart/disk.cpp
deleted file mode 100644
index b07d9dd6dc0..00000000000
--- a/src/devices/bus/msx_cart/disk.cpp
+++ /dev/null
@@ -1,613 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Wilbert Pol
-/*****************************************************************************
- *
- * MSX Floopy drive interface add-on cartridges
- *
- * Currently supported:
- * - National FS-CF351 + FS-FD351 - MB8877A - DSDD 3.5" Floppy drive + interface
- * - Panasonic FS-FD1 - WD2793? - DSDD 3.5" Floppy drive + interface
- * - Panasonic FS-FD1A - TC8566F - DSDD 3.5" Floppy drive with builtin interface
- * - Rom label reads: "FDC BIOS V1.0 / COPYRIGHT MEI / 1987 DASFD1AA1"
- * - Philips VY-0010 (Interface cartridge + 1 3.5" SS floppy drive)
- *
- * Not supported yet:
- * - Canon VF-100 - DSDD 3.5" Floppy drive + interface + 1 floppy disk containing MSX-DOS
- * - Talent DPF-550/5 - WD1772 - DSDD 5.25" Floppy drive (360KB) plus interface (manufactured by Daewoo)
- * - Rom label markings: MSX DISK / DPF 555D
- *
- * Drive only:
- * - Philps VY-0011 - 3.5" SSDD Floppy drive
- * - Talent DPF-560 - DSDD 5.25" Floppy drive
- *
- * To be investigated:
- * - AVT DPF-500 - WD1772? - DD 5.25" Floppy drive + interface + 1 floppy disk containing MSX-DOS
- * - Daewoo CPF-350C - DD 3.5" Floppy drive
- * - Daewoo CPF-360C - DD 3.5" Floppy drive
- * - Daewoo MPF-550 - DSDD 5.25" Floppy drive + interface
- * = Daewoo MPF-560 - DSDD 5.25" Floppy drive
- * - DMX Interface para drive - Interface + 1 floppy disk containg MSX-DOS 1.0
- * - Fenner FD-300 - DSDD 3.5" Floppy drive
- * - Fenner FD-400 - Floppy interface for FD-300
- * - Hitachi MPF-310CH - DSDD Floppy drive
- * - hitachi MPC-310CH - Interface for MPF-310CH
- * - JVC HC-F303 - Floppy drive
- * - Mitsubishi ML-30FD - DSDD 3.5" Floppy drive
- * - Mitsubishi ML-30DC - Floppy interface
- * - Philips NMS-1200 - Floppy interface
- * - Philips NMS-9111 - 3.5" Floppy drive
- * - Philips NMS-9113 - 3.5" Floppy drive
- * - Sakir AFD-01 - SSDD 3.5" Floppy drive
- * - Sanyo MFD-001 - 360KB 5.25" Floppy drive + interface?
- * - Sanyo MFD-002 - 360KB 5.25" Floppy drive (2nd drive for MFD-001?)
- * - Sanyo MFD-25FD - DSDD 3.5" Floppy drive
- * - Sanyo MFD-35 - SSDD 3.5" Floppy drive + interface
- * - Sharp Epcom HB-3600 - WD2793 - Floppy interface Intended to be used with HB-6000 (5.25" SS? drive), Brazil
- * - Sold as part of HB-3600 + HB-6000 bundle according to wikipedia
- * - Sharp Epcom HB-6000 - 360KB 5.25" drive
- * - Sony HBD-100 - SSDD 3.5" Floppy drivbe
- * - Sony HBD-20W - DSDD 3.5" Floppy drive
- * - Sony HBD-30X/30W - DSDD 3.5" drive
- * - Sony HBD-50 - SSDD 3.5" drive (drive only?)
- * - Sony HBD-F1 (interface only?) - WD2793 - 3.5" DSDD drive??
- * - Sony HBX-30 (interface only, meant for 30W) - WD2793
- * - Sony WS2793-02 - WD2793? - Interface for HBD-50
- * - Spectravideo SVI-213 - MB8877A - Floppy interface for SVI-707
- * - Spectravideo SVI-707 - MB8877A - 5.25" SSDD? drive (320KB) - There seem to be 2 ROMs on the PCB, apparently one is for MSX and one is for CP/M operation?
- * - See https://plus.google.com/photos/115644813183575095400/albums/5223347091895442113?banner=pwa
- * - Spectravideo SVI-717 - Interface for 2 drives?
- * - Spectravideo SVI-787 - SSDD 3.5" Floppy drive
- * - Spectravideo SVI-801 - Interface
- * - Toshiba HX-F100 - Floppy drive
- * - Toshiba HX-F101 - SSDD 3.5" Floppy drive + interface
- * - Yamaha FD-01 - SSDD 3.5" Floppy drive
- * - Yamaha FD-03 - DSDD 3.5" Floppy drive
- * - Yamaha FD-05 - DSDD 3.5" Floppy drive
- * - Other models:
- * - ACVS 3.5" Floppy drive interface
- * - Tradeco floppy interface
- * - Angeisa 3.5" Floppy drive
- * - Angeisa 5.25" 360KB Floppy drive
- * - Angeisa 5.25" 720KB Floppy drive
- * - Angeisa floppy drive interface
- * - Datagame floppy drive interface
- * - Digital Design DSDD 3.5" Floppy drive
- * - Digital Design 5.25" 360KB Floppy drive
- * - Digital Design 5.25" 720KB Floppy drive
- * - Digital Design floppy drive interface
- * - DMX 3.5" Floppy drive
- * - DMX floppy drive interface
- * - Liftron 3.5" Floppy drive
- * - Liftron floppy drive interface
- * - Microsol DRX-180 5.25" Floppy drive FS
- * - Microsol DRX-360 5.25" Floppy drive FD
- * - Microsol DRX-720 5.25" Floppy drive 80 track (720KB)
- * - Microsol CDX-1 floppy interface
- * - Microsol CDX-2 floppy interface
- * - Racidata 3.5" Floppy drive
- * - Racidata 5.25" Floppy drive
- * - Racidata floppy interface
- * - Sileman Triton-s 3.5" FS Floppy drive
- * - Sileman Triton-d 3.5" FD Floppy drive
- * - Talent TPF-723 5.25" Floppy drive
- * - Talent TPF-725 5.25" Flpppy drive
- * - Technohead Leopard 3.5" Floppy drive
- * - Technohead Leopard 5.25" Floppy drive
- * - Technohead floppy interface
- * - More??
- *
- * Several model references found in Vitropedia (ISBN 9781409212774)
- *
- ****************************************************************************/
-
-#include "emu.h"
-#include "disk.h"
-#include "formats/msx_dsk.h"
-#include "softlist_dev.h"
-
-DEFINE_DEVICE_TYPE(MSX_CART_VY0010, msx_cart_vy0010_device, "msx_cart_vy0010", "MSX Cartridge - VY0010")
-DEFINE_DEVICE_TYPE(MSX_CART_FSFD1, msx_cart_fsfd1_device, "msx_cart_fsfd1", "MSX Cartridge - FS-FD1")
-DEFINE_DEVICE_TYPE(MSX_CART_FSFD1A, msx_cart_fsfd1a_device, "msx_cart_fsfd1a", "MSX Cartridge - FS-FD1A")
-DEFINE_DEVICE_TYPE(MSX_CART_FSCF351, msx_cart_fscf351_device, "msx_cart_fscf351", "MSX Cartridge - FS-CF351")
-
-
-void msx_cart_disk_device::floppy_formats(format_registration &fr)
-{
- fr.add_mfm_containers();
- fr.add(FLOPPY_MSX_FORMAT);
-}
-
-
-static void msx_floppies(device_slot_interface &device)
-{
- device.option_add("35dd", FLOPPY_35_DD);
- device.option_add("35ssdd", FLOPPY_35_SSDD);
-}
-
-
-msx_cart_disk_device::msx_cart_disk_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, type, tag, owner, clock)
- , msx_cart_interface(mconfig, *this)
- , m_floppy0(*this, "fdc:0")
- , m_floppy1(*this, "fdc:1")
- , m_floppy(nullptr)
-{
-}
-
-
-msx_cart_disk_wd_device::msx_cart_disk_wd_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
- : msx_cart_disk_device(mconfig, type, tag, owner, clock)
- , m_fdc(*this, "fdc")
-{
-}
-
-
-msx_cart_disk_type1_device::msx_cart_disk_type1_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
- : msx_cart_disk_wd_device(mconfig, type, tag, owner, clock)
- , m_led(*this, "led0")
- , m_side_control(0)
- , m_control(0)
-{
-}
-
-
-msx_cart_disk_type2_device::msx_cart_disk_type2_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
- : msx_cart_disk_wd_device(mconfig, type, tag, owner, clock)
- , m_led(*this, "led0")
- , m_control(0)
-{
-}
-
-
-msx_cart_vy0010_device::msx_cart_vy0010_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : msx_cart_disk_type1_device(mconfig, MSX_CART_VY0010, tag, owner, clock)
-{
-}
-
-
-msx_cart_fsfd1_device::msx_cart_fsfd1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : msx_cart_disk_type1_device(mconfig, MSX_CART_FSFD1, tag, owner, clock)
-{
-}
-
-
-msx_cart_fscf351_device::msx_cart_fscf351_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : msx_cart_disk_type2_device(mconfig, MSX_CART_FSCF351, tag, owner, clock)
-{
-}
-
-
-msx_cart_disk_tc8566_device::msx_cart_disk_tc8566_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
- : msx_cart_disk_device(mconfig, type, tag, owner, clock)
- , m_fdc(*this, "fdc")
-{
-}
-
-
-msx_cart_fsfd1a_device::msx_cart_fsfd1a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : msx_cart_disk_tc8566_device(mconfig, MSX_CART_FSFD1A, tag, owner, clock)
-{
-}
-
-
-void msx_cart_disk_device::initialize_cartridge()
-{
- if ( get_rom_size() != 0x4000 )
- {
- fatalerror("msx_cart_disk_device: Invalid ROM size\n");
- }
-}
-
-
-void msx_cart_vy0010_device::device_add_mconfig(machine_config &config)
-{
- // From VY-0010 schematic:
- // HLT pulled high
- // SSO/-ENMF + -DDEN + ENP + -5/8 - pulled low
- // READY inverted in VY-0010 cartridge and pulled low on VY-0010/VY-0011 floppy drive
- WD2793(config, m_fdc, 4_MHz_XTAL / 4);
- m_fdc->set_force_ready(true);
-
- // Single sided 3.5" floppy drive
- FLOPPY_CONNECTOR(config, "fdc:0", msx_floppies, "35ssdd", msx_cart_disk_device::floppy_formats);
-
- // Attach software lists
- // We do not know in what kind of machine the user has inserted the floppy interface
- // so we list all msx floppy software lists.
- //
- SOFTWARE_LIST(config, "flop_list").set_original("msx2_flop");
- SOFTWARE_LIST(config, "msx1_flop_list").set_compatible("msx1_flop");
-}
-
-void msx_cart_fsfd1_device::device_add_mconfig(machine_config &config)
-{
- WD2793(config, m_fdc, 4_MHz_XTAL / 4);
-
- // Double sided 3.5" floppy drive
- FLOPPY_CONNECTOR(config, "fdc:0", msx_floppies, "35dd", msx_cart_disk_device::floppy_formats);
-
- // Attach software lists
- // We do not know in what kind of machine the user has inserted the floppy interface
- // so we list all msx floppy software lists.
- //
- SOFTWARE_LIST(config, "flop_list").set_original("msx2_flop");
- SOFTWARE_LIST(config, "msx1_flop_list").set_compatible("msx1_flop");
-}
-
-
-void msx_cart_fsfd1a_device::device_add_mconfig(machine_config &config)
-{
- TC8566AF(config, m_fdc, 16'000'000);
-
- // Double sided 3.5" floppy drive
- FLOPPY_CONNECTOR(config, "fdc:0", msx_floppies, "35dd", msx_cart_disk_device::floppy_formats);
-
- // Attach software lists
- // We do not know in what kind of machine the user has inserted the floppy interface
- // so we list all msx floppy software lists.
- //
- SOFTWARE_LIST(config, "flop_list").set_original("msx2_flop");
- SOFTWARE_LIST(config, "msx1_flop_list").set_compatible("msx1_flop");
-}
-
-
-void msx_cart_fscf351_device::device_add_mconfig(machine_config &config)
-{
- MB8877(config, m_fdc, 4_MHz_XTAL / 4);
- m_fdc->set_force_ready(true);
-
- // Double sided 3.5" floppy drive
- FLOPPY_CONNECTOR(config, "fdc:0", msx_floppies, "35dd", msx_cart_disk_device::floppy_formats);
-
- // Attach software lists
- // We do not know in what kind of machine the user has inserted the floppy interface
- // so we list all msx floppy software lists.
- //
- SOFTWARE_LIST(config, "flop_list").set_original("msx2_flop");
- SOFTWARE_LIST(config, "msx1_flop_list").set_compatible("msx1_flop");
-}
-
-
-void msx_cart_disk_type1_device::device_start()
-{
- m_led.resolve();
-
- save_item(NAME(m_side_control));
- save_item(NAME(m_control));
-}
-
-
-void msx_cart_disk_type1_device::device_post_load()
-{
- uint8_t data = m_control;
-
- // To make sure the FDD busy led status gets set correctly
- m_control ^= 0x40;
-
- set_control(data);
-}
-
-
-void msx_cart_disk_type1_device::set_control(uint8_t data)
-{
- uint8_t old_m_control = m_control;
-
- m_control = data;
-
- switch (m_control & 0x03)
- {
- case 0:
- case 2:
- m_floppy = m_floppy0 ? m_floppy0->get_device() : nullptr;
- break;
-
- case 1:
- m_floppy = m_floppy1 ? m_floppy1->get_device() : nullptr;
- break;
-
- default:
- m_floppy = nullptr;
- break;
- }
-
- if (m_floppy)
- {
- m_floppy->mon_w((m_control & 0x80) ? 0 : 1);
- m_floppy->ss_w(m_side_control & 0x01);
- }
-
- m_fdc->set_floppy(m_floppy);
-
- if ((old_m_control ^ m_control) & 0x40)
- {
- m_led = BIT(~m_control, 6);
- }
-}
-
-
-void msx_cart_disk_type1_device::set_side_control(uint8_t data)
-{
- m_side_control = data;
-
- if (m_floppy)
- {
- m_floppy->ss_w(m_side_control & 0x01);
- }
-}
-
-
-void msx_cart_disk_type1_device::device_reset()
-{
- m_fdc->dden_w(false);
-}
-
-
-uint8_t msx_cart_disk_type1_device::read_cart(offs_t offset)
-{
- switch (offset)
- {
- case 0x7ff8:
- case 0xbff8:
- return m_fdc->status_r();
-
- case 0x7ff9:
- case 0xbff9:
- return m_fdc->track_r();
-
- case 0x7ffa:
- case 0xbffa:
- return m_fdc->sector_r();
-
- case 0x7ffb:
- case 0xbffb:
- return m_fdc->data_r();
-
- case 0x7ffc:
- case 0xbffc:
- return 0xfe | (m_side_control & 0x01);
-
- case 0x7ffd:
- case 0xbffd:
- return ( m_control & 0x83 ) | 0x78;
-
- case 0x7fff:
- case 0xbfff:
- return 0x3f | (m_fdc->intrq_r() ? 0 : 0x40) | (m_fdc->drq_r() ? 0 : 0x80);
- }
-
- if (offset >= 0x4000 && offset < 0x8000)
- {
- return get_rom_base()[offset & 0x3fff];
- }
- return 0xff;
-}
-
-
-void msx_cart_disk_type1_device::write_cart(offs_t offset, uint8_t data)
-{
- switch (offset)
- {
- case 0x7ff8:
- case 0xbff8:
- m_fdc->cmd_w(data);
- break;
-
- case 0x7ff9:
- case 0xbff9:
- m_fdc->track_w(data);
- break;
-
- case 0x7ffa:
- case 0xbffa:
- m_fdc->sector_w(data);
- break;
-
- case 0x7ffb:
- case 0xbffb:
- m_fdc->data_w(data);
- break;
-
- case 0x7ffc:
- case 0xbffc:
- set_side_control(data);
- break;
-
- case 0x7ffd:
- case 0xbffd:
- set_control(data);
- break;
-
- default:
- logerror("msx_cart_disk_type1_device::write_cart: Unmapped write writing %02x to %04x\n", data, offset);
- break;
- }
-}
-
-
-void msx_cart_disk_type2_device::device_start()
-{
- m_led.resolve();
-
- save_item(NAME(m_control));
-}
-
-
-void msx_cart_disk_type2_device::device_reset()
-{
- m_fdc->dden_w(false);
-}
-
-
-void msx_cart_disk_type2_device::device_post_load()
-{
- uint8_t data = m_control;
-
- // To make sure the FDD busy led status gets set correctly
- m_control ^= 0x40;
-
- set_control(data);
-}
-
-
-void msx_cart_disk_type2_device::set_control(uint8_t data)
-{
- uint8_t old_m_control = m_control;
-
- m_control = data;
-
- switch (m_control & 3)
- {
- case 1:
- m_floppy = m_floppy0 ? m_floppy0->get_device() : nullptr;
- break;
-
- case 2:
- m_floppy = m_floppy1 ? m_floppy1->get_device() : nullptr;
- break;
-
- default:
- m_floppy = nullptr;
- break;
- }
-
- if (m_floppy)
- {
- m_floppy->mon_w((m_control & 0x08) ? 0 : 1);
- m_floppy->ss_w((m_control & 0x04) ? 1 : 0);
- }
-
- m_fdc->set_floppy(m_floppy);
-
- if ((old_m_control ^ m_control) & 0x40)
- {
- m_led = BIT(~m_control, 6);
- }
-}
-
-
-uint8_t msx_cart_disk_type2_device::read_cart(offs_t offset)
-{
- switch (offset)
- {
- case 0x7fb8:
- case 0xbfb8:
- return m_fdc->status_r();
-
- case 0x7fb9:
- case 0xbfb9:
- return m_fdc->track_r();
-
- case 0x7fba:
- case 0xbfba:
- return m_fdc->sector_r();
-
- case 0x7fbb:
- case 0xbfbb:
- return m_fdc->data_r();
-
- case 0x7fbc:
- case 0xbfbc:
- return 0x3f | (m_fdc->drq_r() ? 0 : 0x40) | (m_fdc->intrq_r() ? 0x80 : 0);
- }
-
- if (offset >= 0x4000 && offset < 0x8000)
- {
- return get_rom_base()[offset & 0x3fff];
- }
- return 0xff;
-}
-
-
-void msx_cart_disk_type2_device::write_cart(offs_t offset, uint8_t data)
-{
- switch (offset)
- {
- case 0x7fb8:
- case 0xbfb8:
- m_fdc->cmd_w(data);
- break;
-
- case 0x7fb9:
- case 0xbfb9:
- m_fdc->track_w(data);
- break;
-
- case 0x7fba:
- case 0xbfba:
- m_fdc->sector_w(data);
- break;
-
- case 0x7fbb:
- case 0xbfbb:
- m_fdc->data_w(data);
- break;
-
- case 0x7fbc:
- case 0xbfbc:
- set_control(data);
- break;
-
- default:
- logerror("msx_cart_disk_type2_device::write_cart: Unmapped write writing %02x to %04x\n", data, offset);
- break;
- }
-}
-
-
-
-
-void msx_cart_fsfd1a_device::device_start()
-{
-}
-
-
-void msx_cart_fsfd1a_device::device_reset()
-{
-}
-
-
-uint8_t msx_cart_fsfd1a_device::read_cart(offs_t offset)
-{
- switch (offset)
- {
- case 0x7ffa:
- case 0xbffa:
- return m_fdc->msr_r();
-
- case 0x7ffb:
- case 0xbffb:
- return m_fdc->fifo_r();
- }
-
- if (offset >= 0x4000 && offset < 0x8000)
- {
- return get_rom_base()[offset & 0x3fff];
- }
- return 0xff;
-}
-
-
-void msx_cart_fsfd1a_device::write_cart(offs_t offset, uint8_t data)
-{
- switch (offset)
- {
- case 0x7ff8:
- case 0xbff8:
- m_fdc->dor_w(data);
- break;
-
- case 0x7ff9:
- case 0xbff9:
- m_fdc->cr1_w(data);
- break;
-
- case 0x7ffb:
- case 0xbffb:
- m_fdc->fifo_w(data);
- break;
-
- default:
- logerror("msx_cart_fsfd1a_device::write_cart: Unmapped write writing %02x to %04x\n", data, offset);
- break;
- }
-}
diff --git a/src/devices/bus/msx_cart/disk.h b/src/devices/bus/msx_cart/disk.h
deleted file mode 100644
index fd8d640157f..00000000000
--- a/src/devices/bus/msx_cart/disk.h
+++ /dev/null
@@ -1,145 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Wilbert Pol
-#ifndef MAME_BUS_MSX_CART_DISK_H
-#define MAME_BUS_MSX_CART_DISK_H
-
-#pragma once
-
-#include "bus/msx_cart/cartridge.h"
-#include "machine/wd_fdc.h"
-#include "machine/upd765.h"
-#include "imagedev/floppy.h"
-
-
-DECLARE_DEVICE_TYPE(MSX_CART_VY0010, msx_cart_vy0010_device)
-DECLARE_DEVICE_TYPE(MSX_CART_FSFD1, msx_cart_fsfd1_device)
-DECLARE_DEVICE_TYPE(MSX_CART_FSFD1A, msx_cart_fsfd1a_device)
-DECLARE_DEVICE_TYPE(MSX_CART_FSCF351, msx_cart_fscf351_device)
-
-
-class msx_cart_disk_device : public device_t, public msx_cart_interface
-{
-public:
- virtual void initialize_cartridge() override;
-
-protected:
- msx_cart_disk_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
-
- required_device<floppy_connector> m_floppy0;
- optional_device<floppy_connector> m_floppy1;
- floppy_image_device *m_floppy;
-
- static void floppy_formats(format_registration &fr);
-};
-
-
-class msx_cart_disk_wd_device : public msx_cart_disk_device
-{
-protected:
- msx_cart_disk_wd_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
-
- required_device<wd_fdc_analog_device_base> m_fdc;
-};
-
-
-class msx_cart_disk_type1_device : public msx_cart_disk_wd_device
-{
-public:
- virtual uint8_t read_cart(offs_t offset) override;
- virtual void write_cart(offs_t offset, uint8_t data) override;
-
-protected:
- msx_cart_disk_type1_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
-
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_post_load() override;
-
- output_finder<> m_led;
- uint8_t m_side_control;
- uint8_t m_control;
-
- void set_side_control(uint8_t data);
- void set_control(uint8_t data);
-};
-
-
-class msx_cart_disk_type2_device : public msx_cart_disk_wd_device
-{
-public:
- virtual uint8_t read_cart(offs_t offset) override;
- virtual void write_cart(offs_t offset, uint8_t data) override;
-
-protected:
- msx_cart_disk_type2_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
-
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_post_load() override;
-
- output_finder<> m_led;
- uint8_t m_control;
-
- void set_control(uint8_t data);
-};
-
-
-class msx_cart_vy0010_device : public msx_cart_disk_type1_device
-{
-public:
- msx_cart_vy0010_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- virtual void device_add_mconfig(machine_config &config) override;
-};
-
-
-class msx_cart_fsfd1_device : public msx_cart_disk_type1_device
-{
-public:
- msx_cart_fsfd1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- virtual void device_add_mconfig(machine_config &config) override;
-};
-
-
-class msx_cart_fscf351_device : public msx_cart_disk_type2_device
-{
-public:
- msx_cart_fscf351_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- virtual void device_add_mconfig(machine_config &config) override;
-};
-
-
-class msx_cart_disk_tc8566_device : public msx_cart_disk_device
-{
-protected:
- msx_cart_disk_tc8566_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
-
- required_device<tc8566af_device> m_fdc;
-};
-
-
-class msx_cart_fsfd1a_device : public msx_cart_disk_tc8566_device
-{
-public:
- msx_cart_fsfd1a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- virtual void device_start() override;
- virtual void device_reset() override;
-
- // device-level overrides
- virtual void device_add_mconfig(machine_config &config) override;
-
- virtual uint8_t read_cart(offs_t offset) override;
- virtual void write_cart(offs_t offset, uint8_t data) override;
-};
-
-
-#endif // MAME_BUS_MSX_CART_DISK_H
diff --git a/src/devices/bus/msx_cart/dooly.cpp b/src/devices/bus/msx_cart/dooly.cpp
deleted file mode 100644
index a0c4c7b4f83..00000000000
--- a/src/devices/bus/msx_cart/dooly.cpp
+++ /dev/null
@@ -1,67 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Wilbert Pol
-#include "emu.h"
-#include "dooly.h"
-
-
-DEFINE_DEVICE_TYPE(MSX_CART_DOOLY, msx_cart_dooly_device, "msx_cart_dooly", "MSX Cartridge - Dooly")
-
-
-msx_cart_dooly_device::msx_cart_dooly_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, MSX_CART_DOOLY, tag, owner, clock)
- , msx_cart_interface(mconfig, *this)
- , m_prot(0)
-{
-}
-
-
-void msx_cart_dooly_device::device_start()
-{
- save_item(NAME(m_prot));
-}
-
-
-void msx_cart_dooly_device::device_reset()
-{
- m_prot = 0;
-}
-
-
-void msx_cart_dooly_device::initialize_cartridge()
-{
- if (get_rom_size() != 0x8000)
- {
- fatalerror("dooly: Invalid ROM size\n");
- }
-}
-
-
-uint8_t msx_cart_dooly_device::read_cart(offs_t offset)
-{
- if (offset >= 0x4000 && offset < 0xc000)
- {
- uint8_t data = get_rom_base()[offset - 0x4000];
-
- switch (m_prot)
- {
- case 0x04:
- data = bitswap<8>(data, 7, 6, 5, 4, 3, 1, 0, 2);
- break;
- }
- return data;
- }
- return 0xff;
-}
-
-
-void msx_cart_dooly_device::write_cart(offs_t offset, uint8_t data)
-{
- if (offset >= 0x4000 && offset < 0xc000)
- {
- m_prot = data & 0x07;
- if (m_prot != 0 && m_prot != 4)
- {
- logerror("msx_cart_dooly_device: unhandled write %02x to %04x\n", data, offset);
- }
- }
-}
diff --git a/src/devices/bus/msx_cart/dooly.h b/src/devices/bus/msx_cart/dooly.h
deleted file mode 100644
index 76f58ae762d..00000000000
--- a/src/devices/bus/msx_cart/dooly.h
+++ /dev/null
@@ -1,34 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Wilbert Pol
-#ifndef MAME_BUS_MSX_CART_DOOLY_H
-#define MAME_BUS_MSX_CART_DOOLY_H
-
-#pragma once
-
-#include "bus/msx_cart/cartridge.h"
-
-
-DECLARE_DEVICE_TYPE(MSX_CART_DOOLY, msx_cart_dooly_device)
-
-
-class msx_cart_dooly_device : public device_t, public msx_cart_interface
-{
-public:
- msx_cart_dooly_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void initialize_cartridge() override;
-
- virtual uint8_t read_cart(offs_t offset) override;
- virtual void write_cart(offs_t offset, uint8_t data) override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
-
-private:
- uint8_t m_prot;
-};
-
-
-#endif // MAME_BUS_MSX_CART_DOOLY_H
diff --git a/src/devices/bus/msx_cart/easi_speech.cpp b/src/devices/bus/msx_cart/easi_speech.cpp
deleted file mode 100644
index 6a39316c191..00000000000
--- a/src/devices/bus/msx_cart/easi_speech.cpp
+++ /dev/null
@@ -1,62 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:hap
-/******************************************************************************
-
-Easi-Speech cartridge (R.Amy, 1987)
-
-The program adds a hook to 0xfd29, usage appears to be something like this:
-defusr0=&hfd29
-x=usr0("hello")
-
-TODO:
-- Speech doesn't work. At boot, it's supposed to say "M S X easy speech".
- Maybe ald_w data is scrambled a bit? The expected usage in notes above
- also does not work.
-
-******************************************************************************/
-
-#include "emu.h"
-#include "easi_speech.h"
-
-
-DEFINE_DEVICE_TYPE(MSX_CART_EASISPEECH, msx_cart_easispeech_device, "msx_cart_easispeech", "MSX Cartridge - Easi-Speech")
-
-
-msx_cart_easispeech_device::msx_cart_easispeech_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, MSX_CART_EASISPEECH, tag, owner, clock)
- , msx_cart_interface(mconfig, *this)
- , m_speech(*this, "speech")
-{
-}
-
-ROM_START( msx_cart_easispeech )
- ROM_REGION( 0x10000, "speech", 0 )
- ROM_LOAD( "sp0256a-al2", 0x1000, 0x0800, CRC(b504ac15) SHA1(e60fcb5fa16ff3f3b69d36c7a6e955744d3feafc) )
-ROM_END
-
-const tiny_rom_entry *msx_cart_easispeech_device::device_rom_region() const
-{
- return ROM_NAME( msx_cart_easispeech );
-}
-
-void msx_cart_easispeech_device::device_add_mconfig(machine_config &config)
-{
- SP0256(config, m_speech, 3120000); // frequency unknown
- m_speech->add_route(ALL_OUTPUTS, ":speaker", 1.00);
-}
-
-uint8_t msx_cart_easispeech_device::read_cart(offs_t offset)
-{
- if (offset >= 0x4000 && offset < 0x8000)
- return get_rom_base()[offset & 0x1fff];
- if (offset >= 0x8000 && offset < 0xc000)
- return m_speech->lrq_r() << 7;
-
- return 0xff;
-}
-
-void msx_cart_easispeech_device::write_cart(offs_t offset, uint8_t data)
-{
- if (offset >= 0x8000 && offset < 0xc000)
- m_speech->ald_w(data >> 2);
-}
diff --git a/src/devices/bus/msx_cart/easi_speech.h b/src/devices/bus/msx_cart/easi_speech.h
deleted file mode 100644
index 2aba350c4c7..00000000000
--- a/src/devices/bus/msx_cart/easi_speech.h
+++ /dev/null
@@ -1,33 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:hap
-#ifndef MAME_BUS_MSX_CART_EASISPEECH_H
-#define MAME_BUS_MSX_CART_EASISPEECH_H
-
-#pragma once
-
-#include "bus/msx_cart/cartridge.h"
-#include "sound/sp0256.h"
-
-
-DECLARE_DEVICE_TYPE(MSX_CART_EASISPEECH, msx_cart_easispeech_device)
-
-
-class msx_cart_easispeech_device : public device_t, public msx_cart_interface
-{
-public:
- msx_cart_easispeech_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual uint8_t read_cart(offs_t offset) override;
- virtual void write_cart(offs_t offset, uint8_t data) override;
-
-protected:
- // device-level overrides
- virtual void device_start() override { ; }
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
-
-private:
- required_device<sp0256_device> m_speech;
-};
-
-#endif // MAME_BUS_MSX_CART_EASISPEECH_H
diff --git a/src/devices/bus/msx_cart/fmpac.cpp b/src/devices/bus/msx_cart/fmpac.cpp
deleted file mode 100644
index 75af22353dc..00000000000
--- a/src/devices/bus/msx_cart/fmpac.cpp
+++ /dev/null
@@ -1,171 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Wilbert Pol
-/**********************************************************************************
-
-When backing up the SRAM from an FM-PAC the file seems to be prefixed
-with: PAC2 BACKUP DATA. We only store the raw sram contents.
-
-**********************************************************************************/
-
-#include "emu.h"
-#include "fmpac.h"
-#include "speaker.h"
-
-DEFINE_DEVICE_TYPE(MSX_CART_FMPAC, msx_cart_fmpac_device, "msx_cart_fmpac", "MSX Cartridge - FM-PAC")
-
-
-msx_cart_fmpac_device::msx_cart_fmpac_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, MSX_CART_FMPAC, tag, owner, clock)
- , msx_cart_interface(mconfig, *this)
- , m_ym2413(*this, "ym2413")
- , m_selected_bank(0)
- , m_bank_base(nullptr)
- , m_sram_active(false)
- , m_opll_active(false)
- , m_1ffe(0)
- , m_1fff(0)
- , m_7ff6(0)
-{
-}
-
-
-void msx_cart_fmpac_device::device_add_mconfig(machine_config &config)
-{
- // This is actually incorrect. The sound output is passed back into the MSX machine where it is mixed internally and output through the system 'speaker'.
- SPEAKER(config, "mono").front_center();
- YM2413(config, m_ym2413, XTAL(10'738'635)/3).add_route(ALL_OUTPUTS, "mono", 0.40);
-}
-
-
-void msx_cart_fmpac_device::device_start()
-{
- save_item(NAME(m_selected_bank));
- save_item(NAME(m_sram_active));
- save_item(NAME(m_opll_active));
- save_item(NAME(m_1ffe));
- save_item(NAME(m_1fff));
- save_item(NAME(m_7ff6));
-
- // Install IO read/write handlers
- io_space().install_write_handler(0x7c, 0x7d, write8sm_delegate(*this, FUNC(msx_cart_fmpac_device::write_ym2413)));
-}
-
-
-void msx_cart_fmpac_device::device_post_load()
-{
- restore_banks();
-}
-
-
-void msx_cart_fmpac_device::restore_banks()
-{
- m_bank_base = get_rom_base() + ( m_selected_bank & 0x03 ) * 0x4000;
-}
-
-
-void msx_cart_fmpac_device::device_reset()
-{
- m_selected_bank = 0;
- m_sram_active = false;
- m_opll_active = false;
- m_1ffe = 0;
- m_1fff = 0;
- m_7ff6 = 0;
-}
-
-
-void msx_cart_fmpac_device::initialize_cartridge()
-{
- if ( get_rom_size() != 0x10000 )
- {
- fatalerror("fmpac: Invalid ROM size\n");
- }
-
- if ( get_sram_size() != 0x2000 )
- {
- fatalerror("fmpac: Invalid SRAM size\n");
- }
-
- restore_banks();
-}
-
-
-uint8_t msx_cart_fmpac_device::read_cart(offs_t offset)
-{
- if (offset >= 0x4000 && offset < 0x8000)
- {
- if (offset == 0x7ff6)
- {
- return m_7ff6;
- }
- if (offset == 0x7ff7)
- {
- return m_selected_bank & 0x03;
- }
- if (m_sram_active)
- {
- if (offset & 0x2000)
- {
- return 0xff;
- }
- return get_sram_base()[offset & 0x1fff];
- }
- else
- {
- return m_bank_base[offset & 0x3fff];
- }
- }
- return 0xff;
-}
-
-
-void msx_cart_fmpac_device::write_cart(offs_t offset, uint8_t data)
-{
- if (offset >= 0x4000 && offset < 0x6000)
- {
- if (m_sram_active)
- {
- get_sram_base()[offset & 0x1fff] = data;
- }
- if (offset == 0x5ffe)
- {
- m_1ffe = data;
- }
- if (offset == 0x5fff)
- {
- m_1fff = data;
- }
- m_sram_active = (m_1ffe == 0x4d) && (m_1fff == 0x69);
- }
-
- switch (offset)
- {
- case 0x7ff4:
- case 0x7ff5:
- if (m_opll_active)
- {
- m_ym2413->write(offset & 1, data);
- }
- break;
-
- case 0x7ff6:
- m_7ff6 = data & 0x11;
- m_opll_active = (m_7ff6 & 0x01);
- break;
-
- case 0x7ff7:
- m_selected_bank = data;
- restore_banks();
- break;
- }
-
-}
-
-
-void msx_cart_fmpac_device::write_ym2413(offs_t offset, uint8_t data)
-{
- if (m_opll_active)
- {
- m_ym2413->write(offset & 1, data);
- }
-}
diff --git a/src/devices/bus/msx_cart/fmpac.h b/src/devices/bus/msx_cart/fmpac.h
deleted file mode 100644
index 9175849eaba..00000000000
--- a/src/devices/bus/msx_cart/fmpac.h
+++ /dev/null
@@ -1,50 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Wilbert Pol
-#ifndef MAME_BUS_MSX_CART_FMPAC_H
-#define MAME_BUS_MSX_CART_FMPAC_H
-
-#pragma once
-
-#include "bus/msx_cart/cartridge.h"
-#include "sound/ymopl.h"
-
-
-DECLARE_DEVICE_TYPE(MSX_CART_FMPAC, msx_cart_fmpac_device)
-
-
-class msx_cart_fmpac_device : public device_t, public msx_cart_interface
-{
-public:
- msx_cart_fmpac_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void initialize_cartridge() override;
-
- virtual uint8_t read_cart(offs_t offset) override;
- virtual void write_cart(offs_t offset, uint8_t data) override;
-
-protected:
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_post_load() override;
-
- // device-level overrides
- virtual void device_add_mconfig(machine_config &config) override;
-
- void restore_banks();
-
-private:
- void write_ym2413(offs_t offset, uint8_t data);
-
- required_device<ym2413_device> m_ym2413;
-
- uint8_t m_selected_bank;
- uint8_t *m_bank_base;
- bool m_sram_active;
- bool m_opll_active;
- uint8_t m_1ffe;
- uint8_t m_1fff;
- uint8_t m_7ff6;
-};
-
-
-#endif // MAME_BUS_MSX_CART_FMPAC_H
diff --git a/src/devices/bus/msx_cart/fs_sr022.cpp b/src/devices/bus/msx_cart/fs_sr022.cpp
deleted file mode 100644
index bb84a759214..00000000000
--- a/src/devices/bus/msx_cart/fs_sr022.cpp
+++ /dev/null
@@ -1,71 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Wilbert Pol
-#include "emu.h"
-#include "fs_sr022.h"
-
-
-DEFINE_DEVICE_TYPE(MSX_CART_FS_SR022, msx_cart_fs_sr022_device, "msx_cart_fs_sr022", "MSX Cartridge - FS-SR022")
-
-
-msx_cart_fs_sr022_device::msx_cart_fs_sr022_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, MSX_CART_FS_SR022, tag, owner, clock)
- , msx_cart_interface(mconfig, *this)
- , m_bunsetsu_rom(nullptr)
- , m_bunsetsu_address(0)
-{
-}
-
-
-void msx_cart_fs_sr022_device::device_start()
-{
- save_item(NAME(m_bunsetsu_address));
-}
-
-
-void msx_cart_fs_sr022_device::device_reset()
-{
- m_bunsetsu_address = 0;
-}
-
-
-void msx_cart_fs_sr022_device::initialize_cartridge()
-{
- if (get_rom_size() != 0x40000)
- {
- fatalerror("fs_sr022: Invalid ROM size\n");
- }
- m_bunsetsu_rom = get_rom_base() + 0x20000;
-}
-
-
-uint8_t msx_cart_fs_sr022_device::read_cart(offs_t offset)
-{
- if (offset >= 0x4000 && offset < 0xc000)
- {
- if (offset == 0xbfff) {
- return m_bunsetsu_rom[m_bunsetsu_address++ & 0x1ffff];
- }
-
- return get_rom_base()[offset - 0x4000];
- }
- return 0xff;
-}
-
-
-void msx_cart_fs_sr022_device::write_cart(offs_t offset, uint8_t data)
-{
- switch (offset)
- {
- case 0xbffc:
- m_bunsetsu_address = (m_bunsetsu_address & 0xffff00) | data;
- break;
-
- case 0xbffd:
- m_bunsetsu_address = (m_bunsetsu_address & 0xff00ff) | (data << 8);
- break;
-
- case 0xbffe:
- m_bunsetsu_address = (m_bunsetsu_address & 0x00ffff) | (data << 16);
- break;
- }
-}
diff --git a/src/devices/bus/msx_cart/fs_sr022.h b/src/devices/bus/msx_cart/fs_sr022.h
deleted file mode 100644
index 2456b90a101..00000000000
--- a/src/devices/bus/msx_cart/fs_sr022.h
+++ /dev/null
@@ -1,35 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Wilbert Pol
-#ifndef MAME_BUS_MSX_CART_FS_SR022_H
-#define MAME_BUS_MSX_CART_FS_SR022_H
-
-#pragma once
-
-#include "bus/msx_cart/cartridge.h"
-
-
-DECLARE_DEVICE_TYPE(MSX_CART_FS_SR022, msx_cart_fs_sr022_device)
-
-
-class msx_cart_fs_sr022_device : public device_t, public msx_cart_interface
-{
-public:
- msx_cart_fs_sr022_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void initialize_cartridge() override;
-
- virtual uint8_t read_cart(offs_t offset) override;
- virtual void write_cart(offs_t offset, uint8_t data) override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
-
-private:
- const uint8_t *m_bunsetsu_rom;
- uint32_t m_bunsetsu_address;
-};
-
-
-#endif // MAME_BUS_MSX_CART_FS_SR022_H
diff --git a/src/devices/bus/msx_cart/halnote.cpp b/src/devices/bus/msx_cart/halnote.cpp
deleted file mode 100644
index 43f7947ec2c..00000000000
--- a/src/devices/bus/msx_cart/halnote.cpp
+++ /dev/null
@@ -1,160 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Wilbert Pol
-#include "emu.h"
-#include "halnote.h"
-
-
-DEFINE_DEVICE_TYPE(MSX_CART_HALNOTE, msx_cart_halnote_device, "msx_cart_halnote", "MSX Cartridge - Halnote")
-
-
-msx_cart_halnote_device::msx_cart_halnote_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, MSX_CART_HALNOTE, tag, owner, clock)
- , msx_cart_interface(mconfig, *this)
- , m_selected_bank{ 0, 0, 0, 0, 0, 0, 0, 0 }
- , m_bank_base{ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr }
-{
-}
-
-
-void msx_cart_halnote_device::device_start()
-{
- save_item(NAME(m_selected_bank));
-}
-
-
-void msx_cart_halnote_device::device_post_load()
-{
- restore_banks();
-}
-
-
-void msx_cart_halnote_device::map_bank(int bank)
-{
- if (bank < 2)
- {
- return;
- }
-
- // Special banks
- if (bank == 6 || bank == 7)
- {
- m_bank_base[bank] = get_rom_base() + 0x80000 + (m_selected_bank[bank] * 0x800);
- return;
- }
-
- m_bank_base[bank] = get_rom_base() + ((m_selected_bank[bank] * 0x2000) & 0xFFFFF);
- if (bank == 2)
- {
- if (m_selected_bank[bank] & 0x80)
- {
- m_bank_base[0] = get_sram_base();
- m_bank_base[1] = get_sram_base() + 0x2000;
- }
- else
- {
- m_bank_base[0] = nullptr;
- m_bank_base[1] = nullptr;
- }
- }
-}
-
-
-void msx_cart_halnote_device::restore_banks()
-{
- for (int i = 0; i < 8; i++)
- {
- map_bank(i);
- }
-}
-
-
-void msx_cart_halnote_device::device_reset()
-{
- for (auto & elem : m_selected_bank)
- {
- elem = 0;
- }
-}
-
-
-void msx_cart_halnote_device::initialize_cartridge()
-{
- if (get_rom_size() != 0x100000)
- {
- fatalerror("halnote: Invalid ROM size\n");
- }
-
- restore_banks();
-}
-
-
-uint8_t msx_cart_halnote_device::read_cart(offs_t offset)
-{
- if (offset >= 0xc000)
- {
- return 0xFF;
- }
-
- if ((offset & 0xf000) == 0x7000 && (m_selected_bank[3] & 0x80))
- {
- return m_bank_base[6 + ((offset >> 11) & 0x01)][offset & 0x7ff];
- }
-
- const uint8_t *mem = m_bank_base[offset >> 13];
-
- if (mem)
- {
- return mem[offset & 0x1fff];
- }
- return 0xff;
-}
-
-
-void msx_cart_halnote_device::write_cart(offs_t offset, uint8_t data)
-{
- if (offset < 0x4000)
- {
- if (m_bank_base[0] != nullptr)
- {
- m_sram[offset & 0x3fff] = data;
- return;
- }
- }
-
- switch (offset)
- {
- case 0x4FFF:
- m_selected_bank[2] = data;
- map_bank(2);
- break;
-
- case 0x6FFF: // 6000-7FFF
- m_selected_bank[3] = data;
- map_bank(3);
- break;
-
- case 0x77FF:
- m_selected_bank[6] = data;
- map_bank(6);
- break;
-
- case 0x7FFF:
- m_selected_bank[7] = data;
- map_bank(7);
- break;
-
- case 0x8FFF:
- m_selected_bank[4] = data;
- map_bank(4);
- break;
-
- case 0xAFFF:
- m_selected_bank[5] = data;
- map_bank(5);
- break;
-
- default:
- logerror("msx_cart_halnote_device: Unhandled write %02x to %04x\n", data, offset);
- break;
- }
-}
diff --git a/src/devices/bus/msx_cart/halnote.h b/src/devices/bus/msx_cart/halnote.h
deleted file mode 100644
index a9c1972afeb..00000000000
--- a/src/devices/bus/msx_cart/halnote.h
+++ /dev/null
@@ -1,40 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Wilbert Pol
-#ifndef MAME_BUS_MSX_CART_HALNOTE_H
-#define MAME_BUS_MSX_CART_HALNOTE_H
-
-#pragma once
-
-#include "bus/msx_cart/cartridge.h"
-
-
-DECLARE_DEVICE_TYPE(MSX_CART_HALNOTE, msx_cart_halnote_device)
-
-
-class msx_cart_halnote_device : public device_t, public msx_cart_interface
-{
-public:
- msx_cart_halnote_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void initialize_cartridge() override;
-
- virtual uint8_t read_cart(offs_t offset) override;
- virtual void write_cart(offs_t offset, uint8_t data) override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_post_load() override;
-
- void restore_banks();
-
-private:
- uint8_t m_selected_bank[8];
- uint8_t *m_bank_base[8];
-
- void map_bank(int bank);
-};
-
-
-#endif // MAME_BUS_MSX_CART_HALNOTE_H
diff --git a/src/devices/bus/msx_cart/hfox.cpp b/src/devices/bus/msx_cart/hfox.cpp
deleted file mode 100644
index 007155b6e5b..00000000000
--- a/src/devices/bus/msx_cart/hfox.cpp
+++ /dev/null
@@ -1,83 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Wilbert Pol
-#include "emu.h"
-#include "hfox.h"
-
-
-DEFINE_DEVICE_TYPE(MSX_CART_HFOX, msx_cart_hfox_device, "msx_cart_hfox", "MSX Cartridge - Hurry Fox")
-
-
-msx_cart_hfox_device::msx_cart_hfox_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, MSX_CART_HFOX, tag, owner, clock)
- , msx_cart_interface(mconfig, *this)
- , m_selected_bank{ 0, 0 }
- , m_bank_base{ nullptr, nullptr }
-{
-}
-
-
-void msx_cart_hfox_device::device_start()
-{
- save_item(NAME(m_selected_bank));
-}
-
-
-void msx_cart_hfox_device::device_post_load()
-{
- restore_banks();
-}
-
-
-void msx_cart_hfox_device::restore_banks()
-{
- m_bank_base[0] = get_rom_base() + ((m_selected_bank[0] & 0x01) * 0x8000);
- m_bank_base[1] = get_rom_base() + ((m_selected_bank[1] & 0x01) * 0x8000) + 0x4000;
-}
-
-
-void msx_cart_hfox_device::device_reset()
-{
- m_selected_bank[0] = m_selected_bank[1] = 0;
-}
-
-
-void msx_cart_hfox_device::initialize_cartridge()
-{
- if (get_rom_size() < 0x10000)
- {
- fatalerror("hfox: Invalid ROM size\n");
- }
-
- restore_banks();
-}
-
-
-uint8_t msx_cart_hfox_device::read_cart(offs_t offset)
-{
- if (offset >= 0x4000 && offset < 0xc000)
- {
- return m_bank_base[offset >> 15][offset & 0x3fff];
- }
- return 0xff;
-}
-
-
-void msx_cart_hfox_device::write_cart(offs_t offset, uint8_t data)
-{
- switch (offset)
- {
- case 0x6000:
- m_selected_bank[0] = data;
- restore_banks();
- break;
-
- case 0x7000:
- m_selected_bank[1] = data;
- restore_banks();
- break;
-
- default:
- logerror("msx_cart_hfox_device: unhandled write %02x to %04x\n", data, offset);
- break;
- }
-}
diff --git a/src/devices/bus/msx_cart/hfox.h b/src/devices/bus/msx_cart/hfox.h
deleted file mode 100644
index 6254bae3610..00000000000
--- a/src/devices/bus/msx_cart/hfox.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Wilbert Pol
-#ifndef MAME_BUS_MSX_CART_HFOX_H
-#define MAME_BUS_MSX_CART_HFOX_H
-
-#include "bus/msx_cart/cartridge.h"
-
-
-DECLARE_DEVICE_TYPE(MSX_CART_HFOX, msx_cart_hfox_device)
-
-
-class msx_cart_hfox_device : public device_t, public msx_cart_interface
-{
-public:
- msx_cart_hfox_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void initialize_cartridge() override;
-
- virtual uint8_t read_cart(offs_t offset) override;
- virtual void write_cart(offs_t offset, uint8_t data) override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_post_load() override;
-
- void restore_banks();
-
-private:
- uint8_t m_selected_bank[2];
- uint8_t *m_bank_base[2];
-};
-
-
-#endif // MAME_BUS_MSX_CART_HFOX_H
diff --git a/src/devices/bus/msx_cart/holy_quran.cpp b/src/devices/bus/msx_cart/holy_quran.cpp
deleted file mode 100644
index 046ed194502..00000000000
--- a/src/devices/bus/msx_cart/holy_quran.cpp
+++ /dev/null
@@ -1,119 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Wilbert Pol
-#include "emu.h"
-#include "holy_quran.h"
-
-
-DEFINE_DEVICE_TYPE(MSX_CART_HOLY_QURAN, msx_cart_holy_quran_device, "msx_cart_holy_quran", "MSX Cartridge - Holy Quran")
-
-
-msx_cart_holy_quran_device::msx_cart_holy_quran_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, MSX_CART_HOLY_QURAN, tag, owner, clock)
- , msx_cart_interface(mconfig, *this)
- , m_selected_bank{ 0, 0, 0, 0 }
- , m_bank_base{ nullptr, nullptr, nullptr, nullptr }
- , m_decrypt(false)
-{
- /* protection uses a simple rotation on databus, some lines inverted:
- D0 D4 D4 D5
- D1 ~ D3 D5 ~ D2
- D2 ~ D6 D6 D7
- D3 ~ D0 D7 D1 */
- for (int i=0; i < 0x100; i++)
- {
- m_lookup_prot[i] = (((i << 4) & 0x50) | ((i >> 3) & 5) | ((i << 1) & 0xa0) | ((i << 2) & 8) | ((i >> 6) & 2)) ^ 0x4d;
- }
-}
-
-
-void msx_cart_holy_quran_device::device_start()
-{
- save_item(NAME(m_selected_bank));
- save_item(NAME(m_decrypt));
-}
-
-
-void msx_cart_holy_quran_device::device_post_load()
-{
- restore_banks();
-}
-
-
-void msx_cart_holy_quran_device::restore_banks()
-{
- m_bank_base[0] = get_rom_base() + (m_selected_bank[0] & 0x7f) * 0x2000;
- m_bank_base[1] = get_rom_base() + (m_selected_bank[1] & 0x7f) * 0x2000;
- m_bank_base[2] = get_rom_base() + (m_selected_bank[2] & 0x7f) * 0x2000;
- m_bank_base[3] = get_rom_base() + (m_selected_bank[3] & 0x7f) * 0x2000;
-}
-
-
-void msx_cart_holy_quran_device::device_reset()
-{
- for (auto & elem : m_selected_bank)
- {
- elem = 0;
- }
-}
-
-
-void msx_cart_holy_quran_device::initialize_cartridge()
-{
- if (get_rom_size() != 0x100000)
- {
- fatalerror("holy_quran: Invalid ROM size\n");
- }
-
- restore_banks();
-}
-
-
-uint8_t msx_cart_holy_quran_device::read_cart(offs_t offset)
-{
- if (offset >= 0x4000 && offset < 0xc000)
- {
- uint8_t data = m_bank_base[(offset - 0x4000) >> 13][offset & 0x1fff];
-
- if (m_decrypt)
- {
- return m_lookup_prot[data];
- }
-
- // The decryption should actually start working after the first M1 cycle executing something
- // from the cartridge.
- if (offset == ((m_rom[3] << 8) | m_rom[2]) && !machine().side_effects_disabled())
- {
- m_decrypt = true;
- }
-
- return data;
- }
- return 0xff;
-}
-
-
-void msx_cart_holy_quran_device::write_cart(offs_t offset, uint8_t data)
-{
- switch (offset)
- {
- case 0x5000:
- m_selected_bank[0] = data;
- restore_banks();
- break;
- case 0x5400:
- m_selected_bank[1] = data;
- restore_banks();
- break;
- case 0x5800:
- m_selected_bank[2] = data;
- restore_banks();
- break;
- case 0x5c00:
- m_selected_bank[3] = data;
- restore_banks();
- break;
- default:
- logerror("msx_cart_holy_quran_device: unhandled write %02x to %04x\n", data, offset);
- break;
- }
-}
diff --git a/src/devices/bus/msx_cart/holy_quran.h b/src/devices/bus/msx_cart/holy_quran.h
deleted file mode 100644
index 8d63a8271d9..00000000000
--- a/src/devices/bus/msx_cart/holy_quran.h
+++ /dev/null
@@ -1,40 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Wilbert Pol
-#ifndef MAME_BUS_MSX_CART_HOLY_QURAN_H
-#define MAME_BUS_MSX_CART_HOLY_QURAN_H
-
-#pragma once
-
-#include "bus/msx_cart/cartridge.h"
-
-
-DECLARE_DEVICE_TYPE(MSX_CART_HOLY_QURAN, msx_cart_holy_quran_device)
-
-
-class msx_cart_holy_quran_device : public device_t, public msx_cart_interface
-{
-public:
- msx_cart_holy_quran_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void initialize_cartridge() override;
-
- virtual uint8_t read_cart(offs_t offset) override;
- virtual void write_cart(offs_t offset, uint8_t data) override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_post_load() override;
-
- void restore_banks();
-
-private:
- uint8_t m_lookup_prot[256];
- uint8_t m_selected_bank[4];
- uint8_t *m_bank_base[4];
- bool m_decrypt;
-};
-
-
-#endif // MAME_BUS_MSX_CART_HOLY_QURAN_H
diff --git a/src/devices/bus/msx_cart/ink.cpp b/src/devices/bus/msx_cart/ink.cpp
deleted file mode 100644
index e3053a5da7d..00000000000
--- a/src/devices/bus/msx_cart/ink.cpp
+++ /dev/null
@@ -1,55 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:hap
-/******************************************************************************
-
-Ink cartridge (Matra, 2006)
-
-48KB ROM data on an AMD Am29F040B(label scratched off), the game uses it
-for protection.
-
-******************************************************************************/
-
-#include "emu.h"
-#include "ink.h"
-
-DEFINE_DEVICE_TYPE(MSX_CART_INK, msx_cart_ink_device, "msx_cart_ink", "MSX Cartridge - Ink")
-
-
-msx_cart_ink_device::msx_cart_ink_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, MSX_CART_INK, tag, owner, clock)
- , msx_cart_interface(mconfig, *this)
- , m_flash(*this, "flash")
-{
-}
-
-ROM_START( msx_cart_ink )
- ROM_REGION(0x80000, "flash", ROMREGION_ERASEFF)
-ROM_END
-
-const tiny_rom_entry *msx_cart_ink_device::device_rom_region() const
-{
- return ROM_NAME( msx_cart_ink );
-}
-
-void msx_cart_ink_device::device_add_mconfig(machine_config &config)
-{
- AMD_29F040(config, m_flash);
-}
-
-void msx_cart_ink_device::initialize_cartridge()
-{
- size_t size = get_rom_size() > 0x80000 ? 0x80000 : get_rom_size();
- memcpy(memregion("flash")->base(), get_rom_base(), size);
-}
-
-
-uint8_t msx_cart_ink_device::read_cart(offs_t offset)
-{
- return m_flash->read(offset);
-}
-
-void msx_cart_ink_device::write_cart(offs_t offset, uint8_t data)
-{
- // /RD connects to flashrom A16-A18
- m_flash->write(offset | 0x70000, data);
-}
diff --git a/src/devices/bus/msx_cart/ink.h b/src/devices/bus/msx_cart/ink.h
deleted file mode 100644
index 933385c575d..00000000000
--- a/src/devices/bus/msx_cart/ink.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:hap
-#ifndef MAME_BUS_MSX_CART_INK_H
-#define MAME_BUS_MSX_CART_INK_H
-
-#pragma once
-
-#include "bus/msx_cart/cartridge.h"
-#include "machine/intelfsh.h"
-
-
-DECLARE_DEVICE_TYPE(MSX_CART_INK, msx_cart_ink_device)
-
-
-class msx_cart_ink_device : public device_t, public msx_cart_interface
-{
-public:
- msx_cart_ink_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void initialize_cartridge() override;
-
- virtual uint8_t read_cart(offs_t offset) override;
- virtual void write_cart(offs_t offset, uint8_t data) override;
-
-protected:
- // device-level overrides
- virtual void device_start() override { ; }
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
-
-private:
- required_device<amd_29f040_device> m_flash;
-};
-
-
-#endif // MAME_BUS_MSX_CART_INK_H
diff --git a/src/devices/bus/msx_cart/konami.cpp b/src/devices/bus/msx_cart/konami.cpp
deleted file mode 100644
index 5954cb95091..00000000000
--- a/src/devices/bus/msx_cart/konami.cpp
+++ /dev/null
@@ -1,944 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Wilbert Pol
-#include "emu.h"
-#include "konami.h"
-
-#include "speaker.h"
-
-
-DEFINE_DEVICE_TYPE(MSX_CART_KONAMI, msx_cart_konami_device, "msx_cart_konami", "MSX Cartridge - KONAMI")
-DEFINE_DEVICE_TYPE(MSX_CART_KONAMI_SCC, msx_cart_konami_scc_device, "msx_cart_konami_scc", "MSX Cartridge - KONAMI+SCC")
-DEFINE_DEVICE_TYPE(MSX_CART_GAMEMASTER2, msx_cart_gamemaster2_device, "msx_cart_gamemaster2", "MSX Cartridge - GAMEMASTER2")
-DEFINE_DEVICE_TYPE(MSX_CART_SYNTHESIZER, msx_cart_synthesizer_device, "msx_cart_synthesizer", "MSX Cartridge - Synthesizer")
-DEFINE_DEVICE_TYPE(MSX_CART_SOUND_SNATCHER, msx_cart_konami_sound_snatcher_device, "msx_cart_sound_snatcher", "MSX Cartridge - Sound Snatcher")
-DEFINE_DEVICE_TYPE(MSX_CART_SOUND_SDSNATCHER, msx_cart_konami_sound_sdsnatcher_device, "msx_cart_sound_sdsnatcher", "MSX Cartridge - Sound SD Snatcher")
-DEFINE_DEVICE_TYPE(MSX_CART_KEYBOARD_MASTER, msx_cart_keyboard_master_device, "msx_cart_keyboard_master", "MSX Cartridge - Keyboard Master")
-
-
-msx_cart_konami_device::msx_cart_konami_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, MSX_CART_KONAMI, tag, owner, clock)
- , msx_cart_interface(mconfig, *this)
- , m_bank_mask(0)
-{
- for (int i = 0; i < 4; i++)
- {
- m_selected_bank[i] = i;
- }
- for (auto & elem : m_bank_base)
- {
- elem = nullptr;
- }
-}
-
-
-void msx_cart_konami_device::device_start()
-{
- save_item(NAME(m_selected_bank));
-}
-
-
-void msx_cart_konami_device::device_post_load()
-{
- restore_banks();
-}
-
-
-void msx_cart_konami_device::restore_banks()
-{
- m_bank_base[0] = get_rom_base() + ( m_selected_bank[0] & m_bank_mask ) * 0x2000;
- m_bank_base[1] = get_rom_base() + ( m_selected_bank[1] & m_bank_mask ) * 0x2000;
- m_bank_base[2] = get_rom_base() + ( m_selected_bank[0] & m_bank_mask ) * 0x2000;
- m_bank_base[3] = get_rom_base() + ( m_selected_bank[1] & m_bank_mask ) * 0x2000;
- m_bank_base[4] = get_rom_base() + ( m_selected_bank[2] & m_bank_mask ) * 0x2000;
- m_bank_base[5] = get_rom_base() + ( m_selected_bank[3] & m_bank_mask ) * 0x2000;
- m_bank_base[6] = get_rom_base() + ( m_selected_bank[2] & m_bank_mask ) * 0x2000;
- m_bank_base[7] = get_rom_base() + ( m_selected_bank[3] & m_bank_mask ) * 0x2000;
-}
-
-
-void msx_cart_konami_device::device_reset()
-{
- for (int i = 0; i < 4; i++)
- {
- m_selected_bank[i] = i;
- }
-}
-
-
-void msx_cart_konami_device::initialize_cartridge()
-{
- uint32_t size = get_rom_size();
-
- if ( get_rom_size() > 256 * 0x2000 )
- {
- fatalerror("konami: ROM is too big\n");
- }
-
- uint16_t banks = size / 0x2000;
-
- if (size != banks * 0x2000 || (~(banks - 1) % banks))
- {
- fatalerror("konami: Invalid ROM size\n");
- }
-
- m_bank_mask = banks - 1;
-
- restore_banks();
-}
-
-
-uint8_t msx_cart_konami_device::read_cart(offs_t offset)
-{
- return m_bank_base[offset >> 13][offset & 0x1fff];
-}
-
-
-void msx_cart_konami_device::write_cart(offs_t offset, uint8_t data)
-{
- switch (offset & 0xe000)
- {
- case 0x4000:
- m_selected_bank[0] = data;
- m_bank_base[0] = get_rom_base() + ( m_selected_bank[0] & m_bank_mask ) * 0x2000;
- m_bank_base[2] = get_rom_base() + ( m_selected_bank[0] & m_bank_mask ) * 0x2000;
- break;
-
- case 0x6000:
- m_selected_bank[1] = data;
- m_bank_base[1] = get_rom_base() + ( m_selected_bank[1] & m_bank_mask ) * 0x2000;
- m_bank_base[3] = get_rom_base() + ( m_selected_bank[1] & m_bank_mask ) * 0x2000;
- break;
-
- case 0x8000:
- m_selected_bank[2] = data;
- m_bank_base[4] = get_rom_base() + ( m_selected_bank[2] & m_bank_mask ) * 0x2000;
- m_bank_base[6] = get_rom_base() + ( m_selected_bank[2] & m_bank_mask ) * 0x2000;
- break;
-
- case 0xa000:
- m_selected_bank[3] = data;
- m_bank_base[5] = get_rom_base() + ( m_selected_bank[3] & m_bank_mask ) * 0x2000;
- m_bank_base[7] = get_rom_base() + ( m_selected_bank[3] & m_bank_mask ) * 0x2000;
- break;
- }
-}
-
-
-
-
-msx_cart_konami_scc_device::msx_cart_konami_scc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, MSX_CART_KONAMI_SCC, tag, owner, clock)
- , msx_cart_interface(mconfig, *this)
- , m_k051649(*this, "k051649")
- , m_bank_mask(0)
- , m_scc_active(false)
-{
- for (int i = 0; i < 4; i++)
- {
- m_selected_bank[i] = i;
- }
- for (auto & elem : m_bank_base)
- {
- elem = nullptr;
- }
-}
-
-
-void msx_cart_konami_scc_device::device_add_mconfig(machine_config &config)
-{
- // This is actually incorrect. The sound output is passed back into the MSX machine where it is mixed internally and output through the system 'speaker'.
- SPEAKER(config, "mono").front_center();
- K051649(config, m_k051649, XTAL(10'738'635)/3).add_route(ALL_OUTPUTS, "mono", 0.15);
-}
-
-
-void msx_cart_konami_scc_device::device_start()
-{
- save_item(NAME(m_selected_bank));
- save_item(NAME(m_scc_active));
-}
-
-
-void msx_cart_konami_scc_device::device_post_load()
-{
- restore_banks();
-}
-
-
-void msx_cart_konami_scc_device::restore_banks()
-{
- m_bank_base[0] = get_rom_base() + ( m_selected_bank[2] & m_bank_mask ) * 0x2000;
- m_bank_base[1] = get_rom_base() + ( m_selected_bank[3] & m_bank_mask ) * 0x2000;
- m_bank_base[2] = get_rom_base() + ( m_selected_bank[0] & m_bank_mask ) * 0x2000;
- m_bank_base[3] = get_rom_base() + ( m_selected_bank[1] & m_bank_mask ) * 0x2000;
- m_bank_base[4] = get_rom_base() + ( m_selected_bank[2] & m_bank_mask ) * 0x2000;
- m_bank_base[5] = get_rom_base() + ( m_selected_bank[3] & m_bank_mask ) * 0x2000;
- m_bank_base[6] = get_rom_base() + ( m_selected_bank[0] & m_bank_mask ) * 0x2000;
- m_bank_base[7] = get_rom_base() + ( m_selected_bank[1] & m_bank_mask ) * 0x2000;
-}
-
-
-void msx_cart_konami_scc_device::device_reset()
-{
- for (int i = 0; i < 4; i++)
- {
- m_selected_bank[i] = i;
- }
- m_scc_active = false;
-}
-
-
-void msx_cart_konami_scc_device::initialize_cartridge()
-{
- uint32_t size = get_rom_size();
-
- if ( get_rom_size() > 256 * 0x2000 )
- {
- fatalerror("konami_scc: ROM is too big\n");
- }
-
- uint16_t banks = size / 0x2000;
-
- if (size != banks * 0x2000 || (~(banks - 1) % banks))
- {
- fatalerror("konami_scc: Invalid ROM size\n");
- }
-
- m_bank_mask = banks - 1;
-
- restore_banks();
-}
-
-
-uint8_t msx_cart_konami_scc_device::read_cart(offs_t offset)
-{
- if ( m_scc_active && offset >= 0x9800 && offset < 0xa000 )
- {
- if (offset & 0x80)
- {
- if ((offset & 0xff) >= 0xe0)
- {
- return m_k051649->k051649_test_r();
- }
- return 0xff;
- }
- else
- {
- return m_k051649->k051649_waveform_r(offset & 0x7f);
- }
- }
-
- return m_bank_base[offset >> 13][offset & 0x1fff];
-}
-
-
-void msx_cart_konami_scc_device::write_cart(offs_t offset, uint8_t data)
-{
- switch (offset & 0xf800)
- {
- case 0x5000:
- m_selected_bank[0] = data;
- m_bank_base[2] = get_rom_base() + ( m_selected_bank[0] & m_bank_mask ) * 0x2000;
- m_bank_base[6] = get_rom_base() + ( m_selected_bank[0] & m_bank_mask ) * 0x2000;
- break;
-
- case 0x7000:
- m_selected_bank[1] = data;
- m_bank_base[3] = get_rom_base() + ( m_selected_bank[1] & m_bank_mask ) * 0x2000;
- m_bank_base[7] = get_rom_base() + ( m_selected_bank[1] & m_bank_mask ) * 0x2000;
- break;
-
- case 0x9000:
- m_selected_bank[2] = data;
- m_scc_active = ( ( data & 0x3f ) == 0x3f );
- m_bank_base[0] = get_rom_base() + ( m_selected_bank[2] & m_bank_mask ) * 0x2000;
- m_bank_base[4] = get_rom_base() + ( m_selected_bank[2] & m_bank_mask ) * 0x2000;
- break;
-
- case 0x9800:
- if ( m_scc_active )
- {
- offset &= 0xff;
-
- if (offset < 0x80)
- {
- m_k051649->k051649_waveform_w(offset, data);
- }
- else if (offset < 0xa0)
- {
- offset &= 0x0f;
- if (offset < 0x0a)
- {
- m_k051649->k051649_frequency_w(offset, data);
- }
- else if (offset < 0x0f)
- {
- m_k051649->k051649_volume_w(offset - 0xa, data);
- }
- else
- {
- m_k051649->k051649_keyonoff_w(data);
- }
- }
- else if (offset >= 0xe0)
- {
- m_k051649->k051649_test_w(data);
- }
- }
- break;
-
- case 0xb000:
- m_selected_bank[3] = data;
- m_bank_base[1] = get_rom_base() + ( m_selected_bank[3] & m_bank_mask ) * 0x2000;
- m_bank_base[5] = get_rom_base() + ( m_selected_bank[3] & m_bank_mask ) * 0x2000;
- break;
- }
-}
-
-
-
-
-
-
-msx_cart_gamemaster2_device::msx_cart_gamemaster2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, MSX_CART_GAMEMASTER2, tag, owner, clock)
- , msx_cart_interface(mconfig, *this)
-{
- for (auto & elem : m_selected_bank)
- {
- elem = 0;
- }
- for (auto & elem : m_bank_base)
- {
- elem = nullptr;
- }
-}
-
-
-void msx_cart_gamemaster2_device::device_start()
-{
- save_item(NAME(m_selected_bank));
-}
-
-
-void msx_cart_gamemaster2_device::device_post_load()
-{
- restore_banks();
-}
-
-
-void msx_cart_gamemaster2_device::setup_bank(uint8_t bank)
-{
- switch (bank)
- {
- case 0:
- if (m_selected_bank[0] & 0x10)
- {
- m_bank_base[1] = get_sram_base() + ((m_selected_bank[0] & 0x20) ? 0x1000 : 0);
- m_bank_base[3] = get_sram_base() + ((m_selected_bank[0] & 0x20) ? 0x1000 : 0);
- }
- else
- {
- m_bank_base[1] = get_rom_base() + ( m_selected_bank[0] & 0x0f ) * 0x2000;
- m_bank_base[3] = get_rom_base() + ( m_selected_bank[0] & 0x0f ) * 0x2000;
- }
- break;
-
- case 1:
- if (m_selected_bank[1] & 0x10)
- {
- m_bank_base[4] = get_sram_base() + ((m_selected_bank[1] & 0x20) ? 0x1000 : 0);
- m_bank_base[6] = get_sram_base() + ((m_selected_bank[1] & 0x20) ? 0x1000 : 0);
- }
- else
- {
- m_bank_base[4] = get_rom_base() + ( m_selected_bank[1] & 0x0f ) * 0x2000;
- m_bank_base[6] = get_rom_base() + ( m_selected_bank[1] & 0x0f ) * 0x2000;
- }
- break;
-
- case 2:
- if (m_selected_bank[2] & 0x10)
- {
- m_bank_base[5] = get_sram_base() + ((m_selected_bank[2] & 0x20) ? 0x1000 : 0);
- m_bank_base[7] = get_sram_base() + ((m_selected_bank[2] & 0x20) ? 0x1000 : 0);
- }
- else
- {
- m_bank_base[5] = get_rom_base() + ( m_selected_bank[2] & 0x0f ) * 0x2000;
- m_bank_base[7] = get_rom_base() + ( m_selected_bank[2] & 0x0f ) * 0x2000;
- }
- break;
- }
-}
-
-
-void msx_cart_gamemaster2_device::restore_banks()
-{
- m_bank_base[0] = get_rom_base();
- m_bank_base[2] = get_rom_base();
- setup_bank(0);
- setup_bank(1);
- setup_bank(2);
-}
-
-
-void msx_cart_gamemaster2_device::device_reset()
-{
- for (int i = 0; i < 3; i++)
- {
- m_selected_bank[i] = i + 1;
- }
-}
-
-
-void msx_cart_gamemaster2_device::initialize_cartridge()
-{
- if ( get_rom_size() != 0x20000 )
- {
- fatalerror("gamemaster2: Invalid ROM size\n");
- }
-
- if (get_sram_size() != 0x2000)
- {
- fatalerror("gamemaster2: Invalid SRAM size\n");
- }
-
- restore_banks();
-}
-
-
-uint8_t msx_cart_gamemaster2_device::read_cart(offs_t offset)
-{
- uint8_t bank = offset >> 13;
-
- switch (bank)
- {
- case 1:
- case 3:
- if (m_selected_bank[0] & 0x10)
- {
- return m_bank_base[bank][offset & 0x0fff];
- }
- break;
-
- case 4:
- case 6:
- if (m_selected_bank[1] & 0x10)
- {
- return m_bank_base[bank][offset & 0x0fff];
- }
- break;
-
- case 5:
- case 7:
- if (m_selected_bank[2] & 0x10)
- {
- return m_bank_base[bank][offset & 0x0fff];
- }
- break;
- }
- return m_bank_base[bank][offset & 0x1fff];
-}
-
-
-void msx_cart_gamemaster2_device::write_cart(offs_t offset, uint8_t data)
-{
- switch (offset & 0xf000)
- {
- case 0x6000:
- m_selected_bank[0] = data;
- setup_bank(0);
- break;
-
- case 0x8000:
- m_selected_bank[1] = data;
- setup_bank(1);
- break;
-
- case 0xa000:
- m_selected_bank[2] = data;
- setup_bank(2);
- break;
-
- case 0xb000:
- if (m_selected_bank[2] & 0x10)
- {
- m_bank_base[5][offset & 0x0fff] = data;
- }
- break;
- }
-}
-
-
-
-
-
-msx_cart_synthesizer_device::msx_cart_synthesizer_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, MSX_CART_SYNTHESIZER, tag, owner, clock)
- , msx_cart_interface(mconfig, *this)
- , m_bank_base(nullptr)
- , m_dac(*this, "dac")
-{
-}
-
-
-void msx_cart_synthesizer_device::device_add_mconfig(machine_config &config)
-{
- // This is actually incorrect. The sound output is passed back into the MSX machine where it is mixed internally and output through the system 'speaker'.
- SPEAKER(config, "speaker").front_center();
- DAC_8BIT_R2R(config, m_dac, 0).add_route(ALL_OUTPUTS, "speaker", 0.1); // unknown DAC
-}
-
-
-void msx_cart_synthesizer_device::device_start()
-{
-}
-
-
-void msx_cart_synthesizer_device::initialize_cartridge()
-{
- if ( get_rom_size() != 0x8000 )
- {
- fatalerror("synthesizer: Invalid ROM size\n");
- }
-
- m_bank_base = get_rom_base();
-}
-
-
-uint8_t msx_cart_synthesizer_device::read_cart(offs_t offset)
-{
- if (offset >= 0x4000 && offset < 0xc000 )
- {
- return m_bank_base[offset - 0x4000];
- }
- return 0xff;
-}
-
-
-void msx_cart_synthesizer_device::write_cart(offs_t offset, uint8_t data)
-{
- if ((offset & 0xc010) == 0x4000)
- {
- m_dac->write(data);
- }
-}
-
-
-
-
-msx_cart_konami_sound_device::msx_cart_konami_sound_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, type, tag, owner, clock)
- , msx_cart_interface(mconfig, *this)
- , m_k052539(*this, "k052539")
- , m_scc_active(false)
- , m_sccplus_active(false)
- , m_scc_mode(0)
-{
- for (auto & elem : m_selected_bank)
- {
- elem = 0;
- }
- for (auto & elem : m_bank_base)
- {
- elem = nullptr;
- }
- for (auto & elem : m_ram_bank)
- {
- elem = nullptr;
- }
- for (auto & elem : m_ram_enabled)
- {
- elem = false;
- }
-}
-
-
-void msx_cart_konami_sound_device::device_add_mconfig(machine_config &config)
-{
- // This is actually incorrect. The sound output is passed back into the MSX machine where it is mixed internally and output through the system 'speaker'.
- SPEAKER(config, "mono").front_center();
- K051649(config, m_k052539, XTAL(10'738'635)/3).add_route(ALL_OUTPUTS, "mono", 0.15);
-}
-
-
-void msx_cart_konami_sound_device::device_start()
-{
- save_item(NAME(m_selected_bank));
- save_item(NAME(m_scc_active));
- save_item(NAME(m_sccplus_active));
- save_item(NAME(m_ram_enabled));
-}
-
-
-void msx_cart_konami_sound_device::device_post_load()
-{
- restore_banks();
-}
-
-
-void msx_cart_konami_sound_device::restore_banks()
-{
- for (int i = 0; i < 4; i++)
- {
- setup_bank(i);
- }
-}
-
-
-void msx_cart_konami_sound_device::setup_bank(uint8_t bank)
-{
- switch (bank)
- {
- case 0:
- m_bank_base[2] = m_ram_bank[m_selected_bank[0] & 0x0f];
- m_bank_base[6] = m_ram_bank[m_selected_bank[0] & 0x0f];
- break;
-
- case 1:
- m_bank_base[3] = m_ram_bank[m_selected_bank[1] & 0x0f];
- m_bank_base[7] = m_ram_bank[m_selected_bank[1] & 0x0f];
- break;
-
- case 2:
- m_bank_base[0] = m_ram_bank[m_selected_bank[2] & 0x0f];
- m_bank_base[4] = m_ram_bank[m_selected_bank[2] & 0x0f];
- break;
-
- case 3:
- m_bank_base[1] = m_ram_bank[m_selected_bank[3] & 0x0f];
- m_bank_base[5] = m_ram_bank[m_selected_bank[3] & 0x0f];
- break;
- }
-}
-
-
-void msx_cart_konami_sound_device::device_reset()
-{
- for (int i = 0; i < 4; i++)
- {
- m_selected_bank[i] = i;
- m_ram_enabled[i] = false;
- }
- m_scc_active = false;
- m_sccplus_active = false;
-}
-
-
-void msx_cart_konami_sound_device::initialize_cartridge()
-{
- restore_banks();
-}
-
-
-uint8_t msx_cart_konami_sound_device::read_cart(offs_t offset)
-{
- if ( m_scc_active && offset >= 0x9800 && offset < 0x9fe0 )
- {
- offset &= 0xff;
- if (offset < 0x80)
- {
- return m_k052539->k051649_waveform_r(offset);
- }
- if (offset < 0xa0)
- {
- return 0xff;
- }
- if (offset < 0xc0)
- {
- return m_k052539->k051649_waveform_r(offset & 0x9f);
- }
- if (offset < 0xe0)
- {
- return m_k052539->k051649_test_r();
- }
- return 0xff;
- }
- else if ( m_sccplus_active && offset >= 0xb800 && offset < 0xbfe0)
- {
- offset &= 0xff;
-
- if (offset < 0xa0)
- {
- return m_k052539->k052539_waveform_r(offset);
- }
- if (offset >= 0xc0 && offset < 0xe0)
- {
- return m_k052539->k051649_test_r();
- }
- return 0xff;
- }
-
- uint8_t *base = m_bank_base[offset >> 13];
-
- if (base != nullptr)
- {
- return base[offset & 0x1fff];
- }
- return 0xff;
-}
-
-
-void msx_cart_konami_sound_device::write_cart(offs_t offset, uint8_t data)
-{
- switch (offset & 0xe000)
- {
- case 0x4000:
- if (m_ram_enabled[0] && m_bank_base[2] != nullptr)
- {
- m_bank_base[2][offset & 0x1fff] = data;
- }
- if ((offset & 0x1800) == 0x1000)
- {
- m_selected_bank[0] = data;
- setup_bank(0);
- }
- break;
-
- case 0x6000:
- if (m_ram_enabled[1] && m_bank_base[3] != nullptr)
- {
- m_bank_base[3][offset & 0x1fff] = data;
- }
- if ((offset & 0x1800) == 0x1000)
- {
- m_selected_bank[1] = data;
- setup_bank(1);
- }
- break;
-
- case 0x8000:
- if (m_ram_enabled[2] && m_bank_base[0] != nullptr)
- {
- m_bank_base[0][offset & 0x1fff] = data;
- }
- switch (offset & 0x1800)
- {
- case 0x1000: // 0x9000-0x97ff
- m_selected_bank[2] = data;
- m_scc_active = ( ( data & 0x3f ) == 0x3f );
- setup_bank(2);
- break;
-
- case 0x1800: // 0x9800-0x9fff
- if ( m_scc_active )
- {
- offset &= 0xff;
-
- if (offset < 0x80)
- {
- m_k052539->k051649_waveform_w(offset, data);
- }
- else if (offset < 0xa0)
- {
- offset &= 0x0f;
- if (offset < 0x0a)
- {
- m_k052539->k051649_frequency_w(offset, data);
- }
- else if (offset < 0x0f)
- {
- m_k052539->k051649_volume_w(offset - 0xa, data);
- }
- else
- {
- m_k052539->k051649_keyonoff_w(data);
- }
- }
- else if (offset >= 0xe0)
- {
- m_k052539->k051649_test_w(data);
- }
- }
- break;
- }
- break;
-
- case 0xa000:
- if (m_ram_enabled[3] && m_bank_base[1] != nullptr)
- {
- m_bank_base[1][offset & 0x1fff] = data;
- }
- switch (offset & 0x1800)
- {
- // 0xb000-0xb7ff
- case 0x1000:
- m_selected_bank[3] = data;
- setup_bank(3);
- break;
-
- // 0xb800-0xbfff
- case 0x1800:
- if ((offset & 0x7fe) == 0x7fe)
- {
- // 0xbffe-0xbfff
- /* write to mode register */
- m_scc_mode = data;
-
- m_ram_enabled[0] = ((m_scc_mode & 0x10) || (m_scc_mode & 0x01));
- m_ram_enabled[1] = ((m_scc_mode & 0x10) || (m_scc_mode & 0x02));
- m_ram_enabled[2] = ((m_scc_mode & 0x10) || ((m_scc_mode & 0x04) && (m_scc_mode & 0x20)));
- m_ram_enabled[3] = (m_scc_mode & 0x10);
-
- m_scc_active = ((m_selected_bank[2] & 0x3f) == 0x3f) && !(m_scc_mode & 0x20);
- m_sccplus_active = (m_selected_bank[3] & 0x80) && (m_scc_mode & 0x20);
- }
- else
- {
- if (m_sccplus_active)
- {
- offset &= 0xff;
- if (offset < 0xa0)
- {
- m_k052539->k052539_waveform_w(offset, data);
- }
- else if (offset < 0xc0)
- {
- offset &= 0x0f;
- if (offset < 0x0a)
- {
- m_k052539->k051649_frequency_w(offset, data);
- }
- else if (offset < 0x0f)
- {
- m_k052539->k051649_volume_w(offset - 0x0a, data);
- }
- else if (offset == 0x0f)
- {
- m_k052539->k051649_keyonoff_w(data);
- }
- }
- else if (offset < 0xe0)
- {
- m_k052539->k051649_test_w(data);
- }
- }
- }
- break;
- }
- break;
- }
-}
-
-
-msx_cart_konami_sound_snatcher_device::msx_cart_konami_sound_snatcher_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : msx_cart_konami_sound_device(mconfig, MSX_CART_SOUND_SNATCHER, tag, owner, clock)
-{
-}
-
-
-void msx_cart_konami_sound_snatcher_device::initialize_cartridge()
-{
- msx_cart_konami_sound_device::initialize_cartridge();
-
- if (get_ram_size() != 0x10000)
- {
- fatalerror("sound_snatcher: Invalid RAM size\n");
- }
-
- // The Snatcher Sound cartridge has 64KB RAM available by selecting ram banks 0-7
-
- for (int i = 0; i < 8; i++)
- {
- m_ram_bank[i] = get_ram_base() + i * 0x2000;
- }
-}
-
-
-msx_cart_konami_sound_sdsnatcher_device::msx_cart_konami_sound_sdsnatcher_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : msx_cart_konami_sound_device(mconfig, MSX_CART_SOUND_SDSNATCHER, tag, owner, clock)
-{
-}
-
-
-void msx_cart_konami_sound_sdsnatcher_device::initialize_cartridge()
-{
- msx_cart_konami_sound_device::initialize_cartridge();
-
- if (get_ram_size() != 0x10000)
- {
- fatalerror("sound_sdsnatcher: Invalid RAM size\n");
- }
-
- // The SD Snatcher Sound cartrdige has 64KB RAM available by selecting ram banks 8-15
-
- for (int i = 0; i < 8; i++)
- {
- m_ram_bank[8+i] = get_ram_base() + i * 0x2000;
- }
-
-}
-
-
-
-msx_cart_keyboard_master_device::msx_cart_keyboard_master_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, MSX_CART_KEYBOARD_MASTER, tag, owner, clock)
- , msx_cart_interface(mconfig, *this)
- , m_vlm5030(*this, "vlm5030")
-{
-}
-
-
-void msx_cart_keyboard_master_device::vlm_map(address_map &map)
-{
- map(0x0000, 0xffff).r(FUNC(msx_cart_keyboard_master_device::read_vlm));
-}
-
-
-void msx_cart_keyboard_master_device::device_add_mconfig(machine_config &config)
-{
- // This is actually incorrect. The sound output is passed back into the MSX machine where it is mixed internally and output through the system 'speaker'.
- SPEAKER(config, "mono").front_center();
- VLM5030(config, m_vlm5030, XTAL(3'579'545));
- m_vlm5030->add_route(ALL_OUTPUTS, "mono", 0.40);
- m_vlm5030->set_addrmap(0, &msx_cart_keyboard_master_device::vlm_map);
-}
-
-
-void msx_cart_keyboard_master_device::device_start()
-{
- // Install IO read/write handlers
- io_space().install_write_handler(0x00, 0x00, write8smo_delegate(*m_vlm5030, FUNC(vlm5030_device::data_w)));
- io_space().install_write_handler(0x20, 0x20, write8smo_delegate(*this, FUNC(msx_cart_keyboard_master_device::io_20_w)));
- io_space().install_read_handler(0x00, 0x00, read8smo_delegate(*this, FUNC(msx_cart_keyboard_master_device::io_00_r)));
-}
-
-
-void msx_cart_keyboard_master_device::initialize_cartridge()
-{
- if (get_rom_size() != 0x4000)
- {
- fatalerror("keyboard_master: Invalid ROM size\n");
- }
-}
-
-
-uint8_t msx_cart_keyboard_master_device::read_cart(offs_t offset)
-{
- if (offset >= 0x4000 && offset < 0x8000)
- {
- return m_rom[offset & 0x3fff];
- }
- return 0xff;
-}
-
-
-uint8_t msx_cart_keyboard_master_device::read_vlm(offs_t offset)
-{
- return m_rom_vlm5030[offset];
-}
-
-
-void msx_cart_keyboard_master_device::io_20_w(uint8_t data)
-{
- m_vlm5030->rst((data & 0x01) ? 1 : 0);
- m_vlm5030->vcu((data & 0x04) ? 1 : 0);
- m_vlm5030->st((data & 0x02) ? 1 : 0);
-}
-
-
-uint8_t msx_cart_keyboard_master_device::io_00_r()
-{
- return m_vlm5030->bsy() ? 0x10 : 0x00;
-}
diff --git a/src/devices/bus/msx_cart/konami.h b/src/devices/bus/msx_cart/konami.h
deleted file mode 100644
index 58ad4f3cfb7..00000000000
--- a/src/devices/bus/msx_cart/konami.h
+++ /dev/null
@@ -1,207 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Wilbert Pol
-#ifndef MAME_BUS_MSX_CART_KONAMI_H
-#define MAME_BUS_MSX_CART_KONAMI_H
-
-#include "bus/msx_cart/cartridge.h"
-#include "sound/k051649.h"
-#include "sound/vlm5030.h"
-#include "sound/dac.h"
-
-
-DECLARE_DEVICE_TYPE(MSX_CART_KONAMI, msx_cart_konami_device)
-DECLARE_DEVICE_TYPE(MSX_CART_KONAMI_SCC, msx_cart_konami_scc_device)
-DECLARE_DEVICE_TYPE(MSX_CART_GAMEMASTER2, msx_cart_gamemaster2_device)
-DECLARE_DEVICE_TYPE(MSX_CART_SYNTHESIZER, msx_cart_synthesizer_device)
-DECLARE_DEVICE_TYPE(MSX_CART_SOUND_SNATCHER, msx_cart_konami_sound_snatcher_device)
-DECLARE_DEVICE_TYPE(MSX_CART_SOUND_SDSNATCHER, msx_cart_konami_sound_sdsnatcher_device)
-DECLARE_DEVICE_TYPE(MSX_CART_KEYBOARD_MASTER, msx_cart_keyboard_master_device)
-
-
-class msx_cart_konami_device : public device_t, public msx_cart_interface
-{
-public:
- msx_cart_konami_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void initialize_cartridge() override;
-
- virtual uint8_t read_cart(offs_t offset) override;
- virtual void write_cart(offs_t offset, uint8_t data) override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_post_load() override;
-
- void restore_banks();
-
-private:
- uint8_t m_bank_mask;
- uint8_t m_selected_bank[4];
- uint8_t *m_bank_base[8];
-};
-
-
-class msx_cart_konami_scc_device : public device_t, public msx_cart_interface
-{
-public:
- msx_cart_konami_scc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void initialize_cartridge() override;
-
- virtual uint8_t read_cart(offs_t offset) override;
- virtual void write_cart(offs_t offset, uint8_t data) override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_post_load() override;
-
- virtual void device_add_mconfig(machine_config &config) override;
-
- void restore_banks();
-
-private:
- required_device<k051649_device> m_k051649;
-
- uint8_t m_bank_mask;
- uint8_t m_selected_bank[4];
- uint8_t *m_bank_base[8];
- bool m_scc_active;
-};
-
-
-class msx_cart_gamemaster2_device : public device_t, public msx_cart_interface
-{
-public:
- msx_cart_gamemaster2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void initialize_cartridge() override;
-
- virtual uint8_t read_cart(offs_t offset) override;
- virtual void write_cart(offs_t offset, uint8_t data) override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_post_load() override;
-
- void restore_banks();
-
-private:
- uint8_t m_selected_bank[3];
- uint8_t *m_bank_base[8];
-
- void setup_bank(uint8_t bank);
-};
-
-
-class msx_cart_synthesizer_device : public device_t, public msx_cart_interface
-{
-public:
- msx_cart_synthesizer_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void initialize_cartridge() override;
-
- virtual uint8_t read_cart(offs_t offset) override;
- virtual void write_cart(offs_t offset, uint8_t data) override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
-
- virtual void device_add_mconfig(machine_config &config) override;
-
-private:
- uint8_t *m_bank_base;
- required_device<dac_byte_interface> m_dac;
-};
-
-
-class msx_cart_konami_sound_device : public device_t, public msx_cart_interface
-{
-public:
- virtual void initialize_cartridge() override;
-
- virtual uint8_t read_cart(offs_t offset) override;
- virtual void write_cart(offs_t offset, uint8_t data) override;
-
-protected:
- msx_cart_konami_sound_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
-
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_post_load() override;
-
- virtual void device_add_mconfig(machine_config &config) override;
-
- void restore_banks();
-
- uint8_t *m_ram_bank[16];
-
-private:
- // This is actually a K052539
- required_device<k051649_device> m_k052539;
-
- uint8_t m_selected_bank[4];
- uint8_t *m_bank_base[8];
- bool m_scc_active;
- bool m_sccplus_active;
- bool m_ram_enabled[4];
- uint8_t m_scc_mode;
-
- void setup_bank(uint8_t bank);
-};
-
-
-class msx_cart_konami_sound_snatcher_device : public msx_cart_konami_sound_device
-{
-public:
- msx_cart_konami_sound_snatcher_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void initialize_cartridge() override;
-};
-
-
-class msx_cart_konami_sound_sdsnatcher_device : public msx_cart_konami_sound_device
-{
-public:
- msx_cart_konami_sound_sdsnatcher_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void initialize_cartridge() override;
-};
-
-
-
-class msx_cart_keyboard_master_device : public device_t, public msx_cart_interface
-{
-public:
- msx_cart_keyboard_master_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- // device-level overrides
- virtual void device_start() override;
-
- virtual void device_add_mconfig(machine_config &config) override;
-
- virtual void initialize_cartridge() override;
-
- virtual uint8_t read_cart(offs_t offset) override;
-
-private:
- required_device<vlm5030_device> m_vlm5030;
-
- uint8_t read_vlm(offs_t offset);
- void io_20_w(uint8_t data);
- uint8_t io_00_r();
-
- void vlm_map(address_map &map);
-};
-
-
-
-#endif // MAME_BUS_MSX_CART_KONAMI_H
diff --git a/src/devices/bus/msx_cart/korean.cpp b/src/devices/bus/msx_cart/korean.cpp
deleted file mode 100644
index e12f15bd43d..00000000000
--- a/src/devices/bus/msx_cart/korean.cpp
+++ /dev/null
@@ -1,300 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Wilbert Pol
-#include "emu.h"
-#include "korean.h"
-
-DEFINE_DEVICE_TYPE(MSX_CART_KOREAN_80IN1, msx_cart_korean_80in1_device, "msx_cart_korean_80in1", "MSX Cartridge - Korean 80-in-1")
-DEFINE_DEVICE_TYPE(MSX_CART_KOREAN_90IN1, msx_cart_korean_90in1_device, "msx_cart_korean_90in1", "MSX Cartridge - Korean 90-in-1")
-DEFINE_DEVICE_TYPE(MSX_CART_KOREAN_126IN1, msx_cart_korean_126in1_device, "msx_cart_korean_126in1", "MSX Cartridge - Korean 126-in-1")
-
-
-msx_cart_korean_80in1_device::msx_cart_korean_80in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, MSX_CART_KOREAN_80IN1, tag, owner, clock)
- , msx_cart_interface(mconfig, *this)
- , m_bank_mask(0)
- , m_selected_bank{ 0, 1, 2, 3 }
- , m_bank_base{ nullptr, nullptr, nullptr, nullptr }
-{
-}
-
-
-void msx_cart_korean_80in1_device::device_start()
-{
- save_item(NAME(m_selected_bank));
-}
-
-
-void msx_cart_korean_80in1_device::device_post_load()
-{
- restore_banks();
-}
-
-
-void msx_cart_korean_80in1_device::setup_bank(uint8_t bank)
-{
- m_bank_base[bank] = get_rom_base() + ( m_selected_bank[bank] & m_bank_mask ) * 0x2000;
-}
-
-
-void msx_cart_korean_80in1_device::restore_banks()
-{
- for (int i = 0; i < 4; i++)
- {
- setup_bank(i);
- }
-}
-
-
-void msx_cart_korean_80in1_device::device_reset()
-{
- for (int i = 0; i < 4; i++)
- {
- m_selected_bank[i] = i;
- }
-}
-
-
-void msx_cart_korean_80in1_device::initialize_cartridge()
-{
- uint32_t size = get_rom_size();
-
- if ( size > 256 * 0x2000 )
- {
- fatalerror("korean_80in1: ROM is too big\n");
- }
-
- uint16_t banks = size / 0x2000;
-
- if (size != banks * 0x2000 || (~(banks - 1) % banks))
- {
- fatalerror("korean_80in1: Invalid ROM size\n");
- }
-
- m_bank_mask = banks - 1;
-
- restore_banks();
-}
-
-
-uint8_t msx_cart_korean_80in1_device::read_cart(offs_t offset)
-{
- if (offset >= 0x4000 && offset < 0xc000)
- {
- return m_bank_base[(offset - 0x4000) >> 13][offset & 0x1fff];
- }
-
- return 0xff;
-}
-
-
-void msx_cart_korean_80in1_device::write_cart(offs_t offset, uint8_t data)
-{
- if (offset >= 0x4000 && offset < 0x4004)
- {
- uint8_t bank = offset & 3;
-
- m_selected_bank[bank] = data;
- setup_bank(bank);
- }
-}
-
-
-
-
-
-msx_cart_korean_90in1_device::msx_cart_korean_90in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, MSX_CART_KOREAN_90IN1, tag, owner, clock)
- , msx_cart_interface(mconfig, *this)
- , m_bank_mask(0)
- , m_selected_bank(0)
- , m_bank_base{ nullptr, nullptr, nullptr, nullptr }
-{
-}
-
-
-void msx_cart_korean_90in1_device::device_start()
-{
- save_item(NAME(m_selected_bank));
-
- // Install IO read/write handlers
- io_space().install_write_handler(0x77, 0x77, write8smo_delegate(*this, FUNC(msx_cart_korean_90in1_device::banking)));
-}
-
-
-void msx_cart_korean_90in1_device::device_post_load()
-{
- restore_banks();
-}
-
-
-void msx_cart_korean_90in1_device::restore_banks()
-{
- uint8_t *base = get_rom_base();
-
- switch (m_selected_bank & 0xc0)
- {
- case 0x80:
- base += (m_selected_bank & 0x3e & m_bank_mask) * 0x4000;
- m_bank_base[0] = base;
- m_bank_base[1] = base + 0x2000;
- m_bank_base[2] = base + 0x4000;
- m_bank_base[3] = base + 0x6000;
- break;
-
- case 0xc0:
- base += (m_selected_bank & m_bank_mask) * 0x4000;
- m_bank_base[0] = base;
- m_bank_base[1] = base + 0x2000;
- m_bank_base[2] = base + 0x2000;
- m_bank_base[3] = base;
- break;
-
- default:
- base += (m_selected_bank & m_bank_mask) * 0x4000;
- m_bank_base[0] = base;
- m_bank_base[1] = base + 0x2000;
- m_bank_base[2] = base;
- m_bank_base[3] = base + 0x2000;
- break;
- }
-}
-
-
-void msx_cart_korean_90in1_device::device_reset()
-{
- m_selected_bank = 0;
-}
-
-
-void msx_cart_korean_90in1_device::initialize_cartridge()
-{
- uint32_t size = get_rom_size();
-
- if ( size > 64 * 0x4000 )
- {
- fatalerror("korean_90in1: ROM is too big\n");
- }
-
- uint16_t banks = size / 0x4000;
-
- if (size != banks * 0x4000 || (~(banks - 1) % banks))
- {
- fatalerror("korean_90in1: Invalid ROM size\n");
- }
-
- m_bank_mask = banks - 1;
-
- restore_banks();
-}
-
-
-uint8_t msx_cart_korean_90in1_device::read_cart(offs_t offset)
-{
- if (offset >= 0x4000 && offset < 0xc000)
- {
- return m_bank_base[(offset - 0x4000) >> 13][offset & 0x1fff];
- }
-
- return 0xff;
-}
-
-
-void msx_cart_korean_90in1_device::banking(uint8_t data)
-{
- m_selected_bank = data;
- restore_banks();
-}
-
-
-
-
-
-msx_cart_korean_126in1_device::msx_cart_korean_126in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, MSX_CART_KOREAN_126IN1, tag, owner, clock)
- , msx_cart_interface(mconfig, *this)
- , m_bank_mask(0)
- , m_selected_bank{ 0, 1 }
- , m_bank_base{ nullptr, nullptr }
-{
-}
-
-
-void msx_cart_korean_126in1_device::device_start()
-{
- save_item(NAME(m_selected_bank));
-}
-
-
-void msx_cart_korean_126in1_device::device_post_load()
-{
- restore_banks();
-}
-
-
-void msx_cart_korean_126in1_device::setup_bank(uint8_t bank)
-{
- m_bank_base[bank] = get_rom_base() + ( m_selected_bank[bank] & m_bank_mask ) * 0x4000;
-}
-
-
-void msx_cart_korean_126in1_device::restore_banks()
-{
- for (int i = 0; i < 2; i++)
- {
- setup_bank(i);
- }
-}
-
-
-void msx_cart_korean_126in1_device::device_reset()
-{
- for (int i = 0; i < 2; i++)
- {
- m_selected_bank[i] = i;
- }
-}
-
-
-void msx_cart_korean_126in1_device::initialize_cartridge()
-{
- uint32_t size = get_rom_size();
-
- if ( size > 256 * 0x4000 )
- {
- fatalerror("korean_126in1: ROM is too big\n");
- }
-
- uint16_t banks = size / 0x4000;
-
- if (size != banks * 0x4000 || (~(banks - 1) % banks))
- {
- fatalerror("korean_126in1: Invalid ROM size\n");
- }
-
- m_bank_mask = banks - 1;
-
- restore_banks();
-}
-
-
-uint8_t msx_cart_korean_126in1_device::read_cart(offs_t offset)
-{
- if (offset >= 0x4000 && offset < 0xc000)
- {
- return m_bank_base[offset >> 15][offset & 0x3fff];
- }
-
- return 0xff;
-}
-
-
-void msx_cart_korean_126in1_device::write_cart(offs_t offset, uint8_t data)
-{
- if (offset >= 0x4000 && offset < 0x4002)
- {
- uint8_t bank = offset & 1;
-
- m_selected_bank[bank] = data;
- setup_bank(bank);
- }
-}
diff --git a/src/devices/bus/msx_cart/korean.h b/src/devices/bus/msx_cart/korean.h
deleted file mode 100644
index 62c5a6ba82b..00000000000
--- a/src/devices/bus/msx_cart/korean.h
+++ /dev/null
@@ -1,94 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Wilbert Pol
-#ifndef MAME_BUS_MSX_CART_KOREAN_H
-#define MAME_BUS_MSX_CART_KOREAN_H
-
-#pragma once
-
-#include "bus/msx_cart/cartridge.h"
-
-
-DECLARE_DEVICE_TYPE(MSX_CART_KOREAN_80IN1, msx_cart_korean_80in1_device)
-DECLARE_DEVICE_TYPE(MSX_CART_KOREAN_90IN1, msx_cart_korean_90in1_device)
-DECLARE_DEVICE_TYPE(MSX_CART_KOREAN_126IN1, msx_cart_korean_126in1_device)
-
-
-class msx_cart_korean_80in1_device : public device_t, public msx_cart_interface
-{
-public:
- msx_cart_korean_80in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void initialize_cartridge() override;
-
- virtual uint8_t read_cart(offs_t offset) override;
- virtual void write_cart(offs_t offset, uint8_t data) override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_post_load() override;
-
-private:
- void restore_banks();
- void setup_bank(uint8_t bank);
-
- uint8_t m_bank_mask;
- uint8_t m_selected_bank[4];
- uint8_t *m_bank_base[4];
-};
-
-
-class msx_cart_korean_90in1_device : public device_t, public msx_cart_interface
-{
-public:
- msx_cart_korean_90in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void initialize_cartridge() override;
-
- virtual uint8_t read_cart(offs_t offset) override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_post_load() override;
-
-private:
- void banking(uint8_t data);
-
- void restore_banks();
-
- uint8_t m_bank_mask;
- uint8_t m_selected_bank;
- uint8_t *m_bank_base[4];
-};
-
-
-class msx_cart_korean_126in1_device : public device_t, public msx_cart_interface
-{
-public:
- msx_cart_korean_126in1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void initialize_cartridge() override;
-
- virtual uint8_t read_cart(offs_t offset) override;
- virtual void write_cart(offs_t offset, uint8_t data) override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_post_load() override;
-
-private:
- void restore_banks();
- void setup_bank(uint8_t bank);
-
- uint8_t m_bank_mask;
- uint8_t m_selected_bank[2];
- uint8_t *m_bank_base[2];
-};
-
-
-#endif // MAME_BUS_MSX_CART_KOREAN_H
diff --git a/src/devices/bus/msx_cart/majutsushi.cpp b/src/devices/bus/msx_cart/majutsushi.cpp
deleted file mode 100644
index c94f5a00dc5..00000000000
--- a/src/devices/bus/msx_cart/majutsushi.cpp
+++ /dev/null
@@ -1,116 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Wilbert Pol
-#include "emu.h"
-#include "majutsushi.h"
-
-#include "speaker.h"
-
-
-DEFINE_DEVICE_TYPE(MSX_CART_MAJUTSUSHI, msx_cart_majutsushi_device, "msx_cart_majutsushi", "MSX Cartridge - Majutsushi")
-
-
-msx_cart_majutsushi_device::msx_cart_majutsushi_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, MSX_CART_MAJUTSUSHI, tag, owner, clock)
- , msx_cart_interface(mconfig, *this)
- , m_dac(*this, "dac")
-{
- for (auto & elem : m_selected_bank)
- {
- elem = 0;
- }
- for (auto & elem : m_bank_base)
- {
- elem = nullptr;
- }
-}
-
-
-void msx_cart_majutsushi_device::device_add_mconfig(machine_config &config)
-{
- // This is actually incorrect. The sound output is passed back into the MSX machine where it is mixed internally and output through the system 'speaker'.
- SPEAKER(config, "speaker").front_center();
- DAC_8BIT_R2R(config, m_dac, 0).add_route(ALL_OUTPUTS, "speaker", 0.05); // unknown DAC
-}
-
-
-void msx_cart_majutsushi_device::device_start()
-{
- save_item(NAME(m_selected_bank));
-}
-
-
-void msx_cart_majutsushi_device::device_post_load()
-{
- restore_banks();
-}
-
-
-void msx_cart_majutsushi_device::restore_banks()
-{
- m_bank_base[0] = get_rom_base() + ( m_selected_bank[0] & 0x0f ) * 0x2000;
- m_bank_base[1] = get_rom_base() + ( m_selected_bank[1] & 0x0f ) * 0x2000;
- m_bank_base[2] = get_rom_base() + ( m_selected_bank[0] & 0x0f ) * 0x2000;
- m_bank_base[3] = get_rom_base() + ( m_selected_bank[1] & 0x0f ) * 0x2000;
- m_bank_base[4] = get_rom_base() + ( m_selected_bank[2] & 0x0f ) * 0x2000;
- m_bank_base[5] = get_rom_base() + ( m_selected_bank[3] & 0x0f ) * 0x2000;
- m_bank_base[6] = get_rom_base() + ( m_selected_bank[2] & 0x0f ) * 0x2000;
- m_bank_base[7] = get_rom_base() + ( m_selected_bank[3] & 0x0f ) * 0x2000;
-}
-
-
-void msx_cart_majutsushi_device::device_reset()
-{
- for (int i = 0; i < 4; i++)
- {
- m_selected_bank[i] = i;
- }
-}
-
-
-void msx_cart_majutsushi_device::initialize_cartridge()
-{
- if ( get_rom_size() != 0x20000 )
- {
- fatalerror("majutsushi: Invalid ROM size\n");
- }
-
- restore_banks();
-}
-
-
-uint8_t msx_cart_majutsushi_device::read_cart(offs_t offset)
-{
- return m_bank_base[offset >> 13][offset & 0x1fff];
-}
-
-
-void msx_cart_majutsushi_device::write_cart(offs_t offset, uint8_t data)
-{
- switch (offset & 0xe000)
- {
- case 0x4000:
- if (offset & 0x1000)
- {
- m_dac->write(data);
- }
- break;
-
- case 0x6000:
- m_selected_bank[1] = data & 0x0f;
- m_bank_base[1] = get_rom_base() + m_selected_bank[1] * 0x2000;
- m_bank_base[3] = get_rom_base() + m_selected_bank[1] * 0x2000;
- break;
-
- case 0x8000:
- m_selected_bank[2] = data & 0x0f;
- m_bank_base[4] = get_rom_base() + m_selected_bank[2] * 0x2000;
- m_bank_base[6] = get_rom_base() + m_selected_bank[2] * 0x2000;
- break;
-
- case 0xa000:
- m_selected_bank[3] = data & 0x0f;
- m_bank_base[5] = get_rom_base() + m_selected_bank[3] * 0x2000;
- m_bank_base[7] = get_rom_base() + m_selected_bank[3] * 0x2000;
- break;
- }
-}
diff --git a/src/devices/bus/msx_cart/majutsushi.h b/src/devices/bus/msx_cart/majutsushi.h
deleted file mode 100644
index ebdf549272e..00000000000
--- a/src/devices/bus/msx_cart/majutsushi.h
+++ /dev/null
@@ -1,43 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Wilbert Pol
-#ifndef MAME_BUS_MSX_CART_MAJUTSUSHI_H
-#define MAME_BUS_MSX_CART_MAJUTSUSHI_H
-
-#pragma once
-
-#include "bus/msx_cart/cartridge.h"
-#include "sound/dac.h"
-
-
-DECLARE_DEVICE_TYPE(MSX_CART_MAJUTSUSHI, msx_cart_majutsushi_device)
-
-
-class msx_cart_majutsushi_device : public device_t, public msx_cart_interface
-{
-public:
- msx_cart_majutsushi_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void initialize_cartridge() override;
-
- virtual uint8_t read_cart(offs_t offset) override;
- virtual void write_cart(offs_t offset, uint8_t data) override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_post_load() override;
-
- virtual void device_add_mconfig(machine_config &config) override;
-
- void restore_banks();
-
-private:
- required_device<dac_byte_interface> m_dac;
-
- uint8_t m_selected_bank[4];
- uint8_t *m_bank_base[8];
-};
-
-
-#endif // MAME_BUS_MSX_CART_MAJUTSUSHI_H
diff --git a/src/devices/bus/msx_cart/moonsound.h b/src/devices/bus/msx_cart/moonsound.h
deleted file mode 100644
index 62f614ae729..00000000000
--- a/src/devices/bus/msx_cart/moonsound.h
+++ /dev/null
@@ -1,42 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Wilbert Pol
-#ifndef MAME_BUS_MSX_CART_MOONSOUND_H
-#define MAME_BUS_MSX_CART_MOONSOUND_H
-
-#pragma once
-
-#include "bus/msx_cart/cartridge.h"
-#include "sound/ymopl.h"
-
-
-DECLARE_DEVICE_TYPE(MSX_CART_MOONSOUND, msx_cart_moonsound_device)
-
-
-class msx_cart_moonsound_device : public device_t, public msx_cart_interface
-{
-public:
- msx_cart_moonsound_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
-
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
-
-private:
- DECLARE_WRITE_LINE_MEMBER(irq_w);
- void write_ymf278b_fm(offs_t offset, uint8_t data);
- uint8_t read_ymf278b_fm(offs_t offset);
- void write_ymf278b_pcm(offs_t offset, uint8_t data);
- uint8_t read_ymf278b_pcm(offs_t offset);
- uint8_t read_c0();
-
- void ymf278b_map(address_map &map);
-
- required_device<ymf278b_device> m_ymf278b;
-};
-
-
-#endif // MAME_BUS_MSX_CART_MOONSOUND_H
diff --git a/src/devices/bus/msx_cart/msx_audio.cpp b/src/devices/bus/msx_cart/msx_audio.cpp
deleted file mode 100644
index 3f8fd1fd772..00000000000
--- a/src/devices/bus/msx_cart/msx_audio.cpp
+++ /dev/null
@@ -1,379 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Wilbert Pol
-/**********************************************************************************
-
-Emulation of the different MSX-AUDIO devices:
-
-- Panasonic FS-CA1
- - Y8950
- - 4KB ram
- - Connector for Toshiba HX-MU901 keyboard
-
-- Toshiba HX-MU900
- - Y8950
- - No midi ports
- - No ram
- - Connector for Toshiba HX-MU901 keyboard
-
-- Philips NMS-1205
- - Y8950
- - Midi ports
- - 32KB sample ram
- - Connector for Philips NMS-1160 keyboard
-
-
-The keyboards:
-- Toshiba HX-MU901
- - 49 keys: 4 full octaves + high C
- - ENTER key
- - SELECT key
- - multi sensor (?)
-
-- Philips NMS-1160
- - 61 keys: 5 full octaves + high C
- - Different wiring, so incompatible with the other keyboards
-
-- Panasonic YK-20
- - 49 keys: 4 full octaves + high C
-
-
-TODO:
-- Test MIDI in/out/through
-- Sample RAM, doesn't seem to get written to
-- Test NMS-1160 keyboard
-- HX-MU901: ENTER/SELECT keys and multi sensors
-- NMS1160: Test the keyboard
-- NMS1205: Add DAC
-- NMS1205/FSCA1: Add muting of dac and y8950 based on io config writes.
-
-
-For testing the sample ram (playback of a cuckoo sound, the volume of the sound is quite low):
-- Disable firmware on the fs-ca1
-- Execute the following basic commands:
- - CALL AUDIO
- - CALL COPY PCM(#1,0)
- - CALL PLAY PCM(0)
-
-See also http://www.mccm.hetlab.tk/millennium/milc/gc/topic_26.htm (dutch)
-and/or http://ngs.no.coocan.jp/doc/wiki.cgi/datapack?page=4.2+MSX-AUDIO+%B3%C8%C4%A5BASIC (japanese)
-
-
-**********************************************************************************/
-
-#include "emu.h"
-#include "msx_audio.h"
-#include "bus/msx_cart/msx_audio_kb.h"
-
-#include "speaker.h"
-
-
-DEFINE_DEVICE_TYPE(MSX_CART_MSX_AUDIO_HXMU900, msx_cart_msx_audio_hxmu900_device, "msx_audio_hxmu900", "MSX Cartridge - MSX-AUDIO HX-MU900")
-DEFINE_DEVICE_TYPE(MSX_CART_MSX_AUDIO_NMS1205, msx_cart_msx_audio_nms1205_device, "msx_audio_nms1205", "MSX Cartridge - MSX-AUDIO NMS-1205")
-DEFINE_DEVICE_TYPE(MSX_CART_MSX_AUDIO_FSCA1, msx_cart_msx_audio_fsca1_device, "msx_audio_fsca1", "MSX Cartridge - MSX-AUDIO FS-CA1")
-
-
-msx_cart_msx_audio_hxmu900_device::msx_cart_msx_audio_hxmu900_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, MSX_CART_MSX_AUDIO_HXMU900, tag, owner, clock)
- , msx_cart_interface(mconfig, *this)
- , m_y8950(*this, "y8950")
-{
-}
-
-
-void msx_cart_msx_audio_hxmu900_device::device_add_mconfig(machine_config &config)
-{
- // This is actually incorrect. The sound output is passed back into the MSX machine where it is mixed internally and output through the system 'speaker'.
- SPEAKER(config, "mono").front_center();
- Y8950(config, m_y8950, XTAL(3'579'545)); // Not verified
- m_y8950->add_route(ALL_OUTPUTS, "mono", 0.40);
- m_y8950->keyboard_write().set("kbdc", FUNC(msx_audio_kbdc_port_device::write));
- m_y8950->keyboard_read().set("kbdc", FUNC(msx_audio_kbdc_port_device::read));
-
- MSX_AUDIO_KBDC_PORT(config, "kbdc", msx_audio_keyboards, nullptr);
-}
-
-
-void msx_cart_msx_audio_hxmu900_device::device_start()
-{
- // Install IO read/write handlers
- io_space().install_write_handler(0xc0, 0xc1, write8sm_delegate(*m_y8950, FUNC(y8950_device::write)));
- io_space().install_read_handler(0xc0, 0xc1, read8sm_delegate(*m_y8950, FUNC(y8950_device::read)));
-}
-
-
-void msx_cart_msx_audio_hxmu900_device::initialize_cartridge()
-{
- if (get_rom_size() < 0x8000)
- {
- fatalerror("msx_audio: Invalid ROM size\n");
- }
-}
-
-
-uint8_t msx_cart_msx_audio_hxmu900_device::read_cart(offs_t offset)
-{
- if (offset >= 0x4000 && offset < 0xC000)
- {
- return m_rom[offset - 0x4000];
- }
- return 0xff;
-}
-
-
-ROM_START( msx_hxmu )
- ROM_REGION(0x8000, "y8950", ROMREGION_ERASE00)
-ROM_END
-
-
-const tiny_rom_entry *msx_cart_msx_audio_hxmu900_device::device_rom_region() const
-{
- return ROM_NAME( msx_hxmu );
-}
-
-
-
-
-
-msx_cart_msx_audio_nms1205_device::msx_cart_msx_audio_nms1205_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, MSX_CART_MSX_AUDIO_NMS1205, tag, owner, clock)
- , msx_cart_interface(mconfig, *this)
- , m_y8950(*this, "y8950")
- , m_acia6850(*this, "acia6850")
- , m_mdout(*this, "mdout")
- , m_mdthru(*this, "mdthru")
-{
-}
-
-
-void msx_cart_msx_audio_nms1205_device::device_add_mconfig(machine_config &config)
-{
- // This is actually incorrect. The sound output is passed back into the MSX machine where it is mixed internally and output through the system 'speaker'.
- // At the same time the sound is also output on two output on the nms1205 cartridge itself
- SPEAKER(config, "mono").front_center();
- Y8950(config, m_y8950, XTAL(3'579'545));
- m_y8950->add_route(ALL_OUTPUTS, "mono", 0.40);
- m_y8950->keyboard_write().set("kbdc", FUNC(msx_audio_kbdc_port_device::write));
- m_y8950->keyboard_read().set("kbdc", FUNC(msx_audio_kbdc_port_device::read));
- m_y8950->irq_handler().set(FUNC(msx_cart_msx_audio_nms1205_device::irq_write));
-
- MSX_AUDIO_KBDC_PORT(config, "kbdc", msx_audio_keyboards, nullptr);
-
- // There is a 2 MHz crystal on the PCB, the 6850 TX and RX clocks are derived from it
- ACIA6850(config, m_acia6850, 0);
- m_acia6850->txd_handler().set("mdout", FUNC(midi_port_device::write_txd));
-
- MIDI_PORT(config, "mdin", midiin_slot, "midiin").rxd_handler().set(FUNC(msx_cart_msx_audio_nms1205_device::midi_in));
- MIDI_PORT(config, m_mdthru, midiout_slot, "midiout");
- MIDI_PORT(config, m_mdout, midiout_slot, "midiout");
-}
-
-
-ROM_START( msx_nms1205 )
- ROM_REGION(0x8000, "y8950", ROMREGION_ERASE00)
-ROM_END
-
-
-const tiny_rom_entry *msx_cart_msx_audio_nms1205_device::device_rom_region() const
-{
- return ROM_NAME( msx_nms1205 );
-}
-
-
-WRITE_LINE_MEMBER(msx_cart_msx_audio_nms1205_device::irq_write)
-{
- // Trigger IRQ on the maincpu
- // The 8950 seems to trigger an irq on reset, this causes an infinite loop of continuously triggering
- // the MSX's interrupt handler. The 8950 irq will never be cleared the nms1205's irq handler hook hasn't
- // been installed yet.
-// m_out_irq_cb(state);
-}
-
-
-WRITE_LINE_MEMBER(msx_cart_msx_audio_nms1205_device::midi_in)
-{
- // MIDI in signals is sent to both the 6850 and the MIDI thru output port
- m_acia6850->write_rxd(state);
- m_mdthru->write_txd(state);
-}
-
-
-void msx_cart_msx_audio_nms1205_device::device_start()
-{
- // Install IO read/write handlers
- io_space().install_write_handler(0xc0, 0xc1, write8sm_delegate(*m_y8950, FUNC(y8950_device::write)));
- io_space().install_read_handler(0xc0, 0xc1, read8sm_delegate(*m_y8950, FUNC(y8950_device::read)));
- io_space().install_write_handler(0x00, 0x01, write8sm_delegate(*m_acia6850, FUNC(acia6850_device::write)));
- io_space().install_read_handler(0x04, 0x05, read8sm_delegate(*m_acia6850, FUNC(acia6850_device::read)));
-}
-
-
-void msx_cart_msx_audio_nms1205_device::initialize_cartridge()
-{
- if (get_rom_size() < 0x8000)
- {
- fatalerror("msx_audio: Invalid ROM size\n");
- }
-}
-
-
-uint8_t msx_cart_msx_audio_nms1205_device::read_cart(offs_t offset)
-{
- if (offset >= 0x4000 && offset < 0xC000)
- {
- return m_rom[offset - 0x4000];
- }
- return 0xff;
-}
-
-
-
-
-
-
-
-msx_cart_msx_audio_fsca1_device::msx_cart_msx_audio_fsca1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, MSX_CART_MSX_AUDIO_FSCA1, tag, owner, clock)
- , msx_cart_interface(mconfig, *this)
- , m_y8950(*this, "y8950")
- , m_io_config(*this, "CONFIG")
- , m_region_y8950(*this, "y8950")
- , m_7ffe(0)
- , m_7fff(0)
-{
-}
-
-
-void msx_cart_msx_audio_fsca1_device::device_add_mconfig(machine_config &config)
-{
- // This is actually incorrect. The sound output is passed back into the MSX machine where it is mixed internally and output through the system 'speaker'.
- SPEAKER(config, "mono").front_center();
- Y8950(config, m_y8950, XTAL(3'579'545));
- m_y8950->add_route(ALL_OUTPUTS, "mono", 0.40);
- m_y8950->keyboard_write().set("kbdc", FUNC(msx_audio_kbdc_port_device::write));
- m_y8950->keyboard_read().set("kbdc", FUNC(msx_audio_kbdc_port_device::read));
- m_y8950->io_read().set(FUNC(msx_cart_msx_audio_fsca1_device::y8950_io_r));
- m_y8950->io_write().set(FUNC(msx_cart_msx_audio_fsca1_device::y8950_io_w));
-
- MSX_AUDIO_KBDC_PORT(config, "kbdc", msx_audio_keyboards, nullptr);
-}
-
-
-static INPUT_PORTS_START( msx_audio_fsca1 )
- PORT_START("CONFIG")
- PORT_CONFNAME( 0x04, 0x04, "FS-CA1 Firmware switch")
- PORT_CONFSETTING( 0x04, "On" )
- PORT_CONFSETTING( 0x00, "Off" )
- PORT_BIT(0xFB, IP_ACTIVE_HIGH, IPT_UNKNOWN)
-INPUT_PORTS_END
-
-
-ioport_constructor msx_cart_msx_audio_fsca1_device::device_input_ports() const
-{
- return INPUT_PORTS_NAME( msx_audio_fsca1 );
-}
-
-
-ROM_START( msx_fsca1 )
- ROM_REGION(0x8000, "y8950", ROMREGION_ERASE00)
-ROM_END
-
-
-const tiny_rom_entry *msx_cart_msx_audio_fsca1_device::device_rom_region() const
-{
- return ROM_NAME( msx_fsca1 );
-}
-
-
-void msx_cart_msx_audio_fsca1_device::device_start()
-{
- // Install IO read/write handlers
- io_space().install_write_handler(0xc0, 0xc3, write8sm_delegate(*this, FUNC(msx_cart_msx_audio_fsca1_device::write_y8950)));
- io_space().install_read_handler(0xc0, 0xc3, read8sm_delegate(*this, FUNC(msx_cart_msx_audio_fsca1_device::read_y8950)));
-}
-
-
-void msx_cart_msx_audio_fsca1_device::initialize_cartridge()
-{
- if (get_rom_size() < 0x20000)
- {
- fatalerror("msx_audio_fsca1: Invalid ROM size\n");
- }
-}
-
-
-uint8_t msx_cart_msx_audio_fsca1_device::read_cart(offs_t offset)
-{
- if (m_7ffe == 0 && (offset & 0xB000) == 0x3000)
- {
- return m_sram[offset & 0xfff];
- }
- return m_rom[((m_7ffe & 0x03) << 15) | (offset & 0x7fff)];
-}
-
-
-void msx_cart_msx_audio_fsca1_device::write_cart(offs_t offset, uint8_t data)
-{
- if (offset == 0x7ffe)
- {
- m_7ffe = data;
- return;
- }
-
- if (offset == 0x7fff)
- {
- m_7fff = data;
- return;
- }
-
- if (m_7ffe == 0 && (offset & 0xb000) == 0x3000)
- {
- m_sram[offset & 0xfff] = data;
- return;
- }
-
- logerror("msx_cart_msx_audio_fsca1_device: Unhandled write %02x to %04x\n", data, offset);
-}
-
-
-void msx_cart_msx_audio_fsca1_device::write_y8950(offs_t offset, uint8_t data)
-{
- if (offset & 2)
- {
- if (m_7fff & 0x02)
- {
- m_y8950->write(offset, data);
- }
- }
- else
- {
- if (m_7fff & 0x01)
- {
- m_y8950->write(offset, data);
- }
- }
-}
-
-
-uint8_t msx_cart_msx_audio_fsca1_device::read_y8950(offs_t offset)
-{
- if (offset & 2)
- {
- return (m_7fff & 0x02) ? m_y8950->read(offset) : 0xff;
- }
- else
- {
- return (m_7fff & 0x01) ? m_y8950->read(offset) : 0xff;
- }
-}
-
-
-void msx_cart_msx_audio_fsca1_device::y8950_io_w(uint8_t data)
-{
- logerror("msx_fsca1::y8950_io_w: %02x\n", data);
-}
-
-
-uint8_t msx_cart_msx_audio_fsca1_device::y8950_io_r()
-{
- return m_io_config->read();
-}
diff --git a/src/devices/bus/msx_cart/msx_audio.h b/src/devices/bus/msx_cart/msx_audio.h
deleted file mode 100644
index 490169244af..00000000000
--- a/src/devices/bus/msx_cart/msx_audio.h
+++ /dev/null
@@ -1,99 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Wilbert Pol
-#ifndef MAME_BUS_MSX_CART_MSX_AUDIO_H
-#define MAME_BUS_MSX_CART_MSX_AUDIO_H
-
-#pragma once
-
-#include "bus/msx_cart/cartridge.h"
-#include "sound/ymopl.h"
-#include "machine/6850acia.h"
-#include "bus/midi/midi.h"
-
-
-DECLARE_DEVICE_TYPE(MSX_CART_MSX_AUDIO_HXMU900, msx_cart_msx_audio_hxmu900_device)
-DECLARE_DEVICE_TYPE(MSX_CART_MSX_AUDIO_NMS1205, msx_cart_msx_audio_nms1205_device)
-DECLARE_DEVICE_TYPE(MSX_CART_MSX_AUDIO_FSCA1, msx_cart_msx_audio_fsca1_device)
-
-
-class msx_cart_msx_audio_hxmu900_device : public device_t, public msx_cart_interface
-{
-public:
- msx_cart_msx_audio_hxmu900_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void initialize_cartridge() override;
-
- virtual uint8_t read_cart(offs_t offset) override;
-
-protected:
- virtual void device_start() override;
-
- // device-level overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
-
-private:
- required_device<y8950_device> m_y8950;
-};
-
-
-class msx_cart_msx_audio_nms1205_device : public device_t, public msx_cart_interface
-{
-public:
- msx_cart_msx_audio_nms1205_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void initialize_cartridge() override;
-
- virtual uint8_t read_cart(offs_t offset) override;
-
-protected:
- virtual void device_start() override;
-
- // device-level overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
-
-private:
- DECLARE_WRITE_LINE_MEMBER(midi_in);
- DECLARE_WRITE_LINE_MEMBER(irq_write);
-
- required_device<y8950_device> m_y8950;
- required_device<acia6850_device> m_acia6850;
- required_device<midi_port_device> m_mdout;
- required_device<midi_port_device> m_mdthru;
-};
-
-
-class msx_cart_msx_audio_fsca1_device : public device_t, public msx_cart_interface
-{
-public:
- msx_cart_msx_audio_fsca1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void initialize_cartridge() override;
-
- virtual uint8_t read_cart(offs_t offset) override;
- virtual void write_cart(offs_t offset, uint8_t data) override;
-
-protected:
- virtual void device_start() override;
-
- // device-level overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual ioport_constructor device_input_ports() const override;
- virtual const tiny_rom_entry *device_rom_region() const override;
-
-private:
- void write_y8950(offs_t offset, uint8_t data);
- uint8_t read_y8950(offs_t offset);
-
- void y8950_io_w(uint8_t data);
- uint8_t y8950_io_r();
-
- required_device<y8950_device> m_y8950;
- required_ioport m_io_config;
- required_memory_region m_region_y8950;
- uint8_t m_7ffe;
- uint8_t m_7fff;
-};
-
-#endif // MAME_BUS_MSX_CART_MSX_AUDIO_H
diff --git a/src/devices/bus/msx_cart/msxdos2.cpp b/src/devices/bus/msx_cart/msxdos2.cpp
deleted file mode 100644
index 7f3e506b007..00000000000
--- a/src/devices/bus/msx_cart/msxdos2.cpp
+++ /dev/null
@@ -1,71 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Wilbert Pol
-#include "emu.h"
-#include "msxdos2.h"
-
-DEFINE_DEVICE_TYPE(MSX_CART_MSXDOS2, msx_cart_msxdos2_device, "msx_cart_msxdos2", "MSX Cartridge - MSXDOS2")
-
-
-msx_cart_msxdos2_device::msx_cart_msxdos2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, MSX_CART_MSXDOS2, tag, owner, clock)
- , msx_cart_interface(mconfig, *this)
- , m_selected_bank(0)
- , m_bank_base(nullptr)
-{
-}
-
-
-void msx_cart_msxdos2_device::device_start()
-{
- save_item(NAME(m_selected_bank));
-}
-
-
-void msx_cart_msxdos2_device::device_post_load()
-{
- restore_banks();
-}
-
-
-void msx_cart_msxdos2_device::restore_banks()
-{
- m_bank_base = get_rom_base() + ( m_selected_bank & 0x03 ) * 0x4000;
-}
-
-
-void msx_cart_msxdos2_device::device_reset()
-{
- m_selected_bank = 0;
-}
-
-
-void msx_cart_msxdos2_device::initialize_cartridge()
-{
- if (get_rom_size() != 0x10000)
- {
- fatalerror("msxdos2: Invalid ROM size\n");
- }
-
- restore_banks();
-}
-
-
-uint8_t msx_cart_msxdos2_device::read_cart(offs_t offset)
-{
- if (offset >= 0x4000 && offset < 0x8000)
- {
- return m_bank_base[offset & 0x3fff];
- }
-
- return 0xff;
-}
-
-
-void msx_cart_msxdos2_device::write_cart(offs_t offset, uint8_t data)
-{
- if (offset == 0x6000)
- {
- m_selected_bank = data;
- restore_banks();
- }
-}
diff --git a/src/devices/bus/msx_cart/msxdos2.h b/src/devices/bus/msx_cart/msxdos2.h
deleted file mode 100644
index dd5eb51d245..00000000000
--- a/src/devices/bus/msx_cart/msxdos2.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Wilbert Pol
-#ifndef MAME_BUS_MSX_CART_MSXDOS2_H
-#define MAME_BUS_MSX_CART_MSXDOS2_H
-
-#pragma once
-
-#include "bus/msx_cart/cartridge.h"
-
-
-DECLARE_DEVICE_TYPE(MSX_CART_MSXDOS2, msx_cart_msxdos2_device)
-
-
-class msx_cart_msxdos2_device : public device_t, public msx_cart_interface
-{
-public:
- msx_cart_msxdos2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void initialize_cartridge() override;
-
- virtual uint8_t read_cart(offs_t offset) override;
- virtual void write_cart(offs_t offset, uint8_t data) override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_post_load() override;
-
- void restore_banks();
-
-private:
- uint8_t m_selected_bank;
- uint8_t *m_bank_base;
-};
-
-
-#endif // MAME_BUS_MSX_CART_MSXDOS2_H
diff --git a/src/devices/bus/msx_cart/nomapper.cpp b/src/devices/bus/msx_cart/nomapper.cpp
deleted file mode 100644
index 24ebbb38e0d..00000000000
--- a/src/devices/bus/msx_cart/nomapper.cpp
+++ /dev/null
@@ -1,94 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Wilbert Pol
-
-#include "emu.h"
-#include "nomapper.h"
-
-DEFINE_DEVICE_TYPE(MSX_CART_NOMAPPER, msx_cart_nomapper_device, "msx_cart_nomapper", "MSX Cartridge - ROM")
-
-
-msx_cart_nomapper_device::msx_cart_nomapper_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, MSX_CART_NOMAPPER, tag, owner, clock)
- , msx_cart_interface(mconfig, *this)
- , m_start_address(0)
- , m_end_address(0)
-{
-}
-
-void msx_cart_nomapper_device::device_start()
-{
-}
-
-void msx_cart_nomapper_device::initialize_cartridge()
-{
- uint32_t size = get_rom_size();
- uint8_t *rom = get_rom_base();
-
- // determine start address
- // default to $4000
- m_start_address = 0x4000;
-
- switch (size)
- {
- /* 8KB/16KB */
- case 0x2000: case 0x4000:
- {
- uint16_t start = rom[3] << 8 | rom[2];
-
- // start address of $0000: call address in the $4000 region: $4000, else $8000
- if (start == 0)
- {
- if ((rom[5] & 0xc0) == 0x40)
- m_start_address = 0x4000;
- else
- m_start_address = 0x8000;
- }
-
- // start address in the $8000 region: $8000, else default
- else if ((start & 0xc000) == 0x8000)
- m_start_address = 0x8000;
-
- break;
- }
-
- /* 32KB */
- case 0x8000:
- // take default, check when no "AB" at $0000, but "AB" at $4000
- if (rom[0] != 'A' && rom[1] != 'B' && rom[0x4000] == 'A' && rom[0x4001] == 'B')
- {
- uint16_t start = rom[0x4003] << 8 | rom[0x4002];
-
- // start address of $0000 and call address in the $4000 region, or start address outside the $8000 region: $0000, else default
- if ((start == 0 && (rom[0x4005] & 0xc0) == 0x40) || start < 0x8000 || start >= 0xc000)
- m_start_address = 0;
- }
-
- break;
-
- /* 48KB */
- case 0xc000:
- // "AB" at $0000, but no "AB" at $4000, not "AB": $0000
- if (rom[0] == 'A' && rom[1] == 'B' && rom[0x4000] != 'A' && rom[0x4001] != 'B')
- m_start_address = 0x4000;
- else
- m_start_address = 0;
-
- break;
-
- /* 64KB */
- default:
- m_start_address = 0;
- break;
- }
-
- m_end_address = std::min<uint32_t>(m_start_address + size, 0x10000);
-}
-
-uint8_t msx_cart_nomapper_device::read_cart(offs_t offset)
-{
- if ( offset >= m_start_address && offset < m_end_address )
- {
- return get_rom_base()[offset - m_start_address];
- }
- return 0xff;
-}
diff --git a/src/devices/bus/msx_cart/nomapper.h b/src/devices/bus/msx_cart/nomapper.h
deleted file mode 100644
index eb5e40e1d08..00000000000
--- a/src/devices/bus/msx_cart/nomapper.h
+++ /dev/null
@@ -1,31 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Wilbert Pol
-#ifndef MAME_BUS_MSX_CART_NOMAPPER_H
-#define MAME_BUS_MSX_CART_NOMAPPER_H
-
-#pragma once
-
-#include "bus/msx_cart/cartridge.h"
-
-
-DECLARE_DEVICE_TYPE(MSX_CART_NOMAPPER, msx_cart_nomapper_device)
-
-
-class msx_cart_nomapper_device : public device_t, public msx_cart_interface
-{
-public:
- msx_cart_nomapper_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- // device-level overrides
- virtual void device_start() override;
-
- virtual void initialize_cartridge() override;
-
- virtual uint8_t read_cart(offs_t offset) override;
-
-private:
- uint32_t m_start_address;
- uint32_t m_end_address;
-};
-
-#endif // MAME_BUS_MSX_CART_NOMAPPER_H
diff --git a/src/devices/bus/msx_cart/rtype.cpp b/src/devices/bus/msx_cart/rtype.cpp
deleted file mode 100644
index 6cda0efb4e8..00000000000
--- a/src/devices/bus/msx_cart/rtype.cpp
+++ /dev/null
@@ -1,82 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Wilbert Pol
-#include "emu.h"
-#include "rtype.h"
-
-DEFINE_DEVICE_TYPE(MSX_CART_RTYPE, msx_cart_rtype_device, "msx_cart_rtype", "MSX Cartridge - R-Type")
-
-
-msx_cart_rtype_device::msx_cart_rtype_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, MSX_CART_RTYPE, tag, owner, clock)
- , msx_cart_interface(mconfig, *this)
- , m_selected_bank(0)
-{
- for (auto & elem : m_bank_base)
- {
- elem = nullptr;
- }
-}
-
-
-void msx_cart_rtype_device::device_start()
-{
- save_item(NAME(m_selected_bank));
-}
-
-
-void msx_cart_rtype_device::device_post_load()
-{
- restore_banks();
-}
-
-
-void msx_cart_rtype_device::restore_banks()
-{
- m_bank_base[0] = get_rom_base() + 15 * 0x4000;
- if (m_selected_bank & 0x10)
- {
- m_selected_bank &= 0x17;
- }
- m_bank_base[1] = get_rom_base() + m_selected_bank * 0x4000;
-}
-
-
-void msx_cart_rtype_device::device_reset()
-{
- m_selected_bank = 15;
-}
-
-
-void msx_cart_rtype_device::initialize_cartridge()
-{
- if ( get_rom_size() != 0x80000 && get_rom_size() != 0x60000 )
- {
- fatalerror("rtype: Invalid ROM size\n");
- }
-
- restore_banks();
-}
-
-
-uint8_t msx_cart_rtype_device::read_cart(offs_t offset)
-{
- if (offset >= 0x4000 && offset < 0xc000)
- {
- return m_bank_base[offset >> 15][offset & 0x3fff];
- }
- return 0xff;
-}
-
-
-void msx_cart_rtype_device::write_cart(offs_t offset, uint8_t data)
-{
- if (offset >= 0x7000 && offset < 0x8000)
- {
- m_selected_bank = data & 0x1f;
- if (m_selected_bank & 0x10)
- {
- m_selected_bank &= 0x17;
- }
- m_bank_base[1] = get_rom_base() + m_selected_bank * 0x4000;
- }
-}
diff --git a/src/devices/bus/msx_cart/rtype.h b/src/devices/bus/msx_cart/rtype.h
deleted file mode 100644
index 31583455a0a..00000000000
--- a/src/devices/bus/msx_cart/rtype.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Wilbert Pol
-#ifndef MAME_BUS_MSX_CART_RTYPE_H
-#define MAME_BUS_MSX_CART_RTYPE_H
-
-#pragma once
-
-#include "bus/msx_cart/cartridge.h"
-
-
-DECLARE_DEVICE_TYPE(MSX_CART_RTYPE, msx_cart_rtype_device)
-
-
-class msx_cart_rtype_device : public device_t, public msx_cart_interface
-{
-public:
- msx_cart_rtype_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void initialize_cartridge() override;
-
- virtual uint8_t read_cart(offs_t offset) override;
- virtual void write_cart(offs_t offset, uint8_t data) override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_post_load() override;
-
- void restore_banks();
-
-private:
- uint8_t m_selected_bank;
- uint8_t *m_bank_base[2];
-};
-
-
-#endif // MAME_BUS_MSX_CART_RTYPE_H
diff --git a/src/devices/bus/msx_cart/super_swangi.cpp b/src/devices/bus/msx_cart/super_swangi.cpp
deleted file mode 100644
index b3385f96e29..00000000000
--- a/src/devices/bus/msx_cart/super_swangi.cpp
+++ /dev/null
@@ -1,76 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Wilbert Pol
-#include "emu.h"
-#include "super_swangi.h"
-
-
-DEFINE_DEVICE_TYPE(MSX_CART_SUPER_SWANGI, msx_cart_super_swangi_device, "msx_cart_super_swangi", "MSX Cartridge - Super Swangi")
-
-
-msx_cart_super_swangi_device::msx_cart_super_swangi_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, MSX_CART_SUPER_SWANGI, tag, owner, clock)
- , msx_cart_interface(mconfig, *this)
- , m_selected_bank(0)
-{
- m_bank_base[0] = m_bank_base[1] = nullptr;
-}
-
-
-void msx_cart_super_swangi_device::device_start()
-{
- save_item(NAME(m_selected_bank));
-}
-
-
-void msx_cart_super_swangi_device::device_post_load()
-{
- restore_banks();
-}
-
-
-void msx_cart_super_swangi_device::restore_banks()
-{
- m_bank_base[0] = get_rom_base();
- m_bank_base[1] = get_rom_base() + (((m_selected_bank >> 1) * 0x4000) & 0xffff);
-}
-
-
-void msx_cart_super_swangi_device::device_reset()
-{
- m_selected_bank = 0;
-}
-
-
-void msx_cart_super_swangi_device::initialize_cartridge()
-{
- if (get_rom_size() < 0x10000)
- {
- fatalerror("super_swangi: Invalid ROM size\n");
- }
-
- restore_banks();
-}
-
-
-uint8_t msx_cart_super_swangi_device::read_cart(offs_t offset)
-{
- if (offset >= 0x4000 && offset < 0xc000)
- {
- return m_bank_base[offset >> 15][offset & 0x3fff];
- }
- return 0xff;
-}
-
-
-void msx_cart_super_swangi_device::write_cart(offs_t offset, uint8_t data)
-{
- if (offset == 0x8000)
- {
- m_selected_bank = data;
- restore_banks();
- }
- else
- {
- logerror("msx_cart_super_swangi_device: unhandled write %02x to %04x\n", data, offset);
- }
-}
diff --git a/src/devices/bus/msx_cart/super_swangi.h b/src/devices/bus/msx_cart/super_swangi.h
deleted file mode 100644
index f0f5ee216bd..00000000000
--- a/src/devices/bus/msx_cart/super_swangi.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Wilbert Pol
-#ifndef MAME_BUS_MSX_CART_SUPER_SWANGI_H
-#define MAME_BUS_MSX_CART_SUPER_SWANGI_H
-
-#pragma once
-
-#include "bus/msx_cart/cartridge.h"
-
-
-DECLARE_DEVICE_TYPE(MSX_CART_SUPER_SWANGI, msx_cart_super_swangi_device)
-
-
-class msx_cart_super_swangi_device : public device_t, public msx_cart_interface
-{
-public:
- msx_cart_super_swangi_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void initialize_cartridge() override;
-
- virtual uint8_t read_cart(offs_t offset) override;
- virtual void write_cart(offs_t offset, uint8_t data) override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_post_load() override;
-
- void restore_banks();
-
-private:
- uint8_t m_selected_bank;
- uint8_t *m_bank_base[2];
-};
-
-
-#endif // MAME_BUS_MSX_CART_SUPER_SWANGI_H
diff --git a/src/devices/bus/msx_cart/superloderunner.cpp b/src/devices/bus/msx_cart/superloderunner.cpp
deleted file mode 100644
index 168f9187f8d..00000000000
--- a/src/devices/bus/msx_cart/superloderunner.cpp
+++ /dev/null
@@ -1,65 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Wilbert Pol
-#include "emu.h"
-#include "superloderunner.h"
-
-DEFINE_DEVICE_TYPE(MSX_CART_SUPERLODERUNNER, msx_cart_superloderunner_device, "msx_cart_superloderunner", "MSX Cartridge - Super Lode Runner")
-
-
-msx_cart_superloderunner_device::msx_cart_superloderunner_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, MSX_CART_SUPERLODERUNNER, tag, owner, clock)
- , msx_cart_interface(mconfig, *this)
- , m_selected_bank(0)
- , m_bank_base(nullptr)
-{
-}
-
-
-void msx_cart_superloderunner_device::device_start()
-{
- save_item(NAME(m_selected_bank));
-
- // Install evil memory write handler
- memory_space().install_write_handler(0x0000, 0x0000, write8smo_delegate(*this, FUNC(msx_cart_superloderunner_device::banking)));
-}
-
-
-void msx_cart_superloderunner_device::device_post_load()
-{
- restore_banks();
-}
-
-
-void msx_cart_superloderunner_device::restore_banks()
-{
- m_bank_base = get_rom_base() + (m_selected_bank & 0x0f) * 0x4000;
-}
-
-
-void msx_cart_superloderunner_device::initialize_cartridge()
-{
- if (get_rom_size() != 0x20000)
- {
- fatalerror("superloderunner: Invalid ROM size\n");
- }
-
- restore_banks();
-}
-
-
-uint8_t msx_cart_superloderunner_device::read_cart(offs_t offset)
-{
- if (offset >= 0x8000 && offset < 0xc000)
- {
- return m_bank_base[offset & 0x3fff];
- }
-
- return 0xff;
-}
-
-
-void msx_cart_superloderunner_device::banking(uint8_t data)
-{
- m_selected_bank = data;
- restore_banks();
-}
diff --git a/src/devices/bus/msx_cart/superloderunner.h b/src/devices/bus/msx_cart/superloderunner.h
deleted file mode 100644
index bd763ca2c08..00000000000
--- a/src/devices/bus/msx_cart/superloderunner.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Wilbert Pol
-#ifndef MAME_BUS_MSX_CART_SUPERLODERUNNER_H
-#define MAME_BUS_MSX_CART_SUPERLODERUNNER_H
-
-#pragma once
-
-#include "bus/msx_cart/cartridge.h"
-
-
-DECLARE_DEVICE_TYPE(MSX_CART_SUPERLODERUNNER, msx_cart_superloderunner_device)
-
-
-class msx_cart_superloderunner_device : public device_t, public msx_cart_interface
-{
-public:
- msx_cart_superloderunner_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void initialize_cartridge() override;
-
- virtual uint8_t read_cart(offs_t offset) override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_post_load() override;
-
- void restore_banks();
-
-private:
- void banking(uint8_t data);
-
- uint8_t m_selected_bank;
- uint8_t *m_bank_base;
-};
-
-
-#endif // MAME_BUS_MSX_CART_SUPERLODERUNNER_H
diff --git a/src/devices/bus/msx_cart/yamaha.cpp b/src/devices/bus/msx_cart/yamaha.cpp
deleted file mode 100644
index b2cb15a37b0..00000000000
--- a/src/devices/bus/msx_cart/yamaha.cpp
+++ /dev/null
@@ -1,208 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Wilbert Pol
-/**************************************************************************
-
-Yamaha SFG01/SFG05 emulation
-
-**************************************************************************/
-
-#include "emu.h"
-#include "yamaha.h"
-
-#include "bus/midi/midi.h"
-#include "speaker.h"
-
-
-DEFINE_DEVICE_TYPE(MSX_CART_SFG01, msx_cart_sfg01_device, "msx_cart_sfg01", "MSX Cartridge - SFG01")
-DEFINE_DEVICE_TYPE(MSX_CART_SFG05, msx_cart_sfg05_device, "msx_cart_sfg05", "MSX Cartridge - SFG05")
-
-
-msx_cart_sfg_device::msx_cart_sfg_device(const machine_config &mconfig, const device_type type, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, type, tag, owner, clock)
- , msx_cart_interface(mconfig, *this)
- , m_region_sfg(*this, "sfg")
- , m_ym2151(*this, "ym2151")
- , m_kbdc(*this, "kbdc")
- , m_ym2148(*this, "ym2148")
- , m_ym2151_irq_state(CLEAR_LINE)
- , m_ym2148_irq_state(CLEAR_LINE)
- , m_rom_mask(0)
-{
-}
-
-
-msx_cart_sfg01_device::msx_cart_sfg01_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : msx_cart_sfg_device(mconfig, MSX_CART_SFG01, tag, owner, clock)
-{
-}
-
-
-msx_cart_sfg05_device::msx_cart_sfg05_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : msx_cart_sfg_device(mconfig, MSX_CART_SFG05, tag, owner, clock)
-{
-}
-
-
-void msx_cart_sfg_device::device_add_mconfig(machine_config &config)
-{
- // YM2151 (OPM)
- // YM3012 (DAC)
- // YM2148 (MKS)
-
- SPEAKER(config, "lspeaker").front_left();
- SPEAKER(config, "rspeaker").front_right();
- ym2151_device &ym2151(YM2151(config, m_ym2151, XTAL(3'579'545))); // The SFG01 uses a YM2151, the SFG05 uses a YM2164, input clock comes from the main cpu frequency
- ym2151.irq_handler().set(FUNC(msx_cart_sfg_device::ym2151_irq_w));
- ym2151.add_route(0, "lspeaker", 0.80);
- ym2151.add_route(1, "rspeaker", 0.80);
-
- YM2148(config, m_ym2148, XTAL(4'000'000));
- m_ym2148->txd_handler().set("mdout", FUNC(midi_port_device::write_txd));
- m_ym2148->port_write_handler().set("kbdc", FUNC(msx_audio_kbdc_port_device::write));
- m_ym2148->port_read_handler().set("kbdc", FUNC(msx_audio_kbdc_port_device::read));
- m_ym2148->irq_handler().set(FUNC(msx_cart_sfg_device::ym2148_irq_w));
-
- MSX_AUDIO_KBDC_PORT(config, m_kbdc, msx_audio_keyboards, nullptr);
-
- MIDI_PORT(config, "mdout", midiout_slot, "midiout");
- MIDI_PORT(config, "mdin", midiin_slot, "midiin").rxd_handler().set("ym2148", FUNC(ym2148_device::write_rxd));
-}
-
-void msx_cart_sfg05_device::device_add_mconfig(machine_config &config)
-{
- msx_cart_sfg_device::device_add_mconfig(config);
-
- ym2164_device &ym2164(YM2164(config.replace(), m_ym2151, XTAL(3'579'545)));
- ym2164.irq_handler().set(FUNC(msx_cart_sfg05_device::ym2151_irq_w));
- ym2164.add_route(0, "lspeaker", 0.80);
- ym2164.add_route(1, "rspeaker", 0.80);
-}
-
-
-ROM_START( msx_sfg01 )
- ROM_REGION(0x4000, "sfg", 0)
- ROM_LOAD("sfg01.rom", 0x0, 0x4000, CRC(0995fb36) SHA1(434651305f92aa770a89e40b81125fb22d91603d)) // correct label is almost certainly "yamaha__ym2211-22702__48_18_89_b.ic104" though the datecode portion may vary between late 1983 and mid 1984
-ROM_END
-
-
-const tiny_rom_entry *msx_cart_sfg01_device::device_rom_region() const
-{
- return ROM_NAME( msx_sfg01 );
-}
-
-
-ROM_START( msx_sfg05 )
- ROM_REGION(0x8000, "sfg", 0)
- ROM_SYSTEM_BIOS( 0, "sfg05", "SFG05 (original)" )
- ROMX_LOAD( "sfg05.rom", 0x0, 0x8000, CRC(2425c279) SHA1(d956167e234f60ad916120437120f86fc8c3c321), ROM_BIOS(0) ) // correct label MIGHT be "yamaha__ym2301-23959.ic104" but this needs redump/verification
- ROM_SYSTEM_BIOS( 1, "sfg05a", "SFG05 (SFG01 upgrade)" ) // SFG01 PCB, Yamaha official upgrade, has YM2151 instead of YM2164
- ROMX_LOAD( "sfg05a.rom", 0x0, 0x8000, CRC(5bc237f8) SHA1(930338f45c08228108c0831cc4a26014c2674718), ROM_BIOS(1) ) // this came on a single eprom on a daughterboard on an SFG01 board which had been factory upgraded to SFG05
-ROM_END
-
-
-const tiny_rom_entry *msx_cart_sfg05_device::device_rom_region() const
-{
- return ROM_NAME( msx_sfg05 );
-}
-
-
-void msx_cart_sfg_device::device_start()
-{
- // Set rom mask
- m_rom_mask = m_region_sfg->bytes() - 1;
-
- // This should probably moved up in the bus/slot hierarchy for the msx driver
- cpu_device *maincpu = machine().device<cpu_device>("maincpu");
- maincpu->set_irq_acknowledge_callback(*this, FUNC(msx_cart_sfg_device::irq_callback));
-}
-
-
-IRQ_CALLBACK_MEMBER(msx_cart_sfg_device::irq_callback)
-{
- return m_ym2148->get_irq_vector();
-}
-
-
-WRITE_LINE_MEMBER(msx_cart_sfg_device::ym2151_irq_w)
-{
- m_ym2151_irq_state = state ? ASSERT_LINE : CLEAR_LINE;
- check_irq();
-}
-
-
-WRITE_LINE_MEMBER(msx_cart_sfg_device::ym2148_irq_w)
-{
- m_ym2148_irq_state = state ? ASSERT_LINE : CLEAR_LINE;
- check_irq();
-}
-
-
-void msx_cart_sfg_device::check_irq()
-{
- if (m_ym2151_irq_state != CLEAR_LINE || m_ym2148_irq_state != CLEAR_LINE)
- {
- irq_out(ASSERT_LINE);
- }
- else
- {
- irq_out(CLEAR_LINE);
- }
-}
-
-
-uint8_t msx_cart_sfg_device::read_cart(offs_t offset)
-{
- switch (offset & 0x3fff)
- {
- case 0x3ff0: // YM-2151 status read
- case 0x3ff1: // YM-2151 status read mirror?
- return m_ym2151->read(offset & 1);
-
- case 0x3ff2: // YM-2148 keyboard column read
- case 0x3ff3: // YM-2148 --
- case 0x3ff4: // YM-2148 --
- case 0x3ff5: // YM-2148 MIDI UART data read register
- case 0x3ff6: // YM-2148 MIDI UART status register
- // ------x- - 1 = received a byte/receive buffer full?
- // -------x - 1 = ready to send next byte/send buffer empty?
- return m_ym2148->read(offset & 7);
- }
-
- if (offset < 0x8000)
- {
- return m_region_sfg->as_u8(offset & m_rom_mask);
- }
-
- return 0xff;
-}
-
-
-void msx_cart_sfg_device::write_cart(offs_t offset, uint8_t data)
-{
- switch (offset & 0x3fff)
- {
- case 0x3ff0: // YM-2151 register
- case 0x3ff1: // YM-2151 data
- m_ym2151->write(offset & 1, data);
- break;
-
- case 0x3ff2: // YM-2148 write keyboard row
- case 0x3ff3: // YM-2148 MIDI IRQ vector
- case 0x3ff4: // YM-2148 External IRQ vector
- case 0x3ff5: // YM-2148 MIDI UART data write register
- case 0x3ff6: // YM-2148 MIDI UART command register
- // On startup the sfg01 writes 0x80
- // followed by 0x05.
- // Other write seen in the code: 0x15
- //
- // x------- - 1 = reset
- // -----x-- - 1 = enable receiving / sending midi data
- // -------x - 1 = enable receiving / sending midi data
- m_ym2148->write(offset & 7, data);
- break;
-
- default:
- logerror("msx_cart_sfg_device::write_cart: write %02x to %04x\n", data, offset);
- break;
- }
-}
diff --git a/src/devices/bus/msx_cart/yamaha.h b/src/devices/bus/msx_cart/yamaha.h
deleted file mode 100644
index cd4c036cab8..00000000000
--- a/src/devices/bus/msx_cart/yamaha.h
+++ /dev/null
@@ -1,67 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Wilbert Pol
-#ifndef MAME_BUS_MSX_CART_YAMAHA_H
-#define MAME_BUS_MSX_CART_YAMAHA_H
-
-#pragma once
-
-#include "bus/msx_cart/cartridge.h"
-#include "sound/ymopm.h"
-#include "bus/msx_cart/msx_audio_kb.h"
-#include "machine/ym2148.h"
-
-
-DECLARE_DEVICE_TYPE(MSX_CART_SFG01, msx_cart_sfg01_device)
-DECLARE_DEVICE_TYPE(MSX_CART_SFG05, msx_cart_sfg05_device)
-
-
-class msx_cart_sfg_device : public device_t, public msx_cart_interface
-{
-public:
- virtual uint8_t read_cart(offs_t offset) override;
- virtual void write_cart(offs_t offset, uint8_t data) override;
-
-protected:
- msx_cart_sfg_device(const machine_config &mconfig, const device_type type, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void device_start() override;
-
- // device-level overrides
- virtual void device_add_mconfig(machine_config &config) override;
-
- IRQ_CALLBACK_MEMBER(irq_callback);
-
- DECLARE_WRITE_LINE_MEMBER(ym2151_irq_w);
- DECLARE_WRITE_LINE_MEMBER(ym2148_irq_w);
-
- required_memory_region m_region_sfg;
- required_device<ym_generic_device> m_ym2151;
- required_device<msx_audio_kbdc_port_device> m_kbdc;
- required_device<ym2148_device> m_ym2148;
- int m_ym2151_irq_state;
- int m_ym2148_irq_state;
- uint32_t m_rom_mask;
-
- void check_irq();
-};
-
-
-class msx_cart_sfg01_device : public msx_cart_sfg_device
-{
-public:
- msx_cart_sfg01_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual const tiny_rom_entry *device_rom_region() const override;
-};
-
-
-class msx_cart_sfg05_device : public msx_cart_sfg_device
-{
-public:
- msx_cart_sfg05_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
-};
-
-#endif // MAME_BUS_MSX_CART_YAMAHA_H
diff --git a/src/devices/bus/msx_slot/cartridge.cpp b/src/devices/bus/msx_slot/cartridge.cpp
deleted file mode 100644
index 667bbaf3cc7..00000000000
--- a/src/devices/bus/msx_slot/cartridge.cpp
+++ /dev/null
@@ -1,372 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Wilbert Pol
-#include "emu.h"
-#include "bus/msx_slot/cartridge.h"
-#include "hashfile.h"
-
-
-enum
-{
- NOMAPPER = 0,
- ASCII8,
- ASCII8_SRAM,
- ASCII16,
- ASCII16_SRAM,
- CROSSBLAIM,
- GAMEMASTER2,
- KOREAN_80IN1,
- KOREAN_90IN1,
- KOREAN_126IN1,
- FMPAC,
- RTYPE,
- KONAMI,
- KONAMI_SCC,
- SUPERLODERUNNER,
- MAJUTSUSHI,
- DISK_ROM,
- SYNTHESIZER,
- MSXDOS2
-};
-
-
-DEFINE_DEVICE_TYPE(MSX_SLOT_CARTRIDGE, msx_slot_cartridge_device, "msx_slot_cartridge", "MSX Cartridge slot")
-DEFINE_DEVICE_TYPE(MSX_SLOT_YAMAHA_EXPANSION, msx_slot_yamaha_expansion_device, "msx_slot_yamaha_expansion", "MSX Yamaha Expansion slot")
-
-
-msx_slot_cartridge_device::msx_slot_cartridge_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : msx_slot_cartridge_device(mconfig, MSX_SLOT_CARTRIDGE, tag, owner, clock)
-{
-}
-
-
-msx_slot_cartridge_device::msx_slot_cartridge_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, type, tag, owner, clock)
- , device_cartrom_image_interface(mconfig, *this)
- , device_slot_interface(mconfig, *this)
- , msx_internal_slot_interface(mconfig, *this)
- , m_irq_handler(*this)
- , m_cartridge(nullptr)
-{
-}
-
-
-static const struct
-{
- int pcb_id;
- const char *slot_option;
-} slot_list[] =
-{
- { NOMAPPER, "nomapper" },
- { ASCII8, "ascii8" },
- { ASCII8_SRAM, "ascii8_sram" },
- { ASCII16, "ascii16" },
- { ASCII16_SRAM, "ascii16_sram" },
- { CROSSBLAIM, "cross_blaim" },
- { GAMEMASTER2, "gamemaster2" },
- { KOREAN_80IN1, "korean_80in1" },
- { KOREAN_90IN1, "korean_90in1" },
- { KOREAN_126IN1, "korean_126in1" },
- { FMPAC, "fmpac" },
- { RTYPE, "rtype" },
- { KONAMI, "konami" },
- { KONAMI_SCC, "konami_scc" },
- { SUPERLODERUNNER, "superloderunner" },
- { MAJUTSUSHI, "majutsushi" },
- { DISK_ROM, "disk_rom" },
- { SYNTHESIZER, "synthesizer" },
- { MSXDOS2, "msxdos2" }
-};
-
-
-static const char *msx_cart_get_slot_option(int type)
-{
- for (auto & elem : slot_list)
- {
- if (elem.pcb_id == type)
- return elem.slot_option;
- }
-
- return slot_list[0].slot_option;
-}
-
-
-void msx_slot_cartridge_device::device_resolve_objects()
-{
- m_irq_handler.resolve_safe();
- m_cartridge = dynamic_cast<msx_cart_interface *>(get_card_device());
- if (m_cartridge)
- m_cartridge->m_exp = this;
-}
-
-
-void msx_slot_cartridge_device::device_start()
-{
-}
-
-
-image_init_result msx_slot_cartridge_device::call_load()
-{
- if ( m_cartridge )
- {
- if (loaded_through_softlist())
- {
- uint32_t length;
-
- // Allocate and copy rom contents
- length = get_software_region_length("rom");
- m_cartridge->rom_alloc( length );
- if (length > 0)
- {
- uint8_t *rom_base = m_cartridge->get_rom_base();
- memcpy(rom_base, get_software_region("rom"), length);
- }
-
- // Allocate and copy vlm5030 rom contents
- length = get_software_region_length("vlm5030");
- m_cartridge->rom_vlm5030_alloc(length);
- if (length > 0)
- {
- uint8_t *rom_base = m_cartridge->get_rom_vlm5030_base();
- memcpy(rom_base, get_software_region("vlm5030"), length);
- }
-
- // Allocate ram
- length = get_software_region_length("ram");
- m_cartridge->ram_alloc( length );
-
- // Allocate sram
- length = get_software_region_length("sram");
- m_cartridge->sram_alloc( length );
- }
- else
- {
- uint32_t length = this->length();
-
- // determine how much space to allocate
- uint32_t length_aligned = 0x10000;
-
- if (length <= 0x2000)
- length_aligned = 0x2000;
- else if (length <= 0x4000)
- length_aligned = 0x4000;
- else if (length <= 0x8000)
- length_aligned = 0x8000;
- else if (length <= 0xc000)
- length_aligned = 0xc000;
- else
- {
- while (length_aligned < length )
- length_aligned *= 2;
- }
-
- m_cartridge->rom_alloc(length_aligned);
- m_cartridge->ram_alloc(0);
- m_cartridge->sram_alloc(0);
-
- if (fread(m_cartridge->get_rom_base(), length) != length)
- {
- seterror(image_error::UNSPECIFIED, "Unable to fully read file");
- return image_init_result::FAIL;
- }
-
- // Check if there's some mapper related
- std::string extrainfo;
- if (hashfile_extrainfo(*this, extrainfo))
- {
- }
- }
-
- m_cartridge->m_exp = this;
- m_cartridge->initialize_cartridge();
-
- if (m_cartridge->get_sram_size() > 0)
- {
- battery_load(m_cartridge->get_sram_base(), m_cartridge->get_sram_size(), 0x00);
- }
- }
- return image_init_result::PASS;
-}
-
-
-void msx_slot_cartridge_device::call_unload()
-{
- if (m_cartridge)
- {
- if (m_cartridge->get_sram_size() > 0)
- {
- battery_save(m_cartridge->get_sram_base(), m_cartridge->get_sram_size());
- }
- }
-}
-
-
-WRITE_LINE_MEMBER(msx_slot_cartridge_device::irq_out)
-{
- m_irq_handler(state);
-}
-
-
-int msx_slot_cartridge_device::get_cart_type(const uint8_t *rom, uint32_t length)
-{
- if (length < 0x2000)
- {
- return -1;
- }
-
- if (length < 0x10000)
- {
- return NOMAPPER;
- }
-
- if ( (rom[0x10] == 'Y') && (rom[0x11] == 'Z') && (length > 0x18000) )
- {
- return GAMEMASTER2;
- }
-
- int kon4 = 0, kon5 = 0, asc8 = 0, asc16 = 0;
-
- for (int i=0; i < length-3; i++)
- {
- if (rom[i] == 0x32 && rom[i+1] == 0)
- {
- switch (rom[i+2])
- {
- case 0x60:
- case 0x70:
- asc16++;
- asc8++;
- break;
-
- case 0x68:
- case 0x78:
- asc8++;
- asc16--;
- break;
- }
-
- switch (rom[i+2])
- {
- case 0x60:
- case 0x80:
- case 0xa0:
- kon4++;
- break;
-
- case 0x50:
- case 0x70:
- case 0x90:
- case 0xb0:
- kon5++;
- break;
- }
- }
- }
-
- if (std::max(kon4, kon5) > std::max(asc8, asc16))
- {
- return (kon5 > kon4) ? KONAMI_SCC : KONAMI;
- }
- else
- {
- return (asc8 > asc16) ? ASCII8 : ASCII16;
- }
-}
-
-
-std::string msx_slot_cartridge_device::get_default_card_software(get_default_card_software_hook &hook) const
-{
- if (hook.image_file())
- {
- const char *slot_string = "nomapper";
- int type = NOMAPPER;
-
- // Check if there's some mapper related information in the hashfiles
- std::string extrainfo;
- if (hook.hashfile_extrainfo(extrainfo))
- {
- int extrainfo_type = -1;
- if (1 == sscanf(extrainfo.c_str(), "%d", &extrainfo_type))
- {
- static const struct { int extrainfo; int mapper; } extrainfo_map[] = {
- //{ 0, NOMAPPER },
- { 1, MSXDOS2 },
- { 2, KONAMI_SCC },
- { 3, KONAMI },
- { 4, ASCII8 },
- { 5, ASCII16 },
- { 6, GAMEMASTER2 },
- { 7, ASCII8_SRAM },
- { 8, ASCII16_SRAM },
- { 9, RTYPE },
- { 10, MAJUTSUSHI },
- { 11, FMPAC },
- { 12, SUPERLODERUNNER },
- { 13, SYNTHESIZER },
- { 14, CROSSBLAIM },
- { 15, DISK_ROM },
- { 16, KOREAN_80IN1 },
- { 17, KOREAN_126IN1 }
- };
-
- for (auto & elem : extrainfo_map)
- {
- if (elem.extrainfo == extrainfo_type)
- {
- type = elem.mapper;
- }
- }
- }
- }
-
- if (type == NOMAPPER)
- {
- // Not identified through hashfile, try automatic detection
- uint64_t length;
- hook.image_file()->length(length); // FIXME: check error return, guard against excessively large files
- std::vector<uint8_t> rom(length);
- size_t actual;
- hook.image_file()->read(&rom[0], length, actual); // FIXME: check error return or read returning short
- type = get_cart_type(&rom[0], length);
- }
-
- if (type > NOMAPPER)
- {
- slot_string = msx_cart_get_slot_option(type);
- }
-
- return std::string(slot_string);
- }
- return software_get_default_slot("nomapper");
-}
-
-
-uint8_t msx_slot_cartridge_device::read(offs_t offset)
-{
- if ( m_cartridge )
- {
- return m_cartridge->read_cart(offset);
- }
- return 0xFF;
-}
-
-
-void msx_slot_cartridge_device::write(offs_t offset, uint8_t data)
-{
- if ( m_cartridge )
- {
- m_cartridge->write_cart(offset, data);
- }
-}
-
-
-
-
-msx_slot_yamaha_expansion_device::msx_slot_yamaha_expansion_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : msx_slot_cartridge_device(mconfig, MSX_SLOT_YAMAHA_EXPANSION, tag, owner, clock)
-{
-}
-
-
-void msx_slot_yamaha_expansion_device::device_start()
-{
-}
diff --git a/src/devices/bus/msx_slot/cartridge.h b/src/devices/bus/msx_slot/cartridge.h
deleted file mode 100644
index 68d827edc93..00000000000
--- a/src/devices/bus/msx_slot/cartridge.h
+++ /dev/null
@@ -1,74 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Wilbert Pol
-#ifndef MAME_BUS_MSX_SLOT_CARTRIDGE_H
-#define MAME_BUS_MSX_SLOT_CARTRIDGE_H
-
-#pragma once
-
-#include "slot.h"
-#include "bus/msx_cart/cartridge.h"
-#include "imagedev/cartrom.h"
-
-
-DECLARE_DEVICE_TYPE(MSX_SLOT_CARTRIDGE, msx_slot_cartridge_device)
-DECLARE_DEVICE_TYPE(MSX_SLOT_YAMAHA_EXPANSION, msx_slot_yamaha_expansion_device)
-
-
-class msx_slot_cartridge_device : public device_t
- , public device_cartrom_image_interface
- , public device_slot_interface
- , public msx_internal_slot_interface
-{
-public:
- // construction/destruction
- msx_slot_cartridge_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- // configuration helpers
- auto irq_handler() { return m_irq_handler.bind(); }
-
- // image-level overrides
- virtual image_init_result call_load() override;
- virtual void call_unload() override;
- virtual bool is_reset_on_load() const noexcept override { return true; }
- virtual const char *image_interface() const noexcept override { return "msx_cart"; }
- virtual const char *file_extensions() const noexcept override { return "mx1,bin,rom"; }
-
- // slot interface overrides
- virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
-
- // msx_internal_slot-level overrides
- virtual uint8_t read(offs_t offset) override;
- virtual void write(offs_t offset, uint8_t data) override;
-
- DECLARE_WRITE_LINE_MEMBER(irq_out);
-
-protected:
- msx_slot_cartridge_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
-
- // device-level overrides
- virtual void device_resolve_objects() override;
- virtual void device_start() override;
-
- devcb_write_line m_irq_handler;
- msx_cart_interface *m_cartridge;
-
- static int get_cart_type(const uint8_t *rom, uint32_t length);
-};
-
-
-class msx_slot_yamaha_expansion_device : public msx_slot_cartridge_device
-{
-public:
- // construction/destruction
- msx_slot_yamaha_expansion_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual const char *image_interface() const noexcept override { return "msx_yamaha_60pin"; }
- virtual const char *image_type_name() const noexcept override { return "cartridge60pin"; }
- virtual const char *image_brief_type_name() const noexcept override { return "cart60p"; }
-
-protected:
- virtual void device_start() override;
-};
-
-
-#endif // MAME_BUS_MSX_SLOT_CARTRIDGE_H
diff --git a/src/devices/bus/msx_slot/disk.cpp b/src/devices/bus/msx_slot/disk.cpp
deleted file mode 100644
index 78a15b7d841..00000000000
--- a/src/devices/bus/msx_slot/disk.cpp
+++ /dev/null
@@ -1,806 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Wilbert Pol
-/*
-From: erbo@xs4all.nl (erik de boer)
-
-sony and philips have used (almost) the same design
-and this is the memory layout
-but it is not a msx standard !
-
-WD1793 or wd2793 registers
-
-address
-
-7FF8H read status register
- write command register
-7FF9H r/w track register (r/o on NMS 8245 and Sony)
-7FFAH r/w sector register (r/o on NMS 8245 and Sony)
-7FFBH r/w data register
-
-
-hardware registers
-
-address
-
-7FFCH r/w bit 0 side select
-7FFDH r/w b7>M-on , b6>in-use , b1>ds1 , b0>ds0 (all neg. logic)
-7FFEH not used
-7FFFH read b7>drq , b6>intrq
-
-set on 7FFDH bit 2 always to 0 (some use it as disk change reset)
-
-*/
-
-#include "emu.h"
-#include "disk.h"
-
-
-DEFINE_DEVICE_TYPE(MSX_SLOT_DISK1, msx_slot_disk1_device, "msx_slot_disk1", "MSX Internal floppy type 1")
-DEFINE_DEVICE_TYPE(MSX_SLOT_DISK2, msx_slot_disk2_device, "msx_slot_disk2", "MSX Internal floppy type 2")
-DEFINE_DEVICE_TYPE(MSX_SLOT_DISK3, msx_slot_disk3_device, "msx_slot_disk3", "MSX Internal floppy type 3")
-DEFINE_DEVICE_TYPE(MSX_SLOT_DISK4, msx_slot_disk4_device, "msx_slot_disk4", "MSX Internal floppy type 4")
-DEFINE_DEVICE_TYPE(MSX_SLOT_DISK5, msx_slot_disk5_device, "msx_slot_disk5", "MSX Internal floppy type 5")
-DEFINE_DEVICE_TYPE(MSX_SLOT_DISK6, msx_slot_disk6_device, "msx_slot_disk6", "MSX Internal floppy type 6")
-
-
-msx_slot_disk_device::msx_slot_disk_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
- : msx_slot_rom_device(mconfig, type, tag, owner, clock)
- , m_floppy0(nullptr)
- , m_floppy1(nullptr)
- , m_floppy2(nullptr)
- , m_floppy3(nullptr)
- , m_floppy(nullptr)
- , m_fdc_tag(nullptr)
- , m_floppy0_tag(nullptr)
- , m_floppy1_tag(nullptr)
- , m_floppy2_tag(nullptr)
- , m_floppy3_tag(nullptr)
-{
-}
-
-
-void msx_slot_disk_device::device_start()
-{
- msx_slot_rom_device::device_start();
-
- if (m_fdc_tag == nullptr)
- {
- fatalerror("msx_slot_disk_device: no FDC tag specified\n");
- }
-
- m_floppy0 = m_floppy0_tag ? owner()->subdevice<floppy_connector>(m_floppy0_tag) : nullptr;
- m_floppy1 = m_floppy1_tag ? owner()->subdevice<floppy_connector>(m_floppy1_tag) : nullptr;
- m_floppy2 = m_floppy2_tag ? owner()->subdevice<floppy_connector>(m_floppy2_tag) : nullptr;
- m_floppy3 = m_floppy3_tag ? owner()->subdevice<floppy_connector>(m_floppy3_tag) : nullptr;
-
- if (m_floppy0 == nullptr && m_floppy1 == nullptr)
- {
- logerror("msx_slot_disk_device: Warning: both floppy0 and floppy1 were not found\n");
- }
-}
-
-
-msx_slot_wd_disk_device::msx_slot_wd_disk_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
- : msx_slot_disk_device(mconfig, type, tag, owner, clock)
- , m_fdc(nullptr)
- , m_led(*this, "led0")
-{
-}
-
-
-void msx_slot_wd_disk_device::device_start()
-{
- msx_slot_disk_device::device_start();
-
- m_led.resolve();
- m_fdc = owner()->subdevice<wd_fdc_analog_device_base>(m_fdc_tag);
-
- if (m_fdc == nullptr)
- {
- fatalerror("msx_slot_wd_disk_device: Unable to find FDC with tag '%s'\n", m_fdc_tag);
- }
-}
-
-
-msx_slot_tc8566_disk_device::msx_slot_tc8566_disk_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
- : msx_slot_disk_device(mconfig, type, tag, owner, clock)
- , m_fdc(nullptr)
-{
-}
-
-
-void msx_slot_tc8566_disk_device::device_start()
-{
- msx_slot_disk_device::device_start();
-
- m_fdc = owner()->subdevice<tc8566af_device>(m_fdc_tag);
-
- if (m_fdc == nullptr)
- {
- fatalerror("msx_slot_tc8566_disk_device: Unable to find FDC with tag '%s'\n", m_fdc_tag);
- }
-}
-
-
-
-msx_slot_disk1_device::msx_slot_disk1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : msx_slot_wd_disk_device(mconfig, MSX_SLOT_DISK1, tag, owner, clock)
- , m_side_control(0)
- , m_control(0)
-{
-}
-
-
-void msx_slot_disk1_device::device_start()
-{
- msx_slot_wd_disk_device::device_start();
-
- save_item(NAME(m_side_control));
- save_item(NAME(m_control));
-}
-
-
-void msx_slot_disk1_device::device_reset()
-{
- m_fdc->dden_w(false);
-}
-
-
-void msx_slot_disk1_device::device_post_load()
-{
- uint8_t data = m_control;
-
- // To make sure the FDD busy led status gets set correctly
- m_control ^= 0x40;
-
- set_control(data);
-}
-
-
-void msx_slot_disk1_device::set_side_control(uint8_t data)
-{
- m_side_control = data;
-
- if (m_floppy)
- {
- m_floppy->ss_w(m_side_control & 0x01);
- }
-}
-
-
-void msx_slot_disk1_device::set_control(uint8_t data)
-{
- uint8_t old_m_control = m_control;
-
- m_control = data;
-
- switch (m_control & 0x03)
- {
- case 0:
- case 2:
- m_floppy = m_floppy0 ? m_floppy0->get_device() : nullptr;
- break;
-
- case 1:
- m_floppy = m_floppy1 ? m_floppy1->get_device() : nullptr;
- break;
-
- default:
- m_floppy = nullptr;
- break;
- }
-
- if (m_floppy)
- {
- m_floppy->mon_w((m_control & 0x80) ? 0 : 1);
- m_floppy->ss_w(m_side_control & 0x01);
- }
-
- m_fdc->set_floppy(m_floppy);
-
- if ((old_m_control ^ m_control) & 0x40)
- {
- m_led = BIT(~m_control, 6);
- }
-}
-
-
-uint8_t msx_slot_disk1_device::read(offs_t offset)
-{
- switch (offset)
- {
- case 0x7ff8:
- case 0xbff8:
- return m_fdc->status_r();
-
- case 0x7ff9:
- case 0xbff9:
- return m_fdc->track_r();
-
- case 0x7ffa:
- case 0xbffa:
- return m_fdc->sector_r();
-
- case 0x7ffb:
- case 0xbffb:
- return m_fdc->data_r();
-
- case 0x7ffc:
- case 0xbffc:
- return 0xfe | (m_side_control & 0x01);
-
- case 0x7ffd:
- case 0xbffd:
- return ( m_control & 0x83 ) | 0x78;
-
- case 0x7fff:
- case 0xbfff:
- return 0x3f | (m_fdc->intrq_r() ? 0 : 0x40) | (m_fdc->drq_r() ? 0 : 0x80);
- }
-
- return msx_slot_rom_device::read(offset);
-}
-
-
-void msx_slot_disk1_device::write(offs_t offset, uint8_t data)
-{
- switch (offset)
- {
- case 0x7ff8:
- case 0xbff8:
- m_fdc->cmd_w(data);
- break;
-
- case 0x7ff9:
- case 0xbff9:
- m_fdc->track_w(data);
- break;
-
- case 0x7ffa:
- case 0xbffa:
- m_fdc->sector_w(data);
- break;
-
- case 0x7ffb:
- case 0xbffb:
- m_fdc->data_w(data);
- break;
-
- case 0x7ffc:
- case 0xbffc:
- set_side_control(data);
- break;
-
- case 0x7ffd:
- case 0xbffd:
- set_control(data);
- break;
-
- default:
- logerror("msx_slot_disk1_device::write: Unmapped write writing %02x to %04x\n", data, offset);
- break;
-
- }
-}
-
-
-msx_slot_disk2_device::msx_slot_disk2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : msx_slot_wd_disk_device(mconfig, MSX_SLOT_DISK2, tag, owner, clock)
- , m_control(0)
-{
-}
-
-
-void msx_slot_disk2_device::device_start()
-{
- msx_slot_wd_disk_device::device_start();
-
- save_item(NAME(m_control));
-}
-
-
-void msx_slot_disk2_device::device_reset()
-{
- m_fdc->dden_w(false);
-}
-
-
-void msx_slot_disk2_device::device_post_load()
-{
- uint8_t data = m_control;
-
- // To make sure the FDD busy led status gets set correctly
- m_control ^= 0x40;
-
- set_control(data);
-}
-
-
-void msx_slot_disk2_device::set_control(uint8_t data)
-{
- uint8_t old_m_control = m_control;
-
- m_control = data;
-
- switch (m_control & 3)
- {
- case 1:
- m_floppy = m_floppy0 ? m_floppy0->get_device() : nullptr;
- break;
-
- case 2:
- m_floppy = m_floppy1 ? m_floppy1->get_device() : nullptr;
- break;
-
- default:
- m_floppy = nullptr;
- break;
- }
-
- if (m_floppy)
- {
- m_floppy->mon_w((m_control & 0x08) ? 0 : 1);
- m_floppy->ss_w((m_control & 0x04) ? 1 : 0);
- }
-
- m_fdc->set_floppy(m_floppy);
-
- if ((old_m_control ^ m_control) & 0x40)
- {
- m_led = BIT(~m_control, 6);
- }
-}
-
-
-uint8_t msx_slot_disk2_device::read(offs_t offset)
-{
- switch (offset)
- {
- case 0x7fb8:
- case 0xbfb8:
- return m_fdc->status_r();
-
- case 0x7fb9:
- case 0xbfb9:
- return m_fdc->track_r();
-
- case 0x7fba:
- case 0xbfba:
- return m_fdc->sector_r();
-
- case 0x7fbb:
- case 0xbfbb:
- return m_fdc->data_r();
-
- case 0x7fbc:
- case 0xbfbc:
- return 0x3f | (m_fdc->drq_r() ? 0 : 0x40) | (m_fdc->intrq_r() ? 0x80 : 0);
- }
-
- return msx_slot_rom_device::read(offset);
-}
-
-
-void msx_slot_disk2_device::write(offs_t offset, uint8_t data)
-{
- switch (offset)
- {
- case 0x7fb8:
- case 0xbfb8:
- m_fdc->cmd_w(data);
- break;
-
- case 0x7fb9:
- case 0xbfb9:
- m_fdc->track_w(data);
- break;
-
- case 0x7fba:
- case 0xbfba:
- m_fdc->sector_w(data);
- break;
-
- case 0x7fbb:
- case 0xbfbb:
- m_fdc->data_w(data);
- break;
-
- case 0x7fbc:
- case 0xbfbc:
- set_control(data);
- break;
-
- default:
- logerror("msx_slot_disk2_device::write: Unmapped write writing %02x to %04x\n", data, offset);
- break;
- }
-}
-
-
-
-
-
-
-msx_slot_disk3_device::msx_slot_disk3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : msx_slot_tc8566_disk_device(mconfig, MSX_SLOT_DISK3, tag, owner, clock)
-{
-}
-
-
-void msx_slot_disk3_device::write(offs_t offset, uint8_t data)
-{
- switch (offset)
- {
- case 0x7ff8: // CR0 : 0 - 0 - MEN1 - MEN0 - 0 - -FRST - 0 - DSA
- m_fdc->dor_w(data);
- break;
-
- case 0x7ff9: // CR1 : 0 - 0 - C4E - C4 - SBME - SBM - TCE - FDCTC
- m_fdc->cr1_w(data);
- break;
-
- case 0x7ffb: // Data Register
- m_fdc->fifo_w(data);
- break;
-
- default:
- logerror("msx_slot_disk3_device::write: Unmapped write writing %02x to %04x\n", data, offset);
- break;
- }
-}
-
-
-uint8_t msx_slot_disk3_device::read(offs_t offset)
-{
- switch (offset)
- {
- case 0x7ffa: // Status Register
- return m_fdc->msr_r();
- case 0x7ffb: // Data Register
- return m_fdc->fifo_r();
- }
-
- return msx_slot_rom_device::read(offset);
-}
-
-
-
-
-
-msx_slot_disk4_device::msx_slot_disk4_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : msx_slot_tc8566_disk_device(mconfig, MSX_SLOT_DISK4, tag, owner, clock)
-{
-}
-
-
-void msx_slot_disk4_device::write(offs_t offset, uint8_t data)
-{
- switch (offset)
- {
- case 0x7ff1: // FDD : x - x - MC1 - MC0 - x - x - x - x
- break;
-
- case 0x7ff2: // CR0 : 0 - 0 - MEN1 - MEN0 - 0 - -FRST - 0 - DSA
- m_fdc->dor_w(data);
- break;
-
- case 0x7ff3: // CR1 : 0 - 0 - C4E - C4 - SBME - SBM - TCE - FDCTC
- m_fdc->cr1_w(data);
- break;
-
- case 0x7ff5: // Data Register
- m_fdc->fifo_w(data);
- break;
-
- default:
- logerror("msx_slot_disk4_device::write: Unmapped write writing %02x to %04x\n", data, offset);
- break;
- }
-}
-
-
-uint8_t msx_slot_disk4_device::read(offs_t offset)
-{
- switch (offset)
- {
- case 0x7ff1: // FDD : x - x - MC1 - MC0 - x - x - x - x
- logerror("msx_slot_disk4_device::write: Unmapped read from Media Change register\n");
- break;
-
- case 0x7ff4: // Status Register
- return m_fdc->msr_r();
- case 0x7ff5: // Data Register
- return m_fdc->fifo_r();
- }
-
- return msx_slot_rom_device::read(offset);
-}
-
-
-
-
-msx_slot_disk5_device::msx_slot_disk5_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : msx_slot_wd_disk_device(mconfig, MSX_SLOT_DISK5, tag, owner, clock)
- , m_control(0)
-{
-}
-
-
-void msx_slot_disk5_device::device_start()
-{
- msx_slot_wd_disk_device::device_start();
-
- save_item(NAME(m_control));
-
- // Install IO read/write handlers
- io_space().install_write_handler(0xd0, 0xd4, write8sm_delegate(*this, FUNC(msx_slot_disk5_device::io_write)));
- io_space().install_read_handler(0xd0, 0xd4, read8sm_delegate(*this, FUNC(msx_slot_disk5_device::io_read)));
-}
-
-
-void msx_slot_disk5_device::device_reset()
-{
- m_fdc->dden_w(false);
-}
-
-
-void msx_slot_disk5_device::device_post_load()
-{
- set_control(m_control);
-}
-
-
-void msx_slot_disk5_device::set_control(uint8_t control)
-{
- m_control = control;
-
- switch (m_control & 0x0f)
- {
- case 0x01:
- m_floppy = m_floppy0 ? m_floppy0->get_device() : nullptr;
- break;
-
- case 0x02:
- m_floppy = m_floppy1 ? m_floppy1->get_device() : nullptr;
- break;
-
- case 0x04:
- m_floppy = m_floppy2 ? m_floppy2->get_device() : nullptr;
- break;
-
- case 0x08:
- m_floppy = m_floppy3 ? m_floppy3->get_device() : nullptr;
- break;
-
- default:
- m_floppy = nullptr;
- break;
- }
-
- if (m_floppy)
- {
- m_floppy->mon_w((m_control & 0x20) ? 0 : 1);
- m_floppy->ss_w((m_control & 0x10) ? 1 : 0);
- }
-
- m_fdc->set_floppy(m_floppy);
-}
-
-
-uint8_t msx_slot_disk5_device::io_read(offs_t offset)
-{
- switch (offset)
- {
- case 0x00:
- return m_fdc->status_r();
-
- case 0x01:
- return m_fdc->track_r();
-
- case 0x02:
- return m_fdc->sector_r();
-
- case 0x03:
- return m_fdc->data_r();
-
- case 0x04:
- return 0x3f | (m_fdc->drq_r() ? 0 : 0x40) | (m_fdc->intrq_r() ? 0x80 : 0);
- }
-
- return 0xff;
-}
-
-
-void msx_slot_disk5_device::io_write(offs_t offset, uint8_t data)
-{
- switch (offset)
- {
- case 0x00:
- m_fdc->cmd_w(data);
- break;
-
- case 0x01:
- m_fdc->track_w(data);
- break;
-
- case 0x02:
- m_fdc->sector_w(data);
- break;
-
- case 0x03:
- m_fdc->data_w(data);
- break;
-
- case 0x04:
- set_control(data);
- break;
- }
-}
-
-
-
-msx_slot_disk6_device::msx_slot_disk6_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : msx_slot_wd_disk_device(mconfig, MSX_SLOT_DISK6, tag, owner, clock)
- , m_side_motor(0)
- , m_drive_select0(0)
- , m_drive_select1(0)
-{
-}
-
-
-void msx_slot_disk6_device::device_start()
-{
- msx_slot_wd_disk_device::device_start();
-
- save_item(NAME(m_side_motor));
- save_item(NAME(m_drive_select0));
- save_item(NAME(m_drive_select1));
-}
-
-
-void msx_slot_disk6_device::device_reset()
-{
- m_fdc->dden_w(false);
-}
-
-
-void msx_slot_disk6_device::device_post_load()
-{
- select_drive();
-}
-
-
-void msx_slot_disk6_device::select_drive()
-{
- if (m_drive_select1)
- {
- m_floppy = m_floppy1 ? m_floppy1->get_device() : nullptr;
- if (!m_floppy)
- {
- m_drive_select1 = 0;
- }
- }
-
- if (m_drive_select0)
- {
- m_floppy = m_floppy0 ? m_floppy0->get_device() : nullptr;
- if (!m_floppy)
- {
- m_drive_select0 = 0;
- }
- }
-
- m_fdc->set_floppy(m_floppy);
-
- set_side_motor();
-}
-
-
-void msx_slot_disk6_device::set_side_motor()
-{
- if (m_floppy)
- {
- m_floppy->mon_w((m_side_motor & 0x02) ? 0 : 1);
- m_floppy->ss_w(m_side_motor & 0x01);
- }
-}
-
-
-uint8_t msx_slot_disk6_device::read(offs_t offset)
-{
- switch (offset)
- {
- case 0x7ff0: // status?
- case 0x7ff8:
- return m_fdc->status_r();
-
- case 0x7ff1: // track?
- case 0x7ff9:
- return m_fdc->track_r();
-
- case 0x7ff2: // sector?
- case 0x7ffa:
- return m_fdc->sector_r();
-
- case 0x7ff3: // data?
- case 0x7ffb:
- return m_fdc->data_r();
-
- case 0x7ff4:
- case 0x7ffc:
- // bit 0 = side control
- // bit 1 = motor control
- return 0xfc | m_side_motor;
- break;
-
- // This reads back a 1 in bit 0 if drive0 is present and selected
- case 0x7ff5:
- case 0x7ffd:
- return 0xfe | m_drive_select0;
-
- // This reads back a 1 in bit 0 if drive1 is present and selected
- case 0x7ff6:
- case 0x7ffe:
- return 0xfe | m_drive_select1;
-
- case 0x7ff7:
- case 0x7fff:
- return 0x3f | (m_fdc->intrq_r() ? 0 : 0x40) | (m_fdc->drq_r() ? 0 : 0x80);
- }
-
- return msx_slot_rom_device::read(offset);
-}
-
-
-void msx_slot_disk6_device::write(offs_t offset, uint8_t data)
-{
- switch (offset)
- {
- case 0x7ff0: // cmd?
- case 0x7ff8:
- m_fdc->cmd_w(data);
- break;
-
- case 0x7ff1: // track?
- case 0x7ff9:
- m_fdc->track_w(data);
- break;
-
- case 0x7ff2: // sector?
- case 0x7ffa:
- m_fdc->sector_w(data);
- break;
-
- case 0x7ff3: // data?
- case 0x7ffb:
- m_fdc->data_w(data);
- break;
-
- // Side and motort control
- // bit 0 = side select
- // bit 1 = motor on/off
- case 0x7ff4:
- case 0x7ffc:
- m_side_motor = data;
- set_side_motor();
- break;
-
- // bit 0 - select drive 0
- case 0x7ff5:
- case 0x7ffd:
- m_drive_select0 = data;
- select_drive();
- break;
-
- // bit 1 - select drive 1
- case 0x7ff6:
- case 0x7ffe:
- m_drive_select1 = data;
- select_drive();
- break;
-
- default:
- logerror("msx_slot_disk6_device::write: Unmapped write writing %02x to %04x\n", data, offset);
- break;
- }
-}
diff --git a/src/devices/bus/msx_slot/disk.h b/src/devices/bus/msx_slot/disk.h
deleted file mode 100644
index 184ea2caf66..00000000000
--- a/src/devices/bus/msx_slot/disk.h
+++ /dev/null
@@ -1,201 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Wilbert Pol
-#ifndef MAME_BUS_MSX_SLOT_DISK_H
-#define MAME_BUS_MSX_SLOT_DISK_H
-
-#pragma once
-
-#include "bus/msx_slot/slot.h"
-#include "bus/msx_slot/rom.h"
-#include "machine/wd_fdc.h"
-#include "machine/upd765.h"
-#include "imagedev/floppy.h"
-
-
-/* WD FDC accessed through 7ffx */
-DECLARE_DEVICE_TYPE(MSX_SLOT_DISK1, msx_slot_disk1_device)
-/* WD FDC accessed through 7fbx */
-DECLARE_DEVICE_TYPE(MSX_SLOT_DISK2, msx_slot_disk2_device)
-/* TC8566 accessed through 7ff8-7fff */
-DECLARE_DEVICE_TYPE(MSX_SLOT_DISK3, msx_slot_disk3_device)
-/* TC8566 accessed through 7ff0-7ff7 (used in Turob-R, untested) */
-DECLARE_DEVICE_TYPE(MSX_SLOT_DISK4, msx_slot_disk4_device)
-/* WD FDC accessed through i/o ports 0xd0-0xd4 */
-DECLARE_DEVICE_TYPE(MSX_SLOT_DISK5, msx_slot_disk5_device)
-/* WD FDC accessed through 7ff0-7ff? (used in Toshiba HX34) */
-DECLARE_DEVICE_TYPE(MSX_SLOT_DISK6, msx_slot_disk6_device)
-
-
-class msx_slot_disk_device : public msx_slot_rom_device
-{
-public:
- // configuration helpers
- void set_fdc_tag(const char *tag) { m_fdc_tag = tag; }
- void set_floppy0_tag(const char *tag) { m_floppy0_tag = tag; }
- void set_floppy1_tag(const char *tag) { m_floppy1_tag = tag; }
- void set_floppy2_tag(const char *tag) { m_floppy2_tag = tag; }
- void set_floppy3_tag(const char *tag) { m_floppy3_tag = tag; }
-
- void set_tags(const char *fdc_tag, const char *floppy0_tag, const char *floppy1_tag)
- {
- m_fdc_tag = fdc_tag;
- m_floppy0_tag = floppy0_tag;
- m_floppy1_tag = floppy1_tag;
- }
- void set_tags(const char *fdc_tag, const char *floppy0_tag, const char *floppy1_tag, const char *floppy2_tag, const char *floppy3_tag)
- {
- m_fdc_tag = fdc_tag;
- m_floppy0_tag = floppy0_tag;
- m_floppy1_tag = floppy1_tag;
- m_floppy2_tag = floppy2_tag;
- m_floppy3_tag = floppy3_tag;
- }
-
-protected:
- msx_slot_disk_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void device_start() override;
-
- floppy_connector *m_floppy0;
- floppy_connector *m_floppy1;
- floppy_connector *m_floppy2;
- floppy_connector *m_floppy3;
- floppy_image_device *m_floppy;
-
- const char *m_fdc_tag;
- const char *m_floppy0_tag;
- const char *m_floppy1_tag;
- const char *m_floppy2_tag;
- const char *m_floppy3_tag;
-};
-
-
-class msx_slot_wd_disk_device : public msx_slot_disk_device
-{
-protected:
- msx_slot_wd_disk_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void device_start() override;
-
- wd_fdc_analog_device_base *m_fdc;
- output_finder<> m_led;
-};
-
-
-class msx_slot_tc8566_disk_device : public msx_slot_disk_device
-{
-protected:
- msx_slot_tc8566_disk_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void device_start() override;
-
- tc8566af_device *m_fdc;
-};
-
-
-class msx_slot_disk1_device : public msx_slot_wd_disk_device
-{
-public:
- msx_slot_disk1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual uint8_t read(offs_t offset) override;
- virtual void write(offs_t offset, uint8_t data) override;
-
-protected:
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_post_load() override;
-
-private:
- uint8_t m_side_control;
- uint8_t m_control;
-
- void set_control(uint8_t data);
- void set_side_control(uint8_t data);
-};
-
-
-class msx_slot_disk2_device : public msx_slot_wd_disk_device
-{
-public:
- msx_slot_disk2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual uint8_t read(offs_t offset) override;
- virtual void write(offs_t offset, uint8_t data) override;
-
-protected:
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_post_load() override;
-
-private:
- uint8_t m_control;
-
- void set_control(uint8_t data);
-};
-
-
-class msx_slot_disk3_device : public msx_slot_tc8566_disk_device
-{
-public:
- msx_slot_disk3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual uint8_t read(offs_t offset) override;
- virtual void write(offs_t offset, uint8_t data) override;
-};
-
-
-class msx_slot_disk4_device : public msx_slot_tc8566_disk_device
-{
-public:
- msx_slot_disk4_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual uint8_t read(offs_t offset) override;
- virtual void write(offs_t offset, uint8_t data) override;
-};
-
-
-class msx_slot_disk5_device : public msx_slot_wd_disk_device
-{
-public:
- msx_slot_disk5_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_post_load() override;
-
-private:
- uint8_t io_read(offs_t offset);
- void io_write(offs_t offset, uint8_t data);
-
- uint8_t m_control;
-
- void set_control(uint8_t control);
-};
-
-
-class msx_slot_disk6_device : public msx_slot_wd_disk_device
-{
-public:
- msx_slot_disk6_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- virtual uint8_t read(offs_t offset) override;
- virtual void write(offs_t offset, uint8_t data) override;
-
-protected:
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_post_load() override;
-
-private:
- uint8_t m_side_motor;
- uint8_t m_drive_select0;
- uint8_t m_drive_select1;
-
- void set_side_motor();
- void select_drive();
-};
-
-
-#endif // MAME_BUS_MSX_SLOT_DISK_H
diff --git a/src/devices/bus/msx_slot/fs4600.cpp b/src/devices/bus/msx_slot/fs4600.cpp
deleted file mode 100644
index 0f328985f6f..00000000000
--- a/src/devices/bus/msx_slot/fs4600.cpp
+++ /dev/null
@@ -1,142 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Wilbert Pol
-/*
- Emulation for the internal firmware mapper in the National FS-4600.
-*/
-
-#include "emu.h"
-#include "fs4600.h"
-
-
-DEFINE_DEVICE_TYPE(MSX_SLOT_FS4600, msx_slot_fs4600_device, "msx_slot_fs4600", "MSX Internal FS4600 Firmware")
-
-
-msx_slot_fs4600_device::msx_slot_fs4600_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, MSX_SLOT_FS4600, tag, owner, clock)
- , msx_internal_slot_interface(mconfig, *this)
- , m_nvram(*this, "nvram")
- , m_rom_region(*this, finder_base::DUMMY_TAG)
- , m_region_offset(0)
- , m_rom(nullptr)
- , m_selected_bank{ 0, 0, 0, 0 }
- , m_bank_base{ nullptr, nullptr, nullptr, nullptr }
- , m_sram_address(0)
- , m_control(0)
-{
- memset(m_sram, 0, sizeof(m_sram));
-}
-
-
-void msx_slot_fs4600_device::device_add_mconfig(machine_config &config)
-{
- NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0);
-}
-
-
-void msx_slot_fs4600_device::device_start()
-{
- // Sanity checks
- if (m_rom_region->bytes() < m_region_offset + 0x100000)
- {
- fatalerror("Memory region '%s' is too small for the FS4600 firmware\n", m_rom_region.finder_tag());
- }
-
- m_rom = m_rom_region->base() + m_region_offset;
- m_nvram->set_base(m_sram, 0x1000);
-
- save_item(NAME(m_selected_bank));
- save_item(NAME(m_sram_address));
- save_item(NAME(m_control));
-
- restore_banks();
-}
-
-
-void msx_slot_fs4600_device::device_post_load()
-{
- restore_banks();
-}
-
-
-void msx_slot_fs4600_device::restore_banks()
-{
- for (int i = 0; i < 4; i++)
- {
- m_bank_base[i] = m_rom + ( ( m_selected_bank[i] * 0x4000 ) & 0x0fffff );
- }
-}
-
-
-uint8_t msx_slot_fs4600_device::read(offs_t offset)
-{
- if ((m_control & 0x02) && ((offset & 0x3fff) == 0x3ffd))
- {
- return m_sram[m_sram_address++ & 0xfff];
- }
- if ((m_control & 0x04) && (offset& 0x7ff8) == 0x7ff0)
- {
- return m_selected_bank[(offset >> 1) & 0x03];
- }
- return m_bank_base[offset >> 14][offset & 0x3fff];
-}
-
-
-void msx_slot_fs4600_device::write(offs_t offset, uint8_t data)
-{
- if (offset == 0x7ff9)
- {
- m_control = data;
- }
- else
- {
- if (m_control & 0x02)
- {
- switch (offset & 0x3fff)
- {
- case 0x3ffa:
- m_sram_address = (m_sram_address & 0x00ffff) | (data << 16);
- break;
-
- case 0x3ffb:
- m_sram_address = (m_sram_address & 0xff00ff) | (data << 8);
- break;
-
- case 0x3ffc:
- m_sram_address = (m_sram_address & 0xffff00) | data;
- break;
-
- case 0x3ffd:
- m_sram[m_sram_address++ & 0xfff] = data;
- break;
-
- default:
- logerror("msx_slot_fs4600: Unhandled write %02x to %04x\n", data, offset);
- break;
- }
- }
- else
- {
- switch (offset)
- {
- case 0x6000:
- m_selected_bank[1] = data;
- m_bank_base[1] = m_rom + ( ( m_selected_bank[1] * 0x4000 ) & 0x0fffff );
- break;
-
- case 0x6400:
- m_selected_bank[0] = data;
- m_bank_base[0] = m_rom + ( ( m_selected_bank[0] * 0x4000 ) & 0x0fffff );
- break;
-
- case 0x7000:
- m_selected_bank[2] = data;
- m_bank_base[2] = m_rom + ( ( m_selected_bank[2] * 0x4000 ) & 0x0fffff );
- break;
-
- default:
- logerror("msx_slot_fs4600: Unhandled write %02x to %04x\n", data, offset);
- break;
- }
- }
- }
-}
diff --git a/src/devices/bus/msx_slot/music.cpp b/src/devices/bus/msx_slot/music.cpp
deleted file mode 100644
index 1c5daf86b67..00000000000
--- a/src/devices/bus/msx_slot/music.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Wilbert Pol
-#include "emu.h"
-#include "music.h"
-
-
-DEFINE_DEVICE_TYPE(MSX_SLOT_MUSIC, msx_slot_music_device, "msx_slot_music", "MSX Internal MSX-MUSIC")
-
-
-msx_slot_music_device::msx_slot_music_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : msx_slot_rom_device(mconfig, MSX_SLOT_MUSIC, tag, owner, clock)
- , m_ym2413(nullptr)
- , m_ym2413_tag(nullptr)
-{
-}
-
-
-void msx_slot_music_device::device_start()
-{
- msx_slot_rom_device::device_start();
-
- if (m_ym2413_tag == nullptr)
- {
- fatalerror("msx_slot_music_device: no YM2413 tag specified\n");
- }
-
- m_ym2413 = owner()->subdevice<ym2413_device>(m_ym2413_tag);
-
- if (m_ym2413 == nullptr)
- {
- fatalerror("msx_slot_ym2413_device: Unable to find YM2413 with tag '%s'\n", m_ym2413_tag);
- }
-
- // Install IO read/write handlers
- io_space().install_write_handler(0x7c, 0x7d, write8sm_delegate(*this, FUNC(msx_slot_music_device::write_ym2413)));
-}
-
-
-uint8_t msx_slot_music_device::read(offs_t offset)
-{
- return msx_slot_rom_device::read(offset);
-}
-
-
-void msx_slot_music_device::write_ym2413(offs_t offset, uint8_t data)
-{
- m_ym2413->write(offset & 1, data);
-}
diff --git a/src/devices/bus/msx_slot/panasonic08.cpp b/src/devices/bus/msx_slot/panasonic08.cpp
deleted file mode 100644
index 0c46350051e..00000000000
--- a/src/devices/bus/msx_slot/panasonic08.cpp
+++ /dev/null
@@ -1,164 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Wilbert Pol
-/*
-
- Emulation of the firmware mapper as found in Panasonic FS-A1WX andFS-A1WSX machines.
-
-Todo:
-- Anything besides the basic mapping
-- SRAM?
-*/
-
-#include "emu.h"
-#include "panasonic08.h"
-
-
-DEFINE_DEVICE_TYPE(MSX_SLOT_PANASONIC08, msx_slot_panasonic08_device, "msx_slot_panasonic08", "MSX Internal Panasonic08")
-
-
-msx_slot_panasonic08_device::msx_slot_panasonic08_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, MSX_SLOT_PANASONIC08, tag, owner, clock)
- , msx_internal_slot_interface(mconfig, *this)
- , m_nvram(*this, "nvram")
- , m_rom_region(*this, finder_base::DUMMY_TAG)
- , m_region_offset(0)
- , m_rom(nullptr)
- , m_control(0)
-{
- for (int i = 0; i < 8; i++)
- {
- m_selected_bank[i] = 0;
- m_bank_base[i] = nullptr;
- }
-}
-
-
-void msx_slot_panasonic08_device::device_add_mconfig(machine_config &config)
-{
- NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0);
-}
-
-
-void msx_slot_panasonic08_device::device_start()
-{
- // Sanity checks
- if (m_rom_region->bytes() < m_region_offset + 0x200000)
- {
- fatalerror("Memory region '%s' is too small for the FS4600 firmware\n", m_rom_region.finder_tag());
- }
-
- m_sram.resize(0x4000);
-
- m_nvram->set_base(&m_sram[0], 0x4000);
-
- m_rom = m_rom_region->base() + m_region_offset;
-
- save_item(NAME(m_selected_bank));
- save_item(NAME(m_control));
-
- restore_banks();
-}
-
-
-void msx_slot_panasonic08_device::device_post_load()
-{
- restore_banks();
-}
-
-
-void msx_slot_panasonic08_device::map_bank(int bank)
-{
- if (m_selected_bank[bank] >= 0x80 && m_selected_bank[bank] < 0x84) // Are these banks were sram is present? Mirroring?
- {
- logerror("panasonic08: mapping bank %d to sram\n", bank);
- m_bank_base[bank] = &m_sram[((m_selected_bank[bank] & 0x7f) * 0x2000) & 0x3fff];
- }
- else
- {
- m_bank_base[bank] = m_rom + ( ( m_selected_bank[bank] * 0x2000 ) & 0x1fffff );
- }
-}
-
-
-void msx_slot_panasonic08_device::restore_banks()
-{
- for (int i = 0; i < 8; i++)
- {
- map_bank(i);
- }
-}
-
-
-uint8_t msx_slot_panasonic08_device::read(offs_t offset)
-{
- if (m_control & 0x04)
- {
- // 7ff0 - 6000
- // 7ff1 - 6400
- // 7ff2 - 6800
- // 7ff3 - 6c00
- // 7ff4 - 7000
- // 7ff5 - 7800
- if (offset >= 0x7ff0 && offset < 0x7ff6) // maybe 7ff8 would make more sense here??
- {
- return m_selected_bank[offset - 0x7ff0];
- }
- }
- return m_bank_base[offset >> 13][offset & 0x1fff];
-}
-
-
-void msx_slot_panasonic08_device::write(offs_t offset, uint8_t data)
-{
- if ((offset & 0xc000) == 0x8000 || (offset & 0xc000) == 0x0000)
- {
- uint8_t bank = m_selected_bank[offset >> 13];
- if (bank >= 0x80 && bank < 0x84) // Are these banks were sram is present? Mirroring?
- {
- logerror("msx_slot_panasonic08: writing %02x to sram %04x, bank = %02x\n", data, offset & 0x1fff, bank);
- m_sram[((bank & 0x01) * 0x2000) + (offset & 0x1fff)] = data;
- }
- return;
- }
-
- switch (offset)
- {
- case 0x6000: /* Switched 0x0000-0x1FFF */
- m_selected_bank[0] = data;
- map_bank(0);
- break;
-
- case 0x6400: /* Switches 0x2000-0x3FFF */
- m_selected_bank[1] = data;
- map_bank(1);
- break;
-
- case 0x6800: /* Switches 0x4000-0x5FFF */
- m_selected_bank[2] = data;
- map_bank(2);
- break;
-
- case 0x6c00: /* Switches 0x6000-0x7FFF */
- m_selected_bank[3] = data;
- map_bank(3);
- break;
-
- case 0x7000: /* Switches 0x8000-0x9FFF */
- m_selected_bank[4] = data;
- map_bank(4);
- break;
-
- case 0x7800: /* Switches 0xA000-0xBFFF */
- m_selected_bank[5] = data;
- map_bank(5);
- break;
-
- case 0x7ff9:
- m_control = data;
- break;
-
- default:
- logerror("msx_slot_panasonic08: Unhandled write %02x to %04x\n", data, offset);
- break;
- }
-}
diff --git a/src/devices/bus/msx_slot/ram_mm.cpp b/src/devices/bus/msx_slot/ram_mm.cpp
deleted file mode 100644
index 84498f9afe1..00000000000
--- a/src/devices/bus/msx_slot/ram_mm.cpp
+++ /dev/null
@@ -1,82 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Wilbert Pol
-#include "emu.h"
-#include "ram_mm.h"
-
-DEFINE_DEVICE_TYPE(MSX_SLOT_RAM_MM, msx_slot_ram_mm_device, "msx_slot_ram_mm", "MSX Internal Memory Mapped RAM")
-
-msx_slot_ram_mm_device::msx_slot_ram_mm_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, MSX_SLOT_RAM_MM, tag, owner, clock)
- , msx_internal_slot_interface(mconfig, *this)
- , m_total_size(0)
- , m_bank_mask(0)
- , m_ramio_set_bits(0)
-{
-}
-
-void msx_slot_ram_mm_device::device_start()
-{
- // Valid mapper sizes are 64KB, 128KB, 256KB, 512KB, 1MB, 2MB, and 4MB */
- switch (m_total_size)
- {
- case 64*1024: m_bank_mask = 0x03; break;
- case 128*1024: m_bank_mask = 0x07; break;
- case 256*1024: m_bank_mask = 0x0F; break;
- case 512*1024: m_bank_mask = 0x1F; break;
- case 1024*1024: m_bank_mask = 0x3F; break;
- case 2048*1024: m_bank_mask = 0x7F; break;
- case 4096*1024: m_bank_mask = 0xFF; break;
- default: fatalerror("Invalid memory mapper size specified\n");
- }
-
- m_ram.resize(m_total_size);
-
- for ( int i = 0; i < 4; i++ )
- {
- m_bank_selected[i] = 3 -i;
- m_bank_base[i] = &m_ram[0x4000 * m_bank_selected[i]];
- }
-
- save_item(NAME(m_ram));
- save_item(NAME(m_bank_selected));
-
- // Install IO read/write handlers
- io_space().install_read_handler(0xFC, 0xFF, read8sm_delegate(*this, FUNC(msx_slot_ram_mm_device::read_mapper_bank)));
- io_space().install_write_handler(0xFC, 0xFF, write8sm_delegate(*this, FUNC(msx_slot_ram_mm_device::write_mapper_bank)));
-}
-
-void msx_slot_ram_mm_device::device_post_load()
-{
- restore_banks();
-}
-
-void msx_slot_ram_mm_device::restore_banks()
-{
- for ( int i = 0; i < 3; i++ )
- {
- m_bank_base[i] = &m_ram[0x4000 * ( m_bank_selected[i] & m_bank_mask )];
- }
-}
-
-uint8_t msx_slot_ram_mm_device::read(offs_t offset)
-{
- return m_bank_base[offset >> 14][offset & 0x3fff];
-}
-
-void msx_slot_ram_mm_device::write(offs_t offset, uint8_t data)
-{
- m_bank_base[offset >> 14][offset & 0x3fff] = data;
-}
-
-uint8_t msx_slot_ram_mm_device::read_mapper_bank(offs_t offset)
-{
- return m_bank_selected[offset & 3] | m_ramio_set_bits;
-}
-
-void msx_slot_ram_mm_device::write_mapper_bank(offs_t offset, uint8_t data)
-{
- offset &= 3;
-
- m_bank_selected[offset] = data;
- m_bank_base[offset] = &m_ram[0x4000 * ( m_bank_selected[offset] & m_bank_mask )];
-}
diff --git a/src/devices/bus/msx_slot/ram_mm.h b/src/devices/bus/msx_slot/ram_mm.h
deleted file mode 100644
index 55f13659a4c..00000000000
--- a/src/devices/bus/msx_slot/ram_mm.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Wilbert Pol
-#ifndef MAME_BUS_MSX_SLOT_RAM_MM_H
-#define MAME_BUS_MSX_SLOT_RAM_MM_H
-
-#include "slot.h"
-
-class msx_slot_ram_mm_device : public device_t, public msx_internal_slot_interface
-{
-public:
- msx_slot_ram_mm_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- msx_slot_ram_mm_device &set_total_size(uint32_t total_size) { m_total_size = total_size; return *this; }
- msx_slot_ram_mm_device &set_ramio_bits(uint8_t ramio_set_bits) { m_ramio_set_bits = ramio_set_bits; return *this; }
-
- virtual uint8_t read(offs_t offset) override;
- virtual void write(offs_t offset, uint8_t data) override;
-
-protected:
- virtual void device_start() override;
- virtual void device_post_load() override;
-
- void restore_banks();
-
-private:
- uint8_t read_mapper_bank(offs_t offset);
- void write_mapper_bank(offs_t offset, uint8_t data);
-
- std::vector<uint8_t> m_ram;
- uint32_t m_total_size;
- uint8_t m_bank_mask;
- uint8_t m_bank_selected[4];
- uint8_t *m_bank_base[4];
- uint8_t m_ramio_set_bits;
-};
-
-DECLARE_DEVICE_TYPE(MSX_SLOT_RAM_MM, msx_slot_ram_mm_device)
-
-#endif // MAME_BUS_MSX_SLOT_RAM_MM_H
diff --git a/src/devices/bus/msx_slot/sony08.cpp b/src/devices/bus/msx_slot/sony08.cpp
deleted file mode 100644
index 652ed134457..00000000000
--- a/src/devices/bus/msx_slot/sony08.cpp
+++ /dev/null
@@ -1,172 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Wilbert Pol
-/*
-
- Emulation of the firmware mapper as found in Sony HB-F1XDJ and HB-F1XV machines.
-
-*/
-
-#include "emu.h"
-#include "sony08.h"
-
-
-DEFINE_DEVICE_TYPE(MSX_SLOT_SONY08, msx_slot_sony08_device, "msx_slot_sony08", "MSX Internal SONY08")
-
-
-msx_slot_sony08_device::msx_slot_sony08_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, MSX_SLOT_SONY08, tag, owner, clock)
- , msx_internal_slot_interface(mconfig, *this)
- , m_nvram(*this, "nvram")
- , m_rom_region(*this, finder_base::DUMMY_TAG)
- , m_region_offset(0)
- , m_rom(nullptr)
-{
- for (int i = 0; i < 8; i++)
- {
- m_selected_bank[i] = 0;
- m_bank_base[i] = nullptr;
- }
- memset(m_sram, 0, sizeof(m_sram));
-}
-
-
-void msx_slot_sony08_device::device_add_mconfig(machine_config &config)
-{
- NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0);
-}
-
-
-void msx_slot_sony08_device::device_start()
-{
- // Sanity checks
- if (m_rom_region->bytes() < m_region_offset + 0x100000)
- {
- fatalerror("Memory region '%s' is too small for the SONY08 firmware\n", m_rom_region.finder_tag());
- }
-
- m_rom = m_rom_region->base() + m_region_offset;
-
- m_nvram->set_base(m_sram, 0x4000);
-
- save_item(NAME(m_selected_bank));
-
- restore_banks();
-}
-
-
-void msx_slot_sony08_device::device_post_load()
-{
- restore_banks();
-}
-
-
-void msx_slot_sony08_device::map_bank(int bank)
-{
- if (bank < 2)
- {
- return;
- }
-
- // Special banks
- if (bank == 6 || bank == 7)
- {
- m_bank_base[bank] = m_rom + 0x80000 + (m_selected_bank[bank] * 0x800);
- return;
- }
-
- m_bank_base[bank] = m_rom + ((m_selected_bank[bank] * 0x2000) & 0xFFFFF);
- if (bank == 2)
- {
- if (m_selected_bank[bank] & 0x80)
- {
- m_bank_base[0] = m_sram;
- m_bank_base[1] = m_sram + 0x2000;
- }
- else
- {
- m_bank_base[0] = nullptr;
- m_bank_base[1] = nullptr;
- }
- }
-}
-
-
-void msx_slot_sony08_device::restore_banks()
-{
- for (int i = 0; i < 8; i++)
- {
- map_bank(i);
- }
-}
-
-
-uint8_t msx_slot_sony08_device::read(offs_t offset)
-{
- if (offset >= 0xc000)
- {
- return 0xFF;
- }
-
- if ((offset & 0xf000) == 0x7000 && (m_selected_bank[3] & 0x80))
- {
- return m_bank_base[6 + ((offset >> 11) & 0x01)][offset & 0x7ff];
- }
-
- const uint8_t *mem = m_bank_base[offset >> 13];
-
- if (mem)
- {
- return mem[offset & 0x1fff];
- }
- return 0xFF;
-}
-
-
-void msx_slot_sony08_device::write(offs_t offset, uint8_t data)
-{
- if (offset < 0x4000)
- {
- if (m_bank_base[0] != nullptr)
- {
- m_sram[offset & 0x3fff] = data;
- return;
- }
- }
-
- switch (offset)
- {
- case 0x4FFF:
- m_selected_bank[2] = data;
- map_bank(2);
- break;
-
- case 0x6FFF: // 6000-7FFF
- m_selected_bank[3] = data;
- map_bank(3);
- break;
-
- case 0x77FF:
- m_selected_bank[6] = data;
- map_bank(6);
- break;
-
- case 0x7FFF:
- m_selected_bank[7] = data;
- map_bank(7);
- break;
-
- case 0x8FFF:
- m_selected_bank[4] = data;
- map_bank(4);
- break;
-
- case 0xAFFF:
- m_selected_bank[5] = data;
- map_bank(5);
- break;
-
- default:
- logerror("Unhandled write %02x to %04x\n", data, offset);
- break;
- }
-}
diff --git a/src/devices/bus/mtu130/board.cpp b/src/devices/bus/mtu130/board.cpp
new file mode 100644
index 00000000000..cfdbecc8c05
--- /dev/null
+++ b/src/devices/bus/mtu130/board.cpp
@@ -0,0 +1,37 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+
+// MTU-130 extension board
+
+#include "emu.h"
+#include "board.h"
+
+DEFINE_DEVICE_TYPE(MTU130_EXTENSION, mtu130_extension_device, "mtu130_extension", "MTU130 extension board slot")
+
+mtu130_extension_device::mtu130_extension_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, MTU130_EXTENSION, tag, owner, clock),
+ device_single_card_slot_interface<mtu130_extension_interface>(mconfig, *this),
+ m_irq_merger(*this, finder_base::DUMMY_TAG)
+{
+}
+
+void mtu130_extension_device::map_io(address_space_installer &space)
+{
+ auto dev = get_card_device();
+ if(dev)
+ dev->map_io(space);
+}
+
+void mtu130_extension_device::device_start()
+{
+}
+
+mtu130_extension_interface::mtu130_extension_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "extension_board")
+{
+}
+
+void mtu130_extension_interface::set_irq(bool state) const
+{
+ downcast<mtu130_extension_device *>(device().owner())->set_irq(state);
+}
diff --git a/src/devices/bus/mtu130/board.h b/src/devices/bus/mtu130/board.h
new file mode 100644
index 00000000000..a7556757c5e
--- /dev/null
+++ b/src/devices/bus/mtu130/board.h
@@ -0,0 +1,69 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+
+// MTU-130 extension board
+
+#ifndef MAME_BUS_MTU130_EXTENSION_H
+#define MAME_BUS_MTU130_EXTENSION_H
+
+#include "machine/input_merger.h"
+
+class mtu130_extension_interface : public device_interface
+{
+public:
+ mtu130_extension_interface(const machine_config &mconfig, device_t &device);
+ virtual ~mtu130_extension_interface() = default;
+
+ // Read/write on banks 2/3
+ virtual void write23(offs_t offset, u8 data) = 0;
+ virtual u8 read23(offs_t offset) = 0;
+
+ // Map i/o in the bfxx area.
+ virtual void map_io(address_space_installer &space) = 0;
+
+ void set_irq(bool state) const;
+};
+
+
+
+class mtu130_extension_device : public device_t, public device_single_card_slot_interface<mtu130_extension_interface>
+{
+public:
+ mtu130_extension_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
+ virtual ~mtu130_extension_device() = default;
+
+ // Configuration
+ void set_slot_id(u8 slot_id) { m_slot_id = slot_id; }
+ template<class T> void set_irq_merger(T &&tag) { m_irq_merger.set_tag(std::forward<T>(tag)); }
+
+ // Read/write on banks 2/3, read return 0xff if not driven
+ void write23(offs_t offset, u8 data) {
+ auto dev = get_card_device();
+ if(dev)
+ dev->write23(offset, data);
+ }
+
+ u8 read23(offs_t offset) {
+ auto dev = get_card_device();
+ return dev ? dev->read23(offset) : 0xff;
+ }
+
+ void map_io(address_space_installer &space);
+
+ void set_irq(bool state) const {
+ switch(m_slot_id) {
+ case 0: m_irq_merger->in_w<10>(state); break;
+ case 1: m_irq_merger->in_w<11>(state); break;
+ case 2: m_irq_merger->in_w<12>(state); break;
+ }
+ }
+
+protected:
+ required_device<input_merger_device> m_irq_merger;
+ u8 m_slot_id;
+ virtual void device_start() override;
+};
+
+DECLARE_DEVICE_TYPE(MTU130_EXTENSION, mtu130_extension_device)
+
+#endif
diff --git a/src/devices/bus/mtu130/datamover.cpp b/src/devices/bus/mtu130/datamover.cpp
new file mode 100644
index 00000000000..aeaedcc5f46
--- /dev/null
+++ b/src/devices/bus/mtu130/datamover.cpp
@@ -0,0 +1,172 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+
+// Datamover - 68K-based extension board
+
+#include "emu.h"
+#include "datamover.h"
+
+DEFINE_DEVICE_TYPE(MTU130_DATAMOVER0, mtu130_datamover0_device, "datamover0", "Datamover")
+DEFINE_DEVICE_TYPE(MTU130_DATAMOVER1, mtu130_datamover1_device, "datamover1", "Datamover (alt address)")
+
+mtu130_datamover0_device::mtu130_datamover0_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ mtu130_datamover_base_device(mconfig, MTU130_DATAMOVER0, tag, owner, 0xbfbe, clock)
+{
+}
+
+mtu130_datamover1_device::mtu130_datamover1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ mtu130_datamover_base_device(mconfig, MTU130_DATAMOVER1, tag, owner, 0xbfbc, clock)
+{
+}
+
+mtu130_datamover_base_device::mtu130_datamover_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t base_address, uint32_t clock) :
+ device_t(mconfig, type, tag, owner, clock),
+ mtu130_extension_interface(mconfig, *this),
+ m_cpu(*this, "cpu"),
+ m_ram(*this, "ram"),
+ m_base_address(base_address)
+{
+}
+
+
+void mtu130_datamover_base_device::write23(offs_t offset, u8 data)
+{
+ if(!m_ram_visible)
+ return;
+ if(m_ram_xor)
+ offset ^= 1;
+ offset |= m_ram_bank << 17;
+ if(offset & 1)
+ m_ram[offset >> 1] = (m_ram[offset >> 1] & 0xff00) | data;
+ else
+ m_ram[offset >> 1] = (m_ram[offset >> 1] & 0x00ff) | (data << 8);
+}
+
+u8 mtu130_datamover_base_device::read23(offs_t offset)
+{
+ if(!m_ram_visible)
+ return 0xff;
+ if(m_ram_xor)
+ offset ^= 1;
+ offset |= m_ram_bank << 17;
+ if(offset & 1)
+ return m_ram[offset >> 1];
+ else
+ return m_ram[offset >> 1] >> 8;
+
+}
+
+void mtu130_datamover_base_device::map_io(address_space_installer &space)
+{
+ space.install_device(m_base_address, m_base_address+1, *this, &mtu130_datamover_base_device::m6502_map);
+}
+
+void mtu130_datamover_base_device::device_start()
+{
+ save_item(NAME(m_ram_visible));
+ save_item(NAME(m_ram_xor));
+ save_item(NAME(m_ram_bank));
+ save_item(NAME(m_irq4_req));
+ save_item(NAME(m_irq7_req));
+ save_item(NAME(m_irq6502_req));
+ save_item(NAME(m_irq6502_en));
+}
+
+void mtu130_datamover_base_device::device_reset()
+{
+ m_cpu->set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
+ m_cpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
+
+ m_ram_visible = true;
+ m_ram_xor = false;
+ m_ram_bank = 0;
+ m_irq4_req = false;
+ m_irq7_req = false;
+ m_irq6502_req = false;
+ m_irq6502_en = false;
+}
+
+
+void mtu130_datamover_base_device::device_add_mconfig(machine_config &config)
+{
+ M68000(config, m_cpu, 10_MHz_XTAL/10*8);
+ m_cpu->set_addrmap(AS_PROGRAM, &mtu130_datamover_base_device::m68k_map);
+ m_cpu->set_addrmap(m68000_device::AS_CPU_SPACE, &mtu130_datamover_base_device::m68k_cs_map);
+}
+
+void mtu130_datamover_base_device::m6502_map(address_map &map)
+{
+ map(0, 0).r(FUNC(mtu130_datamover_base_device::status_r)).w(FUNC(mtu130_datamover_base_device::control_w));
+ map(1, 1).w(FUNC(mtu130_datamover_base_device::enable_w));
+}
+
+void mtu130_datamover_base_device::m68k_map(address_map &map)
+{
+ map(0x000000, 0x0fffff).ram().share(m_ram);
+ map(0x100001, 0x100001).rw(FUNC(mtu130_datamover_base_device::irq_req_r), FUNC(mtu130_datamover_base_device::irq_req_w));
+}
+
+void mtu130_datamover_base_device::m68k_cs_map(address_map &map)
+{
+ map(0xfffff3, 0xfffff3).lr8(NAME([] () -> u8 { return 0x19; }));
+ map(0xfffff5, 0xfffff5).lr8(NAME([] () -> u8 { return 0x1a; }));
+ map(0xfffff7, 0xfffff7).lr8(NAME([] () -> u8 { return 0x1b; }));
+ map(0xfffff9, 0xfffff9).lr8(NAME([this] () -> u8 { m_irq4_req = false; m_cpu->set_input_line(4, CLEAR_LINE); return 0x1c; }));
+ map(0xfffffb, 0xfffffb).lr8(NAME([] () -> u8 { return 0x1d; }));
+ map(0xfffffd, 0xfffffd).lr8(NAME([] () -> u8 { return 0x1e; }));
+ map(0xffffff, 0xffffff).lr8(NAME([this] () -> u8 { m_irq7_req = false; m_cpu->set_input_line(7, CLEAR_LINE); return 0x1f; }));
+}
+
+void mtu130_datamover_base_device::control_w(u8 data)
+{
+ if(data & 0x80)
+ m_irq6502_req = false;
+
+ if(data & 0x40)
+ m_irq4_req = true;
+
+ m_irq6502_en = data & 0x20;
+
+ if(data & 0x10)
+ m_irq7_req = true;
+
+ m_cpu->set_input_line(INPUT_LINE_HALT, data & 0x08 ? CLEAR_LINE : ASSERT_LINE);
+ m_cpu->set_input_line(INPUT_LINE_RESET, data & 0x04 ? CLEAR_LINE : ASSERT_LINE);
+
+ if(!(data & 0x04))
+ m_irq4_req = m_irq7_req = m_irq6502_req = false;
+
+ m_ram_xor = data & 0x02;
+
+ set_irq(m_irq6502_req && m_irq6502_en);
+ m_cpu->set_input_line(4, m_irq4_req ? ASSERT_LINE : CLEAR_LINE);
+ m_cpu->set_input_line(7, m_irq7_req ? ASSERT_LINE : CLEAR_LINE);
+}
+
+void mtu130_datamover_base_device::irq_req_w(u8 data)
+{
+ m_irq6502_req = data & 0x01;
+ set_irq(m_irq6502_req && m_irq6502_en);
+}
+
+u8 mtu130_datamover_base_device::irq_req_r()
+{
+ return m_irq6502_req;
+}
+
+void mtu130_datamover_base_device::enable_w(u8 data)
+{
+ m_ram_visible = !(data & 8);
+ m_ram_bank = data & 7;
+}
+
+u8 mtu130_datamover_base_device::status_r()
+{
+ return
+ (m_irq6502_req ? 0x80 : 0x00) |
+ (m_irq4_req ? 0x40 : 0x00) |
+ (m_irq6502_en ? 0x20 : 0x00) |
+ (m_cpu->input_state(INPUT_LINE_HALT) ? 0x00 : 0x10) |
+ (m_ram_visible ? 0x00 : 0x08) |
+ m_ram_bank;
+}
diff --git a/src/devices/bus/mtu130/datamover.h b/src/devices/bus/mtu130/datamover.h
new file mode 100644
index 00000000000..172a75b97b3
--- /dev/null
+++ b/src/devices/bus/mtu130/datamover.h
@@ -0,0 +1,72 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+
+// Datamover - 68K-based extension board
+
+#ifndef MAME_BUS_MTU130_DATAMOVER_H
+#define MAME_BUS_MTU130_DATAMOVER_H
+
+#include "board.h"
+#include "cpu/m68000/m68000.h"
+
+class mtu130_datamover_base_device : public device_t, public mtu130_extension_interface
+{
+public:
+ mtu130_datamover_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t base_address, uint32_t clock = 0);
+ virtual ~mtu130_datamover_base_device() = default;
+
+ virtual void write23(offs_t offset, u8 data) override;
+ virtual u8 read23(offs_t offset) override;
+
+ virtual void map_io(address_space_installer &space) override;
+
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override;
+
+private:
+ required_device<m68000_device> m_cpu;
+ required_shared_ptr<u16> m_ram;
+
+ bool m_ram_visible;
+ bool m_ram_xor;
+ u8 m_ram_bank;
+ bool m_irq4_req;
+ bool m_irq7_req;
+ bool m_irq6502_req;
+ bool m_irq6502_en;
+
+ uint32_t m_base_address;
+
+ void m6502_map(address_map &map);
+ void m68k_map(address_map &map);
+ void m68k_cs_map(address_map &map);
+
+ void control_w(u8 data);
+ void enable_w(u8 data);
+ u8 status_r();
+
+ void irq_req_w(u8 data);
+ u8 irq_req_r();
+};
+
+class mtu130_datamover0_device : public mtu130_datamover_base_device
+{
+public:
+ mtu130_datamover0_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
+ virtual ~mtu130_datamover0_device() = default;
+};
+
+class mtu130_datamover1_device : public mtu130_datamover_base_device
+{
+public:
+ mtu130_datamover1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
+ virtual ~mtu130_datamover1_device() = default;
+};
+
+DECLARE_DEVICE_TYPE(MTU130_DATAMOVER0, mtu130_datamover0_device)
+DECLARE_DEVICE_TYPE(MTU130_DATAMOVER1, mtu130_datamover1_device)
+
+#endif
diff --git a/src/devices/bus/mtx/cfx.cpp b/src/devices/bus/mtx/cfx.cpp
index d80290606c9..a0c75ec89ca 100644
--- a/src/devices/bus/mtx/cfx.cpp
+++ b/src/devices/bus/mtx/cfx.cpp
@@ -52,7 +52,7 @@ void mtx_cfx_device::device_add_mconfig(machine_config &config)
m_pia->out_pb_callback().set([this](uint8_t data) { m_ide_data = (m_ide_data & 0x00ff) | (data << 8); });
m_pia->out_pc_callback().set(FUNC(mtx_cfx_device::portc_w));
- ATA_INTERFACE(config, m_ide).options(ata_devices, "hdd", nullptr, false);
+ ATA_INTERFACE(config, m_ide).options(ata_devices, "cf", nullptr, false);
}
diff --git a/src/devices/bus/mtx/exp.cpp b/src/devices/bus/mtx/exp.cpp
index 4b3f376977a..3a8a5f64801 100644
--- a/src/devices/bus/mtx/exp.cpp
+++ b/src/devices/bus/mtx/exp.cpp
@@ -42,7 +42,7 @@ void device_mtx_exp_interface::rom_alloc(uint32_t size, const char *tag)
{
if (m_rom == nullptr)
{
- m_rom = device().machine().memory().region_alloc(std::string(tag).append(":cart:rom").c_str(), size, 1, ENDIANNESS_LITTLE)->base();
+ m_rom = device().machine().memory().region_alloc(std::string(tag).append(":cart:rom"), size, 1, ENDIANNESS_LITTLE)->base();
m_rom_size = size;
}
}
@@ -77,11 +77,6 @@ mtx_exp_slot_device::mtx_exp_slot_device(const machine_config &mconfig, const ch
void mtx_exp_slot_device::device_start()
{
m_card = get_card_device();
-
- // resolve callbacks
- m_busreq_handler.resolve_safe();
- m_int_handler.resolve_safe();
- m_nmi_handler.resolve_safe();
}
@@ -89,17 +84,14 @@ void mtx_exp_slot_device::device_start()
// call_load
//-------------------------------------------------
-image_init_result mtx_exp_slot_device::call_load()
+std::pair<std::error_condition, std::string> mtx_exp_slot_device::call_load()
{
if (m_card)
{
- uint32_t size = !loaded_through_softlist() ? length() : get_software_region_length("rom");
+ uint32_t const size = !loaded_through_softlist() ? length() : get_software_region_length("rom");
if (size % 0x2000)
- {
- seterror(image_error::INVALIDIMAGE, "Unsupported cartridge size");
- return image_init_result::FAIL;
- }
+ return std::make_pair(image_error::INVALIDLENGTH, "Unsupported cartridge size (must be a multiple of 8K)");
m_card->rom_alloc(size, tag());
@@ -109,7 +101,7 @@ image_init_result mtx_exp_slot_device::call_load()
memcpy(m_card->get_rom_base(), get_software_region("rom"), size);
}
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
diff --git a/src/devices/bus/mtx/exp.h b/src/devices/bus/mtx/exp.h
index dd23586c05e..937db9431d3 100644
--- a/src/devices/bus/mtx/exp.h
+++ b/src/devices/bus/mtx/exp.h
@@ -49,24 +49,24 @@ public:
auto nmi_handler() { return m_nmi_handler.bind(); }
// for the card to use
- DECLARE_WRITE_LINE_MEMBER( busreq_w ) { m_busreq_handler(state); }
- DECLARE_WRITE_LINE_MEMBER( int_w ) { m_int_handler(state); }
- DECLARE_WRITE_LINE_MEMBER( nmi_w ) { m_nmi_handler(state); }
+ void busreq_w(int state) { m_busreq_handler(state); }
+ void int_w(int state) { m_int_handler(state); }
+ void nmi_w(int state) { m_nmi_handler(state); }
virtual void bankswitch(uint8_t data);
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
- // image-level overrides
- virtual image_init_result call_load() override;
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
virtual bool is_reset_on_load() const noexcept override { return true; }
virtual const char *image_interface() const noexcept override { return "mtx_cart"; }
virtual const char *file_extensions() const noexcept override { return "bin,rom"; }
- // slot interface overrides
+ // device_slot_interface implementation
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
private:
diff --git a/src/devices/bus/mtx/sdx.cpp b/src/devices/bus/mtx/sdx.cpp
index 0a27e48f309..3c25ee20568 100644
--- a/src/devices/bus/mtx/sdx.cpp
+++ b/src/devices/bus/mtx/sdx.cpp
@@ -6,10 +6,11 @@
**********************************************************************/
-
#include "emu.h"
#include "sdx.h"
+#include "formats/mtx_dsk.h"
+
//**************************************************************************
// DEVICE DEFINITIONS
@@ -137,8 +138,8 @@ void mtx_sdxbas_device::device_add_mconfig(machine_config &config)
MB8877(config, m_fdc, 8_MHz_XTAL / 8);
m_fdc->hld_wr_callback().set(FUNC(mtx_sdx_device::motor_w));
- FLOPPY_CONNECTOR(config, "fdc:0", sdx_floppies, "525qd", mtx_sdx_device::floppy_formats).enable_sound(true);
- FLOPPY_CONNECTOR(config, "fdc:1", sdx_floppies, "525qd", mtx_sdx_device::floppy_formats).enable_sound(true);
+ for (auto &floppy : m_floppy)
+ FLOPPY_CONNECTOR(config, floppy, sdx_floppies, "525qd", mtx_sdx_device::floppy_formats).enable_sound(true);
}
void mtx_sdxcpm_device::device_add_mconfig(machine_config &config)
@@ -147,8 +148,8 @@ void mtx_sdxcpm_device::device_add_mconfig(machine_config &config)
MB8877(config, m_fdc, 8_MHz_XTAL / 8);
m_fdc->hld_wr_callback().set(FUNC(mtx_sdx_device::motor_w));
- FLOPPY_CONNECTOR(config, "fdc:0", sdx_floppies, "525qd", mtx_sdx_device::floppy_formats).enable_sound(true);
- FLOPPY_CONNECTOR(config, "fdc:1", sdx_floppies, "525qd", mtx_sdx_device::floppy_formats).enable_sound(true);
+ for (auto &floppy : m_floppy)
+ FLOPPY_CONNECTOR(config, floppy, sdx_floppies, "525qd", mtx_sdx_device::floppy_formats).enable_sound(true);
/* 80 column video card - required to be installed in MTX internally */
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
@@ -189,9 +190,8 @@ mtx_sdx_device::mtx_sdx_device(const machine_config &mconfig, device_type type,
, device_mtx_exp_interface(mconfig, *this)
, m_sdx_rom(*this, "sdx_rom")
, m_fdc(*this, "fdc")
- , m_floppy0(*this, "fdc:0")
- , m_floppy1(*this, "fdc:1")
- , m_dsw(*this, "DSW%u", 0)
+ , m_floppy(*this, "fdc:%u", 0U)
+ , m_dsw(*this, "DSW%u", 0U)
{
}
@@ -282,10 +282,11 @@ uint8_t mtx_sdx_device::sdx_status_r()
data |= m_dsw[BIT(m_control, 0)]->read() & 0x0f;
- data |= (m_floppy0->get_device() && m_floppy1->get_device()) ? 0x10 : 0x00;
+ data |= (m_floppy[0]->get_device() && m_floppy[1]->get_device()) ? 0x10 : 0x00;
- if (m_floppy)
- data |= m_floppy->ready_r() ? 0x00 : 0x20;
+ floppy_image_device *floppy = m_floppy[BIT(m_control, 0)]->get_device();
+ if (floppy)
+ data |= floppy->ready_r() ? 0x00 : 0x20;
data |= m_fdc->intrq_r() ? 0x40 : 0x00;
data |= m_fdc->drq_r() ? 0x80 : 0x00;
@@ -307,22 +308,22 @@ void mtx_sdx_device::sdx_control_w(uint8_t data)
m_control = data;
/* bit 0: drive select */
- m_floppy = BIT(data, 0) ? m_floppy1->get_device() : m_floppy0->get_device();
+ floppy_image_device *floppy = m_floppy[BIT(data, 0)]->get_device();
- m_fdc->set_floppy(m_floppy);
+ m_fdc->set_floppy(floppy);
- if (m_floppy)
+ if (floppy)
{
/* bit 1: side select */
- m_floppy->ss_w(BIT(data, 1));
+ floppy->ss_w(BIT(data, 1));
logerror("motor on %d\n", BIT(data, 2));
/* bit 2: motor on */
- m_floppy->mon_w(!(BIT(data, 2) || m_fdc->hld_r()));
+ floppy->mon_w(!(BIT(data, 2) || m_fdc->hld_r()));
logerror("head load %d\n", m_fdc->hld_r());
/* bit 3: motor ready */
//if (BIT(data, 3))
- //m_floppy->mon_w(!BIT(data, 2));
- //m_floppy->mon_w(!BIT(data, 3));
+ //floppy->mon_w(!BIT(data, 2));
+ //floppy->mon_w(!BIT(data, 3));
logerror("motor ready %d\n", BIT(data, 3));
}
@@ -330,10 +331,10 @@ void mtx_sdx_device::sdx_control_w(uint8_t data)
m_fdc->dden_w(!BIT(data, 4));
}
-WRITE_LINE_MEMBER(mtx_sdx_device::motor_w)
+void mtx_sdx_device::motor_w(int state)
{
- if (m_floppy0->get_device()) m_floppy0->get_device()->mon_w(0);
- if (m_floppy1->get_device()) m_floppy1->get_device()->mon_w(0);
+ if (m_floppy[0]->get_device()) m_floppy[0]->get_device()->mon_w(0);
+ if (m_floppy[1]->get_device()) m_floppy[1]->get_device()->mon_w(0);
}
//-------------------------------------------------
diff --git a/src/devices/bus/mtx/sdx.h b/src/devices/bus/mtx/sdx.h
index 5bed06258aa..0fd05343d24 100644
--- a/src/devices/bus/mtx/sdx.h
+++ b/src/devices/bus/mtx/sdx.h
@@ -6,7 +6,6 @@
**********************************************************************/
-
#ifndef MAME_BUS_MTX_EXP_SDX_H
#define MAME_BUS_MTX_EXP_SDX_H
@@ -14,7 +13,6 @@
#include "imagedev/floppy.h"
#include "machine/wd_fdc.h"
#include "video/mc6845.h"
-#include "formats/mtx_dsk.h"
#include "emupal.h"
#include "screen.h"
@@ -34,7 +32,7 @@ public:
uint8_t sdx_status_r();
void sdx_control_w(uint8_t data);
- DECLARE_WRITE_LINE_MEMBER(motor_w);
+ void motor_w(int state);
protected:
// construction/destruction
@@ -42,10 +40,8 @@ protected:
required_memory_region m_sdx_rom;
required_device<mb8877_device> m_fdc;
- required_device<floppy_connector> m_floppy0;
- required_device<floppy_connector> m_floppy1;
+ required_device_array<floppy_connector, 2> m_floppy;
required_ioport_array<2> m_dsw;
- floppy_image_device *m_floppy;
uint8_t m_control;
};
diff --git a/src/devices/bus/multibus/isbc202.cpp b/src/devices/bus/multibus/isbc202.cpp
index 3e281fa230f..97b7bca71ae 100644
--- a/src/devices/bus/multibus/isbc202.cpp
+++ b/src/devices/bus/multibus/isbc202.cpp
@@ -61,6 +61,7 @@
#include "emu.h"
#include "isbc202.h"
#include "formats/img_dsk.h"
+#include "formats/fs_isis.h"
// Debugging
#include "logmacro.h"
@@ -315,7 +316,7 @@ void isbc202_device::io_w(address_space &space, offs_t offset, uint8_t data)
}
}
-WRITE_LINE_MEMBER(isbc202_device::co_w)
+void isbc202_device::co_w(int state)
{
m_inputs[ IN_SEL_CO ] = state;
m_mcu->fi_w(state);
@@ -480,6 +481,7 @@ static void isbc202_floppies(device_slot_interface &device)
static void isbc202_floppy_formats(format_registration &fr)
{
fr.add(FLOPPY_IMG_FORMAT);
+ fr.add(fs::ISIS);
};
void isbc202_device::device_add_mconfig(machine_config &config)
@@ -743,7 +745,7 @@ void isbc202_device::set_output()
LOG_BUS("CPU out of wait state\n");
xack_w(0);
// Ensure the MCU executes a few instruction before the CPU
- machine().scheduler().boost_interleave(attotime::from_usec(1) , attotime::from_usec(5));
+ machine().scheduler().add_quantum(attotime::from_usec(1) , attotime::from_usec(5));
m_inputs[ IN_SEL_START ] = false;
}
if (BIT(m_mask , 4)) {
diff --git a/src/devices/bus/multibus/isbc202.h b/src/devices/bus/multibus/isbc202.h
index 6fc94179364..6f09512a9d1 100644
--- a/src/devices/bus/multibus/isbc202.h
+++ b/src/devices/bus/multibus/isbc202.h
@@ -31,7 +31,7 @@ public:
uint8_t io_r(address_space &space, offs_t offset);
void io_w(address_space &space, offs_t offset, uint8_t data);
- DECLARE_WRITE_LINE_MEMBER(co_w);
+ void co_w(int state);
uint8_t px_r();
diff --git a/src/devices/bus/multibus/labtam_3232.cpp b/src/devices/bus/multibus/labtam_3232.cpp
index 35181ea4a78..11eab51a107 100644
--- a/src/devices/bus/multibus/labtam_3232.cpp
+++ b/src/devices/bus/multibus/labtam_3232.cpp
@@ -34,10 +34,17 @@ labtam_3232_device::labtam_3232_device(machine_config const &mconfig, char const
ROM_START(labtam_3232)
ROM_REGION32_LE(0x10000, "eprom", 0)
- ROM_LOAD32_BYTE("sash_0__g87.bin", 0x0000, 0x4000, CRC(31132de0) SHA1(39f7c1f146346a53c253284ba3437b5f9217f439))
- ROM_LOAD32_BYTE("sash_1__g87.bin", 0x0001, 0x4000, CRC(09b4e8ba) SHA1(b722386fc6e4a634472d5a0501eb41e12d89f7dc))
- ROM_LOAD32_BYTE("sash_2__g87.bin", 0x0002, 0x4000, CRC(d76457b0) SHA1(efd18e0347b0181a0d2aa80098bd4fdb60a82788))
- ROM_LOAD32_BYTE("sash_3__g87.bin", 0x0003, 0x4000, CRC(7817d1b8) SHA1(032df47e1ba34653b5837f68eefa3ecaac17a483))
+ ROM_SYSTEM_BIOS(0, "i87", "Version I87 87/09/28")
+ ROMX_LOAD("sash_0__i87.rom0", 0x0000, 0x4000, CRC(52d760bb) SHA1(bb5d281cc27799827433c6d30570db84e3dfd5b0), ROM_SKIP(3) | ROM_BIOS(0))
+ ROMX_LOAD("sash_1__i87.rom1", 0x0001, 0x4000, CRC(a6e8bf4b) SHA1(c4435d1b0692040b0e515dd1944784c1efd853dc), ROM_SKIP(3) | ROM_BIOS(0))
+ ROMX_LOAD("sash_2__i87.rom2", 0x0002, 0x4000, CRC(5346c475) SHA1(3651b6afc9712efd181221c56dd3d2f954d226cd), ROM_SKIP(3) | ROM_BIOS(0))
+ ROMX_LOAD("sash_3__i87.rom3", 0x0003, 0x4000, CRC(ec3c0c5b) SHA1(0959d9257e94caa2f18aeb00f55824426084b8c8), ROM_SKIP(3) | ROM_BIOS(0))
+
+ ROM_SYSTEM_BIOS(1, "g87", "Version G87 87/07/09")
+ ROMX_LOAD("sash_0__g87.rom0", 0x0000, 0x4000, CRC(31132de0) SHA1(39f7c1f146346a53c253284ba3437b5f9217f439), ROM_SKIP(3) | ROM_BIOS(1))
+ ROMX_LOAD("sash_1__g87.rom1", 0x0001, 0x4000, CRC(09b4e8ba) SHA1(b722386fc6e4a634472d5a0501eb41e12d89f7dc), ROM_SKIP(3) | ROM_BIOS(1))
+ ROMX_LOAD("sash_2__g87.rom2", 0x0002, 0x4000, CRC(d76457b0) SHA1(efd18e0347b0181a0d2aa80098bd4fdb60a82788), ROM_SKIP(3) | ROM_BIOS(1))
+ ROMX_LOAD("sash_3__g87.rom3", 0x0003, 0x4000, CRC(7817d1b8) SHA1(032df47e1ba34653b5837f68eefa3ecaac17a483), ROM_SKIP(3) | ROM_BIOS(1))
ROM_END
static INPUT_PORTS_START(labtam_3232)
diff --git a/src/devices/bus/multibus/labtam_vducom.cpp b/src/devices/bus/multibus/labtam_vducom.cpp
index 3ea3647ad5b..ba80aa45f0f 100644
--- a/src/devices/bus/multibus/labtam_vducom.cpp
+++ b/src/devices/bus/multibus/labtam_vducom.cpp
@@ -8,12 +8,16 @@
* - https://arvutimuuseum.ut.ee/index.php?m=eksponaadid&id=223
*
* TODO:
- * - skeleton only
+ * - keyboard click/bell
+ * - light pen
+ * - parallel ports
*/
#include "emu.h"
#include "labtam_vducom.h"
+#include "machine/input_merger.h"
+
#define VERBOSE 0
#include "logmacro.h"
@@ -28,55 +32,106 @@ enum u7_mask : u8
U7_BLANK = 0x80, // disable blanked screen
};
-DEFINE_DEVICE_TYPE(LABTAM_VDUCOM, labtam_vducom_device, "labtam_vducom", "Labtam 8086 VDU COMM")
+DEFINE_DEVICE_TYPE(LABTAM_8086CPU, labtam_8086cpu_device, "labtam_8086cpu", "Labtam 8086 CPU")
+DEFINE_DEVICE_TYPE(LABTAM_VDUCOM, labtam_vducom_device, "labtam_vducom", "Labtam 8086 VDU COMM")
-labtam_vducom_device::labtam_vducom_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
- : device_t(mconfig, LABTAM_VDUCOM, tag, owner, clock)
+labtam_vducom_device_base::labtam_vducom_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, type, tag, owner, clock)
, device_multibus_interface(mconfig, *this)
, m_cpu(*this, "cpu")
, m_pic(*this, "pic")
, m_ctc(*this, "ctc%u", 0U)
, m_com(*this, "com%u", 0U)
, m_nvram(*this, "nvram%u", 0U)
+ , m_serial(*this, "serial%u", 0U)
+ , m_e4(*this, "E4")
+ , m_mbus(*this, "mbus")
+ , m_installed(false)
+{
+}
+
+labtam_8086cpu_device::labtam_8086cpu_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
+ : labtam_vducom_device_base(mconfig, LABTAM_8086CPU, tag, owner, clock)
+{
+}
+
+labtam_vducom_device::labtam_vducom_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
+ : labtam_vducom_device_base(mconfig, LABTAM_VDUCOM, tag, owner, clock)
, m_crtc(*this, "crtc")
, m_palette(*this, "palette")
, m_screen(*this, "screen")
, m_ram(*this, "ram%u", 0U)
- , m_e4(*this, "E4")
- , m_mbus(*this, "mbus")
- , m_installed(false)
{
}
+ROM_START(labtam_8086cpu)
+ ROM_REGION16_LE(0x10000, "eprom", 0)
+
+ ROM_SYSTEM_BIOS(0, "v0", "v0")
+ ROMX_LOAD("slave_1__0.u34", 0xc000, 0x2000, CRC(f5007dd0) SHA1(2362852d88bf32ce605ad394244dc6e21a6df5c6), ROM_SKIP(1) | ROM_BIOS(0))
+ ROMX_LOAD("slave_1__1.u44", 0xc001, 0x2000, CRC(2de2e667) SHA1(c575d5d53f2fe99569af002c636754dedca09e3b), ROM_SKIP(1) | ROM_BIOS(0))
+ROM_END
+
ROM_START(labtam_vducom)
ROM_REGION16_LE(0x10000, "eprom", 0)
- ROM_LOAD16_BYTE("vdu_com__k84.1-0.u26", 0x0000, 0x4000, CRC(ac27697e) SHA1(eeec9cff06181dffe95a37aefb2b3789a0959b4f))
- ROM_LOAD16_BYTE("vdu_com__k84.1-1.u39", 0x0001, 0x4000, CRC(8b3e567d) SHA1(5ce821004155d02b87ed7b6d14989a9fffc38c6a))
- ROM_LOAD16_BYTE("vdu_com__k84.1-2.u34", 0x8000, 0x4000, CRC(70a2c615) SHA1(67d265be3101dfe33fa705447e1394410e55f518))
- ROM_LOAD16_BYTE("vdu_com__k84.1-3.u44", 0x8001, 0x4000, CRC(dcd7ce03) SHA1(727e5fa72d6088ddf9e8613656d713754d628538))
+
+ ROM_SYSTEM_BIOS(0, "k84", "Version K84 23/11/84") // date not certain
+ ROMX_LOAD("vdu_com__k84.1_0.u26", 0x0000, 0x4000, CRC(ac27697e) SHA1(eeec9cff06181dffe95a37aefb2b3789a0959b4f), ROM_SKIP(1) | ROM_BIOS(0))
+ ROMX_LOAD("vdu_com__k84.1_1.u39", 0x0001, 0x4000, CRC(8b3e567d) SHA1(5ce821004155d02b87ed7b6d14989a9fffc38c6a), ROM_SKIP(1) | ROM_BIOS(0))
+ ROMX_LOAD("vdu_com__k84.1_2.u34", 0x8000, 0x4000, CRC(70a2c615) SHA1(67d265be3101dfe33fa705447e1394410e55f518), ROM_SKIP(1) | ROM_BIOS(0))
+ ROMX_LOAD("vdu_com__k84.1_3.u44", 0x8001, 0x4000, CRC(dcd7ce03) SHA1(727e5fa72d6088ddf9e8613656d713754d628538), ROM_SKIP(1) | ROM_BIOS(0))
+
+ ROM_SYSTEM_BIOS(1, "l83", "Version L83 15/12/83") // date not certain
+ ROMX_LOAD("vdu_com__l83.3_0.u26", 0x0000, 0x4000, CRC(2ff53d1d) SHA1(034a89f25dd03e43bdeae710f55d948483624dbe), ROM_SKIP(1) | ROM_BIOS(1))
+ ROMX_LOAD("vdu_com__l83.3_1.u39", 0x0001, 0x4000, CRC(5c425046) SHA1(baad928d3189ed6112ed1849511ce230ddb66166), ROM_SKIP(1) | ROM_BIOS(1))
+ ROMX_LOAD("vdu_com__l83.3_2.u34", 0x8000, 0x4000, CRC(2ed84e20) SHA1(36fdf5e83b1e8f9b706a221930cec1aa2c587a96), ROM_SKIP(1) | ROM_BIOS(1))
+ ROMX_LOAD("vdu_com__l83.3_3.u44", 0x8001, 0x4000, CRC(c601c308) SHA1(61503b5109183a5814be3fcaa393fde8f5bd5359), ROM_SKIP(1) | ROM_BIOS(1))
ROM_END
static INPUT_PORTS_START(labtam_vducom)
PORT_START("E4")
- PORT_DIPNAME(0x01, 0x01, "Keyboard Select 1") PORT_DIPLOCATION("E4:1")
+ PORT_DIPNAME(0x08, 0x08, "Keyboard Select 1") PORT_DIPLOCATION("E4:1")
PORT_DIPSETTING(0x00, DEF_STR(Yes))
- PORT_DIPSETTING(0x01, DEF_STR(No))
- PORT_DIPNAME(0x02, 0x02, "Disable Graphics") PORT_DIPLOCATION("E4:2")
+ PORT_DIPSETTING(0x08, DEF_STR(No))
+ PORT_DIPNAME(0x10, 0x10, "Disable Graphics") PORT_DIPLOCATION("E4:2")
PORT_DIPSETTING(0x00, DEF_STR(Yes))
- PORT_DIPSETTING(0x02, DEF_STR(No))
+ PORT_DIPSETTING(0x10, DEF_STR(No))
PORT_DIPNAME(0x04, 0x04, "Keyboard Select 0") PORT_DIPLOCATION("E4:3")
PORT_DIPSETTING(0x00, DEF_STR(Yes))
PORT_DIPSETTING(0x04, DEF_STR(No))
- PORT_DIPNAME(0x08, 0x08, "Killer Enable") PORT_DIPLOCATION("E4:4")
+ PORT_DIPNAME(0x20, 0x20, "Killer Enable") PORT_DIPLOCATION("E4:4")
+ PORT_DIPSETTING(0x00, DEF_STR(Yes))
+ PORT_DIPSETTING(0x20, DEF_STR(No))
+ PORT_DIPNAME(0x02, 0x02, "Init NVRAM") PORT_DIPLOCATION("E4:5")
+ PORT_DIPSETTING(0x00, DEF_STR(Yes))
+ PORT_DIPSETTING(0x02, DEF_STR(No))
+ PORT_DIPNAME(0x01, 0x01, "Terminal Mode") PORT_DIPLOCATION("E4:7")
+ PORT_DIPSETTING(0x00, DEF_STR(Yes))
+ PORT_DIPSETTING(0x01, DEF_STR(No))
+ PORT_DIPUNUSED_DIPLOC(0xc0, 0xc0, "E4:6,8")
+INPUT_PORTS_END
+
+static INPUT_PORTS_START(labtam_8086cpu)
+ PORT_START("E4")
+ PORT_DIPNAME(0x08, 0x08, "Keyboard Select 1") PORT_DIPLOCATION("E4:1")
PORT_DIPSETTING(0x00, DEF_STR(Yes))
PORT_DIPSETTING(0x08, DEF_STR(No))
- PORT_DIPNAME(0x10, 0x10, "Init NVRAM") PORT_DIPLOCATION("E4:5")
+ PORT_DIPNAME(0x10, 0x00, "Disable Graphics") PORT_DIPLOCATION("E4:2")
PORT_DIPSETTING(0x00, DEF_STR(Yes))
PORT_DIPSETTING(0x10, DEF_STR(No))
- PORT_DIPNAME(0x40, 0x40, "Terminal Mode") PORT_DIPLOCATION("E4:7")
+ PORT_DIPNAME(0x04, 0x04, "Keyboard Select 0") PORT_DIPLOCATION("E4:3")
+ PORT_DIPSETTING(0x00, DEF_STR(Yes))
+ PORT_DIPSETTING(0x04, DEF_STR(No))
+ PORT_DIPNAME(0x20, 0x20, "Killer Enable") PORT_DIPLOCATION("E4:4")
PORT_DIPSETTING(0x00, DEF_STR(Yes))
- PORT_DIPSETTING(0x40, DEF_STR(No))
- PORT_DIPUNUSED_DIPLOC(0xa0, 0xa0, "E4:6,8")
+ PORT_DIPSETTING(0x20, DEF_STR(No))
+ PORT_DIPNAME(0x02, 0x02, "Init NVRAM") PORT_DIPLOCATION("E4:5")
+ PORT_DIPSETTING(0x00, DEF_STR(Yes))
+ PORT_DIPSETTING(0x02, DEF_STR(No))
+ PORT_DIPNAME(0x01, 0x01, "Terminal Mode") PORT_DIPLOCATION("E4:7")
+ PORT_DIPSETTING(0x00, DEF_STR(Yes))
+ PORT_DIPSETTING(0x01, DEF_STR(No))
+ PORT_DIPUNUSED_DIPLOC(0xc0, 0xc0, "E4:6,8")
INPUT_PORTS_END
static const gfx_layout vducom_char_set_1 =
@@ -107,23 +162,33 @@ const tiny_rom_entry *labtam_vducom_device::device_rom_region() const
return ROM_NAME(labtam_vducom);
}
+const tiny_rom_entry *labtam_8086cpu_device::device_rom_region() const
+{
+ return ROM_NAME(labtam_8086cpu);
+}
+
ioport_constructor labtam_vducom_device::device_input_ports() const
{
return INPUT_PORTS_NAME(labtam_vducom);
}
-void labtam_vducom_device::device_resolve_objects()
+ioport_constructor labtam_8086cpu_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(labtam_8086cpu);
+}
+
+void labtam_vducom_device_base::device_resolve_objects()
{
m_bus->int_callback<3>().set(m_pic, FUNC(pic8259_device::ir6_w));
}
-void labtam_vducom_device::device_start()
+void labtam_vducom_device_base::device_start()
{
save_item(NAME(m_start));
save_item(NAME(m_u7));
}
-void labtam_vducom_device::device_reset()
+void labtam_vducom_device_base::device_reset()
{
if (!m_installed)
m_installed = true;
@@ -135,58 +200,147 @@ void labtam_vducom_device::device_reset()
m_nvram[1]->recall(1);
m_mbus.select(0);
+
+ m_ctc[0]->gate1_w(1);
+ m_ctc[0]->gate2_w(1);
+ m_ctc[0]->gate3_w(1);
+ m_ctc[0]->gate4_w(1);
+ m_ctc[0]->gate5_w(1);
+
+ m_ctc[0]->source1_w(1);
+ m_ctc[0]->source2_w(1);
+ m_ctc[0]->source3_w(1);
+ m_ctc[0]->source4_w(1);
+ m_ctc[0]->source5_w(1);
+
+ m_ctc[1]->gate4_w(1);
+ m_ctc[1]->source5_w(1);
}
-void labtam_vducom_device::device_add_mconfig(machine_config &config)
+void labtam_vducom_device_base::device_add_mconfig(machine_config &config)
{
I8086(config, m_cpu, 16_MHz_XTAL / 2);
- m_cpu->set_addrmap(AS_PROGRAM, &labtam_vducom_device::cpu_mem);
- m_cpu->set_addrmap(AS_IO, &labtam_vducom_device::cpu_pio);
+ m_cpu->set_addrmap(AS_PROGRAM, &labtam_vducom_device_base::cpu_mem);
+ m_cpu->set_addrmap(AS_IO, &labtam_vducom_device_base::cpu_pio);
m_cpu->set_irq_acknowledge_callback(m_pic, FUNC(pic8259_device::inta_cb));
- AM9513(config, m_ctc[0], 4'000'000);
- //m_ctc[0]->out1_cb().set(m_pic, FUNC(pic8259_device::ir0_w));
- m_ctc[0]->out4_cb().set(m_ctc[0], FUNC(am9513_device::gate5_w)); // ?
- m_ctc[0]->out5_cb().set(m_ctc[0], FUNC(am9513_device::source4_w)); // ?
+ AM9513(config, m_ctc[1], 16_MHz_XTAL / 4);
+ m_ctc[1]->out4_cb().set(m_ctc[1], FUNC(am9513_device::gate5_w));
+ m_ctc[1]->out5_cb().set(m_ctc[1], FUNC(am9513_device::source4_w)); // TODO: also keyboard bell
- AM9513(config, m_ctc[1], 4'000'000);
- m_ctc[1]->out1_cb().set(m_com[1], FUNC(upd7201_device::txcb_w));
- m_ctc[1]->out2_cb().set(m_com[1], FUNC(upd7201_device::rxcb_w));
- m_ctc[1]->out3_cb().set(m_com[1], FUNC(upd7201_device::rxca_w));
- m_ctc[1]->out3_cb().append(m_com[1], FUNC(upd7201_device::txca_w));
- m_ctc[1]->out4_cb().set(m_com[0], FUNC(upd7201_device::rxcb_w));
- m_ctc[1]->out5_cb().set(m_com[0], FUNC(upd7201_device::rxca_w));
- m_ctc[1]->out5_cb().append(m_com[0], FUNC(upd7201_device::txca_w));
+ AM9513(config, m_ctc[0], 16_MHz_XTAL / 4);
+ m_ctc[0]->out1_cb().set(m_com[1], FUNC(upd7201_device::txcb_w));
+ m_ctc[0]->out2_cb().set(m_com[1], FUNC(upd7201_device::rxcb_w));
+ m_ctc[0]->out3_cb().set(m_com[1], FUNC(upd7201_device::rxca_w));
+ m_ctc[0]->out3_cb().append(m_com[1], FUNC(upd7201_device::txca_w));
+ m_ctc[0]->out4_cb().set(m_com[0], FUNC(upd7201_device::rxcb_w));
+ m_ctc[0]->out4_cb().append(m_com[0], FUNC(upd7201_device::txcb_w));
+ m_ctc[0]->out5_cb().set(m_com[0], FUNC(upd7201_device::rxca_w));
+ m_ctc[0]->out5_cb().append(m_com[0], FUNC(upd7201_device::txca_w));
PIC8259(config, m_pic);
+ /*
+ * irq source
+ * 0 crtc vsync
+ * 1 light pen strobe
+ * 2 com1
+ * 3 com0
+ * 4 parallel input strobe
+ * 5 parallel printer acknowledge
+ * 6 parallel printer busy
+ * 7 not connected
+ */
m_pic->out_int_callback().set_inputline(m_cpu, INPUT_LINE_INT0);
- UPD7201(config, m_com[0], 4'000'000);
+ UPD7201(config, m_com[0], 16_MHz_XTAL / 4);
m_com[0]->out_int_callback().set(m_pic, FUNC(pic8259_device::ir3_w));
- UPD7201(config, m_com[1], 4'000'000);
+
+ RS232_PORT(config, m_serial[0], default_rs232_devices, nullptr);
+ input_merger_any_high_device &com0dcda(INPUT_MERGER_ANY_HIGH(config, "com0dcda"));
+ input_merger_any_high_device &com0ctsa(INPUT_MERGER_ANY_HIGH(config, "com0ctsa"));
+ m_serial[0]->cts_handler().set(com0ctsa, FUNC(input_merger_any_high_device::in_w<0>));
+ m_serial[0]->dsr_handler().set(com0ctsa, FUNC(input_merger_any_high_device::in_w<1>));
+ com0ctsa.output_handler().set(m_com[0], FUNC(upd7201_device::ctsa_w));
+ m_serial[0]->dcd_handler().set(com0dcda, FUNC(input_merger_any_high_device::in_w<0>));
+ m_serial[0]->dsr_handler().append(com0dcda, FUNC(input_merger_any_high_device::in_w<1>));
+ com0dcda.output_handler().set(m_com[0], FUNC(upd7201_device::dcda_w));
+ m_serial[0]->rxd_handler().set(m_com[0], FUNC(upd7201_device::rxa_w));
+ m_com[0]->out_dtra_callback().set(m_serial[0], FUNC(rs232_port_device::write_dtr));
+ m_com[0]->out_rtsa_callback().set(m_serial[0], FUNC(rs232_port_device::write_rts));
+ m_com[0]->out_txda_callback().set(m_serial[0], FUNC(rs232_port_device::write_txd));
+
+ RS232_PORT(config, m_serial[1], default_rs232_devices, nullptr);
+ input_merger_any_high_device &com0dcdb(INPUT_MERGER_ANY_HIGH(config, "com0dcdb"));
+ input_merger_any_high_device &com0ctsb(INPUT_MERGER_ANY_HIGH(config, "com0ctsb"));
+ m_serial[1]->cts_handler().set(com0ctsb, FUNC(input_merger_any_high_device::in_w<0>));
+ m_serial[1]->dsr_handler().set(com0ctsb, FUNC(input_merger_any_high_device::in_w<1>));
+ com0ctsb.output_handler().set(m_com[0], FUNC(upd7201_device::ctsb_w));
+ m_serial[1]->dcd_handler().set(com0dcdb, FUNC(input_merger_any_high_device::in_w<0>));
+ m_serial[1]->dsr_handler().append(com0dcdb, FUNC(input_merger_any_high_device::in_w<1>));
+ com0dcdb.output_handler().set(m_com[0], FUNC(upd7201_device::dcdb_w));
+ m_serial[1]->rxd_handler().set(m_com[0], FUNC(upd7201_device::rxb_w));
+ m_com[0]->out_txdb_callback().set(m_serial[1], FUNC(rs232_port_device::write_txd));
+ m_com[0]->out_rtsb_callback().set(m_serial[1], FUNC(rs232_port_device::write_rts));
+ m_com[0]->out_dtrb_callback().set(m_serial[1], FUNC(rs232_port_device::write_dtr));
+
+ UPD7201(config, m_com[1], 16_MHz_XTAL / 4);
m_com[1]->out_int_callback().set(m_pic, FUNC(pic8259_device::ir2_w));
+ RS232_PORT(config, m_serial[2], default_rs232_devices, nullptr);
+ input_merger_any_high_device &com1dcda(INPUT_MERGER_ANY_HIGH(config, "com1dcda"));
+ input_merger_any_high_device &com1ctsa(INPUT_MERGER_ANY_HIGH(config, "com1ctsa"));
+ m_serial[2]->cts_handler().set(com1ctsa, FUNC(input_merger_any_high_device::in_w<0>));
+ m_serial[2]->dsr_handler().set(com1ctsa, FUNC(input_merger_any_high_device::in_w<1>));
+ com1ctsa.output_handler().set(m_com[1], FUNC(upd7201_device::ctsa_w));
+ m_serial[2]->dcd_handler().set(com1dcda, FUNC(input_merger_any_high_device::in_w<0>));
+ m_serial[2]->dsr_handler().append(com1dcda, FUNC(input_merger_any_high_device::in_w<1>));
+ com1dcda.output_handler().set(m_com[1], FUNC(upd7201_device::dcda_w));
+ m_serial[2]->rxd_handler().set(m_com[1], FUNC(upd7201_device::rxa_w));
+ m_com[1]->out_dtra_callback().set(m_serial[2], FUNC(rs232_port_device::write_dtr));
+ m_com[1]->out_rtsa_callback().set(m_serial[2], FUNC(rs232_port_device::write_rts));
+ m_com[1]->out_txda_callback().set(m_serial[2], FUNC(rs232_port_device::write_txd));
+
+ RS232_PORT(config, m_serial[3], default_rs232_devices, nullptr);
+ m_serial[3]->dcd_handler().set(m_com[1], FUNC(upd7201_device::dcdb_w));
+ m_serial[3]->cts_handler().set(m_com[1], FUNC(upd7201_device::ctsb_w));
+ m_serial[3]->rxd_handler().set(m_com[1], FUNC(upd7201_device::rxb_w));
+ m_com[1]->out_dtrb_callback().set(m_serial[3], FUNC(rs232_port_device::write_dtr));
+ m_com[1]->out_rtsb_callback().set(m_serial[3], FUNC(rs232_port_device::write_rts));
+ m_com[1]->out_txdb_callback().set(m_serial[3], FUNC(rs232_port_device::write_txd));
+
X2212(config, m_nvram[0]);
X2212(config, m_nvram[1]);
+}
+
+static DEVICE_INPUT_DEFAULTS_START(keyboard_defaults)
+ DEVICE_INPUT_DEFAULTS("RS232_TXBAUD", 0xff, RS232_BAUD_110)
+DEVICE_INPUT_DEFAULTS_END
+
+void labtam_vducom_device::device_add_mconfig(machine_config &config)
+{
+ labtam_vducom_device_base::device_add_mconfig(config);
+
+ m_serial[3]->set_default_option("keyboard");
+ m_serial[3]->set_option_device_input_defaults("keyboard", DEVICE_INPUT_DEFAULTS_NAME(keyboard_defaults));
- MC6845(config, m_crtc, 1'000'000);
+ MC6845(config, m_crtc, 16_MHz_XTAL / 16);
m_crtc->set_show_border_area(false);
m_crtc->set_hpixels_per_column(16);
+ m_crtc->out_vsync_callback().set("pic", FUNC(pic8259_device::ir0_w));
+
m_crtc->set_update_row_callback(FUNC(labtam_vducom_device::update_row));
m_crtc->set_screen(m_screen);
- m_crtc->out_vsync_callback().set(m_pic, FUNC(pic8259_device::ir0_w));
-
PALETTE(config, m_palette, FUNC(labtam_vducom_device::palette_init), 4);
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
- m_screen->set_raw(1'000'000, 62*16, 2*16, 52*16, 78*4, 3*4, 75*4);
+ m_screen->set_raw(16_MHz_XTAL / 16, 62 * 16, 2 * 16, 52 * 16, 78 * 4, 3 * 4, 75 * 4);
m_screen->set_screen_update(m_crtc, FUNC(mc6845_device::screen_update));
// gfxdecode is only to show the font data in the tile viewer
GFXDECODE(config, "gfx", m_palette, labtam_vducom);
}
-void labtam_vducom_device::cpu_mem(address_map &map)
+void labtam_vducom_device_base::cpu_mem(address_map &map)
{
map(0x00000, 0x0ffff).ram().share("ram1");
map(0x10000, 0x1ffff).ram().share("ram0");
@@ -194,26 +348,35 @@ void labtam_vducom_device::cpu_mem(address_map &map)
map(0x80000, 0xfffff).view(m_mbus);
m_mbus[0](0x80000, 0x8ffff).rom().region("eprom", 0).mirror(0x70000);
- m_mbus[1](0x80000, 0xfffff).rw(FUNC(labtam_vducom_device::bus_mem_r), FUNC(labtam_vducom_device::bus_mem_w));
+ m_mbus[1](0x80000, 0xfffff).rw(FUNC(labtam_vducom_device_base::bus_mem_r), FUNC(labtam_vducom_device_base::bus_mem_w));
}
-void labtam_vducom_device::cpu_pio(address_map &map)
+void labtam_vducom_device_base::cpu_pio(address_map &map)
{
- map(0x0000, 0x7fff).rw(FUNC(labtam_vducom_device::bus_pio_r), FUNC(labtam_vducom_device::bus_pio_w));
+ map(0x0000, 0x7fff).rw(FUNC(labtam_vducom_device_base::bus_pio_r), FUNC(labtam_vducom_device_base::bus_pio_w));
- map(0xe000, 0xe000).rw(m_crtc, FUNC(mc6845_device::status_r), FUNC(mc6845_device::address_w));
- map(0xe002, 0xe002).rw(m_crtc, FUNC(mc6845_device::register_r), FUNC(mc6845_device::register_w));
map(0xe400, 0xe403).rw(m_pic, FUNC(pic8259_device::read), FUNC(pic8259_device::write)).umask16(0x00ff);
map(0xe600, 0xe607).rw(m_com[0], FUNC(upd7201_device::ba_cd_r), FUNC(upd7201_device::ba_cd_w)).umask16(0x00ff);
map(0xe800, 0xe807).rw(m_com[1], FUNC(upd7201_device::ba_cd_r), FUNC(upd7201_device::ba_cd_w)).umask16(0x00ff);
map(0xea00, 0xea03).rw(m_ctc[0], FUNC(am9513_device::read8), FUNC(am9513_device::write8)).umask16(0x00ff);
map(0xec00, 0xec03).rw(m_ctc[1], FUNC(am9513_device::read8), FUNC(am9513_device::write8)).umask16(0x00ff);
- map(0xee00, 0xefff).rw(FUNC(labtam_vducom_device::nvram_r), FUNC(labtam_vducom_device::nvram_w)).umask16(0x00ff);
+ map(0xee00, 0xefff).rw(FUNC(labtam_vducom_device_base::nvram_r), FUNC(labtam_vducom_device_base::nvram_w)).umask16(0x00ff);
- map(0xf000, 0xf00f).rw(FUNC(labtam_vducom_device::u15_r), FUNC(labtam_vducom_device::u7_w)).umask16(0x00ff);
+ map(0xf000, 0xf00f).rw(FUNC(labtam_vducom_device_base::u15_r), FUNC(labtam_vducom_device_base::u7_w)).umask16(0x00ff);
map(0xf200, 0xf200).lw8([this](u8 data) { m_start = (m_start & 0xff00) | u16(data) << 0; }, "start_lo");
map(0xf400, 0xf400).lw8([this](u8 data) { m_start = (m_start & 0x00ff) | u16(data) << 8; }, "start_hi");
- map(0xfe00, 0xfe00).lw8([this](u8 data) { m_nvram[0]->store(1); m_nvram[1]->store(1); }, "store_array");
+ //map(0xf600, 0xf600); // r:parallel data input, w:joystick start pulse
+ //map(0xf800, 0xf800); // r:parallel data acknowledge, w:parallel printer output
+ //map(0xfa00, 0xfa00); // w:parallel printer strobe
+ map(0xfe00, 0xfe00).rw(FUNC(labtam_vducom_device_base::nvram_recall), FUNC(labtam_vducom_device_base::nvram_store));
+}
+
+void labtam_vducom_device::cpu_pio(address_map &map)
+{
+ labtam_vducom_device_base::cpu_pio(map);
+
+ map(0xe000, 0xe000).rw(m_crtc, FUNC(mc6845_device::status_r), FUNC(mc6845_device::address_w));
+ map(0xe002, 0xe002).rw(m_crtc, FUNC(mc6845_device::register_r), FUNC(mc6845_device::register_w));
}
void labtam_vducom_device::palette_init(palette_device &palette)
@@ -230,8 +393,8 @@ void labtam_vducom_device::palette_init(palette_device &palette)
// interlace: one plane 800x600, 64k, (black, normal)
MC6845_UPDATE_ROW(labtam_vducom_device::update_row)
{
- required_shared_ptr<u16> const ram = m_ram[BIT(m_u7, 2)];
- offs_t const offset = (m_start >> 1) + ma * 4 + ra * 50;
+ required_shared_ptr<u16> const ram = m_ram[BIT(u7(), 2)];
+ offs_t const offset = (start() >> 1) + ma * 4 + ra * 50;
for (unsigned x = 0; x < x_count; x++)
{
@@ -241,7 +404,7 @@ MC6845_UPDATE_ROW(labtam_vducom_device::update_row)
for (unsigned b = 0; b < 16; b++)
{
unsigned c = BIT(data0, b) << 1;
- if (m_u7 & U7_HALF)
+ if (u7() & U7_HALF)
c |= BIT(data1, b);
bitmap.pix(y, x * 16 + b) = m_palette->pen_color(c);
@@ -249,7 +412,7 @@ MC6845_UPDATE_ROW(labtam_vducom_device::update_row)
}
}
-void labtam_vducom_device::u7_w(offs_t offset, u8 data)
+void labtam_vducom_device_base::u7_w(offs_t offset, u8 data)
{
LOG("u7_w offset %d data %d (%s)\n", offset, data, machine().describe_context());
@@ -261,16 +424,36 @@ void labtam_vducom_device::u7_w(offs_t offset, u8 data)
m_mbus.select(BIT(m_u7, 0));
}
-void labtam_vducom_device::bus_mem_w(offs_t offset, u16 data, u16 mem_mask)
+void labtam_vducom_device_base::bus_mem_w(offs_t offset, u16 data, u16 mem_mask)
{
offs_t const address = (BIT(m_u7, 1) ? 0x80000 : 0) | (offset << 1);
m_bus->space(AS_PROGRAM).write_word(address, data, mem_mask);
}
-u16 labtam_vducom_device::bus_mem_r(offs_t offset, u16 mem_mask)
+u16 labtam_vducom_device_base::bus_mem_r(offs_t offset, u16 mem_mask)
{
offs_t const address = (BIT(m_u7, 1) ? 0x80000 : 0) | (offset << 1);
return m_bus->space(AS_PROGRAM).read_word(address, mem_mask);
}
+
+u8 labtam_vducom_device_base::nvram_recall()
+{
+ m_nvram[0]->recall(1);
+ m_nvram[1]->recall(1);
+
+ m_nvram[0]->recall(0);
+ m_nvram[1]->recall(0);
+
+ return 0;
+}
+
+void labtam_vducom_device_base::nvram_store(u8 data)
+{
+ m_nvram[0]->store(1);
+ m_nvram[1]->store(1);
+
+ m_nvram[0]->store(0);
+ m_nvram[1]->store(0);
+}
diff --git a/src/devices/bus/multibus/labtam_vducom.h b/src/devices/bus/multibus/labtam_vducom.h
index 9db27d05fdd..b30a0337d2f 100644
--- a/src/devices/bus/multibus/labtam_vducom.h
+++ b/src/devices/bus/multibus/labtam_vducom.h
@@ -21,25 +21,20 @@
#include "screen.h"
-class labtam_vducom_device
+class labtam_vducom_device_base
: public device_t
, public device_multibus_interface
{
-public:
- labtam_vducom_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
-
protected:
- // device_t overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
+ labtam_vducom_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock);
+
virtual void device_add_mconfig(machine_config &config) override;
- virtual ioport_constructor device_input_ports() const override;
virtual void device_resolve_objects() override;
virtual void device_start() override;
virtual void device_reset() override;
-private:
void cpu_mem(address_map &map);
- void cpu_pio(address_map &map);
+ virtual void cpu_pio(address_map &map);
void bus_mem_w(offs_t offset, u16 data, u16 mem_mask);
u16 bus_mem_r(offs_t offset, u16 mem_mask);
@@ -52,19 +47,21 @@ private:
u8 u15_r(offs_t offset) { return BIT(m_e4->read(), offset); }
void u7_w(offs_t offset, u8 data);
- void palette_init(palette_device &palette);
- MC6845_UPDATE_ROW(update_row);
+ u16 start() const { return m_start; }
+ u8 u7() const { return m_u7; }
+
+ u8 nvram_recall();
+ void nvram_store(u8 data);
required_device<i8086_cpu_device> m_cpu;
required_device<pic8259_device> m_pic;
required_device_array<am9513_device, 2> m_ctc;
required_device_array<z80sio_device, 2> m_com;
required_device_array<x2212_device, 2> m_nvram;
- required_device<mc6845_device> m_crtc;
- required_device<palette_device> m_palette;
- required_device<screen_device> m_screen;
- required_shared_ptr_array<u16, 2> m_ram;
+ required_device_array<rs232_port_device, 4> m_serial;
+
+private:
required_ioport m_e4;
memory_view m_mbus;
@@ -74,6 +71,40 @@ private:
bool m_installed;
};
-DECLARE_DEVICE_TYPE(LABTAM_VDUCOM, labtam_vducom_device)
+class labtam_8086cpu_device : public labtam_vducom_device_base
+{
+public:
+ labtam_8086cpu_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual ioport_constructor device_input_ports() const override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+};
+
+class labtam_vducom_device : public labtam_vducom_device_base
+{
+public:
+ labtam_vducom_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual ioport_constructor device_input_ports() const override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override;
+
+ virtual void cpu_pio(address_map &map) override;
+
+private:
+ void palette_init(palette_device &palette);
+ MC6845_UPDATE_ROW(update_row);
+
+ required_device<mc6845_device> m_crtc;
+ required_device<palette_device> m_palette;
+ required_device<screen_device> m_screen;
+
+ required_shared_ptr_array<u16, 2> m_ram;
+};
+
+DECLARE_DEVICE_TYPE(LABTAM_8086CPU, labtam_8086cpu_device)
+DECLARE_DEVICE_TYPE(LABTAM_VDUCOM, labtam_vducom_device)
#endif // MAME_BUS_MULTIBUS_LABTAM_VDUCOM_H
diff --git a/src/devices/bus/multibus/labtam_z80sbc.cpp b/src/devices/bus/multibus/labtam_z80sbc.cpp
index 013add4f7e8..db60e831c95 100644
--- a/src/devices/bus/multibus/labtam_z80sbc.cpp
+++ b/src/devices/bus/multibus/labtam_z80sbc.cpp
@@ -88,11 +88,16 @@ labtam_z80sbc_device::labtam_z80sbc_device(machine_config const &mconfig, char c
}
ROM_START(labtam_z80sbc)
+ ROM_SYSTEM_BIOS(0, "c85", "Version C85")
+ ROM_SYSTEM_BIOS(1, "a85", "Version A85")
+
ROM_REGION(0x2000, "eprom0", 0)
- ROM_LOAD("z80_boot__a85_0.u59", 0x0000, 0x2000, CRC(4453c938) SHA1(b04987a07ff7e21f7eb354162ad14b59d17096dd))
+ ROMX_LOAD("z80_boot__c85_0.u59", 0x0000, 0x2000, CRC(472b39ad) SHA1(689c194dee29f895fb4f3e901adab3267e0e2823), ROM_BIOS(0))
+ ROMX_LOAD("z80_boot__a85_0.u59", 0x0000, 0x2000, CRC(4453c938) SHA1(b04987a07ff7e21f7eb354162ad14b59d17096dd), ROM_BIOS(1))
ROM_REGION(0x2000, "eprom1", 0)
- ROM_LOAD("z80_boot__a85_1.u53", 0x0000, 0x2000, CRC(b7d489ea) SHA1(5bd6f3dd1c1f6f3e07706293bfc46a9bfc43d1f2))
+ ROMX_LOAD("z80_boot__c85_1.u53", 0x0000, 0x2000, CRC(8cb2374d) SHA1(20f6ec9ba9c8fb453f6497ffa0fb1dc3611e7d7f), ROM_BIOS(0))
+ ROMX_LOAD("z80_boot__a85_1.u53", 0x0000, 0x2000, CRC(b7d489ea) SHA1(5bd6f3dd1c1f6f3e07706293bfc46a9bfc43d1f2), ROM_BIOS(1))
ROM_END
static INPUT_PORTS_START(labtam_z80sbc)
@@ -252,13 +257,13 @@ void labtam_z80sbc_device::device_reset()
u32 const ram1_select = m_e15[3]->read();
m_bus->space(AS_PROGRAM).install_ram(ram0_select, ram0_select | 0xffff, m_ram0.get());
- m_bus->space(AS_PROGRAM).install_ram(ram1_select, ram1_select | 0xffff, m_ram0.get());
+ m_bus->space(AS_PROGRAM).install_ram(ram1_select, ram1_select | 0xffff, m_ram1.get());
u16 const pio_select = m_e15[2]->read() | m_e15[1]->read() | m_e15[0]->read();
m_bus->space(AS_IO).install_write_handler(pio_select | 0, pio_select | 0, write8smo_delegate(*this, FUNC(labtam_z80sbc_device::fdcclr_w)));
m_bus->space(AS_IO).install_write_handler(pio_select | 2, pio_select | 2, write8smo_delegate(*this, FUNC(labtam_z80sbc_device::netclr_w)));
- m_bus->space(AS_IO).install_write_handler(pio_select | 4, pio_select | 4, write8smo_delegate(*this, FUNC(labtam_z80sbc_device::fdcattn_w)));
+ m_bus->space(AS_IO).install_write_handler(pio_select | 4, pio_select | 4, write8smo_delegate(*this, FUNC(labtam_z80sbc_device::fdcatn_w)));
m_bus->space(AS_IO).install_read_handler(pio_select | 8, pio_select | 8, read8smo_delegate(*this, FUNC(labtam_z80sbc_device::fdcstatus_r)));
m_installed = true;
@@ -276,6 +281,7 @@ static void z80sbc_floppies(device_slot_interface &device)
{
device.option_add("dssd5", FLOPPY_525_SD);
device.option_add("dsdd5", FLOPPY_525_DD);
+ device.option_add("dshd5", FLOPPY_525_HD);
device.option_add("dssd8", FLOPPY_8_DSSD);
device.option_add("dsdd8", FLOPPY_8_DSDD);
}
@@ -333,7 +339,7 @@ void labtam_z80sbc_device::device_add_mconfig(machine_config &config)
m_uic->out_int_callback().set(m_int, FUNC(input_merger_any_high_device::in_w<3>));
WD2793(config, m_fdc, 2'000'000);
- m_fdc->intrq_wr_callback().set(FUNC(labtam_z80sbc_device::fdcint_w));
+ m_fdc->intrq_wr_callback().set(m_uic, FUNC(am9519_device::ireq2_w));
m_fdc->drq_wr_callback().set(m_dma[0], FUNC(z80dma_device::rdy_w));
// WD1002 irq -> Am9519 ireq3
@@ -363,8 +369,8 @@ void labtam_z80sbc_device::cpu_mem(address_map &map)
void labtam_z80sbc_device::cpu_pio(address_map &map)
{
- map(0x0000, 0x0000).lw8([this](u8 data) { LOG("fdcset 0x%02x (%s)\n", data, machine().describe_context()); }, "fdcset");
- //map(0x0008, 0x0008); // TODO: serset: set sio interrupt
+ map(0x0000, 0x0000).mirror(0xff00).lw8([this](u8 data) { LOG("fdcset 0x%02x (%s)\n", data, machine().describe_context()); m_fdcstatus |= 0x01; int_w<3>(0); }, "fdcset");
+ map(0x0008, 0x0008).mirror(0xff00).lw8([this](u8 data) { LOG("serset 0x%02x (%s)\n", data, machine().describe_context()); m_fdcstatus |= 0x02; }, "serset");
map(0x0010, 0x0010).select(0xff00).lw8([this](offs_t offset, u8 data) { m_map_lo[offset >> 8] = data; }, "mapwr0");
map(0x0018, 0x0018).select(0xff00).lw8([this](offs_t offset, u8 data) { m_map_hi[offset >> 8] = data & 0xf0; }, "mapwr1");
@@ -515,17 +521,6 @@ void labtam_z80sbc_device::mapnum_w(u8 data)
m_map_num = data & 0x07;
}
-void labtam_z80sbc_device::fdcint_w(int state)
-{
- if (state)
- m_fdcstatus |= 1U << 0;
- else
- m_fdcstatus &= ~(1U << 0);
-
- m_uic->ireq2_w(state);
- int_w<3>(state);
-}
-
void labtam_z80sbc_device::drive_w(offs_t offset, u8 data)
{
switch (offset)
@@ -569,23 +564,27 @@ void labtam_z80sbc_device::drive_w(offs_t offset, u8 data)
void labtam_z80sbc_device::fdcclr_w(u8 data)
{
- m_uic->ireq4_w(0);
+ LOG("fdcclr 0x%02x (%s)\n", data, machine().describe_context());
+ m_fdcstatus &= ~0x01;
+ int_w<3>(1);
}
void labtam_z80sbc_device::netclr_w(u8 data)
{
- LOG("netclr_w 0x%02x (%s)\n", data, machine().describe_context());
+ LOG("netclr 0x%02x (%s)\n", data, machine().describe_context());
+ m_fdcstatus &= ~0x02;
}
-void labtam_z80sbc_device::fdcattn_w(u8 data)
+void labtam_z80sbc_device::fdcatn_w(u8 data)
{
- LOG("fdcattn_w 0x%02x (%s)\n", data, machine().describe_context());
+ LOG("fdcatn 0x%02x (%s)\n", data, machine().describe_context());
m_uic->ireq4_w(1);
+ m_uic->ireq4_w(0);
}
u8 labtam_z80sbc_device::fdcstatus_r()
{
- LOG("fdcstatus_r (%s)\n", machine().describe_context());
+ LOG("fdcstatus (%s)\n", machine().describe_context());
return m_fdcstatus;
}
diff --git a/src/devices/bus/multibus/labtam_z80sbc.h b/src/devices/bus/multibus/labtam_z80sbc.h
index 2e20d6cd7ca..bff3b52a491 100644
--- a/src/devices/bus/multibus/labtam_z80sbc.h
+++ b/src/devices/bus/multibus/labtam_z80sbc.h
@@ -52,11 +52,10 @@ private:
void intswt_w(u8 data);
void mapnum_w(u8 data);
- void fdcint_w(int state);
void drive_w(offs_t offset, u8 data);
void fdcclr_w(u8 data);
void netclr_w(u8 data);
- void fdcattn_w(u8 data);
+ void fdcatn_w(u8 data);
u8 fdcstatus_r();
u8 drvstatus_r();
diff --git a/src/devices/bus/multibus/multibus.cpp b/src/devices/bus/multibus/multibus.cpp
index f8c64ac0d08..6f08efb58b4 100644
--- a/src/devices/bus/multibus/multibus.cpp
+++ b/src/devices/bus/multibus/multibus.cpp
@@ -41,8 +41,6 @@ device_memory_interface::space_config_vector multibus_device::memory_space_confi
void multibus_device::device_start()
{
- m_int_cb.resolve_all_safe();
- m_xack_cb.resolve_safe();
}
multibus_slot_device::multibus_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
diff --git a/src/devices/bus/multibus/robotron_k7070.cpp b/src/devices/bus/multibus/robotron_k7070.cpp
new file mode 100644
index 00000000000..301b2ec48c3
--- /dev/null
+++ b/src/devices/bus/multibus/robotron_k7070.cpp
@@ -0,0 +1,423 @@
+// license:BSD-3-Clause
+// copyright-holders:Sergey Svishchev
+
+/*
+ * Robotron K7070 and K7072 combo
+ *
+ * K7070 KGS - graphics terminal (K7070.10 model)
+ * K7072 ABG - dumb grayscale framebuffer
+ *
+ * Reference: http://www.tiffe.de/Robotron/MMS16/
+ * Internal test of KGS -- in KGS-K7070.pdf, pp. 19-23
+ *
+ * To do:
+ * - palette
+ * - vertical raster split and text mode
+ */
+
+#include "emu.h"
+#include "robotron_k7070.h"
+
+#define VERBOSE 0
+#include "logmacro.h"
+
+enum kgs_st : u8
+{
+ KGS_ST_OBF = 0x01,
+ KGS_ST_IBF = 0x02,
+ KGS_ST_INT = 0x04,
+ KGS_ST_ERR = 0x80,
+};
+
+DEFINE_DEVICE_TYPE(ROBOTRON_K7070, robotron_k7070_device, "robotron_k7070", "Robotron K7070 KGS")
+
+robotron_k7070_device::robotron_k7070_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, ROBOTRON_K7070, tag, owner, clock)
+ , device_multibus_interface(mconfig, *this)
+ , m_cpu(*this, "cpu")
+ , m_ctc(*this, "ctc")
+ , m_sio(*this, "sio")
+ , m_serial(*this, "serial%u", 0U)
+ , m_palette(*this, "palette")
+ , m_ram(*this, "vram0")
+ , m_dsel(*this, "DSEL%u", 0U)
+ , m_view_lo(*this, "view_lo")
+ , m_view_hi(*this, "view_hi")
+{
+ m_abg_msel = m_kgs_iml = 0;
+ m_abg_func = m_abg_split = 0;
+ m_abg_addr = 0;
+ m_kgs_datao = m_kgs_datai = m_kgs_ctrl = 0;
+ m_nmi_enable = 0;
+}
+
+ROM_START(robotron_k7070)
+ ROM_REGION(0x2000, "eprom", ROMREGION_ERASEFF)
+ ROM_DEFAULT_BIOS("152")
+
+ ROM_SYSTEM_BIOS(0, "152", "Version 152") // ROM from A7100
+ ROMX_LOAD("kgs7070-152.bin", 0x0000, 0x2000, CRC(403f4235) SHA1(d07ccd40f8b600651d513f588bcf1ea4f15ed094), ROM_BIOS(0))
+
+ ROM_SYSTEM_BIOS(1, "153", "Version 153")
+ ROMX_LOAD("kgs7070-153.rom", 0x0000, 0x2000, CRC(a72fe820) SHA1(4b77ab2b59ea8c3632986847ff359df26b16196b), ROM_BIOS(1))
+
+ ROM_SYSTEM_BIOS(2, "154", "Version 154")
+ ROMX_LOAD("kgs7070-154.rom", 0x0000, 0x2000, CRC(2995ade0) SHA1(62516f2e1cb62698445f80fd823d39a1a78a7807), ROM_BIOS(2))
+ROM_END
+
+static INPUT_PORTS_START(robotron_k7070)
+ PORT_START("DSEL0")
+ PORT_DIPNAME(0x01, 0x01, "Codepoint 0x24")
+ PORT_DIPSETTING(0x00, "Currency sign" )
+ PORT_DIPSETTING(0x01, "Dollar sign" )
+ PORT_DIPNAME(0x02, 0x02, "Perform I/O test")
+ PORT_DIPSETTING(0x00, DEF_STR(No) )
+ PORT_DIPSETTING(0x02, DEF_STR(Yes) )
+ PORT_DIPNAME(0x04, 0x00, "Perform VRAM test")
+ PORT_DIPSETTING(0x00, DEF_STR(Yes) )
+ PORT_DIPSETTING(0x04, DEF_STR(No) )
+
+ PORT_START("DSEL1")
+ PORT_DIPNAME(0x03, 0x02, "V.24 Parity")
+ PORT_DIPSETTING(0x00, "No parity" )
+ PORT_DIPSETTING(0x01, "Odd" )
+ PORT_DIPSETTING(0x02, "No parity" )
+ PORT_DIPSETTING(0x03, "Even" )
+ PORT_DIPNAME(0x04, 0x04, "V.24 Character size")
+ PORT_DIPSETTING(0x00, "7 bits")
+ PORT_DIPSETTING(0x04, "8 bits")
+ PORT_DIPNAME(0x38, 0x38, "V.24 Baud rate")
+ PORT_DIPSETTING(0x38, "19200")
+ PORT_DIPSETTING(0x30, "9600")
+ PORT_DIPSETTING(0x28, "4800")
+ PORT_DIPSETTING(0x20, "2400")
+ PORT_DIPSETTING(0x18, "1200")
+ PORT_DIPSETTING(0x10, "600")
+ PORT_DIPSETTING(0x08, "300")
+ PORT_DIPNAME(0x40, 0x40, "IFSS Parity")
+ PORT_DIPSETTING(0x00, "Odd" )
+ PORT_DIPSETTING(0x40, "Even" )
+ PORT_DIPNAME(0x80, 0x80, "IFSS Baud rate")
+ PORT_DIPSETTING(0x00, "9600")
+ PORT_DIPSETTING(0x80, "Same as V.24")
+INPUT_PORTS_END
+
+const tiny_rom_entry *robotron_k7070_device::device_rom_region() const
+{
+ return ROM_NAME(robotron_k7070);
+}
+
+ioport_constructor robotron_k7070_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(robotron_k7070);
+}
+
+void robotron_k7070_device::device_start()
+{
+ save_item(NAME(m_start));
+ save_item(NAME(m_abg_msel));
+ save_item(NAME(m_kgs_iml));
+ save_item(NAME(m_kgs_datao));
+ save_item(NAME(m_kgs_datai));
+ save_item(NAME(m_kgs_ctrl));
+ save_item(NAME(m_nmi_enable));
+
+ m_bus->space(AS_IO).install_readwrite_handler(0x200, 0x203, read16s_delegate(*this, FUNC(robotron_k7070_device::io_r)), write16s_delegate(*this, FUNC(robotron_k7070_device::io_w)));
+}
+
+void robotron_k7070_device::device_reset()
+{
+ m_start = 0;
+ m_kgs_ctrl = KGS_ST_IBF | KGS_ST_OBF;
+ m_kgs_datao = m_kgs_datai = 0;
+ m_kgs_iml = m_abg_msel = 0;
+ m_nmi_enable = false;
+ kgs_memory_remap();
+}
+
+static const z80_daisy_config k7070_daisy_chain[] =
+{
+ { "sio" },
+ { "ctc" },
+ { nullptr }
+};
+
+void robotron_k7070_device::device_add_mconfig(machine_config &config)
+{
+ Z80(config, m_cpu, XTAL(16'000'000) / 4);
+ m_cpu->set_addrmap(AS_PROGRAM, &robotron_k7070_device::cpu_mem);
+ m_cpu->set_addrmap(AS_IO, &robotron_k7070_device::cpu_pio);
+ m_cpu->set_daisy_config(k7070_daisy_chain);
+
+ Z80CTC(config, m_ctc, 16_MHz_XTAL / 3);
+ m_ctc->intr_callback().set_inputline(m_cpu, INPUT_LINE_IRQ0);
+ m_ctc->set_clk<0>(1230750);
+ m_ctc->set_clk<1>(1230750);
+ m_ctc->set_clk<2>(1230750);
+ m_ctc->set_clk<3>(1230750);
+ m_ctc->zc_callback<0>().set(m_sio, FUNC(z80sio_device::rxca_w));
+ m_ctc->zc_callback<0>().append(m_sio, FUNC(z80sio_device::txca_w));
+ m_ctc->zc_callback<1>().set(m_sio, FUNC(z80sio_device::rxtxcb_w));
+
+ Z80SIO(config, m_sio, XTAL(16'000'000) / 4);
+ m_sio->out_int_callback().set_inputline(m_cpu, INPUT_LINE_IRQ0);
+ m_sio->out_txda_callback().set(m_serial[0], FUNC(rs232_port_device::write_txd));
+ m_sio->out_dtra_callback().set(m_serial[0], FUNC(rs232_port_device::write_dtr));
+ m_sio->out_rtsa_callback().set(m_serial[0], FUNC(rs232_port_device::write_rts));
+ m_sio->out_txdb_callback().set(m_serial[1], FUNC(rs232_port_device::write_txd));
+ m_sio->out_dtrb_callback().set([this] (bool state) { m_kgs_iml = !state; kgs_memory_remap(); });
+
+ // V.24 port for tablet
+ RS232_PORT(config, m_serial[0], default_rs232_devices, "loopback");
+ m_serial[0]->rxd_handler().set(m_sio, FUNC(z80sio_device::rxa_w));
+ m_serial[0]->dcd_handler().set(m_sio, FUNC(z80sio_device::dcda_w));
+ m_serial[0]->cts_handler().set(m_sio, FUNC(z80sio_device::ctsa_w));
+
+ // IFSS (current loop) port for keyboard (unused on A7150)
+ RS232_PORT(config, m_serial[1], default_rs232_devices, "loopback");
+ m_serial[1]->rxd_handler().set(m_sio, FUNC(z80sio_device::rxb_w));
+
+ screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
+ screen.set_color(rgb_t::green());
+ screen.set_raw(XTAL(16'000'000), 737, 0, 640, 431, 0, 400);
+ screen.set_screen_update(FUNC(robotron_k7070_device::screen_update_k7072));
+ screen.set_palette(m_palette);
+ screen.screen_vblank().set([this] (bool state) { if (m_nmi_enable) m_cpu->set_input_line(INPUT_LINE_NMI, state); });
+
+ PALETTE(config, m_palette, palette_device::MONOCHROME);
+}
+
+void robotron_k7070_device::cpu_mem(address_map &map)
+{
+ map.unmap_value_high();
+
+ map(0x0000, 0x1fff).view(m_view_lo);
+ m_view_lo[0](0x0000, 0x1fff).rom().region("eprom", 0);
+ m_view_lo[1](0x0000, 0x1fff).ram().share("kgs_ram0");
+
+ map(0x2000, 0x7fff).ram().share("kgs_ram1");
+
+// FIXME handle IML=0 and MSEL=1 (no access to VRAM)
+ map(0x8000, 0xffff).view(m_view_hi);
+ m_view_hi[0](0x8000, 0xffff).ram().share("kgs_ram2");
+ m_view_hi[1](0x8000, 0xffff).ram().share("vram0");
+}
+
+void robotron_k7070_device::cpu_pio(address_map &map)
+{
+ map.unmap_value_high();
+ map.global_mask(0xff);
+
+ map(0x0000, 0x0003).rw(m_ctc, FUNC(z80ctc_device::read), FUNC(z80ctc_device::write));
+ map(0x0008, 0x000b).rw(m_sio, FUNC(z80sio_device::ba_cd_r), FUNC(z80sio_device::ba_cd_w));
+ map(0x0010, 0x0017).rw(FUNC(robotron_k7070_device::kgs_host_r), FUNC(robotron_k7070_device::kgs_host_w)); // p. 11 of KGS-K7070.pdf
+
+ // p. 6 of ABG-K7072.pdf
+ map(0x0020, 0x0021).w(FUNC(robotron_k7070_device::abg_addr_w));
+ map(0x0022, 0x0022).w(FUNC(robotron_k7070_device::abg_func_w));
+ map(0x0023, 0x0023).w(FUNC(robotron_k7070_device::abg_split_w));
+ map(0x0030, 0x003f).noprw(); // palette register
+
+ map(0x0080, 0x0080).w(FUNC(robotron_k7070_device::abg_misc_w));
+}
+
+void robotron_k7070_device::palette_init(palette_device &palette)
+{
+ // 0=black, 1=dim, 2=normal, 3=bold
+
+ palette.set_pen_color(0, rgb_t::black());
+ palette.set_pen_color(1, rgb_t(0x80, 0x80, 0x80));
+ palette.set_pen_color(2, rgb_t(0xc0, 0xc0, 0xc0));
+ palette.set_pen_color(3, rgb_t::white());
+}
+
+uint16_t robotron_k7070_device::io_r(offs_t offset, uint16_t mem_mask)
+{
+ uint8_t data = 0;
+
+ switch (offset)
+ {
+ case 0:
+ data = m_kgs_ctrl;
+ break;
+
+ case 1:
+ data = m_kgs_datai;
+ if (!machine().side_effects_disabled())
+ m_kgs_ctrl &= ~KGS_ST_OBF;
+ break;
+ }
+
+ if (offset && !machine().side_effects_disabled())
+ {
+ LOG("%s: KGS %d == %02x '%c'\n", machine().describe_context(),
+ offset, data, (data > 0x1f && data < 0x7f) ? data : 0x20);
+ }
+
+ return data;
+}
+
+void robotron_k7070_device::io_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ if (offset)
+ {
+ LOG("%s: KGS %d <- %02x '%c', ctrl %02x\n", machine().describe_context(),
+ offset, data, (data > 0x1f && data < 0x7f) ? data : 0x20, m_kgs_ctrl);
+ }
+
+ switch (offset)
+ {
+ case 0:
+ m_kgs_ctrl &= ~(KGS_ST_ERR | KGS_ST_INT);
+ int_w(7, CLEAR_LINE);
+ break;
+
+ case 1:
+ if (m_kgs_ctrl & KGS_ST_IBF)
+ {
+ m_kgs_ctrl |= KGS_ST_ERR;
+ }
+ else
+ {
+ m_kgs_datao = data;
+ m_kgs_ctrl |= KGS_ST_IBF;
+ }
+ break;
+ }
+}
+
+uint32_t robotron_k7070_device::screen_update_k7072(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
+{
+ int addr = m_start;
+
+ for (int y = 0; y < 400; y++)
+ {
+ int horpos = 0;
+ for (int x = 0; x < 80; x++)
+ {
+ uint8_t code = m_ram[addr++ % 32768];
+ for (int b = 0; b < 8; b++)
+ {
+ bitmap.pix(y, horpos++) = BIT(code, 7 - b);
+ }
+ }
+ }
+
+ return 0;
+}
+
+
+uint8_t robotron_k7070_device::kgs_host_r(offs_t offset)
+{
+ uint8_t data = 0;
+
+ switch (offset)
+ {
+ case 0:
+ data = m_kgs_datao;
+ if (!machine().side_effects_disabled())
+ m_kgs_ctrl &= ~(KGS_ST_ERR | KGS_ST_IBF);
+ break;
+
+ case 2:
+ data = m_kgs_ctrl;
+ break;
+
+ case 6:
+ data = m_dsel[0]->read();
+ break;
+
+ case 7:
+ data = m_dsel[1]->read();
+ break;
+
+ default:
+ break;
+ }
+
+ if (offset != 2 && offset != 5 && !machine().side_effects_disabled())
+ {
+ LOG("%s: kgs %d == %02x '%c'\n", machine().describe_context(),
+ offset, data, (data > 0x1f && data < 0x7f) ? data : ' ');
+ }
+
+ return data;
+}
+
+void robotron_k7070_device::kgs_host_w(offs_t offset, uint8_t data)
+{
+ if (offset != 2 && offset != 5)
+ {
+ LOG("%s: kgs %d <- %02x '%c', ctrl %02x\n", machine().describe_context(),
+ offset, data, (data > 0x1f && data < 0x7f) ? data : ' ', m_kgs_ctrl);
+ }
+
+ switch (offset)
+ {
+ case 1:
+ if (m_kgs_ctrl & KGS_ST_OBF)
+ {
+ m_kgs_ctrl |= KGS_ST_ERR;
+ }
+ else
+ {
+ m_kgs_datai = data;
+ m_kgs_ctrl |= KGS_ST_OBF;
+ }
+ break;
+
+ case 3:
+ m_kgs_ctrl |= KGS_ST_INT;
+ int_w(7, ASSERT_LINE);
+ break;
+
+ case 4:
+ m_kgs_ctrl |= KGS_ST_ERR;
+ break;
+
+ case 5:
+ m_abg_msel = data;
+ kgs_memory_remap();
+ break;
+ }
+}
+
+void robotron_k7070_device::abg_addr_w(offs_t offset, uint8_t data)
+{
+ if (offset == 0)
+ m_start |= ((data & 127) << 8);
+ else
+ m_start = data;
+}
+
+/*
+ * bit 0: GRAF This bit must be set if both video levels are to be output in graphics display mode or if the palette registers are to be programmed.
+ * bit 1: /PALP This bit must be set to program the palette register.
+ * bit 2: /KGSP If this bit is reset, the frame buffer can be accessed asynchronously.
+ * bit 3: BLNK Switching this bit causes the points (byte by byte) in which the attribute bit of video level 2 (bit 1) is set to flash in alphanumeric display mode.
+ */
+void robotron_k7070_device::abg_func_w(offs_t offset, uint8_t data)
+{
+ LOG("%s: abg func <- %02x\n", machine().describe_context(), data);
+ m_abg_func = data;
+}
+
+void robotron_k7070_device::abg_split_w(offs_t offset, uint8_t data)
+{
+ LOG("%s: abg split <- %02x (%d -> %d)\n", machine().describe_context(), data, data, data*2);
+ m_abg_split = data;
+}
+
+void robotron_k7070_device::abg_misc_w(offs_t offset, uint8_t data)
+{
+ LOG("%s: abg misc <- %02x\n", machine().describe_context(), data);
+ m_nmi_enable = BIT(data, 7);
+}
+
+void robotron_k7070_device::kgs_memory_remap()
+{
+ LOG("%s: kgs memory: iml %d msel %d\n", machine().describe_context(), m_kgs_iml, m_abg_msel);
+
+ m_view_lo.select(m_kgs_iml);
+ m_view_hi.select(m_abg_msel != 0);
+}
diff --git a/src/devices/bus/multibus/robotron_k7070.h b/src/devices/bus/multibus/robotron_k7070.h
new file mode 100644
index 00000000000..14c0a9c868d
--- /dev/null
+++ b/src/devices/bus/multibus/robotron_k7070.h
@@ -0,0 +1,77 @@
+// license:BSD-3-Clause
+// copyright-holders:Sergey Svishchev
+
+#ifndef MAME_BUS_MULTIBUS_ROBOTRON_K7070_H
+#define MAME_BUS_MULTIBUS_ROBOTRON_K7070_H
+
+#pragma once
+
+#include "multibus.h"
+
+#include "bus/rs232/rs232.h"
+#include "cpu/z80/z80.h"
+#include "machine/z80ctc.h"
+#include "machine/z80sio.h"
+
+#include "emupal.h"
+#include "screen.h"
+
+
+class robotron_k7070_device
+ : public device_t
+ , public device_multibus_interface
+{
+public:
+ robotron_k7070_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual ioport_constructor device_input_ports() const override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+ void cpu_mem(address_map &map);
+ virtual void cpu_pio(address_map &map);
+
+private:
+ required_device<z80_device> m_cpu;
+ required_device<z80ctc_device> m_ctc;
+ required_device<z80sio_device> m_sio;
+ required_device_array<rs232_port_device, 2> m_serial;
+ required_device<palette_device> m_palette;
+ required_shared_ptr<u8> m_ram;
+ required_ioport_array<2> m_dsel;
+
+ memory_view m_view_lo;
+ memory_view m_view_hi;
+
+ u16 m_start;
+
+ bool m_abg_msel, m_kgs_iml;
+ uint8_t m_abg_func, m_abg_split;
+ uint16_t m_abg_addr;
+ uint8_t m_kgs_datao, m_kgs_datai, m_kgs_ctrl;
+ bool m_nmi_enable;
+
+ uint8_t kgs_host_r(offs_t offset);
+ void kgs_host_w(offs_t offset, uint8_t data);
+ void abg_addr_w(offs_t offset, uint8_t data);
+ void abg_func_w(offs_t offset, uint8_t data);
+ void abg_split_w(offs_t offset, uint8_t data);
+ void abg_misc_w(offs_t offset, uint8_t data);
+ void kgs_memory_remap();
+
+ uint32_t screen_update_k7072(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
+ void palette_init(palette_device &palette);
+
+ uint16_t io_r(offs_t offset, uint16_t mem_mask);
+ void io_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+
+ void k7070_cpu_io(address_map &map);
+ void k7070_cpu_mem(address_map &map);
+};
+
+DECLARE_DEVICE_TYPE(ROBOTRON_K7070, robotron_k7070_device)
+
+#endif // MAME_BUS_MULTIBUS_ROBOTRON_K7070_H
diff --git a/src/devices/bus/multibus/robotron_k7071.cpp b/src/devices/bus/multibus/robotron_k7071.cpp
new file mode 100644
index 00000000000..89c26dc39cb
--- /dev/null
+++ b/src/devices/bus/multibus/robotron_k7071.cpp
@@ -0,0 +1,222 @@
+// license:BSD-3-Clause
+// copyright-holders:Sergey Svishchev
+
+/*
+ * Robotron K7071 (ABS) text-only video
+ *
+ * Reference: http://www.tiffe.de/Robotron/MMS16/
+ *
+ * To do:
+ * - fix screen corruption (DMA reprogramming timing?)
+ * - loadable font - CRTC LA0 connected to NMI via gate
+ */
+
+#include "emu.h"
+#include "robotron_k7071.h"
+
+#define VERBOSE 0
+#include "logmacro.h"
+
+enum kgs_st : u8
+{
+ KGS_ST_OBF = 0x01,
+ KGS_ST_IBF = 0x02,
+ KGS_ST_INT = 0x04,
+ KGS_ST_ERR = 0x80,
+};
+
+DEFINE_DEVICE_TYPE(ROBOTRON_K7071, robotron_k7071_device, "robotron_k7071", "Robotron K7071 ABS")
+
+robotron_k7071_device::robotron_k7071_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, ROBOTRON_K7071, tag, owner, clock)
+ , device_multibus_interface(mconfig, *this)
+ , m_cpu(*this, "cpu")
+ , m_dma(*this, "dma")
+ , m_crtc(*this, "crtc")
+ , m_screen(*this, "screen")
+ , m_palette(*this, "palette")
+ , m_ram(*this, "ram")
+ , m_p_chargen(*this, "chargen")
+{
+}
+
+ROM_START(robotron_k7071)
+ ROM_REGION(0x1000, "eprom", ROMREGION_ERASEFF)
+ ROM_LOAD("q209.bin", 0x0000, 0x0800, CRC(efc4aac0) SHA1(2cb4db3572e6ec7f3d3ae8e70d61b509b1fa3203))
+ ROM_LOAD("q210.bin", 0x0800, 0x0800, CRC(d23e00ed) SHA1(eaca53ed784cf263323e9abba24a364b2aadac44))
+
+ ROM_REGION(0x2000, "chargen", ROMREGION_ERASE00)
+ ROM_LOAD("q211.bin", 0x0000, 0x0800, CRC(b6241bc5) SHA1(8428e344df95451a34ad01322e245d2357712010))
+ROM_END
+
+const tiny_rom_entry *robotron_k7071_device::device_rom_region() const
+{
+ return ROM_NAME(robotron_k7071);
+}
+
+void robotron_k7071_device::device_start()
+{
+ save_item(NAME(m_kgs_datao));
+ save_item(NAME(m_kgs_datai));
+ save_item(NAME(m_kgs_ctrl));
+ save_item(NAME(m_nmi_enable));
+
+ m_cpu->space(AS_PROGRAM).specific(m_program);
+ m_bus->space(AS_IO).install_readwrite_handler(0x200, 0x203, read16s_delegate(*this, FUNC(robotron_k7071_device::io_r)), write16s_delegate(*this, FUNC(robotron_k7071_device::io_w)));
+}
+
+void robotron_k7071_device::device_reset()
+{
+ m_kgs_ctrl = KGS_ST_IBF | KGS_ST_OBF;
+ m_kgs_datao = m_kgs_datai = m_nmi_enable = 0;
+}
+
+void robotron_k7071_device::device_add_mconfig(machine_config &config)
+{
+ Z80(config, m_cpu, XTAL(16'000'000) / 6);
+ m_cpu->set_addrmap(AS_PROGRAM, &robotron_k7071_device::cpu_mem);
+ m_cpu->set_addrmap(AS_IO, &robotron_k7071_device::cpu_pio);
+
+ I8257(config, m_dma, XTAL(16'000'000) / 6);
+ m_dma->out_hrq_cb().set(FUNC(robotron_k7071_device::hrq_w));
+ m_dma->in_memr_cb().set([this] (offs_t offset) { return m_program.read_byte(offset); });
+ m_dma->out_iow_cb<0>().set(m_crtc, FUNC(i8275_device::dack_w));
+
+ I8275(config, m_crtc, XTAL(16'000'000) / 8);
+ m_crtc->set_screen(m_screen);
+ m_crtc->set_character_width(8);
+ m_crtc->set_display_callback(FUNC(robotron_k7071_device::display_pixels));
+ m_crtc->drq_wr_callback().set(m_dma, FUNC(i8257_device::dreq0_w));
+ m_crtc->lc_wr_callback().set([this] (int data) { m_cpu->set_input_line(INPUT_LINE_IRQ0, data == 15 ? ASSERT_LINE : CLEAR_LINE); });
+
+ SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
+ m_screen->set_color(rgb_t::green());
+ m_screen->set_raw(XTAL(16'000'000), 736, 0, 640, 432, 0, 416);
+ m_screen->set_screen_update(m_crtc, FUNC(i8275_device::screen_update));
+
+ PALETTE(config, m_palette, palette_device::MONOCHROME_HIGHLIGHT);
+}
+
+void robotron_k7071_device::cpu_mem(address_map &map)
+{
+ map.unmap_value_high();
+
+ map(0x0000, 0x0fff).rom().region("eprom", 0);
+ map(0x1400, 0x1fff).ram().share("ram").mirror(0x8000);
+}
+
+void robotron_k7071_device::cpu_pio(address_map &map)
+{
+ map.unmap_value_high();
+ map.global_mask(0xff);
+
+ map(0x00, 0x08).rw(m_dma, FUNC(i8257_device::read), FUNC(i8257_device::write));
+ map(0x20, 0x21).rw(m_crtc, FUNC(i8275_device::read), FUNC(i8275_device::write));
+ map(0x30, 0x30).noprw(); // chargen ram access
+ map(0x40, 0x40).nopw(); // line counter input for sync generator
+ map(0x50, 0x50).lw8(NAME([this] (u8 data) { m_kgs_ctrl |= KGS_ST_INT; int_w(7, ASSERT_LINE); }));
+ map(0x60, 0x60).lw8(NAME([this] (u8 data) { m_kgs_ctrl |= KGS_ST_ERR; }));
+ map(0x70, 0x71).rw(FUNC(robotron_k7071_device::kgs_host_r), FUNC(robotron_k7071_device::kgs_host_w));
+ map(0x80, 0x80).lw8(NAME([this] (u8 data) { m_nmi_enable = BIT(data, 7); }));
+ map(0xdf, 0xdf).nopw(); // used by IRQ handler
+}
+
+uint16_t robotron_k7071_device::io_r(offs_t offset, uint16_t mem_mask)
+{
+ uint8_t data = 0;
+
+ switch (offset)
+ {
+ case 0:
+ data = m_kgs_ctrl;
+ break;
+
+ case 1:
+ data = m_kgs_datai;
+ if (!machine().side_effects_disabled())
+ m_kgs_ctrl &= ~KGS_ST_OBF;
+ break;
+ }
+
+ return data;
+}
+
+void robotron_k7071_device::io_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ switch (offset)
+ {
+ case 0:
+ m_kgs_ctrl &= ~(KGS_ST_ERR | KGS_ST_INT);
+ int_w(7, CLEAR_LINE);
+ break;
+
+ case 1:
+ if (m_kgs_ctrl & KGS_ST_IBF)
+ {
+ m_kgs_ctrl |= KGS_ST_ERR;
+ }
+ else
+ {
+ m_kgs_datao = data;
+ m_kgs_ctrl |= KGS_ST_IBF;
+ }
+ break;
+ }
+}
+
+
+uint8_t robotron_k7071_device::kgs_host_r(offs_t offset)
+{
+ uint8_t data = 0;
+
+ switch (offset)
+ {
+ case 0:
+ data = m_kgs_ctrl;
+ break;
+
+ case 1:
+ data = m_kgs_datao;
+ if (!machine().side_effects_disabled())
+ m_kgs_ctrl &= ~(KGS_ST_ERR | KGS_ST_IBF);
+ break;
+
+ default:
+ break;
+ }
+
+ return data;
+}
+
+void robotron_k7071_device::kgs_host_w(offs_t offset, uint8_t data)
+{
+ if (offset)
+ {
+ m_kgs_datai = data;
+ m_kgs_ctrl |= KGS_ST_OBF;
+ }
+}
+
+void robotron_k7071_device::hrq_w(int state)
+{
+ // since our Z80 has no support for BUSACK, we assume it is granted immediately
+ m_cpu->set_input_line(Z80_INPUT_LINE_BUSRQ, state);
+ m_cpu->set_input_line(INPUT_LINE_HALT, state); // do we need this?
+ m_dma->hlda_w(state);
+}
+
+I8275_DRAW_CHARACTER_MEMBER(robotron_k7071_device::display_pixels)
+{
+ using namespace i8275_attributes;
+
+ rgb_t const *const palette = m_palette->palette()->entry_list_raw();
+ u8 gfx = (BIT(attrcode, LTEN)) ? 0xff : 0;
+ if (!BIT(attrcode, VSP))
+ gfx = m_p_chargen[linecount | (charcode << 4)];
+
+ if (BIT(attrcode, RVV))
+ gfx ^= 0xff;
+
+ for (u8 i = 0; i < 8; i++)
+ bitmap.pix(y, x + i) = palette[BIT(gfx, 7-i) ? (BIT(attrcode, HLGT) ? 2 : 1) : 0];
+}
diff --git a/src/devices/bus/multibus/robotron_k7071.h b/src/devices/bus/multibus/robotron_k7071.h
new file mode 100644
index 00000000000..55efbd3e05e
--- /dev/null
+++ b/src/devices/bus/multibus/robotron_k7071.h
@@ -0,0 +1,61 @@
+// license:BSD-3-Clause
+// copyright-holders:Sergey Svishchev
+
+#ifndef MAME_BUS_MULTIBUS_ROBOTRON_K7071_H
+#define MAME_BUS_MULTIBUS_ROBOTRON_K7071_H
+
+#pragma once
+
+#include "multibus.h"
+
+#include "cpu/z80/z80.h"
+#include "machine/i8257.h"
+#include "video/i8275.h"
+
+#include "emupal.h"
+#include "screen.h"
+
+
+class robotron_k7071_device
+ : public device_t
+ , public device_multibus_interface
+{
+public:
+ robotron_k7071_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+ void cpu_mem(address_map &map);
+ virtual void cpu_pio(address_map &map);
+
+private:
+ required_device<z80_device> m_cpu;
+ required_device<i8257_device> m_dma;
+ required_device<i8275_device> m_crtc;
+ required_device<screen_device> m_screen;
+ required_device<palette_device> m_palette;
+ required_shared_ptr<u8> m_ram;
+ required_region_ptr<u8> m_p_chargen;
+
+ memory_access<16, 0, 0, ENDIANNESS_LITTLE>::specific m_program;
+
+ uint8_t m_kgs_datao, m_kgs_datai, m_kgs_ctrl;
+ bool m_nmi_enable;
+
+ I8275_DRAW_CHARACTER_MEMBER(display_pixels);
+ void hrq_w(int state);
+
+ uint8_t kgs_host_r(offs_t offset);
+ void kgs_host_w(offs_t offset, uint8_t data);
+
+ uint16_t io_r(offs_t offset, uint16_t mem_mask);
+ void io_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+};
+
+DECLARE_DEVICE_TYPE(ROBOTRON_K7071, robotron_k7071_device)
+
+#endif // MAME_BUS_MULTIBUS_ROBOTRON_K7071_H
diff --git a/src/devices/bus/nabupc/adapter.cpp b/src/devices/bus/nabupc/adapter.cpp
new file mode 100644
index 00000000000..0c6ecef575f
--- /dev/null
+++ b/src/devices/bus/nabupc/adapter.cpp
@@ -0,0 +1,423 @@
+// license:BSD-3-Clause
+// copyright-holders:Brian Johnson
+/*******************************************************************
+ *
+ * NABU PC - Network Adapter Settop Box
+ *
+ *******************************************************************/
+
+#include "emu.h"
+#include "adapter.h"
+
+#include "emuopts.h"
+#include "unzip.h"
+
+#include <tuple>
+
+#define VERBOSE 0
+#include "logmacro.h"
+
+
+//**************************************************************************
+// NABU PC NETWORK ADAPTER DEVICE
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(NABUPC_NETWORK_ADAPTER, bus::nabupc::network_adapter, "nabu_net_adapter", "NABU Network Adapter")
+
+namespace bus::nabupc {
+
+//**************************************************************************
+// SEGMENT FILE LOADING
+//**************************************************************************
+
+// Load segment file from disk
+std::error_condition network_adapter::segment_file::read_archive(util::core_file &stream, uint32_t segment_id)
+{
+ segment_id &= 0xffffff;
+
+ util::core_file::ptr proxy;
+ std::error_condition err = util::core_file::open_proxy(stream, proxy);
+ if (err)
+ return err;
+
+ util::archive_file::ptr zipfile;
+ err = util::archive_file::open_zip(std::move(proxy), zipfile);
+ if (err)
+ return err;
+
+ std::string segment_filename = util::string_format("%06d.nabu", segment_id);
+
+ if (zipfile->search(segment_filename, false) < 0)
+ return std::errc::no_such_file_or_directory;
+
+ // determine the uncompressed length
+ uint64_t uncompressed_length_uint64 = zipfile->current_uncompressed_length();
+ size_t uncompressed_length = (size_t)uncompressed_length_uint64;
+ if (uncompressed_length != uncompressed_length_uint64)
+ return std::errc::not_enough_memory;
+
+ // prepare a buffer for the segment file
+ std::unique_ptr<char[]> segment_buffer(new (std::nothrow) char[uncompressed_length]);
+ if (!segment_buffer)
+ return std::errc::not_enough_memory;
+
+ err = zipfile->decompress(&segment_buffer[0], uncompressed_length);
+ if (err)
+ return err;
+
+ m_segment_id = segment_id;
+ return parse_segment(&segment_buffer[0], uncompressed_length);
+}
+
+std::error_condition network_adapter::segment_file::parse_segment(char *data, size_t length)
+{
+ util::core_file::ptr fd;
+ pak current;
+ uint64_t offset = 0;
+ size_t actual;
+ uint16_t crc;
+ uint8_t npak = 0;
+ std::error_condition err;
+
+ pak_list.clear();
+ err = util::core_file::open_ram(data, length, OPEN_FLAG_READ, fd);
+ if (err)
+ return err;
+
+ memset(current.data, 0, 991);
+ current.segment_id[0] = (m_segment_id & 0xff0000) >> 16;
+ current.segment_id[1] = (m_segment_id & 0x00ff00) >> 8;
+ current.segment_id[2] = (m_segment_id & 0x0000ff);
+ current.owner = 0x01;
+ current.tier[0] = 0x7f;
+ current.tier[1] = 0xff;
+ current.tier[2] = 0xff;
+ current.tier[3] = 0xff;
+ current.mbytes[0] = 0x7f;
+ current.mbytes[1] = 0x80;
+ std::tie(err, actual) = read_at(*fd, offset, current.data, 991);
+ do {
+ crc = 0xffff;
+ if (err) {
+ return err;
+ }
+ if (actual > 0) {
+ current.packet_number = npak;
+ current.pak_number[0] = npak;
+ current.pak_number[1] = 0;
+ current.type = 0x20;
+ if (offset == 0)
+ current.type |= 0x81;
+ if (actual < 991)
+ current.type |= 0x10;
+ current.offset[0] = ((offset) >> 8) & 0xff;
+ current.offset[1] = offset & 0xff;
+ for (int i = 0; i < 1007; ++i) {
+ crc = update_crc(crc, ((char *)&current)[i]);
+ }
+ crc ^= 0xffff;
+ current.crc[0] = (crc >> 8) & 0xff;
+ current.crc[1] = crc & 0xff;
+ pak_list.push_back(current);
+ offset = (++npak * 991);
+ memset(current.data, 0, 991);
+ std::tie(err, actual) = read_at(*fd, offset, current.data, 991);
+ }
+ } while(actual > 0);
+
+ return err;
+}
+
+const network_adapter::segment_file::pak& network_adapter::segment_file::operator[](const int index) const
+{
+ assert(index >= 0 && index < size());
+
+ return pak_list[index];
+}
+
+// crc16 calculation
+uint16_t network_adapter::segment_file::update_crc(uint16_t crc, uint8_t data)
+{
+ uint8_t bc;
+
+ bc = (crc >> 8) ^ data;
+
+ crc <<= 8;
+ crc ^= crc_table[bc];
+
+ return crc;
+}
+
+//**************************************************************************
+// INPUT PORTS
+//**************************************************************************
+
+// CONFIG
+static INPUT_PORTS_START( nabu_network_adapter )
+ PORT_START("CONFIG")
+ PORT_CONFNAME(0x01, 0x00, "Prompt for channel?")
+ PORT_CONFSETTING(0x01, "Yes")
+ PORT_CONFSETTING(0x00, "No")
+INPUT_PORTS_END
+
+//**************************************************************************
+// DEVICE INITIALIZATION
+//**************************************************************************
+
+network_adapter::network_adapter(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, NABUPC_NETWORK_ADAPTER, tag, owner, clock)
+ , device_buffered_serial_interface(mconfig, *this)
+ , device_rs232_port_interface(mconfig, *this)
+ , device_image_interface(mconfig, *this)
+ , m_config(*this, "CONFIG")
+ , m_channel(0)
+ , m_packet(0)
+ , m_segment(0)
+ , m_state(state::START)
+ , m_substate(0)
+ , m_segment_timer(nullptr)
+{
+}
+
+void network_adapter::device_start()
+{
+ m_segment_timer = timer_alloc(FUNC(network_adapter::segment_tick), this);
+
+ machine().save().register_postload(save_prepost_delegate(FUNC(network_adapter::postload), this));
+
+ save_item(NAME(m_state));
+ save_item(NAME(m_substate));
+ save_item(NAME(m_channel));
+ save_item(NAME(m_packet));
+ save_item(NAME(m_segment));
+}
+
+void network_adapter::device_reset()
+{
+ m_state = state::START;
+ m_substate = 0;
+ // initialise state
+ clear_fifo();
+
+ // configure device_buffered_serial_interface
+ set_data_frame(START_BIT_COUNT, DATA_BIT_COUNT, PARITY, STOP_BITS);
+ set_rate(BAUD);
+ receive_register_reset();
+ transmit_register_reset();
+}
+
+void network_adapter::postload()
+{
+ if (is_loaded()) {
+ m_cache.read_archive(image_core_file(), m_segment);
+ }
+}
+
+std::pair<std::error_condition, std::string> network_adapter::call_load()
+{
+ if (is_filetype("pak")) {
+ return std::make_pair(std::error_condition(), std::string());
+ }
+ return std::make_pair(image_error::INVALIDIMAGE, std::string());
+}
+
+//**************************************************************************
+// DEVICE CONFIGURATION
+//**************************************************************************
+
+ioport_constructor network_adapter::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( nabu_network_adapter );
+}
+
+//**************************************************************************
+// SERIAL PROTOCOL
+//**************************************************************************
+
+void network_adapter::input_txd(int state)
+{
+ device_buffered_serial_interface::rx_w(state);
+}
+
+void network_adapter::tra_callback()
+{
+ output_rxd(transmit_register_get_data_bit());
+}
+
+void network_adapter::received_byte(uint8_t byte)
+{
+ LOG("Received Byte 0x%02X\n", byte);
+ switch (m_state) {
+ case state::START:
+ connect(byte, bool(m_config->read() & 1));
+ break;
+ case state::IDLE:
+ idle(byte);
+ break;
+ case state::CHANNEL_REQUEST:
+ channel_request(byte);
+ break;
+ case state::SEGMENT_REQUEST:
+ segment_request(byte);
+ break;
+ case state::HEX81_REQUEST:
+ hex81_request(byte);
+ break;
+ case state::SEND_SEGMENT:
+ send_segment(byte);
+ break;
+ }
+}
+
+//**************************************************************************
+// STATE MACHINE
+//**************************************************************************
+
+void network_adapter::connect(uint8_t byte, bool channel_request = true)
+{
+ if (byte == 0x83 && m_substate == 0) {
+ transmit_byte(0x10);
+ transmit_byte(0x06);
+ transmit_byte(0xe4);
+ } else if (byte == 0x82 && m_substate == 1) {
+ transmit_byte(0x10);
+ transmit_byte(0x06);
+ } else if (byte == 0x01 && m_substate == 2) {
+ transmit_byte(channel_request ? 0x9f : 0x1f);
+ transmit_byte(0x10);
+ transmit_byte(0xe1);
+ m_state = state::IDLE;
+ } else {
+ LOG("Unexpected byte: 0x%02X (%d), restarting Adapter.\n", byte, m_substate);
+ m_state = state::START;
+ m_substate = 0;
+ return;
+ }
+ ++m_substate;
+}
+
+void network_adapter::idle(uint8_t byte)
+{
+ m_substate = 0;
+ switch (byte) {
+ case 0x85:
+ transmit_byte(0x10);
+ transmit_byte(0x06);
+ m_state = state::CHANNEL_REQUEST;
+ break;
+ case 0x84:
+ transmit_byte(0x10);
+ transmit_byte(0x06);
+ m_state = state::SEGMENT_REQUEST;
+ break;
+ case 0x83:
+ transmit_byte(0x10);
+ transmit_byte(0x06);
+ break;
+ case 0x82:
+ transmit_byte(0x10);
+ transmit_byte(0x06);
+ break;
+ case 0x81:
+ transmit_byte(0x10);
+ transmit_byte(0x06);
+ m_state = state::HEX81_REQUEST;
+ break;
+ case 0x01:
+ transmit_byte(0x10);
+ transmit_byte(0x06);
+ break;
+ }
+
+}
+
+void network_adapter::hex81_request(uint8_t byte)
+{
+ if (m_substate == 1) {
+ transmit_byte(0xe4);
+ m_state = state::IDLE;
+ }
+ ++m_substate;
+
+}
+
+void network_adapter::channel_request(uint8_t byte)
+{
+ if (m_substate == 0) {
+ m_channel = (m_channel & 0xff00) | (byte);
+ } else if (m_substate == 1) {
+ m_channel = (m_channel & 0xff) | (byte << 8);
+ transmit_byte(0xe4);
+ LOG("Channel: 0x%04X\n", m_channel);
+ m_state = state::IDLE;
+ }
+ ++m_substate;
+}
+
+void network_adapter::segment_request(uint8_t byte)
+{
+ if (m_substate == 0) {
+ m_packet = byte;
+ } else if (m_substate == 1) {
+ m_segment = (m_segment & 0xffff00) | (byte);
+ } else if (m_substate == 2) {
+ m_segment = (m_segment & 0xff00ff) | (byte << 8);
+ } else if (m_substate == 3) {
+ m_segment = (m_segment & 0xffff) | (byte << 16);
+ transmit_byte(0xe4);
+ transmit_byte(0x91);
+ m_state = state::SEND_SEGMENT;
+ m_substate = 0;
+ LOG("Segment: 0x%06X, Packet: 0x%02X\n", m_segment, m_packet);
+ return;
+ }
+ ++m_substate;
+}
+
+void network_adapter::send_segment(uint8_t byte)
+{
+ if (m_substate == 0) {
+ if (byte != 0x10) {
+ LOG("Expecting byte 0x10 got %02X, restarting.\n", byte);
+ m_state = state::START;
+ m_substate = 0;
+ return;
+ }
+ } else if (m_substate == 1) {
+ if (byte != 0x06) {
+ LOG("Expecting byte 0x06 got %02X, restarting.\n", byte);
+ m_state = state::START;
+ m_substate = 0;
+ return;
+ }
+ m_pak_offset = 0;
+ if (is_loaded() && !m_cache.read_archive(image_core_file(), m_segment)) {
+ m_segment_timer->adjust(attotime::zero, 0, attotime::from_hz(1'000));
+ LOG("Segment sending, returning to idle state\n");
+ } else {
+ LOG("Failed to find segment: %06d, restarting\n", m_segment);
+ transmit_byte(0x10);
+ transmit_byte(0x06);
+ transmit_byte(0xe4);
+ }
+ m_state = state::IDLE;
+ }
+
+ ++m_substate;
+}
+
+TIMER_CALLBACK_MEMBER(network_adapter::segment_tick)
+{
+ char * data = (char*)&m_cache[m_packet];
+ if (data[m_pak_offset] == 0x10) {
+ transmit_byte(data[m_pak_offset]);
+ }
+ transmit_byte(data[m_pak_offset++]);
+ if (m_pak_offset >= sizeof(segment_file::pak)) {
+ transmit_byte(0x10);
+ transmit_byte(0xe1);
+ m_segment_timer->reset();
+ }
+}
+
+} // bus::nabupc
diff --git a/src/devices/bus/nabupc/adapter.h b/src/devices/bus/nabupc/adapter.h
new file mode 100644
index 00000000000..ad26c9d313f
--- /dev/null
+++ b/src/devices/bus/nabupc/adapter.h
@@ -0,0 +1,153 @@
+// license:BSD-3-Clause
+// copyright-holders:Brian Johnson
+/*******************************************************************
+ *
+ * NABU PC - NABU Network Adapter
+ *
+ *******************************************************************/
+
+#ifndef MAME_BUS_NABUPC_ADAPTER_H
+#define MAME_BUS_NABUPC_ADAPTER_H
+
+#pragma once
+
+#include "bus/rs232/rs232.h"
+#include "diserial.h"
+
+namespace bus::nabupc {
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+/* NABU PC Network Adapter */
+
+class network_adapter
+ : public device_t
+ , public device_buffered_serial_interface<16U>
+ , public device_rs232_port_interface
+ , public device_image_interface
+{
+public:
+ // constructor/destructor
+ network_adapter(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+ // device_image_interface implementation
+ virtual bool is_readable() const noexcept override { return true; }
+ virtual bool is_writeable() const noexcept override { return false; }
+ virtual bool is_creatable() const noexcept override { return false; }
+ virtual bool is_reset_on_load() const noexcept override { return false; }
+ virtual bool core_opens_image_file() const noexcept override { return true; }
+ virtual const char *file_extensions() const noexcept override { return "pak"; }
+ virtual const char *image_type_name() const noexcept override { return "Segment Pak"; }
+ virtual const char *image_brief_type_name() const noexcept override { return "hcca"; }
+ virtual std::pair<std::error_condition, std::string> call_load() override;
+
+ virtual void input_txd(int state) override;
+
+protected:
+ // device_t implementation
+ virtual ioport_constructor device_input_ports() const override;
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ // device_buffered_serial_interface implementation
+ virtual void tra_callback() override;
+
+private:
+ // Serial Parameters
+ static constexpr int START_BIT_COUNT = 1;
+ static constexpr int DATA_BIT_COUNT = 8;
+ static constexpr device_serial_interface::parity_t PARITY = device_serial_interface::PARITY_NONE;
+ static constexpr device_serial_interface::stop_bits_t STOP_BITS = device_serial_interface::STOP_BITS_1;
+ static constexpr int BAUD = 111'900;
+
+ virtual void received_byte(uint8_t byte) override;
+
+ void postload();
+
+ // NABU Network Segment File
+ class segment_file {
+ public:
+ struct pak {
+ uint8_t segment_id[3];
+ uint8_t packet_number;
+ uint8_t owner;
+ uint8_t tier[4];
+ uint8_t mbytes[2];
+ uint8_t type;
+ uint8_t pak_number[2];
+ uint8_t offset[2];
+ uint8_t data[991];
+ uint8_t crc[2];
+ };
+ public:
+ std::error_condition read_archive(util::core_file &stream, uint32_t segment_id);
+ std::error_condition load(std::string_view local_path, uint32_t segment_id);
+ const pak& operator[](const int index) const;
+ uint32_t size() const { return pak_list.size(); }
+ private:
+ static constexpr uint16_t crc_table[256] = {
+ 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108, 0x9129, 0xa14a, 0xb16b,
+ 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
+ 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, 0x2462, 0x3443, 0x0420, 0x1401,
+ 0x64e6, 0x74c7, 0x44a4, 0x5485, 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
+ 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, 0xb75b, 0xa77a, 0x9719, 0x8738,
+ 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
+ 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, 0x5af5, 0x4ad4, 0x7ab7, 0x6a96,
+ 0x1a71, 0x0a50, 0x3a33, 0x2a12, 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
+ 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, 0xedae, 0xfd8f, 0xcdec, 0xddcd,
+ 0xad2a, 0xbd0b, 0x8d68, 0x9d49, 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
+ 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, 0x9188, 0x81a9, 0xb1ca, 0xa1eb,
+ 0xd10c, 0xc12d, 0xf14e, 0xe16f, 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
+ 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, 0x02b1, 0x1290, 0x22f3, 0x32d2,
+ 0x4235, 0x5214, 0x6277, 0x7256, 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
+ 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0xa7db, 0xb7fa, 0x8799, 0x97b8,
+ 0xe75f, 0xf77e, 0xc71d, 0xd73c, 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
+ 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, 0x5844, 0x4865, 0x7806, 0x6827,
+ 0x18c0, 0x08e1, 0x3882, 0x28a3, 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
+ 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d,
+ 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
+ 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, 0x6e17, 0x7e36, 0x4e55, 0x5e74,
+ 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
+ };
+ std::error_condition parse_segment(char * buffer, size_t length);
+ uint16_t update_crc(uint16_t crc, uint8_t data);
+
+ uint32_t m_segment_id;
+ std::vector<pak> pak_list;
+ };
+
+ // State Machine
+ enum state {START, IDLE, HEX81_REQUEST, CHANNEL_REQUEST, SEGMENT_REQUEST, SEND_SEGMENT};
+
+ TIMER_CALLBACK_MEMBER(segment_tick);
+
+ void connect(uint8_t byte, bool channel_request);
+ void idle(uint8_t byte);
+ void channel_request(uint8_t byte);
+ void segment_request(uint8_t byte);
+ void hex81_request(uint8_t byte);
+ void send_segment(uint8_t byte);
+ void load_segment(std::string filename);
+
+ required_ioport m_config;
+
+ uint16_t m_channel;
+ uint8_t m_packet;
+ uint32_t m_segment;
+ uint8_t m_state;
+ uint8_t m_substate;
+ uint16_t m_pak_offset;
+
+ emu_timer *m_segment_timer;
+ segment_file m_cache;
+};
+
+} // bus::nabupc
+
+DECLARE_DEVICE_TYPE_NS(NABUPC_NETWORK_ADAPTER, bus::nabupc, network_adapter)
+
+#endif // MAME_BUS_NABUPC_ADAPTER_H
diff --git a/src/devices/bus/nabupc/fdc.cpp b/src/devices/bus/nabupc/fdc.cpp
new file mode 100644
index 00000000000..c8d91aa7fb3
--- /dev/null
+++ b/src/devices/bus/nabupc/fdc.cpp
@@ -0,0 +1,167 @@
+// license:BSD-3-Clause
+// copyright-holders:Brian Johnson
+/*******************************************************************
+ *
+ * NABU PC FDC Card
+ *
+ *******************************************************************/
+
+#include "emu.h"
+#include "fdc.h"
+
+#include "imagedev/floppy.h"
+#include "machine/wd_fdc.h"
+
+#include "formats/nabupc_dsk.h"
+
+
+//**************************************************************************
+// NABU PC FDC DEVICE
+//**************************************************************************
+namespace {
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+/* NABU PC FDC Device */
+
+class fdc_device : public device_t, public bus::nabupc::device_option_expansion_interface
+{
+public:
+ // construction/destruction
+ fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual uint8_t read(offs_t offset) override;
+ virtual void write(offs_t offset, uint8_t data) override;
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+
+private:
+ void ds_w(uint8_t data);
+
+ static void floppy_formats(format_registration &fr);
+
+ required_device<wd2797_device> m_wd2797;
+ required_device_array<floppy_connector, 2> m_floppies;
+};
+
+
+static void nabu_fdc_drives(device_slot_interface &device)
+{
+ device.option_add("525dd", FLOPPY_525_DD);
+ device.option_add("35dd", FLOPPY_35_DD);
+}
+
+//-------------------------------------------------
+// fdc_device - constructor
+//-------------------------------------------------
+fdc_device::fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, NABUPC_OPTION_FDC, tag, owner, clock),
+ device_option_expansion_interface(mconfig, *this),
+ m_wd2797(*this, "fdc"),
+ m_floppies(*this, "fdc:%u", 0)
+{
+}
+
+//-------------------------------------------------
+// device_add_mconfig - device-specific config
+//-------------------------------------------------
+void fdc_device::device_add_mconfig(machine_config &config)
+{
+ WD2797(config, m_wd2797, 4_MHz_XTAL / 4).set_force_ready(true);
+ FLOPPY_CONNECTOR(config, m_floppies[0], nabu_fdc_drives, "525dd", fdc_device::floppy_formats);
+ FLOPPY_CONNECTOR(config, m_floppies[1], nabu_fdc_drives, "525dd", fdc_device::floppy_formats);
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+void fdc_device::device_start()
+{
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+void fdc_device::device_reset()
+{
+ m_wd2797->set_floppy(nullptr);
+ m_wd2797->dden_w(0);
+}
+
+//-------------------------------------------------
+// supported floppy formats
+//-------------------------------------------------
+void fdc_device::floppy_formats(format_registration &fr)
+{
+ fr.add(FLOPPY_NABUPC_FORMAT);
+}
+
+//-------------------------------------------------
+// ds_w - write to drive select/density register
+//-------------------------------------------------
+void fdc_device::ds_w(uint8_t data)
+{
+ m_wd2797->dden_w(BIT(data, 0));
+
+ floppy_image_device *floppy = nullptr;
+
+ if (BIT(data, 1)) floppy = m_floppies[0]->get_device();
+ if (BIT(data, 2)) floppy = m_floppies[1]->get_device();
+
+ m_wd2797->set_floppy(floppy);
+
+ for (auto& fdd : m_floppies)
+ {
+ floppy_image_device *floppy = fdd->get_device();
+ if (floppy)
+ {
+ floppy->mon_w((data & 6) ? 0 : 1);
+ }
+ }
+}
+
+uint8_t fdc_device::read(offs_t offset)
+{
+ uint8_t result;
+
+ switch(offset) {
+ case 0x00:
+ case 0x01:
+ case 0x02:
+ case 0x03:
+ result = m_wd2797->read(offset);
+ break;
+ case 0x0F:
+ result = 0x10;
+ break;
+ default:
+ result = 0xFF;
+ }
+ return result;
+}
+
+void fdc_device::write(offs_t offset, uint8_t data)
+{
+ switch(offset) {
+ case 0x00:
+ case 0x01:
+ case 0x02:
+ case 0x03:
+ m_wd2797->write(offset, data);
+ break;
+ case 0x0F:
+ ds_w(data);
+ break;
+ }
+}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(NABUPC_OPTION_FDC, bus::nabupc::device_option_expansion_interface, fdc_device, "nabupc_option_fdc", "NABU PC Floppy Controller")
diff --git a/src/devices/bus/nabupc/fdc.h b/src/devices/bus/nabupc/fdc.h
new file mode 100644
index 00000000000..864b5cc0353
--- /dev/null
+++ b/src/devices/bus/nabupc/fdc.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:Brian Johnson
+/*******************************************************************
+ *
+ * NABU PC Floppy Controller
+ *
+ *******************************************************************/
+
+#ifndef MAME_BUS_NABUPC_FDC_H
+#define MAME_BUS_NABUPC_FDC_H
+
+#pragma once
+
+#include "option.h"
+
+// device type definition
+DECLARE_DEVICE_TYPE_NS(NABUPC_OPTION_FDC, bus::nabupc, device_option_expansion_interface)
+
+#endif // MAME_BUS_NABUPC_FDC_H
diff --git a/src/devices/bus/nabupc/hdd.cpp b/src/devices/bus/nabupc/hdd.cpp
new file mode 100644
index 00000000000..4e03c9f531d
--- /dev/null
+++ b/src/devices/bus/nabupc/hdd.cpp
@@ -0,0 +1,113 @@
+// license:BSD-3-Clause
+// copyright-holders:Brian Johnson
+/*******************************************************************
+ *
+ * NABU PC HDD Card
+ *
+ *******************************************************************/
+
+#include "emu.h"
+#include "hdd.h"
+
+#include "machine/wd1000.h"
+
+//**************************************************************************
+// NABU PC HDD DEVICE
+//**************************************************************************
+
+
+namespace {
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+/* NABU PC HDD Device */
+
+class hdd_device : public device_t, public bus::nabupc::device_option_expansion_interface
+{
+public:
+ // construction/destruction
+ hdd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ // device_option_expansion_interface implementation
+ virtual uint8_t read(offs_t offset) override;
+ virtual void write(offs_t offset, uint8_t data) override;
+
+protected:
+ // device_t implementation
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_start() override;
+
+private:
+ required_device<wd1000_device> m_hdd;
+};
+
+//-------------------------------------------------
+// hdd_device - constructor
+//-------------------------------------------------
+hdd_device::hdd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, NABUPC_OPTION_HDD, tag, owner, clock),
+ device_option_expansion_interface(mconfig, *this),
+ m_hdd(*this, "hdd")
+{
+}
+
+//-------------------------------------------------
+// device_add_mconfig - device-specific config
+//-------------------------------------------------
+void hdd_device::device_add_mconfig(machine_config &config)
+{
+ WD1000(config, m_hdd, 0);
+
+ HARDDISK(config, "hdd:0", 0);
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+void hdd_device::device_start()
+{
+}
+
+uint8_t hdd_device::read(offs_t offset)
+{
+ uint8_t result = 0xff;
+
+ switch(offset) {
+ case 0x00:
+ case 0x01:
+ case 0x02:
+ case 0x03:
+ case 0x04:
+ case 0x05:
+ case 0x06:
+ case 0x07:
+ result = m_hdd->read(offset);
+ break;
+ case 0x0f:
+ result = 0xe8;
+ break;
+ }
+ return result;
+}
+
+void hdd_device::write(offs_t offset, uint8_t data)
+{
+ switch(offset) {
+ case 0x00:
+ case 0x01:
+ case 0x02:
+ case 0x03:
+ case 0x04:
+ case 0x05:
+ case 0x06:
+ case 0x07:
+ m_hdd->write(offset, data);
+ break;
+ }
+}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(NABUPC_OPTION_HDD, bus::nabupc::device_option_expansion_interface, hdd_device, "nabupc_option_hdd", "NABU PC Hard Disk Controller")
diff --git a/src/devices/bus/nabupc/hdd.h b/src/devices/bus/nabupc/hdd.h
new file mode 100644
index 00000000000..74b9942cd50
--- /dev/null
+++ b/src/devices/bus/nabupc/hdd.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:Brian Johnson
+/*******************************************************************
+ *
+ * NABU PC Hard Drive Controller
+ *
+ *******************************************************************/
+
+#ifndef MAME_BUS_NABUPC_HDD_H
+#define MAME_BUS_NABUPC_HDD_H
+
+#pragma once
+
+#include "option.h"
+
+// device type definition
+DECLARE_DEVICE_TYPE_NS(NABUPC_OPTION_HDD, bus::nabupc, device_option_expansion_interface)
+
+#endif // MAME_BUS_NABUPC_HDD_H
diff --git a/src/devices/bus/nabupc/option.cpp b/src/devices/bus/nabupc/option.cpp
new file mode 100644
index 00000000000..4865a4ccaf9
--- /dev/null
+++ b/src/devices/bus/nabupc/option.cpp
@@ -0,0 +1,135 @@
+// license:BSD-3-Clause
+// copyright-holders:Brian Johnson
+
+/*******************************************************************
+ *
+ * NABU PC Expansion Emulation
+ *
+ *******************************************************************/
+#include "emu.h"
+#include "option.h"
+
+#include "fdc.h"
+#include "hdd.h"
+#include "rs232.h"
+
+DEFINE_DEVICE_TYPE(NABUPC_OPTION_BUS_SLOT, bus::nabupc::option_slot_device, "nabupc_option_slot", "NABU PC Option slot")
+DEFINE_DEVICE_TYPE(NABUPC_OPTION_BUS, bus::nabupc::option_bus_device, "nabupc_option_bus", "NABU PC Option Bus")
+
+namespace bus::nabupc {
+//**************************************************************************
+// NABU SLOT DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// option_bus_slot_device - constructor
+//-------------------------------------------------
+option_slot_device::option_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, NABUPC_OPTION_BUS_SLOT, tag, owner, clock),
+ device_single_card_slot_interface<device_option_expansion_interface>(mconfig, *this),
+ m_bus(*this, finder_base::DUMMY_TAG),
+ m_slot(-1)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+void option_slot_device::device_start()
+{
+ device_option_expansion_interface *const intf(get_card_device());
+ if (intf) {
+ intf->set_option_bus(*m_bus, m_slot);
+ }
+ m_bus->add_slot(*this);
+}
+
+
+uint8_t option_slot_device::io_read(offs_t offset)
+{
+ device_option_expansion_interface *const intf(get_card_device());
+ if (intf) {
+ return intf->read(offset);
+ }
+ return 0xFF;
+}
+
+void option_slot_device::io_write(offs_t offset, uint8_t data)
+{
+ device_option_expansion_interface *const intf(get_card_device());
+ if (intf) {
+ intf->write(offset, data);
+ }
+}
+
+void option_slot_device::int_w(int state) { (*m_bus).set_int_line(state, m_slot); }
+
+
+//**************************************************************************
+// NABU OPTION BUS DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// option_bus_device - constructor
+//-------------------------------------------------
+option_bus_device::option_bus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, NABUPC_OPTION_BUS, tag, owner, clock),
+ m_int_cb(*this)
+{
+}
+
+void option_bus_device::add_slot(option_slot_device &slot)
+{
+ m_slot_list.push_back(&slot);
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+void option_bus_device::device_start()
+{
+}
+
+//-------------------------------------------------
+// device_reset - device-specific startup
+//-------------------------------------------------
+void option_bus_device::device_reset()
+{
+}
+
+
+//**************************************************************************
+// NABU OPTION CARD INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// option_device_expansion_interface - constructor
+//-------------------------------------------------
+device_option_expansion_interface::device_option_expansion_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "nabupc_option_bus"),
+ m_bus(nullptr),
+ m_slot(-1)
+{
+}
+
+//---------------------------------------------------
+// interface_pre_start - device-specific pre startup
+//---------------------------------------------------
+void device_option_expansion_interface::interface_pre_start()
+{
+ if (!m_bus || m_slot == -1)
+ throw device_missing_dependencies();
+}
+
+//-------------------------------------------------
+// SLOT_INTERFACE( option_bus_devices )
+//-------------------------------------------------
+
+void option_bus_devices(device_slot_interface &device)
+{
+ device.option_add("fdc", NABUPC_OPTION_FDC);
+ device.option_add("hdd", NABUPC_OPTION_HDD);
+ device.option_add("rs232", NABUPC_OPTION_RS232);
+}
+
+} // namespace bus::nabupc
diff --git a/src/devices/bus/nabupc/option.h b/src/devices/bus/nabupc/option.h
new file mode 100644
index 00000000000..94b47d642bf
--- /dev/null
+++ b/src/devices/bus/nabupc/option.h
@@ -0,0 +1,156 @@
+// license:BSD-3-Clause
+// copyright-holders:Brian Johnson
+/*
+ NABU PC BUS
+
+ 1 /INT<N>
+ 2 /M1
+ 3 3.58MHz SYSCLK
+ 4 AUDIO<N>
+ 5 /CS<N>
+ 6 A0
+ 7 A1
+ 8 A2
+ 9 A3
+ 10 1.79MHz PCLK
+ 11 /WR
+ 12 /RD
+ 13 /IORQ
+ 14 /WAIT<N>
+ 15 /RESET
+ 16 D0
+ 17 D1
+ 18 D2
+ 19 D3
+ 20 D4
+ 21 D5
+ 22 D6
+ 23 D7
+ 24 +5V
+ 25 +5V
+ 26 GND
+ 27 GND
+ 28 GND
+ 29 +12V
+ 30 -12V
+
+*/
+#ifndef MAME_BUS_NABUPC_OPTION_H
+#define MAME_BUS_NABUPC_OPTION_H
+
+#pragma once
+
+#include <vector>
+
+namespace bus::nabupc {
+
+//**************************************************************************
+// FORWARD DECLARATIONS
+//**************************************************************************
+
+class option_bus_device;
+class device_option_expansion_interface;
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+/* NABU PC Slot Device */
+
+class option_slot_device : public device_t, public device_single_card_slot_interface<device_option_expansion_interface>
+{
+public:
+ // construction/destruction
+ template <typename T, typename U>
+ option_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, T &&bus_tag, int slot, U &&opts, const char *dflt)
+ : option_slot_device(mconfig, tag, owner, bus_tag->clock())
+ {
+ option_reset();
+ opts(*this);
+ set_default_option(dflt);
+ set_fixed(false);
+ m_bus.set_tag(std::forward<T>(bus_tag));
+ m_slot = slot;
+ }
+ option_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ uint8_t io_read(offs_t offset);
+ void io_write(offs_t offset, uint8_t data);
+
+ void int_w(int state);
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+
+ // configuration
+ required_device<option_bus_device> m_bus;
+ int m_slot;
+};
+
+
+/* NABU PC Bus Device */
+
+class option_bus_device : public device_t
+{
+public:
+ // construction/destruction
+ option_bus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ template <unsigned Slot> auto out_int_callback() { return m_int_cb[Slot].bind(); }
+
+ template <unsigned Slot> uint8_t read(offs_t offset) {
+ option_slot_device *slot = (*this)[Slot];
+ return slot->io_read(offset);
+ }
+
+ template <unsigned Slot> void write(offs_t offset, uint8_t data) {
+ option_slot_device *slot = (*this)[Slot];
+ slot->io_write(offset, data);
+ }
+
+ void set_int_line(uint8_t state, uint8_t slot) { m_int_cb[slot](state); }
+
+ void add_slot(option_slot_device &slot);
+ option_slot_device* operator[](int index) const {assert(index < m_slot_list.size()); return m_slot_list[index]; }
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ devcb_write_line::array<5> m_int_cb;
+
+ std::vector<option_slot_device *> m_slot_list;
+};
+
+
+/* NABU PC Option Card interface */
+class device_option_expansion_interface : public device_interface
+{
+public:
+ void set_option_bus(option_bus_device &bus, int slot) { assert(!device().started()); m_bus = &bus; m_slot = slot; }
+
+ virtual uint8_t read(offs_t offset) = 0;
+ virtual void write(offs_t offset, uint8_t data) = 0;
+
+protected:
+ device_option_expansion_interface(const machine_config &mconfig, device_t &device);
+
+ virtual void interface_pre_start() override;
+ option_slot_device* get_slot() { return (*m_bus)[m_slot]; }
+
+ option_bus_device *m_bus;
+ int m_slot;
+};
+
+void option_bus_devices(device_slot_interface &device);
+
+} // namespace bus::nabupc
+
+
+// device type definition
+DECLARE_DEVICE_TYPE_NS(NABUPC_OPTION_BUS_SLOT, bus::nabupc, option_slot_device)
+DECLARE_DEVICE_TYPE_NS(NABUPC_OPTION_BUS, bus::nabupc, option_bus_device)
+
+#endif // MAME_BUS_NABUPC_OPTION_H
diff --git a/src/devices/bus/nabupc/rs232.cpp b/src/devices/bus/nabupc/rs232.cpp
new file mode 100644
index 00000000000..a57066984d3
--- /dev/null
+++ b/src/devices/bus/nabupc/rs232.cpp
@@ -0,0 +1,141 @@
+// license:BSD-3-Clause
+// copyright-holders:Brian Johnson
+/*******************************************************************
+ *
+ * NABU PC RS232 Card
+ *
+ *******************************************************************/
+
+#include "emu.h"
+#include "rs232.h"
+
+#include "bus/rs232/rs232.h"
+#include "machine/i8251.h"
+#include "machine/pit8253.h"
+
+
+namespace {
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+/* NABU PC RS232 Device */
+
+class rs232_device : public device_t, public bus::nabupc::device_option_expansion_interface
+{
+public:
+ // construction/destruction
+ rs232_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ // device_option_expansion_interface implementation
+ virtual uint8_t read(offs_t offset) override;
+ virtual void write(offs_t offset, uint8_t data) override;
+
+protected:
+ // device_t implementation
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_start() override;
+
+ void rxrdy_w(int state);
+
+private:
+ required_device<i8251_device> m_i8251;
+ required_device<pit8253_device> m_pit8253;
+};
+
+//-------------------------------------------------
+// rs232_device - constructor
+//-------------------------------------------------
+rs232_device::rs232_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, NABUPC_OPTION_RS232, tag, owner, clock),
+ device_option_expansion_interface(mconfig, *this),
+ m_i8251(*this, "i8251"),
+ m_pit8253(*this, "i8253")
+{
+}
+
+static DEVICE_INPUT_DEFAULTS_START( terminal )
+ DEVICE_INPUT_DEFAULTS( "RS232_RXBAUD", 0xff, RS232_BAUD_9600 )
+ DEVICE_INPUT_DEFAULTS( "RS232_TXBAUD", 0xff, RS232_BAUD_9600 )
+ DEVICE_INPUT_DEFAULTS( "RS232_DATABITS", 0xff, RS232_DATABITS_8 )
+ DEVICE_INPUT_DEFAULTS( "RS232_PARITY", 0xff, RS232_PARITY_NONE )
+ DEVICE_INPUT_DEFAULTS( "RS232_STOPBITS", 0xff, RS232_STOPBITS_1 )
+DEVICE_INPUT_DEFAULTS_END
+
+//-------------------------------------------------
+// device_add_mconfig - device-specific config
+//-------------------------------------------------
+void rs232_device::device_add_mconfig(machine_config &config)
+{
+ I8251(config, m_i8251, DERIVED_CLOCK(1, 2));
+ m_i8251->rxrdy_handler().set(FUNC(rs232_device::rxrdy_w));
+ m_i8251->txd_handler().set("rs232", FUNC(rs232_port_device::write_txd));
+
+ PIT8253(config, m_pit8253, DERIVED_CLOCK(1, 2));
+ m_pit8253->set_clk<0>(clock() / 2);
+ m_pit8253->out_handler<0>().set(m_i8251, FUNC(i8251_device::write_txc));
+ m_pit8253->set_clk<1>(clock() / 2);
+ m_pit8253->out_handler<1>().set(m_i8251, FUNC(i8251_device::write_rxc));
+
+ rs232_port_device &rs232(RS232_PORT(config, "rs232", default_rs232_devices, nullptr));
+ rs232.rxd_handler().set(m_i8251, FUNC(i8251_device::write_rxd));
+ rs232.cts_handler().set(m_i8251, FUNC(i8251_device::write_cts));
+ rs232.set_option_device_input_defaults("null_modem", DEVICE_INPUT_DEFAULTS_NAME(terminal));
+ rs232.set_option_device_input_defaults("terminal", DEVICE_INPUT_DEFAULTS_NAME(terminal));
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+void rs232_device::device_start()
+{
+}
+
+void rs232_device::rxrdy_w(int state)
+{
+ get_slot()->int_w(!state);
+}
+
+uint8_t rs232_device::read(offs_t offset)
+{
+ uint8_t result = 0xff;
+
+ switch (offset) {
+ case 0x00:
+ case 0x01:
+ result = m_i8251->read(offset);
+ break;
+ case 0x04:
+ case 0x05:
+ case 0x07:
+ result = m_pit8253->read(offset & 3);
+ break;
+ case 0x0f:
+ result = 0x08;
+ }
+ return result;
+}
+
+void rs232_device::write(offs_t offset, uint8_t data)
+{
+ switch (offset) {
+ case 0x00:
+ case 0x01:
+ m_i8251->write(offset, data);
+ break;
+ case 0x04:
+ case 0x05:
+ case 0x07:
+ m_pit8253->write(offset & 3, data);
+ break;
+ }
+}
+
+} // anonymous namespace
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(NABUPC_OPTION_RS232, bus::nabupc::device_option_expansion_interface, rs232_device, "nabupc_option_rs232", "NABU PC RS232 Card")
diff --git a/src/devices/bus/nabupc/rs232.h b/src/devices/bus/nabupc/rs232.h
new file mode 100644
index 00000000000..613f167b932
--- /dev/null
+++ b/src/devices/bus/nabupc/rs232.h
@@ -0,0 +1,20 @@
+// license:BSD-3-Clause
+// copyright-holders:Brian Johnson
+/*******************************************************************
+ *
+ * NABU PC RS232 Controller
+ *
+ *******************************************************************/
+
+#ifndef MAME_BUS_NABUPC_RS232_H
+#define MAME_BUS_NABUPC_RS232_H
+
+#pragma once
+
+#include "option.h"
+
+
+// device type definition
+DECLARE_DEVICE_TYPE_NS(NABUPC_OPTION_RS232, bus::nabupc, device_option_expansion_interface)
+
+#endif // MAME_BUS_NABUPC_RS232_H
diff --git a/src/devices/bus/nasbus/nasbus.cpp b/src/devices/bus/nasbus/nasbus.cpp
index 29fff032d39..2f9ef67b811 100644
--- a/src/devices/bus/nasbus/nasbus.cpp
+++ b/src/devices/bus/nasbus/nasbus.cpp
@@ -70,7 +70,6 @@ nasbus_device::nasbus_device(const machine_config &mconfig, const char *tag, dev
nasbus_device::~nasbus_device()
{
- m_dev.detach_all();
}
//-------------------------------------------------
@@ -79,8 +78,6 @@ nasbus_device::~nasbus_device()
void nasbus_device::device_start()
{
- // resolve callbacks
- m_ram_disable_handler.resolve_safe();
}
//-------------------------------------------------
@@ -98,11 +95,11 @@ void nasbus_device::device_reset()
void nasbus_device::add_card(device_nasbus_card_interface &card)
{
card.set_nasbus_device(*this);
- m_dev.append(card);
+ m_dev.emplace_back(card);
}
// callbacks from slot device to the host
-WRITE_LINE_MEMBER( nasbus_device::ram_disable_w ) { m_ram_disable_handler(state); }
+void nasbus_device::ram_disable_w(int state) { m_ram_disable_handler(state); }
//**************************************************************************
@@ -115,8 +112,7 @@ WRITE_LINE_MEMBER( nasbus_device::ram_disable_w ) { m_ram_disable_handler(state)
device_nasbus_card_interface::device_nasbus_card_interface(const machine_config &mconfig, device_t &device) :
device_interface(device, "nasbus"),
- m_nasbus(nullptr),
- m_next(nullptr)
+ m_nasbus(nullptr)
{
}
diff --git a/src/devices/bus/nasbus/nasbus.h b/src/devices/bus/nasbus/nasbus.h
index 04e1c3942f7..d1cd3a4fa77 100644
--- a/src/devices/bus/nasbus/nasbus.h
+++ b/src/devices/bus/nasbus/nasbus.h
@@ -92,6 +92,9 @@
#pragma once
+#include <functional>
+#include <vector>
+
//**************************************************************************
@@ -125,7 +128,7 @@ public:
protected:
nasbus_slot_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
private:
@@ -153,20 +156,22 @@ public:
template <typename T> void set_io_space(T &&tag, int spacenum) { m_io.set_tag(std::forward<T>(tag), spacenum); }
// from cards
- DECLARE_WRITE_LINE_MEMBER( ram_disable_w );
+ void ram_disable_w(int state);
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
virtual void device_reset() override;
private:
+ using card_vector = std::vector<std::reference_wrapper<device_nasbus_card_interface> >;
+
required_address_space m_program;
required_address_space m_io;
- simple_list<device_nasbus_card_interface> m_dev;
-
devcb_write_line m_ram_disable_handler;
+
+ card_vector m_dev;
};
// device type definition
@@ -176,29 +181,24 @@ DECLARE_DEVICE_TYPE(NASBUS, nasbus_device)
class device_nasbus_card_interface : public device_interface
{
- template <class ElementType> friend class simple_list;
public:
// construction/destruction
virtual ~device_nasbus_card_interface();
void set_nasbus_device(nasbus_device &nasbus);
- device_nasbus_card_interface *next() const { return m_next; }
-
protected:
device_nasbus_card_interface(const machine_config &mconfig, device_t &device);
virtual void interface_pre_start() override;
- DECLARE_WRITE_LINE_MEMBER( ram_disable_w ) { m_nasbus->ram_disable_w(state); }
+ void ram_disable_w(int state) { m_nasbus->ram_disable_w(state); }
address_space &program_space() { return *m_nasbus->m_program; }
address_space &io_space() { return *m_nasbus->m_io; }
private:
nasbus_device *m_nasbus;
-
- device_nasbus_card_interface *m_next;
};
// include here so drivers don't need to
diff --git a/src/devices/bus/neogeo/prot_cmc.cpp b/src/devices/bus/neogeo/prot_cmc.cpp
index 77591827f54..ea085b8ea96 100644
--- a/src/devices/bus/neogeo/prot_cmc.cpp
+++ b/src/devices/bus/neogeo/prot_cmc.cpp
@@ -661,18 +661,6 @@ static const uint8_t m1_address_0_7_xor[256] =
};
-/* The CMC50 hardware does a checksum of the first 64kb of the M1 rom, and
- uses this checksum as the basis of the key with which to decrypt the rom */
-uint16_t cmc_prot_device::generate_cs16(uint8_t *rom, int size)
-{
- uint16_t cs16 = 0x0000;
- for (int i = 0; i < size; i++)
- cs16 += rom[i];
-
- return cs16 & 0xffff;
-}
-
-
int cmc_prot_device::m1_address_scramble(int address, uint16_t key)
{
const int p1[8][16] = {
@@ -711,7 +699,9 @@ void cmc_prot_device::cmc50_m1_decrypt(uint8_t* romcrypt, uint32_t romcrypt_size
std::vector<uint8_t> buffer(rom_size);
- uint16_t key = generate_cs16(rom, 0x10000);
+ /* The CMC50 hardware does a checksum of the first 64kb of the M1 rom, and
+ uses this checksum as the basis of the key with which to decrypt the rom */
+ uint16_t key = util::sum16_creator::simple(rom, 0x10000);
//printf("key %04x\n",key);
@@ -723,36 +713,25 @@ void cmc_prot_device::cmc50_m1_decrypt(uint8_t* romcrypt, uint32_t romcrypt_size
memcpy(rom2,rom, 0x10000);
memcpy(rom2 + 0x10000, rom, 0x80000);
- #if 0
+ if (0)
{
- FILE *fp;
- const char *gamename = machine().system().name;
- char filename[256];
- sprintf(filename, "%s_m1.dump", gamename);
-
- fp=fopen(filename, "w+b");
+ auto filename = std::string(machine().system().name) + "_m1.dump";
+ auto fp = fopen(filename.c_str(), "w+b");
if (fp)
{
fwrite(rom, rom_size, 1, fp);
fclose(fp);
}
}
- #endif
-
- #if 0
+ if (0)
{
- FILE *fp;
- const char *gamename = machine().system().name;
- char filename[256];
- sprintf(filename, "%s_m1extra.dump", gamename);
-
- fp=fopen(filename, "w+b");
+ auto filename = std::string(machine().system().name) + "_m1extra.dump";
+ auto fp = fopen(filename.c_str(), "w+b");
if (fp)
{
fwrite(&rom[0xf800], 0x800, 1, fp);
fclose(fp);
}
}
- #endif
}
diff --git a/src/devices/bus/neogeo/prot_cmc.h b/src/devices/bus/neogeo/prot_cmc.h
index 2853c71aa8f..d1f8dd10b9a 100644
--- a/src/devices/bus/neogeo/prot_cmc.h
+++ b/src/devices/bus/neogeo/prot_cmc.h
@@ -59,7 +59,6 @@ public:
void sfix_decrypt(uint8_t* rom, uint32_t rom_size, uint8_t* fixed, uint32_t fixed_size);
- uint16_t generate_cs16(uint8_t *rom, int size);
int m1_address_scramble(int address, uint16_t key);
void cmc50_m1_decrypt(uint8_t* romcrypt, uint32_t romcrypt_size, uint8_t* romaudio, uint32_t romaudio_size);
diff --git a/src/devices/bus/neogeo/prot_mslugx.cpp b/src/devices/bus/neogeo/prot_mslugx.cpp
index 04b785514a5..38cbb0b436b 100644
--- a/src/devices/bus/neogeo/prot_mslugx.cpp
+++ b/src/devices/bus/neogeo/prot_mslugx.cpp
@@ -1,5 +1,5 @@
// license:BSD-3-Clause
-// copyright-holders:S. Smith,David Haywood,Fabio Priuli
+// copyright-holders:S. Smith, David Haywood, Fabio Priuli, iq_132
#include "emu.h"
#include "prot_mslugx.h"
diff --git a/src/devices/bus/neogeo/prot_mslugx.h b/src/devices/bus/neogeo/prot_mslugx.h
index 02243fff265..0280ad1bbe5 100644
--- a/src/devices/bus/neogeo/prot_mslugx.h
+++ b/src/devices/bus/neogeo/prot_mslugx.h
@@ -1,5 +1,5 @@
// license:BSD-3-Clause
-// copyright-holders:S. Smith,David Haywood,Fabio Priuli
+// copyright-holders:S. Smith, David Haywood, Fabio Priuli, iq_132
#ifndef MAME_BUS_NEOGEO_PROT_MSLUGX_H
#define MAME_BUS_NEOGEO_PROT_MSLUGX_H
diff --git a/src/devices/bus/neogeo/sbp.cpp b/src/devices/bus/neogeo/sbp.cpp
index 0ce1d179248..b778230fb19 100644
--- a/src/devices/bus/neogeo/sbp.cpp
+++ b/src/devices/bus/neogeo/sbp.cpp
@@ -8,6 +8,11 @@
Note: since protection here involves accesses to ROM, we include the scrambling in this
file rather than in a separate prot_* source
+ TODO:
+ - level token counter on the right stays stuck after finishing level 1 (internal token
+ counter still works, so you can still progress)
+ - any other protection checks later on?
+
***********************************************************************************************************/
@@ -22,6 +27,10 @@ neogeo_sbp_cart_device::neogeo_sbp_cart_device(const machine_config &mconfig, co
}
+//-------------------------------------------------
+// mapper specific start/reset
+//-------------------------------------------------
+
void neogeo_sbp_cart_device::device_start()
{
}
@@ -31,12 +40,15 @@ void neogeo_sbp_cart_device::device_reset()
}
+//-------------------------------------------------
+// protection
+//-------------------------------------------------
uint16_t neogeo_sbp_cart_device::protection_r(address_space &space, offs_t offset)
{
uint16_t* rom = (get_rom_size()) ? get_rom_base() : get_region_rom_base();
uint16_t origdata = rom[offset + (0x200/2)];
- uint16_t data = bitswap<16>(origdata, 11,10,9,8,15,14,13,12,3,2,1,0,7,6,5,4);
+ uint16_t data = bitswap<16>(origdata, 11,10,9,8,15,14,13,12,3,2,1,0,7,6,5,4);
int realoffset = 0x200 + (offset * 2);
logerror("sbp_lowerrom_r offset %08x data %04x\n", realoffset, data);
@@ -54,8 +66,7 @@ void neogeo_sbp_cart_device::protection_w(offs_t offset, uint16_t data, uint16_t
int realoffset = 0x200 + (offset * 2);
// the actual data written is just pulled from the end of the rom, and unused space
- // maybe this is just some kind of watchdog for the protection device and it doesn't
- // matter?
+ // maybe this is just some kind of watchdog for the protection device and it doesn't matter?
if (realoffset == 0x1080)
{
if (data == 0x4e75)
@@ -74,12 +85,16 @@ void neogeo_sbp_cart_device::protection_w(offs_t offset, uint16_t data, uint16_t
void neogeo_sbp_cart_device::patch(uint8_t* cpurom, uint32_t cpurom_size)
{
- /* the game code clears the text overlay used ingame immediately after writing it.. why? protection? sloppy code that the hw ignores? imperfect emulation? */
uint16_t* rom = (uint16_t*)cpurom;
+ // the game code clears the text overlay used ingame immediately after writing it..
+ // why? protection? sloppy code that the hw ignores? imperfect emulation?
rom[0x2a6f8/2] = 0x4e71;
rom[0x2a6fa/2] = 0x4e71;
rom[0x2a6fc/2] = 0x4e71;
+
+ // enable joystick inputs
+ rom[0x3ff2d/2] = 0x7001;
}
void neogeo_sbp_cart_device::decrypt_all(DECRYPT_ALL_PARAMS)
diff --git a/src/devices/bus/neogeo/slot.cpp b/src/devices/bus/neogeo/slot.cpp
index f5cd7bf80b8..ce8fd3acf6e 100644
--- a/src/devices/bus/neogeo/slot.cpp
+++ b/src/devices/bus/neogeo/slot.cpp
@@ -224,8 +224,7 @@ void neogeo_cart_slot_device::set_cart_type(const char *slot)
call load
-------------------------------------------------*/
-
-image_init_result neogeo_cart_slot_device::call_load()
+std::pair<std::error_condition, std::string> neogeo_cart_slot_device::call_load()
{
if (m_cart)
{
@@ -304,12 +303,10 @@ image_init_result neogeo_cart_slot_device::call_load()
// SPEED UP WORKAROUND: to speed up sprite drawing routine, let us store the sprite data in
// a different format (we then always access such alt format for drawing)
m_cart->optimize_sprites(m_cart->get_sprites_base(), m_cart->get_sprites_size());
-
- return image_init_result::PASS;
}
}
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
diff --git a/src/devices/bus/neogeo/slot.h b/src/devices/bus/neogeo/slot.h
index 4c86456ff61..0b5fced8f80 100644
--- a/src/devices/bus/neogeo/slot.h
+++ b/src/devices/bus/neogeo/slot.h
@@ -203,15 +203,15 @@ public:
neogeo_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint16_t clock);
virtual ~neogeo_cart_slot_device();
- // image-level overrides
- virtual image_init_result call_load() override;
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
virtual void call_unload() override;
virtual bool is_reset_on_load() const noexcept override { return true; }
virtual const char *image_interface() const noexcept override { return "neo_cart"; }
virtual const char *file_extensions() const noexcept override { return "bin"; }
- // slot interface overrides
+ // device_slot_interface implementation
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
// reading and writing
@@ -328,9 +328,8 @@ public:
get_audio_base(), get_audio_size(),
get_audiocrypt_base(), get_audiocrypt_size()); }
-
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
private:
diff --git a/src/devices/bus/nes/2a03pur.cpp b/src/devices/bus/nes/2a03pur.cpp
index 9105c518844..9425cfdadcf 100644
--- a/src/devices/bus/nes/2a03pur.cpp
+++ b/src/devices/bus/nes/2a03pur.cpp
@@ -19,12 +19,11 @@
#ifdef NES_PCB_DEBUG
-#define VERBOSE 1
+#define VERBOSE (LOG_GENERAL)
#else
-#define VERBOSE 0
+#define VERBOSE (0)
#endif
-
-#define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0)
+#include "logmacro.h"
//-------------------------------------------------
@@ -93,7 +92,7 @@ void nes_2a03pur_device::pcb_reset()
void nes_2a03pur_device::write_l(offs_t offset, u8 data)
{
- LOG_MMC(("2a03 puritans write_l, offset: %04x, data: %02x\n", offset, data));
+ LOG("2a03 puritans write_l, offset: %04x, data: %02x\n", offset, data);
offset += 0x100;
if (offset >= 0x1000)
m_reg[offset & 7] = data;
@@ -101,7 +100,7 @@ void nes_2a03pur_device::write_l(offs_t offset, u8 data)
u8 nes_2a03pur_device::read_h(offs_t offset)
{
- LOG_MMC(("2a03 puritans read_h, offset: %04x\n", offset));
+ LOG("2a03 puritans read_h, offset: %04x\n", offset);
return m_prg[((m_reg[BIT(offset, 12, 3)] * 0x1000) + (offset & 0x0fff)) & (m_prg_size - 1)];
}
diff --git a/src/devices/bus/nes/act53.cpp b/src/devices/bus/nes/act53.cpp
index 9fd4ced2a6b..59955eb74fc 100644
--- a/src/devices/bus/nes/act53.cpp
+++ b/src/devices/bus/nes/act53.cpp
@@ -17,12 +17,11 @@
#ifdef NES_PCB_DEBUG
-#define VERBOSE 1
+#define VERBOSE (LOG_GENERAL)
#else
-#define VERBOSE 0
+#define VERBOSE (0)
#endif
-
-#define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0)
+#include "logmacro.h"
//-------------------------------------------------
@@ -151,7 +150,7 @@ void nes_action53_device::update_mirr()
void nes_action53_device::write_l(offs_t offset, u8 data)
{
- LOG_MMC(("action 53 write_l, offset: %04x, data: %02x\n", offset, data));
+ LOG("action 53 write_l, offset: %04x, data: %02x\n", offset, data);
offset += 0x100;
if (offset >= 0x1000)
m_sel = bitswap<2>(data, 7, 0);
@@ -160,7 +159,7 @@ void nes_action53_device::write_l(offs_t offset, u8 data)
void nes_action53_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("action 53 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("action 53 write_h, offset: %04x, data: %02x\n", offset, data);
if (m_reg[m_sel] != data)
{
diff --git a/src/devices/bus/nes/aladdin.cpp b/src/devices/bus/nes/aladdin.cpp
index 00b444cd395..add680fbfed 100644
--- a/src/devices/bus/nes/aladdin.cpp
+++ b/src/devices/bus/nes/aladdin.cpp
@@ -19,12 +19,11 @@
#ifdef NES_PCB_DEBUG
-#define VERBOSE 1
+#define VERBOSE (LOG_GENERAL)
#else
-#define VERBOSE 0
+#define VERBOSE (0)
#endif
-
-#define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0)
+#include "logmacro.h"
@@ -93,20 +92,19 @@ uint8_t nes_aladdin_slot_device::read(offs_t offset)
}
// 128K for Dizzy The Adventurer, 256K for the others
-image_init_result nes_aladdin_slot_device::call_load()
+std::pair<std::error_condition, std::string> nes_aladdin_slot_device::call_load()
{
if (m_cart)
{
- uint8_t *ROM = m_cart->get_cart_base();
- uint32_t size;
-
+ uint8_t *const ROM = m_cart->get_cart_base();
if (!ROM)
- return image_init_result::FAIL;
+ return std::make_pair(image_error::INTERNAL, std::string());
+ uint32_t size;
if (!loaded_through_softlist())
{
if (length() != 0x20010 && length() != 0x40010)
- return image_init_result::FAIL;
+ return std::make_pair(image_error::INVALIDLENGTH, std::string());
uint8_t temp[0x40010];
size = length() - 0x10;
@@ -114,26 +112,28 @@ image_init_result nes_aladdin_slot_device::call_load()
memcpy(ROM, temp + 0x10, size);
// double check that iNES files are really mapper 71 or 232
+ uint8_t mapper = (temp[6] & 0xf0) >> 4;
+ mapper |= temp[7] & 0xf0;
+ if (mapper != 71 && mapper != 232)
{
- uint8_t mapper = (temp[6] & 0xf0) >> 4;
- mapper |= temp[7] & 0xf0;
- if (mapper != 71 && mapper != 232)
- return image_init_result::FAIL;
+ return std::make_pair(
+ image_error::INVALIDIMAGE,
+ util::string_format("Unsupported iNES mapper %u (must be 71 or 232)", mapper));
}
}
else
{
- if (get_software_region_length("rom") != 0x20000 && get_software_region_length("rom") != 0x40000)
- return image_init_result::FAIL;
-
size = get_software_region_length("rom");
+ if (size != 0x2'0000 && size != 0x4'0000)
+ return std::make_pair(image_error::INVALIDLENGTH, "Unsupported cartridge size (must be 128K or 256K)");
+
memcpy(ROM, get_software_region("rom"), size);
}
m_cart->set_cart_size(size);
}
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
@@ -145,8 +145,7 @@ std::string nes_aladdin_slot_device::get_default_card_software(get_default_card_
hook.image_file()->length(len); // FIXME: check error return, guard against excessively large files
std::vector<uint8_t> rom(len);
- size_t actual;
- hook.image_file()->read(&rom[0], len, actual); // FIXME: check error return or read returning short
+ util::read(*hook.image_file(), &rom[0], len); // FIXME: check error return or read returning short
uint8_t const mapper = ((rom[6] & 0xf0) >> 4) | (rom[7] & 0xf0);
@@ -298,7 +297,7 @@ void nes_aladdin_device::pcb_reset()
uint8_t nes_aladdin_device::read_h(offs_t offset)
{
- LOG_MMC(("aladdin read_h, offset: %04x\n", offset));
+ LOG("aladdin read_h, offset: %04x\n", offset);
// this shall be the proper code, but it's a bit slower, so we access directly the subcart below
//return m_subslot->read(offset);
@@ -310,7 +309,7 @@ uint8_t nes_aladdin_device::read_h(offs_t offset)
void nes_aladdin_device::write_h(offs_t offset, uint8_t data)
{
- LOG_MMC(("aladdin write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("aladdin write_h, offset: %04x, data: %02x\n", offset, data);
m_subslot->write_prg(offset, data);
}
diff --git a/src/devices/bus/nes/aladdin.h b/src/devices/bus/nes/aladdin.h
index 170649fdd30..06203ea1a6d 100644
--- a/src/devices/bus/nes/aladdin.h
+++ b/src/devices/bus/nes/aladdin.h
@@ -63,24 +63,24 @@ public:
nes_aladdin_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual ~nes_aladdin_slot_device();
- // image-level overrides
- virtual image_init_result call_load() override;
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
virtual bool is_reset_on_load() const noexcept override { return true; }
virtual const char *image_interface() const noexcept override { return "ade_cart"; }
virtual const char *file_extensions() const noexcept override { return "nes,bin"; }
- // slot interface overrides
+ // device_slot_interface implementation
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
uint8_t read(offs_t offset);
void write_prg(uint32_t offset, uint8_t data) { if (m_cart) m_cart->write_prg(offset, data); }
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
- aladdin_cart_interface* m_cart;
+ aladdin_cart_interface *m_cart;
};
// device type definition
@@ -160,9 +160,8 @@ public:
virtual void pcb_reset() override;
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
-
virtual void device_add_mconfig(machine_config &config) override;
required_device<nes_aladdin_slot_device> m_subslot;
diff --git a/src/devices/bus/nes/ave.cpp b/src/devices/bus/nes/ave.cpp
index f0f1196191c..8f2b6cace2d 100644
--- a/src/devices/bus/nes/ave.cpp
+++ b/src/devices/bus/nes/ave.cpp
@@ -21,12 +21,11 @@
#ifdef NES_PCB_DEBUG
-#define VERBOSE 1
+#define VERBOSE (LOG_GENERAL)
#else
-#define VERBOSE 0
+#define VERBOSE (0)
#endif
-
-#define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0)
+#include "logmacro.h"
//-------------------------------------------------
@@ -94,7 +93,7 @@ void nes_maxi15_device::pcb_reset()
void nes_nina001_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("nina-001 write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("nina-001 write_m, offset: %04x, data: %02x\n", offset, data);
device_nes_cart_interface::write_m(offset, data); // write WRAM
@@ -127,7 +126,7 @@ void nes_nina001_device::write_m(offs_t offset, u8 data)
void nes_nina006_device::write_l(offs_t offset, u8 data)
{
- LOG_MMC(("nina-006 write_l, offset: %04x, data: %02x\n", offset, data));
+ LOG("nina-006 write_l, offset: %04x, data: %02x\n", offset, data);
offset += 0x100;
if (BIT(offset, 8)) // $41xx, $43xx, ... $5fxx
@@ -151,7 +150,7 @@ void nes_nina006_device::write_l(offs_t offset, u8 data)
u8 nes_maxi15_device::read_h(offs_t offset)
{
- LOG_MMC(("Maxi 15 read_h, offset: %04x\n", offset));
+ LOG("Maxi 15 read_h, offset: %04x\n", offset);
u8 temp = hi_access_rom(offset);
diff --git a/src/devices/bus/nes/bandai.cpp b/src/devices/bus/nes/bandai.cpp
index 9bb61da4262..66bd016c45a 100644
--- a/src/devices/bus/nes/bandai.cpp
+++ b/src/devices/bus/nes/bandai.cpp
@@ -34,13 +34,14 @@
#include "emu.h"
#include "bandai.h"
+#define LOG_UNHANDLED (1U << 1)
+
#ifdef NES_PCB_DEBUG
-#define VERBOSE 1
+#define VERBOSE (LOG_UNHANDLED | LOG_GENERAL)
#else
-#define VERBOSE 0
+#define VERBOSE (LOG_UNHANDLED)
#endif
-
-#define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0)
+#include "logmacro.h"
@@ -197,7 +198,7 @@ void nes_fjump2_device::pcb_reset()
iNES: mapper 96
- In MESS: Preliminary Support.
+ In MAME: Preliminary Support.
-------------------------------------------------*/
@@ -248,7 +249,7 @@ void nes_oekakids_device::ppu_latch(offs_t offset)
void nes_oekakids_device::write_h(offs_t offset, uint8_t data)
{
- LOG_MMC(("oeka kids write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("oeka kids write_h, offset: %04x, data: %02x\n", offset, data);
prg32(data & 0x03);
m_reg = data & 0x04;
@@ -274,7 +275,7 @@ void nes_oekakids_device::write_h(offs_t offset, uint8_t data)
iNES: mappers 16, 153 (see below), 157 & 159
- In MESS: Supported
+ In MAME: Supported
-------------------------------------------------*/
@@ -300,7 +301,7 @@ TIMER_CALLBACK_MEMBER(nes_fcg_device::irq_timer_tick)
void nes_fcg_device::fcg_write(offs_t offset, uint8_t data)
{
- LOG_MMC(("lz93d50_write, offset: %04x, data: %02x\n", offset, data));
+ LOG("lz93d50_write, offset: %04x, data: %02x\n", offset, data);
switch (offset & 0x0f)
{
@@ -331,14 +332,14 @@ void nes_fcg_device::fcg_write(offs_t offset, uint8_t data)
m_irq_count = (m_irq_count & 0x00ff) | (data << 8);
break;
default:
- logerror("lz93d50_write uncaught write, offset: %04x, data: %02x\n", offset, data);
+ LOGMASKED(LOG_UNHANDLED, "lz93d50_write uncaught write, offset: %04x, data: %02x\n", offset, data);
break;
}
}
void nes_fcg_device::write_m(offs_t offset, uint8_t data)
{
- LOG_MMC(("lz93d50 write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("lz93d50 write_m, offset: %04x, data: %02x\n", offset, data);
if (m_battery.empty() && m_prgram.empty())
fcg_write(offset & 0x0f, data);
@@ -353,7 +354,7 @@ void nes_fcg_device::write_m(offs_t offset, uint8_t data)
void nes_lz93d50_24c01_device::write_h(offs_t offset, uint8_t data)
{
- LOG_MMC(("lz93d50_24c01 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("lz93d50_24c01 write_h, offset: %04x, data: %02x\n", offset, data);
switch (offset & 0x0f)
{
@@ -370,7 +371,7 @@ void nes_lz93d50_24c01_device::write_h(offs_t offset, uint8_t data)
uint8_t nes_lz93d50_24c01_device::read_m(offs_t offset)
{
- LOG_MMC(("lz93d50 EEPROM read, offset: %04x\n", offset));
+ LOG("lz93d50 EEPROM read, offset: %04x\n", offset);
if (m_i2c_dir)
return (m_i2cmem->read_sda() & 1) << 4;
else
@@ -383,7 +384,7 @@ uint8_t nes_lz93d50_24c01_device::read_m(offs_t offset)
void nes_lz93d50_24c01_device::device_add_mconfig(machine_config &config)
{
- I2C_24C01(config, m_i2cmem);
+ I2C_X24C01(config, m_i2cmem);
}
void nes_lz93d50_24c02_device::device_add_mconfig(machine_config &config)
@@ -405,7 +406,7 @@ void nes_lz93d50_24c02_device::device_add_mconfig(machine_config &config)
iNES: mappers 153
- In MESS: Supported
+ In MAME: Supported
-------------------------------------------------*/
@@ -422,19 +423,19 @@ void nes_fjump2_device::set_prg()
uint8_t nes_fjump2_device::read_m(offs_t offset)
{
- LOG_MMC(("fjump2 read_m, offset: %04x\n", offset));
+ LOG("fjump2 read_m, offset: %04x\n", offset);
return m_battery[offset & (m_battery.size() - 1)];
}
void nes_fjump2_device::write_m(offs_t offset, uint8_t data)
{
- LOG_MMC(("fjump2 write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("fjump2 write_m, offset: %04x, data: %02x\n", offset, data);
m_battery[offset & (m_battery.size() - 1)] = data;
}
void nes_fjump2_device::write_h(offs_t offset, uint8_t data)
{
- LOG_MMC(("fjump2 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("fjump2 write_h, offset: %04x, data: %02x\n", offset, data);
switch (offset & 0x0f)
{
diff --git a/src/devices/bus/nes/batlab.cpp b/src/devices/bus/nes/batlab.cpp
index e117e6fbf5e..3a9df33a3cf 100644
--- a/src/devices/bus/nes/batlab.cpp
+++ b/src/devices/bus/nes/batlab.cpp
@@ -20,13 +20,14 @@
#include "video/ppu2c0x.h" // this has to be included so that IRQ functions can access ppu2c0x_device::BOTTOM_VISIBLE_SCANLINE
+#define LOG_HIFREQ (1U << 1)
+
#ifdef NES_PCB_DEBUG
-#define VERBOSE 1
+#define VERBOSE (LOG_GENERAL)
#else
-#define VERBOSE 0
+#define VERBOSE (0)
#endif
-
-#define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0)
+#include "logmacro.h"
//-------------------------------------------------
@@ -111,7 +112,7 @@ void nes_batmap_srrx_device::pcb_reset()
void nes_batmap_000_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("batmap_000 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("batmap_000 write_h, offset: %04x, data: %02x\n", offset, data);
switch (offset & 0x6001)
{
@@ -173,7 +174,7 @@ void nes_batmap_srrx_device::hblank_irq(int scanline, bool vblank, bool blanked)
if (m_irq_enable && !blanked && !m_irq_count)
{
- LOG_MMC(("irq fired, scanline: %d\n", scanline));
+ LOG("irq fired, scanline: %d\n", scanline);
set_irq_line(ASSERT_LINE);
}
}
@@ -187,7 +188,7 @@ u8 nes_batmap_srrx_device::read_dpcm()
u8 nes_batmap_srrx_device::read_l(offs_t offset)
{
-// LOG_MMC(("batmap_srrx read_l, offset: %04x", offset));
+ LOGMASKED(LOG_HIFREQ, "batmap_srrx read_l, offset: %04x", offset);
offset += 0x100;
switch (offset & 0x1800)
@@ -203,13 +204,13 @@ u8 nes_batmap_srrx_device::read_l(offs_t offset)
u8 nes_batmap_srrx_device::read_m(offs_t offset)
{
-// LOG_MMC(("batmap_srrx read_m, offset: %04x", offset));
+ LOGMASKED(LOG_HIFREQ, "batmap_srrx read_m, offset: %04x", offset);
return m_prg[(m_reg * 0x2000 + offset) & (m_prg_size - 1)];
}
u8 nes_batmap_srrx_device::read_h(offs_t offset)
{
- LOG_MMC(("batmap_srrx read_h, offset: %04x", offset));
+ LOG("batmap_srrx read_h, offset: %04x", offset);
if ((offset & 0x7000) == 0x4000)
return read_dpcm();
@@ -219,7 +220,7 @@ u8 nes_batmap_srrx_device::read_h(offs_t offset)
void nes_batmap_srrx_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("batmap_srrx write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("batmap_srrx write_h, offset: %04x, data: %02x\n", offset, data);
switch (offset & 0x7000)
{
diff --git a/src/devices/bus/nes/benshieng.cpp b/src/devices/bus/nes/benshieng.cpp
index 9fadad83386..a8dcedd9780 100644
--- a/src/devices/bus/nes/benshieng.cpp
+++ b/src/devices/bus/nes/benshieng.cpp
@@ -16,12 +16,11 @@
#ifdef NES_PCB_DEBUG
-#define VERBOSE 1
+#define VERBOSE (LOG_GENERAL)
#else
-#define VERBOSE 0
+#define VERBOSE (0)
#endif
-
-#define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0)
+#include "logmacro.h"
//-------------------------------------------------
@@ -74,7 +73,7 @@ void nes_benshieng_device::pcb_reset()
void nes_benshieng_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("benshieng write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("benshieng write_h, offset: %04x, data: %02x\n", offset, data);
// m_mmc_dipsetting = ioport("CARTDIPS")->read();
u8 bank = BIT(offset, 10, 2);
diff --git a/src/devices/bus/nes/bootleg.cpp b/src/devices/bus/nes/bootleg.cpp
index c0ac3e1a35c..4ce050033d5 100644
--- a/src/devices/bus/nes/bootleg.cpp
+++ b/src/devices/bus/nes/bootleg.cpp
@@ -25,14 +25,14 @@
#include "video/ppu2c0x.h" // this has to be included so that IRQ functions can access ppu2c0x_device::BOTTOM_VISIBLE_SCANLINE
+#define LOG_HIFREQ (1U << 1)
#ifdef NES_PCB_DEBUG
-#define VERBOSE 1
+#define VERBOSE (LOG_GENERAL)
#else
-#define VERBOSE 0
+#define VERBOSE (0)
#endif
-
-#define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0)
+#include "logmacro.h"
//-------------------------------------------------
@@ -689,7 +689,7 @@ void nes_sc127_device::hblank_irq(int scanline, bool vblank, bool blanked)
if (!blanked && (m_irq_count == 0))
{
- LOG_MMC(("irq fired, scanline: %d\n", scanline));
+ LOG("irq fired, scanline: %d\n", scanline);
set_irq_line(ASSERT_LINE);
m_irq_enable = 0;
}
@@ -698,7 +698,7 @@ void nes_sc127_device::hblank_irq(int scanline, bool vblank, bool blanked)
void nes_sc127_device::write_h(offs_t offset, uint8_t data)
{
- LOG_MMC(("sc127 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("sc127 write_h, offset: %04x, data: %02x\n", offset, data);
switch (offset)
{
@@ -764,7 +764,7 @@ TIMER_CALLBACK_MEMBER(nes_mbaby_device::irq_timer_tick)
void nes_mbaby_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("Mario Baby write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("Mario Baby write_h, offset: %04x, data: %02x\n", offset, data);
if (offset >= 0x7000)
{
@@ -790,7 +790,7 @@ void nes_mbaby_device::write_h(offs_t offset, u8 data)
u8 nes_mbaby_device::read_m(offs_t offset)
{
- LOG_MMC(("Mario Baby read_m, offset: %04x\n", offset));
+ LOG("Mario Baby read_m, offset: %04x\n", offset);
return m_prg[(m_latch * 0x2000) + (offset & 0x1fff)];
}
@@ -808,7 +808,7 @@ u8 nes_mbaby_device::read_m(offs_t offset)
void nes_asn_device::write_h(offs_t offset, uint8_t data)
{
- LOG_MMC(("Ai Senshi Nicol write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("Ai Senshi Nicol write_h, offset: %04x, data: %02x\n", offset, data);
if (offset == 0x0000)
chr8(data, CHRROM);
@@ -819,7 +819,7 @@ void nes_asn_device::write_h(offs_t offset, uint8_t data)
uint8_t nes_asn_device::read_m(offs_t offset)
{
- LOG_MMC(("Ai Senshi Nicol read_m, offset: %04x\n", offset));
+ LOG("Ai Senshi Nicol read_m, offset: %04x\n", offset);
return m_prg[((m_latch * 0x2000) + (offset & 0x1fff)) & (m_prg_size - 1)];
}
@@ -840,13 +840,13 @@ TIMER_CALLBACK_MEMBER(nes_smb3p_device::irq_timer_tick)
// counter does not stop when interrupts are disabled
if (m_irq_count != 0xffff)
m_irq_count++;
- else if (m_irq_enable)
+ if (m_irq_enable && m_irq_count == 0xffff)
set_irq_line(ASSERT_LINE);
}
void nes_smb3p_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("btl_smb3_w, offset: %04x, data: %02x\n", offset, data));
+ LOG("btl_smb3_w, offset: %04x, data: %02x\n", offset, data);
switch (offset & 0x0f)
{
@@ -907,7 +907,7 @@ void nes_smb3p_device::write_h(offs_t offset, u8 data)
void nes_btl_cj_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("btl_cj write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("btl_cj write_h, offset: %04x, data: %02x\n", offset, data);
if (BIT(offset, 4))
{
@@ -949,7 +949,7 @@ void nes_btl_dn_device::hblank_irq(int scanline, bool vblank, bool blanked)
void nes_btl_dn_device::write_h(offs_t offset, uint8_t data)
{
uint8_t bank;
- LOG_MMC(("btl_dn write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("btl_dn write_h, offset: %04x, data: %02x\n", offset, data);
switch (offset & 0x7003)
{
@@ -1005,32 +1005,32 @@ void nes_btl_dn_device::write_h(offs_t offset, uint8_t data)
u8 nes_whirlwind_device::read_m(offs_t offset)
{
- LOG_MMC(("whirlwind read_m, offset: %04x\n", offset));
+ LOG("whirlwind read_m, offset: %04x\n", offset);
return m_prg[((m_reg & m_prg_mask) * 0x2000) + offset];
}
void nes_dh08_device::write_h(offs_t offset, u8 data) // submapper 1
{
- LOG_MMC(("dh08 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("dh08 write_h, offset: %04x, data: %02x\n", offset, data);
if (offset >= 0x7000)
m_reg = data;
}
void nes_le05_device::write_h(offs_t offset, u8 data) // submapper 4
{
- LOG_MMC(("le05 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("le05 write_h, offset: %04x, data: %02x\n", offset, data);
chr8(data & 1, m_chr_source);
}
void nes_lh28_lh54_device::write_h(offs_t offset, u8 data) // submapper 3
{
- LOG_MMC(("lh28_lh54 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("lh28_lh54 write_h, offset: %04x, data: %02x\n", offset, data);
m_reg = data;
}
void nes_lh31_device::write_h(offs_t offset, u8 data) // submapper 2
{
- LOG_MMC(("lh31 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("lh31 write_h, offset: %04x, data: %02x\n", offset, data);
if (offset >= 0x6000)
{
m_reg = data;
@@ -1087,19 +1087,19 @@ void nes_smb2j_device::write_45(offs_t offset, u8 data)
void nes_smb2j_device::write_ex(offs_t offset, u8 data)
{
- LOG_MMC(("smb2j write_ex, offset: %04x, data: %02x\n", offset, data));
+ LOG("smb2j write_ex, offset: %04x, data: %02x\n", offset, data);
nes_smb2j_device::write_45(offset + 0x4020, data);
}
void nes_smb2j_device::write_l(offs_t offset, u8 data)
{
- LOG_MMC(("smb2j write_l, offset: %04x, data: %02x\n", offset, data));
+ LOG("smb2j write_l, offset: %04x, data: %02x\n", offset, data);
nes_smb2j_device::write_45(offset + 0x4100, data);
}
void nes_smb2j_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("smb2j write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("smb2j write_h, offset: %04x, data: %02x\n", offset, data);
if (offset == 0x122) // $8122 is also IRQ for YS-612, mask unknown
nes_smb2j_device::update_irq(data);
@@ -1107,7 +1107,7 @@ void nes_smb2j_device::write_h(offs_t offset, u8 data)
u8 nes_smb2j_device::read_l(offs_t offset)
{
- LOG_MMC(("smb2j read_l, offset: %04x\n", offset));
+ LOG("smb2j read_l, offset: %04x\n", offset);
offset += 0x100;
if (offset >= 0x1000)
@@ -1118,7 +1118,7 @@ u8 nes_smb2j_device::read_l(offs_t offset)
u8 nes_smb2j_device::read_m(offs_t offset)
{
- LOG_MMC(("smb2j read_m, offset: %04x\n", offset));
+ LOG("smb2j read_m, offset: %04x\n", offset);
return m_prg[0x4000 + offset];
}
@@ -1148,7 +1148,7 @@ TIMER_CALLBACK_MEMBER(nes_smb2ja_device::irq_timer_tick)
void nes_smb2ja_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("smb2ja write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("smb2ja write_h, offset: %04x, data: %02x\n", offset, data);
switch (offset & 0x6000)
{
@@ -1168,7 +1168,7 @@ void nes_smb2ja_device::write_h(offs_t offset, u8 data)
u8 nes_smb2ja_device::read_m(offs_t offset)
{
- LOG_MMC(("smb2ja read_m, offset: %04x\n", offset));
+ LOG("smb2ja read_m, offset: %04x\n", offset);
return m_prg[0x06 * 0x2000 + offset]; // fixed 8K bank
}
@@ -1216,19 +1216,19 @@ void nes_smb2jb_device::write_45(offs_t offset, u8 data)
void nes_smb2jb_device::write_ex(offs_t offset, u8 data)
{
- LOG_MMC(("smb2jb write_ex, offset: %04x, data: %02x\n", offset, data));
+ LOG("smb2jb write_ex, offset: %04x, data: %02x\n", offset, data);
write_45(offset + 0x4020, data);
}
void nes_smb2jb_device::write_l(offs_t offset, u8 data)
{
- LOG_MMC(("smb2jb write_l, offset: %04x, data: %02x\n", offset, data));
+ LOG("smb2jb write_l, offset: %04x, data: %02x\n", offset, data);
write_45(offset + 0x4100, data);
}
u8 nes_smb2jb_device::read_m(offs_t offset)
{
- LOG_MMC(("smb2jb read_m, offset: %04x\n", offset));
+ LOG("smb2jb read_m, offset: %04x\n", offset);
return m_prg[(m_bank67 * 0x2000 + offset) & (m_prg_size - 1)];
}
@@ -1252,7 +1252,7 @@ u8 nes_smb2jb_device::read_m(offs_t offset)
void nes_n32_4in1_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("n32_4in1 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("n32_4in1 write_h, offset: %04x, data: %02x\n", offset, data);
if (offset < 0x2000)
{
@@ -1296,13 +1296,13 @@ void nes_n32_4in1_device::write_h(offs_t offset, u8 data)
u8 nes_0353_device::read_m(offs_t offset)
{
-// LOG_MMC(("0353 read_m, offset: %04x\n", offset));
+ LOGMASKED(LOG_HIFREQ, "0353 read_m, offset: %04x\n", offset);
return m_prg[m_reg * 0x2000 + offset];
}
void nes_0353_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("0353 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("0353 write_h, offset: %04x, data: %02x\n", offset, data);
set_nt_mirroring(BIT(data, 4) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
m_reg = data & 0x0f;
@@ -1344,7 +1344,7 @@ TIMER_CALLBACK_MEMBER(nes_09034a_device::irq_timer_tick)
void nes_09034a_device::write_ex(offs_t offset, u8 data)
{
- LOG_MMC(("09-034a write_ex, offset: %04x, data: %02x\n", offset, data));
+ LOG("09-034a write_ex, offset: %04x, data: %02x\n", offset, data);
offset += 0x20;
switch (offset)
@@ -1365,7 +1365,7 @@ void nes_09034a_device::write_ex(offs_t offset, u8 data)
u8 nes_09034a_device::read_ex(offs_t offset)
{
- LOG_MMC(("09-034a read_ex, offset: %04x, data: %02x\n", offset));
+ LOG("09-034a read_ex, offset: %04x, data: %02x\n", offset);
offset += 0x20;
// SMB2 does not boot with the default open bus reads in this range
@@ -1377,7 +1377,7 @@ u8 nes_09034a_device::read_ex(offs_t offset)
u8 nes_09034a_device::read_m(offs_t offset)
{
- LOG_MMC(("09-034a read_m, offset: %04x\n", offset));
+ LOG("09-034a read_m, offset: %04x\n", offset);
// in 0x6000-0x7fff is mapped the 2nd PRG chip which starts after 32K (hence the +4)
return m_prg[(((m_reg + 4) * 0x2000) + offset) & (m_prg_size - 1)];
}
@@ -1412,7 +1412,7 @@ TIMER_CALLBACK_MEMBER(nes_l001_device::irq_timer_tick)
void nes_l001_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("l-001 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("l-001 write_h, offset: %04x, data: %02x\n", offset, data);
switch (offset & 0x6400)
{
@@ -1459,7 +1459,7 @@ TIMER_CALLBACK_MEMBER(nes_batmanfs_device::irq_timer_tick)
void nes_batmanfs_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("batmanfs write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("batmanfs write_h, offset: %04x, data: %02x\n", offset, data);
switch (offset & 0x70)
{
case 0x00:
@@ -1516,7 +1516,7 @@ void nes_batmanfs_device::write_h(offs_t offset, u8 data)
u8 nes_palthena_device::read_m(offs_t offset)
{
-// LOG_MMC(("palthena read_m, offset: %04x\n", offset));
+ LOGMASKED(LOG_HIFREQ, "palthena read_m, offset: %04x\n", offset);
switch (offset & 0x1f00)
{
case 0x0000:
@@ -1531,7 +1531,7 @@ u8 nes_palthena_device::read_m(offs_t offset)
void nes_palthena_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("palthena write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("palthena write_m, offset: %04x, data: %02x\n", offset, data);
switch (offset & 0x1f00)
{
case 0x0000:
@@ -1545,7 +1545,7 @@ void nes_palthena_device::write_m(offs_t offset, u8 data)
u8 nes_palthena_device::read_h(offs_t offset)
{
-// LOG_MMC(("palthena read_h, offset: %04x\n", offset));
+ LOGMASKED(LOG_HIFREQ, "palthena read_h, offset: %04x\n", offset);
u8 page = offset >> 8;
if ((page >= 0x40 && page < 0x52) || page == 0x5f)
return m_prgram[offset & 0x1fff];
@@ -1557,7 +1557,7 @@ u8 nes_palthena_device::read_h(offs_t offset)
void nes_palthena_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("palthena write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("palthena write_h, offset: %04x, data: %02x\n", offset, data);
u8 page = offset >> 8;
if ((page >= 0x40 && page < 0x52) || page == 0x5f)
m_prgram[offset & 0x1fff] = data;
@@ -1585,7 +1585,7 @@ void nes_palthena_device::write_h(offs_t offset, u8 data)
void nes_tobidase_device::write_l(offs_t offset, uint8_t data)
{
- LOG_MMC(("tobidase write_l, offset: %04x, data: %02x\n", offset, data));
+ LOG("tobidase write_l, offset: %04x, data: %02x\n", offset, data);
offset += 0x4100;
if ((offset & 0x63c0) == 0x41c0)
@@ -1594,7 +1594,7 @@ void nes_tobidase_device::write_l(offs_t offset, uint8_t data)
uint8_t nes_tobidase_device::read_m(offs_t offset)
{
- LOG_MMC(("tobidase read_m, offset: %04x\n", offset));
+ LOG("tobidase read_m, offset: %04x\n", offset);
if (m_latch >= 0x0c)
m_latch -= 4;
return m_prg[(m_latch * 0x2000) + (offset & 0x1fff)];
@@ -1616,13 +1616,13 @@ uint8_t nes_tobidase_device::read_m(offs_t offset)
uint8_t nes_lh32_device::read_m(offs_t offset)
{
- LOG_MMC(("lh32 read_m, offset: %04x\n", offset));
+ LOG("lh32 read_m, offset: %04x\n", offset);
return m_prg[(m_latch * 0x2000) + (offset & 0x1fff)];
}
uint8_t nes_lh32_device::read_h(offs_t offset)
{
-// LOG_MMC(("lh32 read_h, offset: %04x\n", offset));
+ LOGMASKED(LOG_HIFREQ, "lh32 read_h, offset: %04x\n", offset);
if (offset >= 0x4000 && offset < 0x6000)
return m_prgram[offset & 0x1fff];
@@ -1632,18 +1632,17 @@ uint8_t nes_lh32_device::read_h(offs_t offset)
void nes_lh32_device::write_m(offs_t offset, uint8_t data)
{
- LOG_MMC(("lh32 write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("lh32 write_m, offset: %04x, data: %02x\n", offset, data);
if (offset == 0) // 0x6000 only?
{
-// printf("write %x\n", data);
m_latch = data & 0xf;
}
}
void nes_lh32_device::write_h(offs_t offset, uint8_t data)
{
- LOG_MMC(("lh32 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("lh32 write_h, offset: %04x, data: %02x\n", offset, data);
if (offset >= 0x4000 && offset < 0x6000)
m_prgram[offset & 0x1fff] = data;
@@ -1663,7 +1662,7 @@ void nes_lh32_device::write_h(offs_t offset, uint8_t data)
void nes_lh42_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("lh42 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("lh42 write_h, offset: %04x, data: %02x\n", offset, data);
switch (offset & 0x6001)
{
@@ -1702,7 +1701,7 @@ void nes_lh42_device::write_h(offs_t offset, u8 data)
void nes_lg25_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("lg25 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("lg25 write_h, offset: %04x, data: %02x\n", offset, data);
switch (offset & 0x6001)
{
@@ -1741,13 +1740,13 @@ void nes_lg25_device::write_h(offs_t offset, u8 data)
u8 nes_lh10_device::read_m(offs_t offset)
{
- LOG_MMC(("lh10 read_m, offset: %04x\n", offset));
+ LOG("lh10 read_m, offset: %04x\n", offset);
return m_prg[(0x0e * 0x2000 + offset) & (m_prg_size - 1)];
}
u8 nes_lh10_device::read_h(offs_t offset)
{
-// LOG_MMC(("lh10 read_h, offset: %04x\n", offset));
+ LOGMASKED(LOG_HIFREQ, "lh10 read_h, offset: %04x\n", offset);
if (offset >= 0x4000 && offset < 0x6000)
return m_prgram[offset & 0x1fff];
@@ -1757,7 +1756,7 @@ u8 nes_lh10_device::read_h(offs_t offset)
void nes_lh10_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("lh10 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("lh10 write_h, offset: %04x, data: %02x\n", offset, data);
switch (offset & 0x6001)
{
@@ -1799,7 +1798,7 @@ void nes_lh10_device::write_h(offs_t offset, u8 data)
void nes_lh51_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("lh51 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("lh51 write_h, offset: %04x, data: %02x\n", offset, data);
switch (offset & 0x6000)
{
@@ -1841,13 +1840,13 @@ TIMER_CALLBACK_MEMBER(nes_lh53_device::irq_timer_tick)
uint8_t nes_lh53_device::read_m(offs_t offset)
{
- LOG_MMC(("lh53 read_m, offset: %04x\n", offset));
+ LOG("lh53 read_m, offset: %04x\n", offset);
return m_prg[m_reg * 0x2000 + offset];
}
uint8_t nes_lh53_device::read_h(offs_t offset)
{
-// LOG_MMC(("lh53 read_h, offset: %04x\n", offset));
+ LOGMASKED(LOG_HIFREQ, "lh53 read_h, offset: %04x\n", offset);
if (offset >= 0x3800 && offset < 0x5800)
return m_prgram[offset - 0x3800];
@@ -1857,7 +1856,7 @@ uint8_t nes_lh53_device::read_h(offs_t offset)
void nes_lh53_device::write_h(offs_t offset, uint8_t data)
{
- LOG_MMC(("lh53 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("lh53 write_h, offset: %04x, data: %02x\n", offset, data);
if (offset >= 0x3800 && offset < 0x5800)
m_prgram[offset - 0x3800] = data;
@@ -1898,7 +1897,7 @@ void nes_lh53_device::write_h(offs_t offset, uint8_t data)
uint8_t nes_2708_device::read_m(offs_t offset)
{
- LOG_MMC(("btl-2708 read_m, offset: %04x\n", offset));
+ LOG("btl-2708 read_m, offset: %04x\n", offset);
if (!m_reg[1])
return m_prgram[offset]; // lower 8K of WRAM
else
@@ -1907,14 +1906,14 @@ uint8_t nes_2708_device::read_m(offs_t offset)
void nes_2708_device::write_m(offs_t offset, uint8_t data)
{
- LOG_MMC(("btl-2708 write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("btl-2708 write_m, offset: %04x, data: %02x\n", offset, data);
// if (!m_reg[1])
m_prgram[offset] = data; // lower 8K of WRAM
}
uint8_t nes_2708_device::read_h(offs_t offset)
{
-// LOG_MMC(("btl-2708 read_h, offset: %04x\n", offset));
+ LOGMASKED(LOG_HIFREQ, "btl-2708 read_h, offset: %04x\n", offset);
if (offset >= 0x3800 && offset < 0x5800 && !m_reg[1])
return m_prgram[0x2000 + ((offset - 0x3800) & 0x1fff)]; // higher 8K of WRAM
@@ -1924,7 +1923,7 @@ uint8_t nes_2708_device::read_h(offs_t offset)
void nes_2708_device::write_h(offs_t offset, uint8_t data)
{
- LOG_MMC(("btl-2708 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("btl-2708 write_h, offset: %04x, data: %02x\n", offset, data);
if (offset >= 0x3800 && offset < 0x5800/* && !m_reg[1]*/)
m_prgram[0x2000 + ((offset - 0x3800) & 0x1fff)] = data; // higher 8K of WRAM
@@ -1961,20 +1960,20 @@ void nes_2708_device::write_h(offs_t offset, uint8_t data)
void nes_ac08_device::write_ex(offs_t offset, uint8_t data)
{
- LOG_MMC(("AC-08 write_ex, offset: %04x, data: %02x\n", offset, data));
+ LOG("AC-08 write_ex, offset: %04x, data: %02x\n", offset, data);
if (offset == 5) // $4025
set_nt_mirroring(!BIT(data, 3) ? PPU_MIRROR_VERT : PPU_MIRROR_HORZ);
}
uint8_t nes_ac08_device::read_m(offs_t offset)
{
- LOG_MMC(("AC-08 read_m, offset: %04x\n", offset));
+ LOG("AC-08 read_m, offset: %04x\n", offset);
return m_prg[(m_latch * 0x2000) + (offset & 0x1fff)];
}
void nes_ac08_device::write_h(offs_t offset, uint8_t data)
{
- LOG_MMC(("AC-08 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("AC-08 write_h, offset: %04x, data: %02x\n", offset, data);
if (offset == 1)
m_latch = BIT(data, 1, 4);
@@ -2001,7 +2000,7 @@ void nes_ac08_device::write_h(offs_t offset, uint8_t data)
uint8_t nes_mmalee_device::read_m(offs_t offset)
{
- LOG_MMC(("mmalee read_m, offset: %04x\n", offset));
+ LOG("mmalee read_m, offset: %04x\n", offset);
if (offset < 0x0800)
return m_prg[0x8000 + offset];
@@ -2013,7 +2012,7 @@ uint8_t nes_mmalee_device::read_m(offs_t offset)
void nes_mmalee_device::write_m(offs_t offset, uint8_t data)
{
- LOG_MMC(("mmalee write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("mmalee write_m, offset: %04x, data: %02x\n", offset, data);
if (!m_prgram.empty() && offset >= 0x1000 && offset < 0x1800) // WRAM only in these 2K
m_prgram[offset & 0x7ff] = data;
@@ -2037,7 +2036,7 @@ void nes_mmalee_device::write_m(offs_t offset, uint8_t data)
uint8_t nes_rt01_device::read_h(offs_t offset)
{
-// LOG_MMC(("rt01 read_h, offset: %04x\n", offset));
+ LOGMASKED(LOG_HIFREQ, "rt01 read_h, offset: %04x\n", offset);
if ((offset >= 0x4e80) && (offset < 0x4f00))
return 0xf2 | (machine().rand() & 0x0d);
@@ -2089,19 +2088,19 @@ void nes_yung08_device::write_45(offs_t offset, u8 data)
void nes_yung08_device::write_ex(offs_t offset, u8 data)
{
- LOG_MMC(("yung08 write_ex, offset: %04x, data: %02x\n", offset, data));
+ LOG("yung08 write_ex, offset: %04x, data: %02x\n", offset, data);
write_45(offset + 0x4020, data);
}
void nes_yung08_device::write_l(offs_t offset, u8 data)
{
- LOG_MMC(("yung08 write_l, offset: %04x, data: %02x\n", offset, data));
+ LOG("yung08 write_l, offset: %04x, data: %02x\n", offset, data);
write_45(offset + 0x4100, data);
}
u8 nes_yung08_device::read_l(offs_t offset)
{
- LOG_MMC(("yung08 read_l, offset: %04x\n", offset));
+ LOG("yung08 read_l, offset: %04x\n", offset);
offset += 0x100;
if ((offset & 0x11ff) == 0x0122) // 0x4122
return m_irq_latch | 0x8a;
@@ -2110,6 +2109,6 @@ u8 nes_yung08_device::read_l(offs_t offset)
u8 nes_yung08_device::read_m(offs_t offset)
{
- LOG_MMC(("yung08 read_m, offset: %04x\n", offset));
+ LOG("yung08 read_m, offset: %04x\n", offset);
return m_prg[0x02 * 0x2000 + offset]; // fixed to bank #2
}
diff --git a/src/devices/bus/nes/camerica.cpp b/src/devices/bus/nes/camerica.cpp
index fd80dca08b0..658add539b8 100644
--- a/src/devices/bus/nes/camerica.cpp
+++ b/src/devices/bus/nes/camerica.cpp
@@ -28,12 +28,11 @@
#ifdef NES_PCB_DEBUG
-#define VERBOSE 1
+#define VERBOSE (LOG_GENERAL)
#else
-#define VERBOSE 0
+#define VERBOSE (0)
#endif
-
-#define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0)
+#include "logmacro.h"
//-------------------------------------------------
@@ -139,7 +138,7 @@ void nes_golden5_device::pcb_reset()
void nes_bf9093_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("bf9093 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bf9093 write_h, offset: %04x, data: %02x\n", offset, data);
switch (offset & 0x6000)
{
@@ -174,7 +173,7 @@ void nes_bf9093_device::write_h(offs_t offset, u8 data)
void nes_bf9096_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("bf9096 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bf9096 write_h, offset: %04x, data: %02x\n", offset, data);
if (offset < 0x4000)
{
@@ -205,7 +204,7 @@ void nes_bf9096_device::write_h(offs_t offset, u8 data)
void nes_golden5_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("golden5 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("golden5 write_h, offset: %04x, data: %02x\n", offset, data);
if (offset >= 0x4000)
{
diff --git a/src/devices/bus/nes/cne.cpp b/src/devices/bus/nes/cne.cpp
index 8300c56928c..0f0bfabb271 100644
--- a/src/devices/bus/nes/cne.cpp
+++ b/src/devices/bus/nes/cne.cpp
@@ -20,12 +20,11 @@
#ifdef NES_PCB_DEBUG
-#define VERBOSE 1
+#define VERBOSE (LOG_GENERAL)
#else
-#define VERBOSE 0
+#define VERBOSE (0)
#endif
-
-#define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0)
+#include "logmacro.h"
//-------------------------------------------------
@@ -84,7 +83,7 @@ void nes_cne_fsb_device::pcb_reset()
void nes_cne_decathl_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("cne_decathl_w, offset: %04x, data: %02x\n", offset, data));
+ LOG("cne_decathl_w, offset: %04x, data: %02x\n", offset, data);
if (offset >= 0x0065)
{
@@ -114,7 +113,7 @@ void nes_cne_decathl_device::write_h(offs_t offset, u8 data)
void nes_cne_fsb_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("cne_fsb write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("cne_fsb write_m, offset: %04x, data: %02x\n", offset, data);
if (offset < 0x0800)
{
@@ -140,7 +139,7 @@ void nes_cne_fsb_device::write_m(offs_t offset, u8 data)
u8 nes_cne_fsb_device::read_m(offs_t offset)
{
- LOG_MMC(("cne_fsb read_m, offset: %04x\n", offset));
+ LOG("cne_fsb read_m, offset: %04x\n", offset);
if (offset >= 0x0800)
return device_nes_cart_interface::read_m(offset);
@@ -167,7 +166,7 @@ u8 nes_cne_fsb_device::read_m(offs_t offset)
void nes_cne_shlz_device::write_l(offs_t offset, u8 data)
{
- LOG_MMC(("cne_shlz write_l, offset: %04x, data: %02x\n", offset, data));
+ LOG("cne_shlz write_l, offset: %04x, data: %02x\n", offset, data);
prg32(data >> 4);
chr8(data & 0x0f, CHRROM);
diff --git a/src/devices/bus/nes/cony.cpp b/src/devices/bus/nes/cony.cpp
index 3e73f35a4bf..1b56fa36ce2 100644
--- a/src/devices/bus/nes/cony.cpp
+++ b/src/devices/bus/nes/cony.cpp
@@ -19,12 +19,11 @@
#ifdef NES_PCB_DEBUG
-#define VERBOSE 1
+#define VERBOSE (LOG_GENERAL)
#else
-#define VERBOSE 0
+#define VERBOSE (0)
#endif
-
-#define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0)
+#include "logmacro.h"
//-------------------------------------------------
@@ -127,7 +126,7 @@ TIMER_CALLBACK_MEMBER(nes_cony_device::irq_timer_tick)
void nes_cony_device::write_l(offs_t offset, u8 data)
{
- LOG_MMC(("cony write_l, offset: %04x, data: %02x\n", offset, data));
+ LOG("cony write_l, offset: %04x, data: %02x\n", offset, data);
offset += 0x100;
if (offset >= m_extra_addr) // scratch ram from 0x5100 or 0x5400
@@ -136,7 +135,7 @@ void nes_cony_device::write_l(offs_t offset, u8 data)
u8 nes_cony_device::read_l(offs_t offset)
{
- LOG_MMC(("cony read_l, offset: %04x\n", offset));
+ LOG("cony read_l, offset: %04x\n", offset);
offset += 0x100;
if (offset >= m_extra_addr) // scratch ram from 0x5100 or 0x5400
@@ -149,7 +148,7 @@ u8 nes_cony_device::read_l(offs_t offset)
void nes_cony_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("cony write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("cony write_m, offset: %04x, data: %02x\n", offset, data);
if (!m_battery.empty())
m_battery[((m_outer_reg >> 6) * 0x2000 + offset) & (m_battery.size() - 1)] = data;
@@ -157,7 +156,7 @@ void nes_cony_device::write_m(offs_t offset, u8 data)
u8 nes_cony_device::read_m(offs_t offset)
{
- LOG_MMC(("cony read_m, offset: %04x\n", offset));
+ LOG("cony read_m, offset: %04x\n", offset);
if (!m_battery.empty())
return m_battery[((m_outer_reg >> 6) * 0x2000 + offset) & (m_battery.size() - 1)];
@@ -201,7 +200,7 @@ void nes_cony_device::set_chr()
void nes_cony_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("cony write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("cony write_h, offset: %04x, data: %02x\n", offset, data);
switch (offset & 0x0300)
{
@@ -280,7 +279,7 @@ void nes_cony1k_device::set_chr()
void nes_yoko_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("yoko write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("yoko write_h, offset: %04x, data: %02x\n", offset, data);
offset = (offset & 0xf0ff) | (offset & 0x0c00) >> 2;
nes_cony_device::write_h(offset, data);
diff --git a/src/devices/bus/nes/datach.cpp b/src/devices/bus/nes/datach.cpp
index 5e71e0af6bc..32e7400c726 100644
--- a/src/devices/bus/nes/datach.cpp
+++ b/src/devices/bus/nes/datach.cpp
@@ -18,17 +18,15 @@
#include "datach.h"
#ifdef NES_PCB_DEBUG
-#define VERBOSE 1
+#define VERBOSE (LOG_GENERAL)
#else
-#define VERBOSE 0
+#define VERBOSE (0)
#endif
-
-#define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0)
+#include "logmacro.h"
#define EEPROM_INTERNAL 0
#define EEPROM_EXTERNAL 1
-
#define TEST_EEPROM 0
//--------------------------------
@@ -92,20 +90,19 @@ uint8_t nes_datach_slot_device::read(offs_t offset)
return 0xff;
}
-image_init_result nes_datach_slot_device::call_load()
+std::pair<std::error_condition, std::string> nes_datach_slot_device::call_load()
{
if (m_cart)
{
- uint8_t *ROM = m_cart->get_cart_base();
-
+ uint8_t *const ROM = m_cart->get_cart_base();
if (!ROM)
- return image_init_result::FAIL;
+ return std::make_pair(image_error::INTERNAL, std::string());
// Existing Datach carts are all 256K, so we only load files of this size
if (!loaded_through_softlist())
{
if (length() != 0x40000 && length() != 0x40010)
- return image_init_result::FAIL;
+ return std::make_pair(image_error::INVALIDLENGTH, std::string());
int shift = length() - 0x40000;
uint8_t temp[0x40010];
@@ -120,20 +117,22 @@ image_init_result nes_datach_slot_device::call_load()
mapper |= temp[7] & 0xf0;
if (mapper != 157 && mapper != 16)
{
- return image_init_result::FAIL;
+ return std::make_pair(
+ image_error::INVALIDIMAGE,
+ util::string_format("Unsupported iNES mapper %u (must be 16 or 157)", mapper));
}
}
}
else
{
if (get_software_region_length("rom") != 0x40000)
- return image_init_result::FAIL;
+ return std::make_pair(image_error::INVALIDLENGTH, "Unsupported cartridge size (must be 256K)");
memcpy(ROM, get_software_region("rom"), 0x40000);
}
}
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
@@ -266,7 +265,7 @@ void nes_datach_device::pcb_reset()
iNES: mappers 157
- In MESS: Supported
+ In MAME: Supported
TODO: Datach carts should actually be handled
separately! Original carts were minicarts to be
@@ -285,7 +284,7 @@ void nes_datach_device::pcb_reset()
uint8_t nes_datach_device::read_m(offs_t offset)
{
- LOG_MMC(("Datach read_m, offset: %04x\n", offset));
+ LOG("Datach read_m, offset: %04x\n", offset);
uint8_t i2c_val = 0;
#if TEST_EEPROM
if (m_i2c_dir)
@@ -302,8 +301,8 @@ uint8_t nes_datach_device::read_m(offs_t offset)
uint8_t nes_datach_device::read_h(offs_t offset)
{
- LOG_MMC(("Datach read_h, offset: %04x\n", offset));
- // this shall be the proper code, but it's a bit slower, so we access directly the subcart below
+ LOG("Datach read_h, offset: %04x\n", offset);
+ // this should be the proper code, but it's a bit slower, so we access directly the subcart below
//return m_subslot->read(offset);
if (m_subslot->m_cart)
@@ -314,7 +313,7 @@ uint8_t nes_datach_device::read_h(offs_t offset)
void nes_datach_device::write_h(offs_t offset, uint8_t data)
{
- LOG_MMC(("Datach write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("Datach write_h, offset: %04x, data: %02x\n", offset, data);
switch (offset & 0x0f)
{
diff --git a/src/devices/bus/nes/datach.h b/src/devices/bus/nes/datach.h
index 80770904596..e9e42379948 100644
--- a/src/devices/bus/nes/datach.h
+++ b/src/devices/bus/nes/datach.h
@@ -64,24 +64,24 @@ public:
nes_datach_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual ~nes_datach_slot_device();
- // image-level overrides
- virtual image_init_result call_load() override;
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
virtual bool is_reset_on_load() const noexcept override { return true; }
virtual const char *image_interface() const noexcept override { return "datach_cart"; }
virtual const char *file_extensions() const noexcept override { return "nes,bin"; }
- // slot interface overrides
+ // device_slot_interface implementation
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
uint8_t read(offs_t offset);
void write_prg_bank(uint8_t bank) { if (m_cart) m_cart->write_prg_bank(bank); }
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
- datach_cart_interface* m_cart;
+ datach_cart_interface *m_cart;
};
// device type definition
@@ -102,16 +102,15 @@ public:
// construction/destruction
nes_datach_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- // optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual uint8_t* get_cart_base();
+ virtual uint8_t *get_cart_base();
protected:
nes_datach_rom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
virtual void device_reset() override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
};
// ======================> nes_datach_24c01_device
@@ -123,7 +122,7 @@ public:
nes_datach_24c01_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
- // optional information overrides
+ // device_t implementation
virtual void device_add_mconfig(machine_config &config) override;
};
@@ -153,7 +152,7 @@ public:
virtual void pcb_reset() override;
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
virtual void device_add_mconfig(machine_config &config) override;
diff --git a/src/devices/bus/nes/discrete.cpp b/src/devices/bus/nes/discrete.cpp
index 5b047a2daad..7705c4ba1bc 100644
--- a/src/devices/bus/nes/discrete.cpp
+++ b/src/devices/bus/nes/discrete.cpp
@@ -20,12 +20,11 @@
#ifdef NES_PCB_DEBUG
-#define VERBOSE 1
+#define VERBOSE (LOG_GENERAL)
#else
-#define VERBOSE 0
+#define VERBOSE (0)
#endif
-
-#define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0)
+#include "logmacro.h"
//-------------------------------------------------
@@ -92,7 +91,7 @@ void nes_74x161x161x32_device::pcb_reset()
// there are two 'variants' depending on hardwired or mapper ctrl mirroring
void nes_74x161x161x32_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("74x161x161x32 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("74x161x161x32 write_h, offset: %04x, data: %02x\n", offset, data);
// this pcb is subject to bus conflict
data = account_bus_conflict(offset, data);
@@ -113,7 +112,7 @@ void nes_74x161x161x32_device::write_h(offs_t offset, u8 data)
void nes_74x139x74_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("74x139x74 write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("74x139x74 write_m, offset: %04x, data: %02x\n", offset, data);
chr8(bitswap<2>(data, 0, 1), CHRROM);
}
@@ -137,7 +136,7 @@ void nes_74x139x74_device::write_m(offs_t offset, u8 data)
void nes_74x377_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("74x377 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("74x377 write_h, offset: %04x, data: %02x\n", offset, data);
// this pcb is subject to bus conflict, but not the prototype of Secret Scout, which actually breaks in case of conflict...
data = account_bus_conflict(offset, data);
@@ -158,7 +157,7 @@ void nes_74x377_device::write_h(offs_t offset, u8 data)
void nes_74x161x138_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("74x161x138 write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("74x161x138 write_m, offset: %04x, data: %02x\n", offset, data);
chr8(data >> 2, CHRROM);
prg32(data);
diff --git a/src/devices/bus/nes/disksys.cpp b/src/devices/bus/nes/disksys.cpp
index d53a2be2aab..582f63a3b21 100644
--- a/src/devices/bus/nes/disksys.cpp
+++ b/src/devices/bus/nes/disksys.cpp
@@ -24,12 +24,11 @@
#include "speaker.h"
#ifdef NES_PCB_DEBUG
- #define VERBOSE 1
+#define VERBOSE (LOG_GENERAL)
#else
- #define VERBOSE 0
+#define VERBOSE (0)
#endif
-
-#define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0)
+#include "logmacro.h"
//-----------------------------------------------
@@ -63,9 +62,9 @@ void nes_disksys_device::device_add_mconfig(machine_config &config)
ROM_START( disksys )
ROM_REGION(0x2000, "drive", 0)
- ROM_SYSTEM_BIOS( 0, "2c33a-01a", "Famicom Disk System Bios")
+ ROM_SYSTEM_BIOS( 0, "2c33a-01a", "Famicom Disk System BIOS")
ROMX_LOAD( "rp2c33a-01a.bin", 0x0000, 0x2000, CRC(5e607dcf) SHA1(57fe1bdee955bb48d357e463ccbf129496930b62), ROM_BIOS(0)) // newer, Nintendo logo has no shadow
- ROM_SYSTEM_BIOS( 1, "2c33-01", "Famicom Disk System Bios, older")
+ ROM_SYSTEM_BIOS( 1, "2c33-01", "Famicom Disk System BIOS, older")
ROMX_LOAD( "rp2c33-01.bin", 0x0000, 0x2000, CRC(1c7ae5d5) SHA1(af5af53f66982e749643fdf8b2acbb7d4d3ed229), ROM_BIOS(1)) // older, Nintendo logo has shadow
ROM_END
@@ -184,7 +183,7 @@ void nes_disksys_device::pcb_reset()
void nes_disksys_device::write_h(offs_t offset, uint8_t data)
{
- LOG_MMC(("Famicom Disk System write_h, offset %04x, data: %02x\n", offset, data));
+ LOG("Famicom Disk System write_h, offset %04x, data: %02x\n", offset, data);
if (offset < 0x6000)
m_prgram[offset + 0x2000] = data;
@@ -192,7 +191,7 @@ void nes_disksys_device::write_h(offs_t offset, uint8_t data)
uint8_t nes_disksys_device::read_h(offs_t offset)
{
- LOG_MMC(("Famicom Disk System read_h, offset: %04x\n", offset));
+ LOG("Famicom Disk System read_h, offset: %04x\n", offset);
if (offset < 0x6000)
return m_prgram[offset + 0x2000];
@@ -202,13 +201,13 @@ uint8_t nes_disksys_device::read_h(offs_t offset)
void nes_disksys_device::write_m(offs_t offset, uint8_t data)
{
- LOG_MMC(("Famicom Disk System write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("Famicom Disk System write_m, offset: %04x, data: %02x\n", offset, data);
m_prgram[offset] = data;
}
uint8_t nes_disksys_device::read_m(offs_t offset)
{
- LOG_MMC(("Famicom Disk System read_m, offset: %04x\n", offset));
+ LOG("Famicom Disk System read_m, offset: %04x\n", offset);
return m_prgram[offset];
}
@@ -224,7 +223,7 @@ void nes_disksys_device::hblank_irq(int scanline, bool vblank, bool blanked)
void nes_disksys_device::write_ex(offs_t offset, uint8_t data)
{
- LOG_MMC(("Famicom Disk System write_ex, offset: %04x, data: %02x\n", offset, data));
+ LOG("Famicom Disk System write_ex, offset: %04x, data: %02x\n", offset, data);
if (offset >= 0x20 && offset < 0x60)
{
@@ -317,7 +316,7 @@ void nes_disksys_device::write_ex(offs_t offset, uint8_t data)
uint8_t nes_disksys_device::read_ex(offs_t offset)
{
- LOG_MMC(("Famicom Disk System read_ex, offset: %04x\n", offset));
+ LOG("Famicom Disk System read_ex, offset: %04x\n", offset);
uint8_t ret = 0x00;
if (offset >= 0x20 && offset < 0x60)
diff --git a/src/devices/bus/nes/event.cpp b/src/devices/bus/nes/event.cpp
index 70aee4b90e0..46be863f5ac 100644
--- a/src/devices/bus/nes/event.cpp
+++ b/src/devices/bus/nes/event.cpp
@@ -17,14 +17,14 @@
#include "emu.h"
#include "event.h"
+#define LOG_HIFREQ (1U << 1)
#ifdef NES_PCB_DEBUG
-#define VERBOSE 1
+#define VERBOSE (LOG_GENERAL)
#else
-#define VERBOSE 0
+#define VERBOSE (0)
#endif
-
-#define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0)
+#include "logmacro.h"
//-------------------------------------------------
@@ -194,7 +194,7 @@ void nes_event_device::set_prg()
u8 nes_event2_device::read_l(offs_t offset)
{
-// LOG_MMC(("event2 read_l, offset: %04x\n", offset));
+ LOGMASKED(LOG_HIFREQ, "event2 read_l, offset: %04x\n", offset);
offset += 0x100;
if (offset >= 0x1800)
return (m_timer_count >= (0x10 | m_dsw->read()) << 25) ? 0x80 : 0;
@@ -206,7 +206,7 @@ u8 nes_event2_device::read_l(offs_t offset)
u8 nes_event2_device::read_m(offs_t offset)
{
-// LOG_MMC(("event2 read_m, offset: %04x\n", offset));
+ LOGMASKED(LOG_HIFREQ, "event2 read_m, offset: %04x\n", offset);
if (m_prgram.empty())
return get_open_bus();
else
@@ -215,7 +215,7 @@ u8 nes_event2_device::read_m(offs_t offset)
void nes_event2_device::write_l(offs_t offset, u8 data)
{
- LOG_MMC(("event2 write_l, offset: %04x, data: %02x\n", offset, data));
+ LOG("event2 write_l, offset: %04x, data: %02x\n", offset, data);
offset += 0x100;
switch (offset & 0x1c00)
@@ -243,7 +243,7 @@ void nes_event2_device::write_l(offs_t offset, u8 data)
void nes_event2_device::write_m(offs_t offset, u8 data)
{
-// LOG_MMC(("event2 write_m, offset: %04x, data: %02x\n", offset, data));
+ LOGMASKED(LOG_HIFREQ, "event2 write_m, offset: %04x, data: %02x\n", offset, data);
if (!m_prgram.empty())
m_prgram[offset % m_prgram.size()] = data;
}
diff --git a/src/devices/bus/nes/ggenie.cpp b/src/devices/bus/nes/ggenie.cpp
index bddebcad512..58cb2655e89 100644
--- a/src/devices/bus/nes/ggenie.cpp
+++ b/src/devices/bus/nes/ggenie.cpp
@@ -19,13 +19,15 @@
#include "ggenie.h"
#include "bus/nes/nes_carts.h"
+#define LOG_HIFREQ (1U << 1)
+#define LOG_INFO (1U << 2)
+
#ifdef NES_PCB_DEBUG
-#define VERBOSE 1
+#define VERBOSE (LOG_INFO | LOG_GENERAL)
#else
-#define VERBOSE 0
+#define VERBOSE (LOG_INFO)
#endif
-
-#define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0)
+#include "logmacro.h"
//-------------------------------------------------
@@ -93,7 +95,7 @@ void nes_ggenie_device::pcb_reset()
void nes_ggenie_device::write_h(offs_t offset, u8 data)
{
-// LOG_MMC(("ggenie write_h, offset: %04x, data: %02x\n", offset, data));
+ LOGMASKED(LOG_HIFREQ, "ggenie write_h, offset: %04x, data: %02x\n", offset, data);
if (m_gg_bypass)
{
@@ -142,16 +144,16 @@ void nes_ggenie_device::write_h(offs_t offset, u8 data)
}
// bit 7 is unused and always zero
- logerror("Game Genie Summary:\n");
+ LOGMASKED(LOG_INFO, "Game Genie Summary:\n");
for (int i = 0; i < 3; i++)
{
- logerror("Code %d: %s\n", i, m_gg_enable[i] ? "Yes" : "No");
+ LOGMASKED(LOG_INFO, "Code %d: %s\n", i, m_gg_enable[i] ? "Yes" : "No");
if (m_gg_enable[i])
{
- logerror("\tAddr: 0x%X\n", m_gg_addr[i]);
- logerror("\tValue: 0x%X\n", m_gg_repl[i]);
+ LOGMASKED(LOG_INFO, "\tAddr: 0x%X\n", m_gg_addr[i]);
+ LOGMASKED(LOG_INFO, "\tValue: 0x%X\n", m_gg_repl[i]);
if (m_gg_is_comp[i])
- logerror("\t if equals: 0x%X\n", m_gg_comp[i]);
+ LOGMASKED(LOG_INFO, "\t if equals: 0x%X\n", m_gg_comp[i]);
}
}
}
diff --git a/src/devices/bus/nes/henggedianzi.cpp b/src/devices/bus/nes/henggedianzi.cpp
index a8de6e93783..46af837c524 100644
--- a/src/devices/bus/nes/henggedianzi.cpp
+++ b/src/devices/bus/nes/henggedianzi.cpp
@@ -23,12 +23,11 @@
#ifdef NES_PCB_DEBUG
-#define VERBOSE 1
+#define VERBOSE (LOG_GENERAL)
#else
-#define VERBOSE 0
+#define VERBOSE (0)
#endif
-
-#define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0)
+#include "logmacro.h"
//-------------------------------------------------
@@ -68,13 +67,13 @@ nes_hengg_xhzs_device::nes_hengg_xhzs_device(const machine_config &mconfig, cons
iNES: mapper 177
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
void nes_hengg_srich_device::write_h(offs_t offset, uint8_t data)
{
- LOG_MMC(("hengg_srich write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("hengg_srich write_h, offset: %04x, data: %02x\n", offset, data);
prg32(data);
set_nt_mirroring(BIT(data, 5) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
@@ -95,13 +94,13 @@ void nes_hengg_srich_device::write_h(offs_t offset, uint8_t data)
iNES: mapper 179
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
void nes_hengg_xhzs_device::write_l(offs_t offset, uint8_t data)
{
- LOG_MMC(("hengg_xhzs write_l, offset: %04x, data: %02x\n", offset, data));
+ LOG("hengg_xhzs write_l, offset: %04x, data: %02x\n", offset, data);
offset += 0x4100;
if (offset & 0x5000)
@@ -110,7 +109,7 @@ void nes_hengg_xhzs_device::write_l(offs_t offset, uint8_t data)
void nes_hengg_xhzs_device::write_h(offs_t offset, uint8_t data)
{
- LOG_MMC(("hengg_xhzs write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("hengg_xhzs write_h, offset: %04x, data: %02x\n", offset, data);
set_nt_mirroring(BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
}
diff --git a/src/devices/bus/nes/hes.cpp b/src/devices/bus/nes/hes.cpp
index b23ad6c9f74..fcc5087c97d 100644
--- a/src/devices/bus/nes/hes.cpp
+++ b/src/devices/bus/nes/hes.cpp
@@ -18,12 +18,11 @@
#ifdef NES_PCB_DEBUG
-#define VERBOSE 1
+#define VERBOSE (LOG_GENERAL)
#else
-#define VERBOSE 0
+#define VERBOSE (0)
#endif
-
-#define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0)
+#include "logmacro.h"
//-------------------------------------------------
@@ -61,7 +60,7 @@ nes_hes_device::nes_hes_device(const machine_config &mconfig, const char *tag, d
void nes_hes_device::write_l(offs_t offset, u8 data)
{
- LOG_MMC(("hes write_l, offset: %04x, data: %02x\n", offset, data));
+ LOG("hes write_l, offset: %04x, data: %02x\n", offset, data);
offset += 0x100;
if (BIT(offset, 8)) // $41xx, $43xx, ... $5fxx
diff --git a/src/devices/bus/nes/irem.cpp b/src/devices/bus/nes/irem.cpp
index f90959825a9..d7454402b05 100644
--- a/src/devices/bus/nes/irem.cpp
+++ b/src/devices/bus/nes/irem.cpp
@@ -21,12 +21,11 @@
#include "irem.h"
#ifdef NES_PCB_DEBUG
-#define VERBOSE 1
+#define VERBOSE (LOG_GENERAL)
#else
-#define VERBOSE 0
+#define VERBOSE (0)
#endif
-
-#define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0)
+#include "logmacro.h"
//-------------------------------------------------
@@ -152,7 +151,7 @@ void nes_h3001_device::pcb_reset()
void nes_lrog017_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("lrog017 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("lrog017 write_h, offset: %04x, data: %02x\n", offset, data);
// this pcb is subject to bus conflict
data = account_bus_conflict(offset, data);
@@ -171,7 +170,7 @@ void nes_lrog017_device::write_h(offs_t offset, u8 data)
void nes_holydivr_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("holy diver write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("holy diver write_h, offset: %04x, data: %02x\n", offset, data);
// this pcb is subject to bus conflict
data = account_bus_conflict(offset, data);
@@ -195,7 +194,7 @@ void nes_holydivr_device::write_h(offs_t offset, u8 data)
void nes_tam_s1_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("tam s1 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("tam s1 write_h, offset: %04x, data: %02x\n", offset, data);
if (offset < 0x4000)
{
@@ -222,7 +221,7 @@ void nes_g101_device::set_prg()
void nes_g101_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("g101 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("g101 write_h, offset: %04x, data: %02x\n", offset, data);
switch (offset & 0x7000)
{
@@ -279,7 +278,7 @@ TIMER_CALLBACK_MEMBER(nes_h3001_device::irq_timer_tick)
void nes_h3001_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("h3001 write_h, offset %04x, data: %02x\n", offset, data));
+ LOG("h3001 write_h, offset %04x, data: %02x\n", offset, data);
switch (offset & 0x7007)
{
diff --git a/src/devices/bus/nes/jaleco.cpp b/src/devices/bus/nes/jaleco.cpp
index a83ebfb5a04..2ce809a4eea 100644
--- a/src/devices/bus/nes/jaleco.cpp
+++ b/src/devices/bus/nes/jaleco.cpp
@@ -23,14 +23,14 @@
#include "speaker.h"
+#define LOG_UNHANDLED (1U << 1)
#ifdef NES_PCB_DEBUG
-#define VERBOSE 1
+#define VERBOSE (LOG_UNHANDLED | LOG_GENERAL)
#else
-#define VERBOSE 0
+#define VERBOSE (LOG_UNHANDLED)
#endif
-
-#define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0)
+#include "logmacro.h"
//-------------------------------------------------
@@ -206,7 +206,7 @@ void nes_ss88006_device::pcb_reset()
void nes_jf11_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("jf11 write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("jf11 write_m, offset: %04x, data: %02x\n", offset, data);
chr8(data, CHRROM);
prg32(data >> 4);
}
@@ -227,7 +227,7 @@ void nes_jf11_device::write_m(offs_t offset, u8 data)
void nes_jf13_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("jf13 write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("jf13 write_m, offset: %04x, data: %02x\n", offset, data);
if (offset < 0x1000)
{
@@ -250,7 +250,7 @@ void nes_jf13_device::write_m(offs_t offset, u8 data)
void nes_jf16_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("jf16 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("jf16 write_h, offset: %04x, data: %02x\n", offset, data);
// this pcb is subject to bus conflict
data = account_bus_conflict(offset, data);
@@ -279,7 +279,7 @@ void nes_jf16_device::write_h(offs_t offset, u8 data)
void nes_jf17_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("jf17 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("jf17 write_h, offset: %04x, data: %02x\n", offset, data);
// this pcb is subject to bus conflict
data = account_bus_conflict(offset, data);
@@ -337,7 +337,7 @@ TIMER_CALLBACK_MEMBER(nes_ss88006_device::irq_timer_tick)
u8 nes_ss88006_device::read_m(offs_t offset)
{
- LOG_MMC(("ss88006 read_m, offset: %04x\n", offset));
+ LOG("ss88006 read_m, offset: %04x\n", offset);
if (m_wram_protect & 1) // RAM enabled
return device_nes_cart_interface::read_m(offset);
@@ -347,7 +347,7 @@ u8 nes_ss88006_device::read_m(offs_t offset)
void nes_ss88006_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("ss88006 write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("ss88006 write_m, offset: %04x, data: %02x\n", offset, data);
if (m_wram_protect == 0x03) // RAM enabled and writable
device_nes_cart_interface::write_m(offset, data);
@@ -355,7 +355,7 @@ void nes_ss88006_device::write_m(offs_t offset, u8 data)
void nes_ss88006_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("ss88006 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("ss88006 write_h, offset: %04x, data: %02x\n", offset, data);
int bank, shift;
@@ -425,7 +425,7 @@ void nes_ss88006_device::write_h(offs_t offset, u8 data)
break;
default:
- logerror("Jaleco SS88006 uncaught write, addr: %04x, value: %02x\n", offset + 0x8000, data);
+ LOGMASKED(LOG_UNHANDLED, "Jaleco SS88006 uncaught write, addr: %04x, value: %02x\n", offset + 0x8000, data);
break;
}
}
diff --git a/src/devices/bus/nes/jncota.cpp b/src/devices/bus/nes/jncota.cpp
index 1206a0dd79b..613acd8e3f3 100644
--- a/src/devices/bus/nes/jncota.cpp
+++ b/src/devices/bus/nes/jncota.cpp
@@ -18,12 +18,11 @@
#ifdef NES_PCB_DEBUG
-#define VERBOSE 1
+#define VERBOSE (LOG_GENERAL)
#else
-#define VERBOSE 0
+#define VERBOSE (0)
#endif
-
-#define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0)
+#include "logmacro.h"
//-------------------------------------------------
@@ -79,7 +78,7 @@ void nes_jncota_kt1001_device::pcb_reset()
void nes_jncota_kt1001_device::write_l(offs_t offset, u8 data)
{
- LOG_MMC(("jncota_kt1001 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("jncota_kt1001 write_h, offset: %04x, data: %02x\n", offset, data);
offset += 0x100;
switch (offset & 0x1803)
diff --git a/src/devices/bus/nes/jy.cpp b/src/devices/bus/nes/jy.cpp
index 655634f22ef..54dd078499e 100644
--- a/src/devices/bus/nes/jy.cpp
+++ b/src/devices/bus/nes/jy.cpp
@@ -24,12 +24,11 @@
#include "video/ppu2c0x.h" // this has to be included so that IRQ functions can access ppu2c0x_device::BOTTOM_VISIBLE_SCANLINE
#ifdef NES_PCB_DEBUG
-#define VERBOSE 1
+#define VERBOSE (LOG_GENERAL)
#else
-#define VERBOSE 0
+#define VERBOSE (0)
#endif
-
-#define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0)
+#include "logmacro.h"
//-------------------------------------------------
@@ -239,7 +238,7 @@ void nes_jy_typea_device::scanline_irq(int scanline, bool vblank, bool blanked)
// 0x5000-0x5fff : sort of protection?
uint8_t nes_jy_typea_device::read_l(offs_t offset)
{
- LOG_MMC(("JY Company write_m, offset: %04x\n", offset));
+ LOG("JY Company write_m, offset: %04x\n", offset);
offset += 0x100;
if (offset >= 0x1000 && offset < 0x1800)
@@ -263,7 +262,7 @@ uint8_t nes_jy_typea_device::read_l(offs_t offset)
void nes_jy_typea_device::write_l(offs_t offset, uint8_t data)
{
- LOG_MMC(("JY Company write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("JY Company write_m, offset: %04x, data: %02x\n", offset, data);
offset += 0x100;
if (offset >= 0x1800)
@@ -280,7 +279,7 @@ void nes_jy_typea_device::write_l(offs_t offset, uint8_t data)
// 0x6000-0x7fff : WRAM or open bus
uint8_t nes_jy_typea_device::read_m(offs_t offset)
{
- LOG_MMC(("JY Company write_m, offset: %04x\n", offset));
+ LOG("JY Company write_m, offset: %04x\n", offset);
if (m_reg[0] & 0x80)
return m_prg[(m_bank_6000 & m_prg_mask) * 0x2000 + (offset & 0x1fff)];
@@ -423,7 +422,7 @@ void nes_jy_typea_device::update_banks(int reg)
void nes_jy_typea_device::write_h(offs_t offset, uint8_t data)
{
- LOG_MMC(("JY Company write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("JY Company write_m, offset: %04x, data: %02x\n", offset, data);
switch (offset & 0x7000)
{
diff --git a/src/devices/bus/nes/kaiser.cpp b/src/devices/bus/nes/kaiser.cpp
index 4635c699895..aaa5a247341 100644
--- a/src/devices/bus/nes/kaiser.cpp
+++ b/src/devices/bus/nes/kaiser.cpp
@@ -31,14 +31,14 @@
#include "emu.h"
#include "kaiser.h"
+#define LOG_HIFREQ (1U << 1)
#ifdef NES_PCB_DEBUG
-#define VERBOSE 1
+#define VERBOSE (LOG_GENERAL)
#else
-#define VERBOSE 0
+#define VERBOSE (0)
#endif
-
-#define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0)
+#include "logmacro.h"
//-------------------------------------------------
@@ -378,7 +378,7 @@ void nes_ks7057_device::pcb_reset()
void nes_ks7058_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("ks7058 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("ks7058 write_h, offset: %04x, data: %02x\n", offset, data);
switch (offset & 0x7080)
{
@@ -405,7 +405,7 @@ void nes_ks7058_device::write_h(offs_t offset, u8 data)
void nes_ks7022_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("ks7022 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("ks7022 write_h, offset: %04x, data: %02x\n", offset, data);
if (offset == 0)
set_nt_mirroring(BIT(data, 2) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
@@ -415,7 +415,7 @@ void nes_ks7022_device::write_h(offs_t offset, u8 data)
u8 nes_ks7022_device::read_h(offs_t offset)
{
- LOG_MMC(("ks7022 read_h, offset: %04x\n", offset));
+ LOG("ks7022 read_h, offset: %04x\n", offset);
if (offset == 0x7ffc)
{
@@ -465,7 +465,7 @@ void nes_ks7032_device::prg_update()
void nes_ks7032_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("ks7032_write, offset: %04x, data: %02x\n", offset, data));
+ LOG("ks7032_write, offset: %04x, data: %02x\n", offset, data);
switch (offset & 0x7000)
{
@@ -500,7 +500,7 @@ void nes_ks7032_device::write_h(offs_t offset, u8 data)
u8 nes_ks7032_device::read_m(offs_t offset)
{
- LOG_MMC(("ks7032 read_m, offset: %04x\n", offset));
+ LOG("ks7032 read_m, offset: %04x\n", offset);
return m_prg[(m_reg[4] * 0x2000 + offset) & (m_prg_size - 1)];
}
@@ -526,7 +526,7 @@ u8 nes_ks7032_device::read_m(offs_t offset)
void nes_ks202_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("ks202 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("ks202 write_h, offset: %04x, data: %02x\n", offset, data);
if (offset >= 0x7000)
{
@@ -583,13 +583,13 @@ u8 nes_ks202_device::read_m(offs_t offset)
u8 nes_ks7016_device::read_m(offs_t offset)
{
-// LOG_MMC(("ks7016 read_m, offset: %04x\n", offset));
+ LOGMASKED(LOG_HIFREQ, "ks7016 read_m, offset: %04x\n", offset);
return m_prg[(m_latch * 0x2000 + offset) & (m_prg_size - 1)];
}
void nes_ks7016_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("ks7016 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("ks7016 write_h, offset: %04x, data: %02x\n", offset, data);
m_latch = BIT(offset, 2, 4);
if (m_latch & 0x08)
@@ -623,7 +623,7 @@ TIMER_CALLBACK_MEMBER(nes_ks7017_device::irq_timer_tick)
void nes_ks7017_device::write_l(offs_t offset, u8 data)
{
- LOG_MMC(("ks7017 write_l, offset: %04x, data: %02x\n", offset, data));
+ LOG("ks7017 write_l, offset: %04x, data: %02x\n", offset, data);
offset += 0x100;
switch (offset & 0x1f00)
@@ -639,7 +639,7 @@ void nes_ks7017_device::write_l(offs_t offset, u8 data)
void nes_ks7017_device::write_ex(offs_t offset, u8 data)
{
- LOG_MMC(("ks7017 write_ex, offset: %04x, data: %02x\n", offset, data));
+ LOG("ks7017 write_ex, offset: %04x, data: %02x\n", offset, data);
offset += 0x4020;
switch (offset)
@@ -659,7 +659,7 @@ void nes_ks7017_device::write_ex(offs_t offset, u8 data)
u8 nes_ks7017_device::read_ex(offs_t offset)
{
- LOG_MMC(("ks7017 read_ex, offset: %04x\n", offset));
+ LOG("ks7017 read_ex, offset: %04x\n", offset);
offset += 0x4020;
if (offset == 0x4030)
@@ -691,7 +691,7 @@ u8 nes_ks7017_device::read_ex(offs_t offset)
void nes_ks7021a_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("ks7021a write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("ks7021a write_h, offset: %04x, data: %02x\n", offset, data);
switch (offset & 0x7000)
{
@@ -727,20 +727,22 @@ void nes_ks7021a_device::write_h(offs_t offset, u8 data)
u8 nes_ks7010_device::read_m(offs_t offset)
{
-// LOG_MMC(("ks7010 read_m, offset: %04x, data: %02x\n", offset, data));
- return m_prg[(m_latch * 0x2000 + offset) & (m_prg_size - 1)];
+ u8 data = m_prg[(m_latch * 0x2000 + offset) & (m_prg_size - 1)];
+ LOGMASKED(LOG_HIFREQ, "ks7010 read_m, offset: %04x, data: %02x\n", offset, data);
+ return data;
}
u8 nes_ks7010_device::read_h(offs_t offset)
{
-// LOG_MMC(("ks7010 read_h, offset: %04x, data: %02x\n", offset, data));
if ((offset >= 0x4ab6 && offset <= 0x4ad6) || offset == 0x6be2 || offset == 0x6be3 || offset == 0x6e32 || offset == 0x7ffc) // HACK! FIXME
{
m_latch = BIT(offset, 2, 4);
chr8(m_latch, CHRROM);
}
- return hi_access_rom(offset);
+ u8 data = hi_access_rom(offset);
+ LOGMASKED(LOG_HIFREQ, "ks7010 read_h, offset: %04x, data: %02x\n", offset, data);
+ return data;
}
/*-------------------------------------------------
@@ -757,7 +759,7 @@ u8 nes_ks7010_device::read_h(offs_t offset)
void nes_ks7012_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("ks7012 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("ks7012 write_h, offset: %04x, data: %02x\n", offset, data);
if (offset == 0x60a0)
prg32(0);
@@ -779,13 +781,13 @@ void nes_ks7012_device::write_h(offs_t offset, u8 data)
void nes_ks7013b_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("ks7013b write_l, offset: %04x, data: %02x\n", offset, data));
+ LOG("ks7013b write_l, offset: %04x, data: %02x\n", offset, data);
prg16_89ab(data);
}
void nes_ks7013b_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("ks7013b write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("ks7013b write_h, offset: %04x, data: %02x\n", offset, data);
set_nt_mirroring((data & 1) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
}
@@ -816,7 +818,7 @@ void nes_ks7013b_device::write_h(offs_t offset, u8 data)
u8 nes_ks7030_device::read_m(offs_t offset)
{
-// LOG_MMC(("ks7030 read_m, offset: %04x\n", offset));
+ LOGMASKED(LOG_HIFREQ, "ks7030 read_m, offset: %04x\n", offset);
if (offset < 0x0c00) // first of 3k WRAM
return m_prgram[offset];
else if (offset < 0x1000) // last 1k of 4k PRG bank
@@ -827,14 +829,14 @@ u8 nes_ks7030_device::read_m(offs_t offset)
void nes_ks7030_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("ks7030 write_m, offset: %04x\n", offset));
+ LOG("ks7030 write_m, offset: %04x\n", offset);
if (offset < 0x0c00) // first 3k of WRAM
m_prgram[offset] = data;
}
u8 nes_ks7030_device::read_h(offs_t offset)
{
-// LOG_MMC(("ks7030 read_h, offset: %04x\n", offset));
+ LOGMASKED(LOG_HIFREQ, "ks7030 read_h, offset: %04x\n", offset);
if (offset < 0x3800 || offset >= 0x5800) // fixed 32k PRG, split 14k and 10k windows
return m_prg[0x18000 + (offset & 0x7fff)];
else if (offset < 0x4000) // middle 2k of WRAM
@@ -847,7 +849,7 @@ u8 nes_ks7030_device::read_h(offs_t offset)
void nes_ks7030_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("ks7030 write_h, offset: %04x\n", offset));
+ LOG("ks7030 write_h, offset: %04x\n", offset);
if (offset < 0x1000)
{
set_nt_mirroring(BIT(offset, 3) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
@@ -881,7 +883,7 @@ void nes_ks7030_device::write_h(offs_t offset, u8 data)
u8 nes_ks7031_device::read_m(offs_t offset)
{
-// LOG_MMC(("ks7031 read_m, offset: %04x\n", offset));
+ LOGMASKED(LOG_HIFREQ, "ks7031 read_m, offset: %04x\n", offset);
return m_prg[(m_reg[BIT(offset, 11, 2)] * 0x0800) + (offset & 0x7ff)];
}
@@ -894,7 +896,7 @@ u8 nes_ks7031_device::read_h(offs_t offset)
void nes_ks7031_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("ks7031 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("ks7031 write_h, offset: %04x, data: %02x\n", offset, data);
m_reg[BIT(offset, 11, 2)] = data & 0x3f;
}
@@ -917,7 +919,7 @@ void nes_ks7031_device::write_h(offs_t offset, u8 data)
u8 nes_ks7037_device::read_m(offs_t offset)
{
-// LOG_MMC(("ks7037 read_m, offset: %04x\n", offset));
+ LOGMASKED(LOG_HIFREQ, "ks7037 read_m, offset: %04x\n", offset);
if (offset < 0x1000)
return m_prgram[offset];
else
@@ -926,14 +928,14 @@ u8 nes_ks7037_device::read_m(offs_t offset)
void nes_ks7037_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("ks7037 write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("ks7037 write_m, offset: %04x, data: %02x\n", offset, data);
if (offset < 0x1000)
m_prgram[offset] = data;
}
u8 nes_ks7037_device::read_h(offs_t offset)
{
-// LOG_MMC(("ks7037 read_h, offset: %04x\n", offset));
+ LOGMASKED(LOG_HIFREQ, "ks7037 read_h, offset: %04x\n", offset);
if (offset >= 0x3000 && offset < 0x4000)
return m_prgram[0x1000 + (offset & 0x0fff)];
@@ -943,7 +945,7 @@ u8 nes_ks7037_device::read_h(offs_t offset)
void nes_ks7037_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("ks7037 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("ks7037 write_h, offset: %04x, data: %02x\n", offset, data);
switch (offset & 0x7000)
{
@@ -984,13 +986,13 @@ void nes_ks7037_device::write_h(offs_t offset, u8 data)
u8 nes_ks7057_device::read_m(offs_t offset)
{
-// LOG_MMC(("ks7057 read_m, offset: %04x\n", offset));
+ LOG("ks7057 read_m, offset: %04x\n", offset);
return m_prg[0x800 * m_reg[BIT(offset, 11, 2) + 4] + (offset & 0x7ff)];
}
u8 nes_ks7057_device::read_h(offs_t offset)
{
-// LOG_MMC(("ks7057 read_h, offset: %04x\n", offset));
+ LOGMASKED(LOG_HIFREQ, "ks7057 read_h, offset: %04x\n", offset);
if (offset < 0x2000)
return m_prg[0x800 * m_reg[BIT(offset, 11, 2)] + (offset & 0x7ff)];
@@ -999,7 +1001,7 @@ u8 nes_ks7057_device::read_h(offs_t offset)
void nes_ks7057_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("ks7057 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("ks7057 write_h, offset: %04x, data: %02x\n", offset, data);
if (offset < 0x2000)
set_nt_mirroring(BIT(data, 0) ? PPU_MIRROR_VERT : PPU_MIRROR_HORZ);
diff --git a/src/devices/bus/nes/karastudio.cpp b/src/devices/bus/nes/karastudio.cpp
index 3b8801bbf52..0cca5acbe11 100644
--- a/src/devices/bus/nes/karastudio.cpp
+++ b/src/devices/bus/nes/karastudio.cpp
@@ -32,7 +32,7 @@
#include "karastudio.h"
#ifdef NES_PCB_DEBUG
-#define VERBOSE 1
+#define VERBOSE (LOG_GENERAL)
#else
#define VERBOSE 0
#endif
@@ -96,33 +96,32 @@ uint8_t nes_kstudio_slot_device::read(offs_t offset)
return 0xff;
}
-image_init_result nes_kstudio_slot_device::call_load()
+std::pair<std::error_condition, std::string> nes_kstudio_slot_device::call_load()
{
if (m_cart)
{
- uint8_t *ROM = m_cart->get_cart_base();
-
+ uint8_t *const ROM = m_cart->get_cart_base();
if (!ROM)
- return image_init_result::FAIL;
+ return std::make_pair(image_error::INTERNAL, std::string());
// Existing expansion carts are all 128K, so we only load files of this size
if (!loaded_through_softlist())
{
if (length() != 0x20000)
- return image_init_result::FAIL;
+ return std::make_pair(image_error::INVALIDLENGTH, "Unsupported cartridge size (must be 128K)");
- fread(&ROM, 0x20000);
+ fread(ROM, 0x20000);
}
else
{
if (get_software_region_length("rom") != 0x20000)
- return image_init_result::FAIL;
+ return std::make_pair(image_error::INVALIDLENGTH, "Unsupported cartridge size (must be 128K)");
memcpy(ROM, get_software_region("rom"), 0x20000);
}
}
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
diff --git a/src/devices/bus/nes/karastudio.h b/src/devices/bus/nes/karastudio.h
index 95ea9b14881..1a1b1cf2132 100644
--- a/src/devices/bus/nes/karastudio.h
+++ b/src/devices/bus/nes/karastudio.h
@@ -62,24 +62,24 @@ public:
nes_kstudio_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual ~nes_kstudio_slot_device();
- // image-level overrides
- virtual image_init_result call_load() override;
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
virtual bool is_reset_on_load() const noexcept override { return true; }
virtual const char *image_interface() const noexcept override { return "ks_cart"; }
virtual const char *file_extensions() const noexcept override { return "bin"; }
- // slot interface overrides
+ // device_slot_interface implementation
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
uint8_t read(offs_t offset);
void write_prg_bank(uint8_t bank) { if (m_cart) m_cart->write_prg_bank(bank); }
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
- kstudio_cart_interface* m_cart;
+ kstudio_cart_interface *m_cart;
};
// device type definition
@@ -101,14 +101,13 @@ public:
// construction/destruction
nes_kstudio_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- // optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual uint8_t* get_cart_base();
+ virtual uint8_t *get_cart_base();
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
virtual void device_reset() override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
};
// device type definition
diff --git a/src/devices/bus/nes/konami.cpp b/src/devices/bus/nes/konami.cpp
index 64835930218..27362d28c8c 100644
--- a/src/devices/bus/nes/konami.cpp
+++ b/src/devices/bus/nes/konami.cpp
@@ -24,14 +24,15 @@
#include "speaker.h"
+#define LOG_UNHANDLED (1U << 1)
#ifdef NES_PCB_DEBUG
-#define VERBOSE 1
+#define VERBOSE (LOG_UNHANDLED | LOG_GENERAL)
#else
-#define VERBOSE 0
+#define VERBOSE (LOG_UNHANDLED)
#endif
+#include "logmacro.h"
-#define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0)
//-------------------------------------------------
// constructor
@@ -209,7 +210,7 @@ void nes_konami_vrc7_device::pcb_reset()
void nes_konami_vrc1_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("VRC-1 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("VRC-1 write_h, offset: %04x, data: %02x\n", offset, data);
switch (offset & 0x7000)
{
@@ -246,7 +247,7 @@ void nes_konami_vrc1_device::write_h(offs_t offset, u8 data)
u8 nes_konami_vrc2_device::read_m(offs_t offset)
{
- LOG_MMC(("VRC-2 read_m, offset: %04x\n", offset));
+ LOG("VRC-2 read_m, offset: %04x\n", offset);
if (!m_battery.empty() || !m_prgram.empty())
return device_nes_cart_interface::read_m(offset);
@@ -256,7 +257,7 @@ u8 nes_konami_vrc2_device::read_m(offs_t offset)
void nes_konami_vrc2_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("VRC-2 write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("VRC-2 write_m, offset: %04x, data: %02x\n", offset, data);
if (!m_battery.empty() || !m_prgram.empty())
device_nes_cart_interface::write_m(offset, data);
@@ -266,7 +267,7 @@ void nes_konami_vrc2_device::write_m(offs_t offset, u8 data)
void nes_konami_vrc2_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("VRC-2 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("VRC-2 write_h, offset: %04x, data: %02x\n", offset, data);
u8 addr_lines = bitswap<2>(offset, m_vrc_ls_prg_a, m_vrc_ls_prg_b);
@@ -292,7 +293,7 @@ void nes_konami_vrc2_device::write_h(offs_t offset, u8 data)
break;
}
default:
- logerror("VRC-2 write_h uncaught write, addr: %04x value: %02x\n", offset + 0x8000, data);
+ LOGMASKED(LOG_UNHANDLED, "VRC-2 write_h uncaught write, addr: %04x value: %02x\n", offset + 0x8000, data);
break;
}
}
@@ -327,7 +328,7 @@ TIMER_CALLBACK_MEMBER(nes_konami_vrc3_device::irq_timer_tick)
void nes_konami_vrc3_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("VRC-3 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("VRC-3 write_h, offset: %04x, data: %02x\n", offset, data);
switch (offset & 0x7000)
{
@@ -357,7 +358,7 @@ void nes_konami_vrc3_device::write_h(offs_t offset, u8 data)
prg16_89ab(data & 0x07);
break;
default:
- logerror("VRC-3 write_h uncaught write, offset %04x, data: %02x\n", offset, data);
+ LOGMASKED(LOG_UNHANDLED, "VRC-3 write_h uncaught write, offset %04x, data: %02x\n", offset, data);
break;
}
}
@@ -449,7 +450,7 @@ void nes_konami_vrc4_device::set_chr(int chr_base, int chr_mask)
u8 nes_konami_vrc4_device::read_m(offs_t offset)
{
- LOG_MMC(("VRC-4 read_m, offset: %04x\n", offset));
+ LOG("VRC-4 read_m, offset: %04x\n", offset);
if (m_wram_enable)
return device_nes_cart_interface::read_m(offset);
@@ -459,7 +460,7 @@ u8 nes_konami_vrc4_device::read_m(offs_t offset)
void nes_konami_vrc4_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("VRC-4 write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("VRC-4 write_m, offset: %04x, data: %02x\n", offset, data);
if (m_wram_enable)
device_nes_cart_interface::write_m(offset, data);
@@ -467,7 +468,7 @@ void nes_konami_vrc4_device::write_m(offs_t offset, u8 data)
void nes_konami_vrc4_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("VRC-4 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("VRC-4 write_h, offset: %04x, data: %02x\n", offset, data);
u8 addr_lines = bitswap<2>(offset, m_vrc_ls_prg_a, m_vrc_ls_prg_b);
@@ -534,7 +535,7 @@ void nes_konami_vrc4_device::write_h(offs_t offset, u8 data)
void nes_konami_vrc6_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("VRC-6 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("VRC-6 write_h, offset: %04x, data: %02x\n", offset, data);
u8 addr_lines = bitswap<2>(offset, m_vrc_ls_prg_a, m_vrc_ls_prg_b);
@@ -578,7 +579,7 @@ void nes_konami_vrc6_device::write_h(offs_t offset, u8 data)
irq_ack_w();
break;
default:
- logerror("VRC-6 write_h uncaught write, addr: %04x value: %02x\n", ((offset & 0x7000) | addr_lines) + 0x8000, data);
+ LOGMASKED(LOG_UNHANDLED, "VRC-6 write_h uncaught write, addr: %04x value: %02x\n", ((offset & 0x7000) | addr_lines) + 0x8000, data);
break;
}
break;
@@ -614,7 +615,7 @@ void nes_konami_vrc6_device::device_add_mconfig(machine_config &config)
void nes_konami_vrc7_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("VRC-7 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("VRC-7 write_h, offset: %04x, data: %02x\n", offset, data);
u8 reg = bitswap<4>(offset, 14, 13, 12, m_vrc_ls_prg_a);
diff --git a/src/devices/bus/nes/legacy.cpp b/src/devices/bus/nes/legacy.cpp
index 8625c4fab97..9d7fd648645 100644
--- a/src/devices/bus/nes/legacy.cpp
+++ b/src/devices/bus/nes/legacy.cpp
@@ -20,12 +20,11 @@
#ifdef NES_PCB_DEBUG
-#define VERBOSE 1
+#define VERBOSE (LOG_GENERAL)
#else
-#define VERBOSE 0
+#define VERBOSE (0)
#endif
-
-#define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0)
+#include "logmacro.h"
//-------------------------------------------------
@@ -117,13 +116,13 @@ void nes_ffe8_device::pcb_reset()
Known Boards: FFE3 Copier Board
Games: Hacked versions of games
- In MESS: Supported? (I have no games to test this)
+ In MAME: Supported? (I have no games to test this)
-------------------------------------------------*/
void nes_ffe3_device::write_h(offs_t offset, uint8_t data)
{
- LOG_MMC(("mapper8 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("mapper8 write_h, offset: %04x, data: %02x\n", offset, data);
chr8(data & 0x07, CHRROM);
prg16_89ab(data >> 3);
@@ -136,7 +135,7 @@ void nes_ffe3_device::write_h(offs_t offset, uint8_t data)
Known Boards: FFE4 Copier Board
Games: Hacked versions of games
- In MESS: Supported? Not sure if we could also have ExRAM or not...
+ In MAME: Supported? Not sure if we could also have ExRAM or not...
However, priority is pretty low for this mapper.
-------------------------------------------------*/
@@ -158,7 +157,7 @@ TIMER_CALLBACK_MEMBER(nes_ffe4_device::irq_timer_tick)
void nes_ffe4_device::write_l(offs_t offset, uint8_t data)
{
- LOG_MMC(("mapper6 write_l, offset: %04x, data: %02x\n", offset, data));
+ LOG("mapper6 write_l, offset: %04x, data: %02x\n", offset, data);
switch (offset)
{
@@ -206,7 +205,7 @@ uint8_t nes_ffe4_device::chr_r(offs_t offset)
void nes_ffe4_device::write_h(offs_t offset, uint8_t data)
{
- LOG_MMC(("mapper6 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("mapper6 write_h, offset: %04x, data: %02x\n", offset, data);
if (!m_latch) // when in "FFE mode" we are forced to use CHRRAM/EXRAM bank?
{
@@ -235,13 +234,13 @@ void nes_ffe4_device::write_h(offs_t offset, uint8_t data)
Known Boards: FFE8 Copier Board
Games: Hacked versions of games
- In MESS: Partially Supported.
+ In MAME: Partially Supported.
-------------------------------------------------*/
void nes_ffe8_device::write_l(offs_t offset, uint8_t data)
{
- LOG_MMC(("mapper17 write_l, offset: %04x, data: %02x\n", offset, data));
+ LOG("mapper17 write_l, offset: %04x, data: %02x\n", offset, data);
switch (offset)
{
diff --git a/src/devices/bus/nes/mmc1.cpp b/src/devices/bus/nes/mmc1.cpp
index 221b81e294e..c2cbccf77e9 100644
--- a/src/devices/bus/nes/mmc1.cpp
+++ b/src/devices/bus/nes/mmc1.cpp
@@ -27,12 +27,11 @@
#include "mmc1.h"
#ifdef NES_PCB_DEBUG
-#define VERBOSE 1
+#define VERBOSE (LOG_GENERAL)
#else
-#define VERBOSE 0
+#define VERBOSE (0)
#endif
-
-#define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0)
+#include "logmacro.h"
//-------------------------------------------------
@@ -215,7 +214,7 @@ void nes_sxrom_device::update_regs(int reg)
void nes_sxrom_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("sxrom write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("sxrom write_h, offset: %04x, data: %02x\n", offset, data);
// There is only one latch and shift counter, shared amongst the 4 regs (testcase: Space Shuttle)
@@ -257,7 +256,7 @@ void nes_sxrom_device::write_h(offs_t offset, u8 data)
void nes_sxrom_device::write_m(offs_t offset, u8 data)
{
u8 bank = BIT(m_reg[1], 2, 2);
- LOG_MMC(("sxrom write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("sxrom write_m, offset: %04x, data: %02x\n", offset, data);
if (!BIT(m_reg[3], 4) || m_mmc1_type == mmc1_type::MMC1A) // WRAM enabled
{
@@ -271,7 +270,7 @@ void nes_sxrom_device::write_m(offs_t offset, u8 data)
u8 nes_sxrom_device::read_m(offs_t offset)
{
u8 bank = BIT(m_reg[1], 2, 2);
- LOG_MMC(("sxrom read_m, offset: %04x\n", offset));
+ LOG("sxrom read_m, offset: %04x\n", offset);
if (!BIT(m_reg[3], 4) || m_mmc1_type == mmc1_type::MMC1A) // WRAM enabled
{
@@ -288,7 +287,7 @@ u8 nes_sxrom_device::read_m(offs_t offset)
void nes_sorom_device::write_m(offs_t offset, u8 data)
{
u8 type = BIT(m_reg[0], 4) ? BIT(m_reg[1], 4) : BIT(m_reg[1], 3);
- LOG_MMC(("sorom write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("sorom write_m, offset: %04x, data: %02x\n", offset, data);
if (!BIT(m_reg[3], 4) || m_mmc1_type == mmc1_type::MMC1A) // WRAM enabled
{
@@ -302,7 +301,7 @@ void nes_sorom_device::write_m(offs_t offset, u8 data)
u8 nes_sorom_device::read_m(offs_t offset)
{
u8 type = BIT(m_reg[0], 4) ? BIT(m_reg[1], 4) : BIT(m_reg[1], 3);
- LOG_MMC(("sorom read_m, offset: %04x\n", offset));
+ LOG("sorom read_m, offset: %04x\n", offset);
if (!BIT(m_reg[3], 4) || m_mmc1_type == mmc1_type::MMC1A) // WRAM enabled
{
@@ -318,7 +317,7 @@ u8 nes_sorom_device::read_m(offs_t offset)
// SZROM has two RAM banks, the first is not battery backed up, the second is.
void nes_szrom_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("szrom write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("szrom write_m, offset: %04x, data: %02x\n", offset, data);
if (!BIT(m_reg[3], 4) || m_mmc1_type == mmc1_type::MMC1A) // WRAM enabled
{
@@ -331,7 +330,7 @@ void nes_szrom_device::write_m(offs_t offset, u8 data)
u8 nes_szrom_device::read_m(offs_t offset)
{
- LOG_MMC(("szrom read_m, offset: %04x\n", offset));
+ LOG("szrom read_m, offset: %04x\n", offset);
if (!BIT(m_reg[3], 4) || m_mmc1_type == mmc1_type::MMC1A) // WRAM enabled
{
diff --git a/src/devices/bus/nes/mmc1_clones.cpp b/src/devices/bus/nes/mmc1_clones.cpp
index 58ee73330cd..8c318c4b96c 100644
--- a/src/devices/bus/nes/mmc1_clones.cpp
+++ b/src/devices/bus/nes/mmc1_clones.cpp
@@ -16,12 +16,11 @@
#ifdef NES_PCB_DEBUG
-#define VERBOSE 1
+#define VERBOSE (LOG_GENERAL)
#else
-#define VERBOSE 0
+#define VERBOSE (0)
#endif
-
-#define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0)
+#include "logmacro.h"
//-------------------------------------------------
@@ -181,7 +180,7 @@ void nes_txc_22110_device::pcb_reset()
void nes_ninjaryu_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("unl_ninjaryu write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("unl_ninjaryu write_h, offset: %04x, data: %02x\n", offset, data);
u8 reg = BIT(offset, 13, 2);
m_reg[reg] = data;
update_regs(reg);
@@ -221,7 +220,7 @@ void nes_bmc_jy012005_device::set_chr()
void nes_bmc_jy012005_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_jy012005 write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_jy012005 write_m, offset: %04x, data: %02x\n", offset, data);
if (!BIT(m_latch0, 7)) // outer bank lock
{
@@ -253,7 +252,7 @@ void nes_bmc_jy820845c_device::update_banks() // used by menu and MHROM games
void nes_bmc_jy820845c_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_jy820845c write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_jy820845c write_m, offset: %04x, data: %02x\n", offset, data);
nes_sxrom_device::write_m(offset, data); // register overlaid on WRAM
@@ -272,7 +271,7 @@ void nes_bmc_jy820845c_device::write_m(offs_t offset, u8 data)
void nes_bmc_jy820845c_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_jy820845c write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_jy820845c write_h, offset: %04x, data: %02x\n", offset, data);
m_latch0 = data;
@@ -298,7 +297,7 @@ void nes_bmc_jy820845c_device::write_h(offs_t offset, u8 data)
void nes_farid_slrom_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("farid_slrom write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("farid_slrom write_m, offset: %04x, data: %02x\n", offset, data);
if (!BIT(m_reg[3], 4) && !BIT(m_outer, 3)) // MMC1 WRAM enabled and outer bank not locked
m_outer = data;
}
@@ -342,7 +341,7 @@ void nes_farid_slrom_device::write_m(offs_t offset, u8 data)
void nes_srpg5in1_device::write_l(offs_t offset, u8 data)
{
- LOG_MMC(("srpg5in1 write_l, offset: %04x, data: %02x\n", offset, data));
+ LOG("srpg5in1 write_l, offset: %04x, data: %02x\n", offset, data);
offset += 0x100;
if (offset >= 0x1000)
@@ -359,7 +358,7 @@ void nes_srpg5in1_device::write_l(offs_t offset, u8 data)
void nes_srpg5in1_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("srpg5in1 write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("srpg5in1 write_m, offset: %04x, data: %02x\n", offset, data);
u8 bank = BIT(m_outer, 1) ? bitswap<3>(m_outer, 1, 2, 0) : (m_outer & 1) << 1 | BIT(m_reg[1], 3);
@@ -369,7 +368,7 @@ void nes_srpg5in1_device::write_m(offs_t offset, u8 data)
u8 nes_srpg5in1_device::read_m(offs_t offset)
{
- LOG_MMC(("srpg5in1 read_m, offset: %04x\n", offset));
+ LOG("srpg5in1 read_m, offset: %04x\n", offset);
u8 bank = BIT(m_outer, 1) ? bitswap<3>(m_outer, 1, 2, 0) : (m_outer & 1) << 1 | BIT(m_reg[1], 3);
@@ -405,7 +404,7 @@ void nes_txc_22110_device::update_banks() // used by menu and Space Shadow
void nes_txc_22110_device::write_l(offs_t offset, u8 data)
{
- LOG_MMC(("TXC 22110 write_l, offset: %04x, data: %02x\n", offset, data));
+ LOG("TXC 22110 write_l, offset: %04x, data: %02x\n", offset, data);
if (offset < 0x100) // $4100 - $41ff
{
m_mode = data;
@@ -421,7 +420,7 @@ void nes_txc_22110_device::write_l(offs_t offset, u8 data)
void nes_txc_22110_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("TXC 22110 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("TXC 22110 write_h, offset: %04x, data: %02x\n", offset, data);
if (m_mode & 1)
nes_sxrom_device::write_h(offset, data);
diff --git a/src/devices/bus/nes/mmc2.cpp b/src/devices/bus/nes/mmc2.cpp
index 02da59b7aad..70c5ac71b5c 100644
--- a/src/devices/bus/nes/mmc2.cpp
+++ b/src/devices/bus/nes/mmc2.cpp
@@ -16,12 +16,11 @@
#ifdef NES_PCB_DEBUG
-#define VERBOSE 1
+#define VERBOSE (LOG_GENERAL)
#else
-#define VERBOSE 0
+#define VERBOSE (0)
#endif
-
-#define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0)
+#include "logmacro.h"
//-------------------------------------------------
@@ -96,7 +95,7 @@ void nes_fxrom_device::pcb_reset()
iNES: mapper 9
- In MESS: Supported
+ In MAME: Supported
-------------------------------------------------*/
@@ -104,25 +103,25 @@ void nes_pxrom_device::ppu_latch(offs_t offset)
{
if ((offset & 0x3ff0) == 0x0fd0)
{
- LOG_MMC(("mmc2 vrom latch switch (bank 0 low): %02x\n", m_reg[0]));
+ LOG("mmc2 vrom latch switch (bank 0 low): %02x\n", m_reg[0]);
m_latch1 = 0xfd;
chr4_0(m_reg[0], CHRROM);
}
else if ((offset & 0x3ff0) == 0x0fe0)
{
- LOG_MMC(("mmc2 vrom latch switch (bank 0 high): %02x\n", m_reg[1]));
+ LOG("mmc2 vrom latch switch (bank 0 high): %02x\n", m_reg[1]);
m_latch1 = 0xfe;
chr4_0(m_reg[1], CHRROM);
}
else if ((offset & 0x3ff0) == 0x1fd0)
{
- LOG_MMC(("mmc2 vrom latch switch (bank 1 low): %02x\n", m_reg[2]));
+ LOG("mmc2 vrom latch switch (bank 1 low): %02x\n", m_reg[2]);
m_latch2 = 0xfd;
chr4_4(m_reg[2], CHRROM);
}
else if ((offset & 0x3ff0) == 0x1fe0)
{
- LOG_MMC(("mmc2 vrom latch switch (bank 0 high): %02x\n", m_reg[3]));
+ LOG("mmc2 vrom latch switch (bank 0 high): %02x\n", m_reg[3]);
m_latch2 = 0xfe;
chr4_4(m_reg[3], CHRROM);
}
@@ -130,7 +129,7 @@ void nes_pxrom_device::ppu_latch(offs_t offset)
void nes_pxrom_device::pxrom_write(offs_t offset, uint8_t data)
{
- LOG_MMC(("pxrom write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("pxrom write_h, offset: %04x, data: %02x\n", offset, data);
switch (offset & 0x7000)
{
case 0x2000:
@@ -160,7 +159,7 @@ void nes_pxrom_device::pxrom_write(offs_t offset, uint8_t data)
set_nt_mirroring(BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
break;
default:
- LOG_MMC(("MMC2 uncaught w: %04x:%02x\n", offset, data));
+ LOG("MMC2 uncaught w: %04x:%02x\n", offset, data);
break;
}
}
@@ -176,13 +175,13 @@ void nes_pxrom_device::pxrom_write(offs_t offset, uint8_t data)
iNES: mapper 10
- In MESS: Supported
+ In MAME: Supported
-------------------------------------------------*/
void nes_fxrom_device::write_h(offs_t offset, uint8_t data)
{
- LOG_MMC(("fxrom write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("fxrom write_h, offset: %04x, data: %02x\n", offset, data);
switch (offset & 0x7000)
{
case 0x2000:
diff --git a/src/devices/bus/nes/mmc3.cpp b/src/devices/bus/nes/mmc3.cpp
index ff9774882fd..79b6c7deefa 100644
--- a/src/devices/bus/nes/mmc3.cpp
+++ b/src/devices/bus/nes/mmc3.cpp
@@ -29,14 +29,14 @@
#include "video/ppu2c0x.h" // this has to be included so that IRQ functions can access ppu2c0x_device::BOTTOM_VISIBLE_SCANLINE
+#define LOG_UNHANDLED (1U << 1)
#ifdef NES_PCB_DEBUG
-#define VERBOSE 1
+#define VERBOSE (LOG_UNHANDLED | LOG_GENERAL)
#else
-#define VERBOSE 0
+#define VERBOSE (LOG_UNHANDLED)
#endif
-
-#define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0)
+#include "logmacro.h"
//-------------------------------------------------
@@ -216,7 +216,7 @@ void nes_txrom_device::hblank_irq(int scanline, bool vblank, bool blanked)
if (m_irq_enable && !blanked && (m_irq_count == 0) && (prior_count || m_irq_clear /*|| !m_mmc3_alt_irq*/)) // according to blargg the latter should be present as well, but it breaks Rampart and Joe & Mac US: they probably use the alt irq!
{
- LOG_MMC(("irq fired, scanline: %d\n", scanline));
+ LOG("irq fired, scanline: %d\n", scanline);
set_irq_line(ASSERT_LINE);
}
}
@@ -264,7 +264,7 @@ void nes_txrom_device::txrom_write(offs_t offset, uint8_t data)
{
uint8_t mmc_helper, cmd;
- LOG_MMC(("txrom_write, offset: %04x, data: %02x\n", offset, data));
+ LOG("txrom_write, offset: %04x, data: %02x\n", offset, data);
switch (offset & 0x6001)
{
@@ -326,14 +326,14 @@ void nes_txrom_device::txrom_write(offs_t offset, uint8_t data)
break;
default:
- logerror("txrom_write uncaught: %04x value: %02x\n", offset + 0x8000, data);
+ LOGMASKED(LOG_UNHANDLED, "txrom_write uncaught: %04x value: %02x\n", offset + 0x8000, data);
break;
}
}
void nes_txrom_device::write_m(offs_t offset, uint8_t data)
{
- LOG_MMC(("txrom write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("txrom write_m, offset: %04x, data: %02x\n", offset, data);
if (BIT(m_wram_protect, 7) && !BIT(m_wram_protect, 6))
{
@@ -346,7 +346,7 @@ void nes_txrom_device::write_m(offs_t offset, uint8_t data)
uint8_t nes_txrom_device::read_m(offs_t offset)
{
- LOG_MMC(("txrom read_m, offset: %04x\n", offset));
+ LOG("txrom read_m, offset: %04x\n", offset);
if (BIT(m_wram_protect, 7))
{
@@ -371,7 +371,7 @@ uint8_t nes_txrom_device::read_m(offs_t offset)
void nes_hkrom_device::write_m(offs_t offset, uint8_t data)
{
uint8_t write_hi, write_lo;
- LOG_MMC(("hkrom write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("hkrom write_m, offset: %04x, data: %02x\n", offset, data);
if (offset < 0x1000)
return;
@@ -389,7 +389,7 @@ void nes_hkrom_device::write_m(offs_t offset, uint8_t data)
uint8_t nes_hkrom_device::read_m(offs_t offset)
{
- LOG_MMC(("hkrom read_m, offset: %04x\n", offset));
+ LOG("hkrom read_m, offset: %04x\n", offset);
if (offset < 0x1000)
return get_open_bus();
@@ -410,7 +410,7 @@ uint8_t nes_hkrom_device::read_m(offs_t offset)
void nes_hkrom_device::write_h(offs_t offset, uint8_t data)
{
uint8_t mmc6_helper;
- LOG_MMC(("hkrom write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("hkrom write_h, offset: %04x, data: %02x\n", offset, data);
switch (offset & 0x6001)
{
@@ -473,7 +473,7 @@ void nes_txsrom_device::set_chr(u8 chr, int chr_base, int chr_mask)
void nes_txsrom_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("txsrom write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("txsrom write_h, offset: %04x, data: %02x\n", offset, data);
switch (offset & 0x6001)
{
@@ -516,7 +516,7 @@ void nes_tqrom_device::chr_cb(int start, int bank, int source)
void nes_qj_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("qj write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("qj write_m, offset: %04x, data: %02x\n", offset, data);
if (BIT(m_wram_protect, 7) && !BIT(m_wram_protect, 6))
{
@@ -542,7 +542,7 @@ void nes_qj_device::write_m(offs_t offset, u8 data)
void nes_zz_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("zz write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("zz write_m, offset: %04x, data: %02x\n", offset, data);
if (BIT(m_wram_protect, 7) && !BIT(m_wram_protect, 6))
{
diff --git a/src/devices/bus/nes/mmc3_clones.cpp b/src/devices/bus/nes/mmc3_clones.cpp
index b74ec375e55..28fc05e8ad8 100644
--- a/src/devices/bus/nes/mmc3_clones.cpp
+++ b/src/devices/bus/nes/mmc3_clones.cpp
@@ -14,14 +14,14 @@
#include "emu.h"
#include "mmc3_clones.h"
+#define LOG_HIFREQ (1U << 1)
#ifdef NES_PCB_DEBUG
-#define VERBOSE 1
+#define VERBOSE (LOG_GENERAL)
#else
-#define VERBOSE 0
+#define VERBOSE (0)
#endif
-
-#define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0)
+#include "logmacro.h"
//-------------------------------------------------
@@ -1055,7 +1055,7 @@ void nes_smd133_device::pcb_reset()
void nes_nitra_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("nitra write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("nitra write_h, offset: %04x, data: %02x\n", offset, data);
txrom_write((offset & 0x6000) | BIT(offset, 10), offset);
}
@@ -1082,7 +1082,7 @@ void nes_bmw8544_device::set_prg(int prg_base, int prg_mask)
u8 nes_bmw8544_device::read_m(offs_t offset)
{
-// LOG_MMC(("bmw8544 read_m, offset: %04x\n", offset));
+ LOGMASKED(LOG_HIFREQ, "bmw8544 read_m, offset: %04x\n", offset);
// CHR banking may be done by reads in this address range
@@ -1091,7 +1091,7 @@ u8 nes_bmw8544_device::read_m(offs_t offset)
void nes_bmw8544_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("bmw8544 write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmw8544 write_m, offset: %04x, data: %02x\n", offset, data);
m_reg = data;
prg8_89(data);
}
@@ -1112,7 +1112,7 @@ void nes_bmw8544_device::write_m(offs_t offset, u8 data)
void nes_fs6_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("fs6 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("fs6 write_h, offset: %04x, data: %02x\n", offset, data);
txrom_write(bitswap<2>(offset, 0, 1) | (offset & ~0x03), data);
}
@@ -1134,7 +1134,7 @@ void nes_fs6_device::write_h(offs_t offset, u8 data)
void nes_sbros11_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("smb11 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("smb11 write_h, offset: %04x, data: %02x\n", offset, data);
txrom_write((offset & 0x6000) | BIT(offset, 2), data);
}
@@ -1168,7 +1168,7 @@ void nes_malisb_device::chr_cb(int start, int bank, int source)
void nes_malisb_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("malisb write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("malisb write_h, offset: %04x, data: %02x\n", offset, data);
offset = (offset & 0x6000) | BIT(offset, 3) | (BIT(offset, 14) & BIT(offset, 2));
txrom_write(offset, data);
@@ -1213,7 +1213,7 @@ void nes_family4646_device::prg_cb(int start, int bank)
void nes_family4646_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("family4646 write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("family4646 write_m, offset: %04x, data: %02x\n", offset, data);
int reg = offset & 0x03;
if (!BIT(m_reg[0], 7)) // lock bit
@@ -1243,13 +1243,13 @@ void nes_family4646_device::write_m(offs_t offset, u8 data)
iNES: mapper 254
- In MESS:
+ In MAME:
-------------------------------------------------*/
void nes_pikay2k_device::write_h(offs_t offset, uint8_t data)
{
- LOG_MMC(("pikay2k write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("pikay2k write_h, offset: %04x, data: %02x\n", offset, data);
switch (offset & 0x6001)
{
@@ -1269,14 +1269,14 @@ void nes_pikay2k_device::write_h(offs_t offset, uint8_t data)
// strange WRAM usage: it is protected at start, and gets unprotected after the first write to 0xa000
void nes_pikay2k_device::write_m(offs_t offset, uint8_t data)
{
- LOG_MMC(("pikay2k write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("pikay2k write_m, offset: %04x, data: %02x\n", offset, data);
m_prgram[offset & 0x1fff] = data;
}
uint8_t nes_pikay2k_device::read_m(offs_t offset)
{
- LOG_MMC(("pikay2k read_m, offset: %04x\n", offset));
+ LOG("pikay2k read_m, offset: %04x\n", offset);
return m_prgram[offset & 0x1fff] ^ (m_reg[0] & m_reg[1]);
}
@@ -1330,7 +1330,7 @@ void nes_8237_device::prg_cb(int start, int bank)
void nes_8237_device::write_l(offs_t offset, u8 data)
{
- LOG_MMC(("unl_8237 write_l, offset: %04x, data: %02x\n", offset, data));
+ LOG("unl_8237 write_l, offset: %04x, data: %02x\n", offset, data);
offset += 0x100;
switch (offset & 0x1007)
@@ -1348,7 +1348,7 @@ void nes_8237_device::write_l(offs_t offset, u8 data)
void nes_8237_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("unl_8237 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("unl_8237 write_h, offset: %04x, data: %02x\n", offset, data);
static constexpr u8 reg_table[8][8] =
{
@@ -1403,7 +1403,7 @@ void nes_8237_device::write_h(offs_t offset, u8 data)
u8 nes_158b_device::read_l(offs_t offset)
{
- LOG_MMC(("unl_158b read_l, offset: %04x\n", offset));
+ LOG("unl_158b read_l, offset: %04x\n", offset);
static constexpr u8 prot_table[8][8] =
{
@@ -1428,7 +1428,7 @@ u8 nes_158b_device::read_l(offs_t offset)
void nes_158b_device::write_l(offs_t offset, u8 data)
{
- LOG_MMC(("unl_158b write_l, offset: %04x, data: %02x\n", offset, data));
+ LOG("unl_158b write_l, offset: %04x, data: %02x\n", offset, data);
switch ((offset + 0x100) & 0x1003)
{
@@ -1464,7 +1464,7 @@ void nes_kasing_device::prg_cb(int start, int bank)
void nes_kasing_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("kasing write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("kasing write_m, offset: %04x, data: %02x\n", offset, data);
if (BIT(offset, 0))
{
@@ -1505,7 +1505,7 @@ void nes_kasing_device::write_m(offs_t offset, u8 data)
void nes_sglionk_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("sglionk write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("sglionk write_h, offset: %04x, data: %02x\n", offset, data);
static constexpr u8 reg_table[2][8] =
{
@@ -1547,7 +1547,7 @@ void nes_sglionk_device::write_h(offs_t offset, u8 data)
void nes_kay_device::write_l(offs_t offset, u8 data)
{
- LOG_MMC(("kay write_l, offset: %04x, data: %02x\n", offset, data));
+ LOG("kay write_l, offset: %04x, data: %02x\n", offset, data);
offset += 0x100;
if (offset >= 0x1000)
@@ -1564,7 +1564,7 @@ void nes_kay_device::write_l(offs_t offset, u8 data)
u8 nes_kay_device::read_l(offs_t offset)
{
- LOG_MMC(("kay read_l, offset: %04x\n", offset));
+ LOG("kay read_l, offset: %04x\n", offset);
static constexpr u8 prot_table[4] = {0x83, 0x83, 0x42, 0x00};
@@ -1595,7 +1595,7 @@ void nes_kay_device::set_prg(int prg_base, int prg_mask)
void nes_kay_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("kay write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("kay write_h, offset: %04x, data: %02x\n", offset, data);
txrom_write(offset, data);
@@ -1642,7 +1642,7 @@ void nes_h2288_device::prg_cb(int start, int bank)
void nes_h2288_device::write_l(offs_t offset, u8 data)
{
- LOG_MMC(("h2288 write_l, offset: %04x, data: %02x\n", offset, data));
+ LOG("h2288 write_l, offset: %04x, data: %02x\n", offset, data);
offset += 0x100;
if (offset >= 0x1800)
@@ -1662,7 +1662,7 @@ void nes_h2288_device::write_l(offs_t offset, u8 data)
void nes_h2288_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("h2288 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("h2288 write_h, offset: %04x, data: %02x\n", offset, data);
static constexpr u8 reg_table[8] = {0, 3, 1, 5, 6, 7, 2, 4};
@@ -1677,13 +1677,13 @@ void nes_h2288_device::write_h(offs_t offset, u8 data)
MMC3 + protection access in 0x4020 - 0x7fff
- in MESS: Partial support
+ in MAME: Partial support
-------------------------------------------------*/
void nes_6035052_device::write_ex(offs_t offset, uint8_t data)
{
- LOG_MMC(("6035052 write_ex, offset: %04x, data: %02x\n", offset, data));
+ LOG("6035052 write_ex, offset: %04x, data: %02x\n", offset, data);
m_prot = data & 0x03;
if (m_prot == 1)
m_prot = 2;
@@ -1691,7 +1691,7 @@ void nes_6035052_device::write_ex(offs_t offset, uint8_t data)
uint8_t nes_6035052_device::read_ex(offs_t offset)
{
- LOG_MMC(("6035052 read_ex, offset: %04x\n", offset));
+ LOG("6035052 read_ex, offset: %04x\n", offset);
return m_prot;
}
@@ -1705,13 +1705,13 @@ uint8_t nes_6035052_device::read_ex(offs_t offset)
iNES: mapper 189
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
void nes_txc_tw_device::write_l(offs_t offset, uint8_t data)
{
- LOG_MMC(("txc_tw write_l, offset: %04x, data: %02x\n", offset, data));
+ LOG("txc_tw write_l, offset: %04x, data: %02x\n", offset, data);
prg32((data >> 4) | data);
}
@@ -1735,7 +1735,7 @@ void nes_txc_tw_device::prg_cb(int start, int bank)
void nes_kof97_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("kof97 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("kof97 write_h, offset: %04x, data: %02x\n", offset, data);
// unscramble address and data
offset = (offset & 0x6000) | BIT(offset, 12);
@@ -1772,7 +1772,7 @@ void nes_kof96_device::chr_cb(int start, int bank, int source)
void nes_kof96_device::write_l(offs_t offset, u8 data)
{
- LOG_MMC(("kof96 write_l, offset: %04x, data: %02x\n", offset, data));
+ LOG("kof96 write_l, offset: %04x, data: %02x\n", offset, data);
offset += 0x100;
if ((offset & 0x1001) == 0x1000)
@@ -1792,7 +1792,7 @@ void nes_kof96_device::write_l(offs_t offset, u8 data)
u8 nes_kof96_device::read_l(offs_t offset)
{
- LOG_MMC(("kof96 read_l, offset: %04x\n", offset));
+ LOG("kof96 read_l, offset: %04x\n", offset);
offset += 0x100;
if (offset >= 0x1000)
@@ -1809,7 +1809,7 @@ u8 nes_kof96_device::read_l(offs_t offset)
iNES: mapper 197
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
@@ -1823,7 +1823,7 @@ void nes_sf3_device::set_chr(uint8_t chr_source, int chr_base, int chr_mask)
void nes_sf3_device::write_h(offs_t offset, uint8_t data)
{
uint8_t cmd;
- LOG_MMC(("sf3 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("sf3 write_h, offset: %04x, data: %02x\n", offset, data);
switch (offset & 0x6001)
{
@@ -1865,7 +1865,7 @@ void nes_sf3_device::write_h(offs_t offset, uint8_t data)
void nes_cocoma_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("cocoma write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("cocoma write_h, offset: %04x, data: %02x\n", offset, data);
if (BIT(offset, 4))
{
@@ -1914,7 +1914,7 @@ void nes_gouder_device::write_l(offs_t offset, u8 data)
0x09,0x19,0x49,0x59,0x09,0x19,0x49,0x59,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};
- LOG_MMC(("gouder write_l, offset: %04x, data: %02x\n", offset, data));
+ LOG("gouder write_l, offset: %04x, data: %02x\n", offset, data);
offset += 0x100;
switch (offset & 0x1800)
@@ -1934,7 +1934,7 @@ void nes_gouder_device::write_l(offs_t offset, u8 data)
u8 nes_gouder_device::read_l(offs_t offset)
{
- LOG_MMC(("gouder read_l, offset: %04x\n", offset));
+ LOG("gouder read_l, offset: %04x\n", offset);
offset += 0x100;
if (offset >= 0x1800)
@@ -1955,7 +1955,7 @@ void nes_gouder_device::prg_cb(int start, int bank)
Sachen boards used for a chinese port of Princess Maker (?)
- in MESS: Very Preliminary support, based on Cah4e3
+ in MAME: Very Preliminary support, based on Cah4e3
code in FCEUMM
-------------------------------------------------*/
@@ -1981,7 +1981,7 @@ void nes_sa9602b_device::prg_cb(int start, int bank)
void nes_sa9602b_device::write_h(offs_t offset, uint8_t data)
{
- LOG_MMC(("sa9602b write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("sa9602b write_h, offset: %04x, data: %02x\n", offset, data);
switch (offset & 0x6001)
{
@@ -2020,7 +2020,7 @@ void nes_sachen_shero_device::chr_cb(int start, int bank, int source)
void nes_sachen_shero_device::write_l(offs_t offset, u8 data)
{
- LOG_MMC(("shero write_l, offset: %04x, data: %02x\n", offset, data));
+ LOG("shero write_l, offset: %04x, data: %02x\n", offset, data);
offset += 0x4100;
if (offset == 0x4100)
@@ -2035,7 +2035,7 @@ void nes_sachen_shero_device::write_l(offs_t offset, u8 data)
u8 nes_sachen_shero_device::read_l(offs_t offset)
{
- LOG_MMC(("shero read_l, offset: %04x\n", offset));
+ LOG("shero read_l, offset: %04x\n", offset);
offset += 0x4100;
if (offset == 0x4100)
@@ -2089,7 +2089,7 @@ void nes_sachen_zgdh_device::set_chr(u8 chr, int chr_base, int chr_mask)
void nes_sachen_zgdh_device::write_l(offs_t offset, u8 data)
{
- LOG_MMC(("zgdh write_l, offset: %04x, data: %02x\n", offset, data));
+ LOG("zgdh write_l, offset: %04x, data: %02x\n", offset, data);
offset += 0x100;
if ((offset & 0x1100) == 0x0100)
@@ -2145,7 +2145,7 @@ void nes_a9746_device::update_banks(uint8_t value)
void nes_a9746_device::write_h(offs_t offset, uint8_t data)
{
- LOG_MMC(("unl_a9746 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("unl_a9746 write_h, offset: %04x, data: %02x\n", offset, data);
switch (offset & 0x6003)
{
@@ -2273,7 +2273,7 @@ void nes_fk23c_device::fk23c_set_chr()
void nes_fk23c_device::write_l(offs_t offset, uint8_t data)
{
- LOG_MMC(("fk23c write_l, offset: %04x, data: %02x\n", offset, data));
+ LOG("fk23c write_l, offset: %04x, data: %02x\n", offset, data);
offset += 0x100;
if (offset >= 0x1000)
@@ -2290,7 +2290,7 @@ void nes_fk23c_device::write_l(offs_t offset, uint8_t data)
void nes_fk23c_device::write_h(offs_t offset, uint8_t data)
{
- LOG_MMC(("fk23c write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("fk23c write_h, offset: %04x, data: %02x\n", offset, data);
if (m_reg[0] & 0x40)
{
@@ -2343,7 +2343,7 @@ void nes_fk23c_device::write_h(offs_t offset, uint8_t data)
void nes_nt639_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("nt639 write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("nt639 write_m, offset: %04x, data: %02x\n", offset, data);
if (BIT(data, 5))
prg32(bitswap<3>(data, 6, 2, 1));
@@ -2363,7 +2363,7 @@ void nes_nt639_device::write_m(offs_t offset, u8 data)
Games: Super 24-in-1
- In MESS: Partially Supported
+ In MAME: Partially Supported
-------------------------------------------------*/
@@ -2387,7 +2387,7 @@ void nes_s24in1sc03_device::chr_cb(int start, int bank, int source)
void nes_s24in1sc03_device::write_l(offs_t offset, uint8_t data)
{
- LOG_MMC(("s24in1sc03 write_l, offset: %04x, data: %02x\n", offset, data));
+ LOG("s24in1sc03 write_l, offset: %04x, data: %02x\n", offset, data);
offset += 0x100;
if (offset == 0x1ff0)
@@ -2446,7 +2446,7 @@ void nes_tech9in1_device::update_banks()
void nes_tech9in1_device::write_l(offs_t offset, u8 data)
{
- LOG_MMC(("tech9in1 write_l, offset: %04x, data: %02x\n", offset, data));
+ LOG("tech9in1 write_l, offset: %04x, data: %02x\n", offset, data);
offset += 0x100;
switch (offset & 0x1003) // writes $5000-$5002, mask is a best guess
@@ -2473,7 +2473,7 @@ void nes_tech9in1_device::write_l(offs_t offset, u8 data)
u8 nes_bmc_5in1_device::read_m(offs_t offset)
{
- LOG_MMC(("bmc_5in1 read_m, offset: %04x\n", offset));
+ LOG("bmc_5in1 read_m, offset: %04x\n", offset);
if ((offset & 0x03) == 0x02)
return (get_open_bus() & 0xfe) | m_jumper->read();
@@ -2483,7 +2483,7 @@ u8 nes_bmc_5in1_device::read_m(offs_t offset)
void nes_bmc_5in1_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_5in1 write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_5in1 write_m, offset: %04x, data: %02x\n", offset, data);
if ((m_wram_protect & 0xc0) == 0x80)
{
@@ -2507,7 +2507,7 @@ void nes_bmc_5in1_device::write_m(offs_t offset, u8 data)
void nes_bmc_8in1_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_8in1 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_8in1 write_h, offset: %04x, data: %02x\n", offset, data);
if (BIT(offset, 12))
{
@@ -2541,7 +2541,7 @@ void nes_bmc_8in1_device::write_h(offs_t offset, u8 data)
void nes_bmc_15in1_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_15in1 write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_15in1 write_m, offset: %04x, data: %02x\n", offset, data);
if (data & 1)
data |= m_jumper; // TODO: add jumper settings, m_jumper is 0 for now
@@ -2564,14 +2564,14 @@ void nes_bmc_15in1_device::write_m(offs_t offset, u8 data)
iNES: mapper 44
- In MESS: Supported. It also uses mmc3_irq.
+ In MAME: Supported. It also uses mmc3_irq.
-------------------------------------------------*/
void nes_bmc_sbig7_device::write_h(offs_t offset, uint8_t data)
{
uint8_t page;
- LOG_MMC(("bmc_sbig7 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_sbig7 write_h, offset: %04x, data: %02x\n", offset, data);
switch (offset & 0x6001)
{
@@ -2609,7 +2609,7 @@ void nes_bmc_sbig7_device::write_h(offs_t offset, uint8_t data)
void nes_bmc_hik8_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_hik8 write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_hik8 write_m, offset: %04x, data: %02x\n", offset, data);
nes_txrom_device::write_m(offset, data); // registers overlay WRAM
@@ -2707,7 +2707,7 @@ void nes_bmc_jy302_device::set_chr(u8 chr, int chr_base, int chr_mask)
u8 nes_bmc_kc885_device::read_h(offs_t offset)
{
-// LOG_MMC(("bmc_kc885 read_h, offset: %04x\n", offset));
+ LOGMASKED(LOG_HIFREQ, "bmc_kc885 read_h, offset: %04x\n", offset);
if (BIT(m_reg[1], 7) & BIT(m_jumper->read(), 2))
return get_open_bus();
@@ -2717,7 +2717,7 @@ u8 nes_bmc_kc885_device::read_h(offs_t offset)
void nes_bmc_kc885_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_kc885 write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_kc885 write_m, offset: %04x, data: %02x\n", offset, data);
if (!BIT(m_reg[3], 6)) // outer register lock bit
{
@@ -2781,7 +2781,7 @@ void nes_bmc_hik4_device::prg_cb(int start, int bank)
void nes_bmc_hik4_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_hik4 write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_hik4 write_m, offset: %04x, data: %02x\n", offset, data);
// mid writes only work when WRAM is enabled and writable
if ((m_wram_protect & 0xc0) == 0x80)
@@ -2854,7 +2854,7 @@ void nes_a88s1_device::prg_cb(int start, int bank)
void nes_a88s1_device::write_l(offs_t offset, u8 data)
{
- LOG_MMC(("a88s1 write_l, offset: %04x, data: %02x\n", offset, data));
+ LOG("a88s1 write_l, offset: %04x, data: %02x\n", offset, data);
offset += 0x100;
if (offset >= 0x1000)
@@ -2881,7 +2881,7 @@ void nes_a88s1_device::write_l(offs_t offset, u8 data)
void nes_bmc_f15_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_f15 write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_f15 write_m, offset: %04x, data: %02x\n", offset, data);
if (BIT(m_wram_protect, 7))
{
@@ -2915,7 +2915,7 @@ void nes_bmc_f15_device::prg_cb(int start, int bank)
u8 nes_bmc_f600_device::read_l(offs_t offset)
{
- LOG_MMC(("bmc_f600 read_l, offset: %04x\n", offset));
+ LOG("bmc_f600 read_l, offset: %04x\n", offset);
offset += 0x100;
if (offset >= 0x1000)
@@ -2926,7 +2926,7 @@ u8 nes_bmc_f600_device::read_l(offs_t offset)
void nes_bmc_f600_device::write_l(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_f600 write_l, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_f600 write_l, offset: %04x, data: %02x\n", offset, data);
offset += 0x100;
if (offset >= 0x1000)
@@ -2945,7 +2945,7 @@ void nes_bmc_f600_device::write_l(offs_t offset, u8 data)
void nes_bmc_f600_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_f600 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_f600 write_h, offset: %04x, data: %02x\n", offset, data);
if ((m_reg & 0x07) == 1)
nes_txsrom_device::write_h(offset, data);
else
@@ -2976,7 +2976,7 @@ void nes_bmc_f600_device::set_chr(u8 chr, int chr_base, int chr_mask)
void nes_bmc_el86xc_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_el86xc write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_el86xc write_m, offset: %04x, data: %02x\n", offset, data);
if (!(offset & 0x1000)) // game only banks via 0x6000, this mask is a guess
{
int outer = bitswap<3>(data, 5, 2, 1);
@@ -3003,7 +3003,7 @@ void nes_bmc_el86xc_device::write_m(offs_t offset, u8 data)
void nes_bmc_gn45_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_gn45 write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_gn45 write_m, offset: %04x, data: %02x\n", offset, data);
nes_txrom_device::write_m(offset, data); // registers overlay WRAM
@@ -3035,7 +3035,7 @@ void nes_bmc_gn45_device::write_m(offs_t offset, u8 data)
void nes_bmc_gold7in1_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_gold7in1 write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_gold7in1 write_m, offset: %04x, data: %02x\n", offset, data);
if ((m_wram_protect & 0xc0) == 0x80 && !m_lock)
{
@@ -3071,7 +3071,7 @@ void nes_bmc_gold7in1_device::write_m(offs_t offset, u8 data)
void nes_bmc_k3006_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_k3006 write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_k3006 write_m, offset: %04x, data: %02x\n", offset, data);
if ((m_wram_protect & 0xc0) == 0x80)
{
if (BIT(offset, 5)) // MMC3 mode
@@ -3113,7 +3113,7 @@ void nes_bmc_k3033_device::prg_cb(int start, int bank)
void nes_bmc_k3033_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_k3033 write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_k3033 write_m, offset: %04x, data: %02x\n", offset, data);
if ((m_wram_protect & 0xc0) == 0x80)
{
@@ -3174,7 +3174,7 @@ void nes_bmc_l6in1_device::set_mirror()
void nes_bmc_l6in1_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_l6in1 write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_l6in1 write_m, offset: %04x, data: %02x\n", offset, data);
if ((m_wram_protect & 0xc0) == 0x80)
{
@@ -3187,7 +3187,7 @@ void nes_bmc_l6in1_device::write_m(offs_t offset, u8 data)
void nes_bmc_l6in1_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_l6in1 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_l6in1 write_h, offset: %04x, data: %02x\n", offset, data);
txrom_write(offset, data);
if ((offset & 0x6001) == 0x2000)
@@ -3226,7 +3226,7 @@ void nes_bmc_00202650_device::set_chr(u8 chr, int chr_base, int chr_mask)
void nes_bmc_00202650_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_00202650 write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_00202650 write_m, offset: %04x, data: %02x\n", offset, data);
if (!m_mmc3_mode)
{
@@ -3262,7 +3262,7 @@ void nes_bmc_411120c_device::prg_cb(int start, int bank)
void nes_bmc_411120c_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_411120c write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_411120c write_m, offset: %04x, data: %02x\n", offset, data);
if (BIT(m_wram_protect, 7))
{
@@ -3325,7 +3325,7 @@ void nes_bmc_810305c_device::set_chr(u8 chr, int chr_base, int chr_mask)
void nes_bmc_810305c_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_810305c write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_810305c write_h, offset: %04x, data: %02x\n", offset, data);
if (BIT(offset, 7)) // outer register
{
@@ -3386,7 +3386,7 @@ void nes_bmc_820720c_device::set_chr(u8 chr, int chr_base, int chr_mask)
void nes_bmc_820720c_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_820720c write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_820720c write_m, offset: %04x, data: %02x\n", offset, data);
if ((m_wram_protect & 0xc0) == 0x80)
{
@@ -3402,7 +3402,7 @@ void nes_bmc_820720c_device::write_m(offs_t offset, u8 data)
void nes_bmc_820720c_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_820720c write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_820720c write_h, offset: %04x, data: %02x\n", offset, data);
txrom_write(offset, data); // MMC3 regs always written (for mirroring in non-MMC3 modes)
@@ -3448,7 +3448,7 @@ void nes_bmc_830118c_device::prg_cb(int start, int bank)
void nes_bmc_830118c_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_830118c write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_830118c write_m, offset: %04x, data: %02x\n", offset, data);
if ((m_wram_protect & 0xc0) == 0x80)
{
@@ -3475,7 +3475,7 @@ void nes_bmc_830118c_device::write_m(offs_t offset, u8 data)
void nes_bmc_830832c_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_830832c write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_830832c write_m, offset: %04x, data: %02x\n", offset, data);
if (offset & 0x1000) // game only writes 0x7000, this mask is a guess
{
m_prg_base = (data & 0x40) >> 1;
@@ -3504,7 +3504,7 @@ void nes_bmc_830832c_device::write_m(offs_t offset, u8 data)
void nes_bmc_yy841101c_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_yy841101c write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_yy841101c write_m, offset: %04x, data: %02x\n", offset, data);
if (offset & 0x1000) // games only write 0x7000, this mask is a guess
{
m_prg_base = data & 0xf0;
@@ -3530,7 +3530,7 @@ void nes_bmc_yy841101c_device::write_m(offs_t offset, u8 data)
void nes_bmc_yy841155c_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_yy841155c write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_yy841155c write_m, offset: %04x, data: %02x\n", offset, data);
if (offset >= 0x1000)
{
@@ -3598,7 +3598,7 @@ inline void nes_pjoy84_device::set_base_mask()
void nes_pjoy84_device::write_m(offs_t offset, uint8_t data)
{
- LOG_MMC(("pjoy84 write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("pjoy84 write_m, offset: %04x, data: %02x\n", offset, data);
switch (offset & 0x03)
{
@@ -3681,7 +3681,7 @@ void nes_smd133_device::smd133_write(offs_t offset, u8 data)
void nes_smd133_device::write_l(offs_t offset, u8 data)
{
- LOG_MMC(("smd133 write_l, offset: %04x, data: %02x\n", offset, data));
+ LOG("smd133 write_l, offset: %04x, data: %02x\n", offset, data);
offset += 0x100;
if (offset >= 0x1000 && m_smd133_addr == 0x5000)
@@ -3690,7 +3690,7 @@ void nes_smd133_device::write_l(offs_t offset, u8 data)
void nes_smd133_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("smd133 write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("smd133 write_m, offset: %04x, data: %02x\n", offset, data);
nes_txrom_device::write_m(offset, data); // registers overlay WRAM
diff --git a/src/devices/bus/nes/mmc5.cpp b/src/devices/bus/nes/mmc5.cpp
index f15b1a7658b..7d534e5e77a 100644
--- a/src/devices/bus/nes/mmc5.cpp
+++ b/src/devices/bus/nes/mmc5.cpp
@@ -20,13 +20,15 @@
#include "speaker.h"
+#define LOG_UNHANDLED (1U << 1)
+#define LOG_BANK_INFO (1U << 2)
+
#ifdef NES_PCB_DEBUG
-#define VERBOSE 1
+#define VERBOSE (LOG_UNHANDLED | LOG_GENERAL)
#else
-#define VERBOSE 0
+#define VERBOSE (LOG_UNHANDLED)
#endif
-
-#define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0)
+#include "logmacro.h"
#define LAST_CHR_REG_A 0
@@ -432,7 +434,7 @@ uint8_t nes_exrom_device::chr_r(offs_t offset)
uint8_t nes_exrom_device::read_l(offs_t offset)
{
int value;
- LOG_MMC(("exrom read_l, offset: %04x\n", offset));
+ LOG("exrom read_l, offset: %04x\n", offset);
offset += 0x100;
if ((offset >= 0x1c00) && (offset <= 0x1fff))
@@ -463,7 +465,7 @@ uint8_t nes_exrom_device::read_l(offs_t offset)
default:
if (!machine().side_effects_disabled())
- logerror("MMC5 uncaught read, offset: %04x\n", offset + 0x4100);
+ LOGMASKED(LOG_UNHANDLED, "MMC5 uncaught read, offset: %04x\n", offset + 0x4100);
return get_open_bus();
}
}
@@ -471,7 +473,7 @@ uint8_t nes_exrom_device::read_l(offs_t offset)
void nes_exrom_device::write_l(offs_t offset, uint8_t data)
{
- LOG_MMC(("exrom write_l, offset: %04x, data: %02x\n", offset, data));
+ LOG("exrom write_l, offset: %04x, data: %02x\n", offset, data);
offset += 0x100;
if ((offset >= 0x1000) && (offset <= 0x1015))
@@ -501,29 +503,29 @@ void nes_exrom_device::write_l(offs_t offset, uint8_t data)
case 0x1100:
m_prg_mode = data & 0x03;
update_prg();
- //LOG_MMC(("MMC5 rom bank mode: %02x\n", data));
+ LOGMASKED(LOG_BANK_INFO, "MMC5 rom bank mode: %02x\n", data);
break;
case 0x1101:
m_chr_mode = data & 0x03;
m_ex1_chr = 0;
m_split_chr = 0;
- //LOG_MMC(("MMC5 vrom bank mode: %02x\n", data));
+ LOGMASKED(LOG_BANK_INFO, "MMC5 vrom bank mode: %02x\n", data);
break;
case 0x1102:
m_wram_protect_1 = data & 0x03;
- LOG_MMC(("MMC5 vram protect 1: %02x\n", data));
+ LOG("MMC5 vram protect 1: %02x\n", data);
break;
case 0x1103:
m_wram_protect_2 = data & 0x03;
- LOG_MMC(("MMC5 vram protect 2: %02x\n", data));
+ LOG("MMC5 vram protect 2: %02x\n", data);
break;
case 0x1104: // Extra VRAM (EXRAM)
m_exram_control = data & 0x03;
- LOG_MMC(("MMC5 exram control: %02x\n", data));
+ LOG("MMC5 exram control: %02x\n", data);
break;
case 0x1105:
@@ -542,7 +544,7 @@ void nes_exrom_device::write_l(offs_t offset, uint8_t data)
break;
case 0x1113:
- LOG_MMC(("MMC5 mid RAM bank select: %02x\n", data & 0x07));
+ LOG("MMC5 mid RAM bank select: %02x\n", data & 0x07);
m_wram_base = data & 0x07;
break;
@@ -603,12 +605,12 @@ void nes_exrom_device::write_l(offs_t offset, uint8_t data)
case 0x1203:
m_irq_count = data;
- LOG_MMC(("MMC5 irq scanline: %d\n", m_irq_count));
+ LOG("MMC5 irq scanline: %d\n", m_irq_count);
break;
case 0x1204:
m_irq_enable = data & 0x80;
- LOG_MMC(("MMC5 irq enable: %02x\n", data));
+ LOG("MMC5 irq enable: %02x\n", data);
break;
case 0x1205:
@@ -620,7 +622,7 @@ void nes_exrom_device::write_l(offs_t offset, uint8_t data)
break;
default:
- logerror("MMC5 uncaught write, offset: %04x, data: %02x\n", offset + 0x4100, data);
+ LOG("MMC5 uncaught write, offset: %04x, data: %02x\n", offset + 0x4100, data);
break;
}
}
@@ -631,7 +633,7 @@ void nes_exrom_device::write_l(offs_t offset, uint8_t data)
// same mechanism is used also when "WRAM" is mapped in higher banks
uint8_t nes_exrom_device::read_m(offs_t offset)
{
- LOG_MMC(("exrom read_m, offset: %04x\n", offset));
+ LOG("exrom read_m, offset: %04x\n", offset);
if (!m_battery.empty() && !m_prgram.empty()) // 2 chips present: first is BWRAM, second is WRAM
{
if (m_wram_base & 0x04)
@@ -649,7 +651,7 @@ uint8_t nes_exrom_device::read_m(offs_t offset)
void nes_exrom_device::write_m(offs_t offset, uint8_t data)
{
- LOG_MMC(("exrom write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("exrom write_m, offset: %04x, data: %02x\n", offset, data);
if (m_wram_protect_1 != 0x02 || m_wram_protect_2 != 0x01)
return;
@@ -662,7 +664,7 @@ void nes_exrom_device::write_m(offs_t offset, uint8_t data)
// some games (e.g. Bandit Kings of Ancient China) write to PRG-RAM through 0x8000-0xdfff
uint8_t nes_exrom_device::read_h(offs_t offset)
{
- LOG_MMC(("exrom read_h, offset: %04x\n", offset));
+ LOG("exrom read_h, offset: %04x\n", offset);
int bank = offset / 0x2000;
if (bank < 3 && offset >= bank * 0x2000 && offset < (bank + 1) * 0x2000 && m_prg_ram_mapped[bank])
@@ -678,7 +680,7 @@ uint8_t nes_exrom_device::read_h(offs_t offset)
void nes_exrom_device::write_h(offs_t offset, uint8_t data)
{
- LOG_MMC(("exrom write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("exrom write_h, offset: %04x, data: %02x\n", offset, data);
int bank = offset / 0x2000;
if (m_wram_protect_1 != 0x02 || m_wram_protect_2 != 0x01 || bank == 3 || !m_prg_ram_mapped[bank])
return;
diff --git a/src/devices/bus/nes/multigame.cpp b/src/devices/bus/nes/multigame.cpp
index 2e13e22a73e..33e377fc6eb 100644
--- a/src/devices/bus/nes/multigame.cpp
+++ b/src/devices/bus/nes/multigame.cpp
@@ -19,13 +19,14 @@
#include "multigame.h"
+#define LOG_HIFREQ (1U << 1)
+
#ifdef NES_PCB_DEBUG
-#define VERBOSE 1
+#define VERBOSE (LOG_GENERAL)
#else
-#define VERBOSE 0
+#define VERBOSE (0)
#endif
-
-#define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0)
+#include "logmacro.h"
//-------------------------------------------------
@@ -1196,7 +1197,7 @@ void nes_bmc_th22913_device::pcb_reset()
void nes_action52_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("ae_act52_w, offset: %04x, data: %02x\n", offset, data));
+ LOG("ae_act52_w, offset: %04x, data: %02x\n", offset, data);
u8 bank = BIT(offset, 6, 7);
u8 mode = !BIT(offset, 5);
@@ -1226,7 +1227,7 @@ void nes_caltron6in1_device::update_chr()
void nes_caltron6in1_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("caltron6in1 write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("caltron6in1 write_m, offset: %04x, data: %02x\n", offset, data);
switch (offset & 0x1800)
{
@@ -1241,7 +1242,7 @@ void nes_caltron6in1_device::write_m(offs_t offset, u8 data)
void nes_caltron6in1_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("caltron6in1 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("caltron6in1 write_h, offset: %04x, data: %02x\n", offset, data);
// this pcb is subject to bus conflict
data = account_bus_conflict(offset, data);
@@ -1267,7 +1268,7 @@ void nes_caltron6in1_device::write_h(offs_t offset, u8 data)
void nes_caltron9in1_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("caltron9in1 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("caltron9in1 write_h, offset: %04x, data: %02x\n", offset, data);
int nibble = BIT(offset, 12, 3);
m_latch[std::min(nibble, 2)] = offset & 0x7f;
@@ -1296,13 +1297,13 @@ void nes_caltron9in1_device::write_h(offs_t offset, u8 data)
iNES: mapper 46
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
void nes_rumblestat_device::write_m(offs_t offset, uint8_t data)
{
- LOG_MMC(("rumblestation write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("rumblestation write_m, offset: %04x, data: %02x\n", offset, data);
m_prg = (m_prg & 0x01) | ((data & 0x0f) << 1);
m_chr = (m_chr & 0x07) | ((data & 0xf0) >> 1);
@@ -1312,7 +1313,7 @@ void nes_rumblestat_device::write_m(offs_t offset, uint8_t data)
void nes_rumblestat_device::write_h(offs_t offset, uint8_t data)
{
- LOG_MMC(("rumblestation write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("rumblestation write_h, offset: %04x, data: %02x\n", offset, data);
// this pcb is subject to bus conflict
data = account_bus_conflict(offset, data);
@@ -1355,7 +1356,7 @@ void nes_svision16_device::update_prg()
void nes_svision16_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("svision16 write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("svision16 write_m, offset: %04x, data: %02x\n", offset, data);
if (!BIT(m_latch1, 4))
{
@@ -1367,14 +1368,14 @@ void nes_svision16_device::write_m(offs_t offset, u8 data)
void nes_svision16_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("svision16 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("svision16 write_h, offset: %04x, data: %02x\n", offset, data);
m_latch2 = data;
update_prg();
}
u8 nes_svision16_device::read_m(offs_t offset)
{
- LOG_MMC(("svision16 read_m, offset: %04x\n", offset));
+ LOG("svision16 read_m, offset: %04x\n", offset);
u8 bank = m_latch1 << 4 | 0x0f;
return m_prg[((bank + 4) * 0x2000 + offset) % m_prg_size]; // +4 due to the 32KB menu
@@ -1394,7 +1395,7 @@ u8 nes_svision16_device::read_m(offs_t offset)
void nes_farid_unrom_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("farid_unrom write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("farid_unrom write_h, offset: %04x, data: %02x\n", offset, data);
// this pcb is subject to bus conflict
data = account_bus_conflict(offset, data);
@@ -1427,7 +1428,7 @@ void nes_farid_unrom_device::write_h(offs_t offset, u8 data)
void nes_kn42_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("kn42 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("kn42 write_h, offset: %04x, data: %02x\n", offset, data);
// this pcb is subject to bus conflict
data = account_bus_conflict(offset, data);
@@ -1441,14 +1442,14 @@ void nes_kn42_device::write_h(offs_t offset, u8 data)
Games: 3-in-1 (N068)
- In MESS: Supported
+ In MAME: Supported
-------------------------------------------------*/
void nes_a65as_device::write_h(offs_t offset, uint8_t data)
{
uint8_t helper = (data & 0x30) >> 1;
- LOG_MMC(("a65as write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("a65as write_h, offset: %04x, data: %02x\n", offset, data);
if (data & 0x80)
set_nt_mirroring(BIT(data, 5) ? PPU_MIRROR_HIGH : PPU_MIRROR_LOW);
@@ -1478,7 +1479,7 @@ void nes_a65as_device::write_h(offs_t offset, uint8_t data)
void nes_t262_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("t262 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("t262 write_h, offset: %04x, data: %02x\n", offset, data);
if (!BIT(m_latch, 13))
{
@@ -1508,14 +1509,14 @@ void nes_t262_device::write_h(offs_t offset, u8 data)
iNES: mapper 39
- In MESS: Partially Supported (problems with PRG bankswitch,
+ In MAME: Partially Supported (problems with PRG bankswitch,
only keyboard exercise work).
-------------------------------------------------*/
void nes_studyngame_device::write_h(offs_t offset, uint8_t data)
{
- LOG_MMC(("studyngame write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("studyngame write_h, offset: %04x, data: %02x\n", offset, data);
prg32(data);
}
@@ -1535,7 +1536,7 @@ void nes_studyngame_device::write_h(offs_t offset, uint8_t data)
void nes_sgun20in1_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("supergun20in1 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("supergun20in1 write_h, offset: %04x, data: %02x\n", offset, data);
// Hogan's Alley in 20-in-1 will occasionally sweep through 0x66xx-0x68xx which
// causes an abrupt goto Bomberman title screen. This mask is a best guess.
@@ -1571,7 +1572,7 @@ void nes_bmc_190in1_device::write_h(offs_t offset, u8 data)
void nes_vt5201_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("vt5201 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("vt5201 write_h, offset: %04x, data: %02x\n", offset, data);
if (!BIT(m_latch, 1)) // lock bit
{
@@ -1589,7 +1590,7 @@ void nes_vt5201_device::write_h(offs_t offset, u8 data)
u8 nes_vt5201_device::read_h(offs_t offset)
{
- LOG_MMC(("bmc_vt5201 read_h, offset: %04x\n", offset));
+ LOG("bmc_vt5201 read_h, offset: %04x\n", offset);
if (BIT(m_latch, 0))
return (get_open_bus() & ~0x03) | m_jumper; // TODO: add jumper settings, m_jumper is 0 for now
@@ -1617,7 +1618,7 @@ void nes_bmc_80013b_device::update_prg()
void nes_bmc_80013b_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_80013b write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_80013b write_h, offset: %04x, data: %02x\n", offset, data);
if (offset & 0x6000)
{
m_reg[1] = data & 0x7f;
@@ -1645,7 +1646,7 @@ void nes_bmc_80013b_device::write_h(offs_t offset, u8 data)
void nes_bmc_810544c_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_810544c write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_810544c write_h, offset: %04x, data: %02x\n", offset, data);
u8 bank = bitswap<4>(offset, 9, 8, 7, 5);
u8 mode = BIT(offset, 6);
@@ -1670,7 +1671,7 @@ void nes_bmc_810544c_device::write_h(offs_t offset, u8 data)
void nes_bmc_830425c_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_830425c write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_830425c write_h, offset: %04x, data: %02x\n", offset, data);
if ((offset & 0x7fe0) == 0x70e0)
m_latch = offset & 0x1f;
@@ -1695,7 +1696,7 @@ void nes_bmc_830425c_device::write_h(offs_t offset, u8 data)
void nes_bmc_830928c_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_830928c write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_830928c write_h, offset: %04x, data: %02x\n", offset, data);
// this pcb is subject to bus conflict
data = account_bus_conflict(offset, data);
@@ -1730,7 +1731,7 @@ void nes_bmc_830928c_device::write_h(offs_t offset, u8 data)
void nes_bmc_850437c_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_850437c write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_850437c write_h, offset: %04x, data: %02x\n", offset, data);
m_reg[(offset & 0x6000) == 0x2000] = data; // outer banking is always at 0xa000, mask is a guess
@@ -1759,7 +1760,7 @@ void nes_bmc_850437c_device::write_h(offs_t offset, u8 data)
void nes_bmc_970630c_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_970630c write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_970630c write_h, offset: %04x, data: %02x\n", offset, data);
u8 bank = BIT(offset, 2, 5);
if (BIT(offset, 9)) // NROM mode
@@ -1780,7 +1781,7 @@ void nes_bmc_970630c_device::write_h(offs_t offset, u8 data)
u8 nes_bmc_970630c_device::read_h(offs_t offset)
{
-// LOG_MMC(("bmc_970630c read_h, offset: %04x\n", offset));
+ LOGMASKED(LOG_HIFREQ, "bmc_970630c read_h, offset: %04x\n", offset);
if (m_latch)
return 0; // TODO: menu supposedly varies by solder pad value returned here, but it doesn't seem to work...
@@ -1802,7 +1803,7 @@ u8 nes_bmc_970630c_device::read_h(offs_t offset)
void nes_ntd03_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("ntd03 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("ntd03 write_h, offset: %04x, data: %02x\n", offset, data);
u8 bank = bitswap<5>(offset, 14, 13, 12, 11, 6);
u8 mode = !BIT(offset, 7);
@@ -1827,7 +1828,7 @@ void nes_ntd03_device::write_h(offs_t offset, u8 data)
void nes_bmc_ctc09_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_ctc09 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_ctc09 write_h, offset: %04x, data: %02x\n", offset, data);
if (BIT(offset, 14))
{
@@ -1863,7 +1864,7 @@ void nes_bmc_ctc09_device::write_h(offs_t offset, u8 data)
u8 nes_bmc_ds927_device::read_h(offs_t offset)
{
-// LOG_MMC(("bmc_ds927 read_h, offset: %04x\n", offset));
+ LOGMASKED(LOG_HIFREQ, "bmc_ds927 read_h, offset: %04x\n", offset);
int bits = m_mode == 1 ? 1 : 2;
@@ -1875,7 +1876,7 @@ u8 nes_bmc_ds927_device::read_h(offs_t offset)
void nes_bmc_ds927_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_ds927 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_ds927 write_h, offset: %04x, data: %02x\n", offset, data);
if (offset < 0x6000)
{
@@ -1927,13 +1928,13 @@ void nes_bmc_ds927_device::write_h(offs_t offset, u8 data)
u8 nes_bmc_gka_device::read_m(offs_t offset)
{
- LOG_MMC(("bmc_gka read_m, offset: %04x\n", offset));
+ LOG("bmc_gka read_m, offset: %04x\n", offset);
return 0; // TODO: menus differ by jumper/DIP settings readable at 0x6000.
}
void nes_bmc_gka_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_gka write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_gka write_h, offset: %04x, data: %02x\n", offset, data);
m_reg[BIT(offset, 11)] = data;
@@ -1968,7 +1969,7 @@ void nes_bmc_gka_device::write_h(offs_t offset, u8 data)
void nes_bmc_gkb_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_gkb write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_gkb write_h, offset: %04x, data: %02x\n", offset, data);
u8 bank = offset & 0x07;
u8 mode = !BIT(offset, 6);
@@ -1996,7 +1997,7 @@ void nes_bmc_gkb_device::write_h(offs_t offset, u8 data)
void nes_bmc_gkcxin1_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_gkcxin1 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_gkcxin1 write_h, offset: %04x, data: %02x\n", offset, data);
prg32(BIT(offset, 3, 2));
chr8(offset & 0x07, CHRROM);
@@ -2017,7 +2018,7 @@ void nes_bmc_gkcxin1_device::write_h(offs_t offset, u8 data)
void nes_bmc_gn91b_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_gn91b write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_gn91b write_h, offset: %04x, data: %02x\n", offset, data);
if (offset < 0x4000)
{
@@ -2046,7 +2047,7 @@ void nes_bmc_gn91b_device::write_h(offs_t offset, u8 data)
u8 nes_bmc_hp898f_device::read_l(offs_t offset)
{
- LOG_MMC(("bmc_hp898f read_l, offset: %04x\n", offset));
+ LOG("bmc_hp898f read_l, offset: %04x\n", offset);
offset += 0x100;
if (offset & 0x1000)
@@ -2057,7 +2058,7 @@ u8 nes_bmc_hp898f_device::read_l(offs_t offset)
void nes_bmc_hp898f_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_hp898f write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_hp898f write_m, offset: %04x, data: %02x\n", offset, data);
if (offset & 0x04)
{
@@ -2085,7 +2086,7 @@ void nes_bmc_hp898f_device::write_m(offs_t offset, u8 data)
void nes_bmc_k3036_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_k3036 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_k3036 write_h, offset: %04x, data: %02x\n", offset, data);
u8 bank = offset & 0x1f;
prg16_89ab(bank);
prg16_cdef(bank | (BIT(offset, 5) ? 0 : 7));
@@ -2106,7 +2107,7 @@ void nes_bmc_k3036_device::write_h(offs_t offset, u8 data)
void nes_bmc_k3046_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_k3046 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_k3046 write_h, offset: %04x, data: %02x\n", offset, data);
// this pcb is subject to bus conflict
data = account_bus_conflict(offset, data);
@@ -2130,7 +2131,7 @@ void nes_bmc_k3046_device::write_h(offs_t offset, u8 data)
void nes_bmc_k3071_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_k3071 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_k3071 write_h, offset: %04x, data: %02x\n", offset, data);
u8 bank = BIT(offset, 1, 5);
u8 mode = BIT(offset, 0);
@@ -2155,7 +2156,7 @@ void nes_bmc_k3071_device::write_h(offs_t offset, u8 data)
void nes_bmc_s009_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_s009 write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_s009 write_m, offset: %04x, data: %02x\n", offset, data);
m_reg = (data & 0x07) << 3;
prg16_89ab(m_reg);
@@ -2166,7 +2167,7 @@ void nes_bmc_s009_device::write_m(offs_t offset, u8 data)
void nes_bmc_s009_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_s009 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_s009 write_h, offset: %04x, data: %02x\n", offset, data);
// this pcb is subject to bus conflict
data = account_bus_conflict(offset, data);
@@ -2188,7 +2189,7 @@ void nes_bmc_s009_device::write_h(offs_t offset, u8 data)
void nes_bmc_sa005a_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_sa005a write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_sa005a write_h, offset: %04x, data: %02x\n", offset, data);
u8 bank = offset & 0x0f;
prg16_89ab(bank);
prg16_cdef(bank);
@@ -2216,7 +2217,7 @@ void nes_bmc_tf2740_device::update_chr()
void nes_bmc_tf2740_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_tf2740 write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_tf2740 write_m, offset: %04x, data: %02x\n", offset, data);
switch (offset & 0x03)
{
@@ -2239,14 +2240,14 @@ void nes_bmc_tf2740_device::write_m(offs_t offset, u8 data)
void nes_bmc_tf2740_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_tf2740 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_tf2740 write_h, offset: %04x, data: %02x\n", offset, data);
m_reg[0] = data;
update_chr();
}
u8 nes_bmc_tf2740_device::read_m(offs_t offset)
{
- LOG_MMC(("bmc_tf2740 read_m, offset: %04x\n", offset));
+ LOG("bmc_tf2740 read_m, offset: %04x\n", offset);
return (get_open_bus() & ~0x03) | m_jumper; // TODO: add jumper settings, m_jumper is 0 for now
}
@@ -2264,7 +2265,7 @@ u8 nes_bmc_tf2740_device::read_m(offs_t offset)
void nes_bmc_th2348_device::write_l(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_th2348 write_l, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_th2348 write_l, offset: %04x, data: %02x\n", offset, data);
offset += 0x100;
if (offset >= 0x1000)
@@ -2279,7 +2280,7 @@ void nes_bmc_th2348_device::write_l(offs_t offset, u8 data)
void nes_bmc_th2348_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_th2348 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_th2348 write_h, offset: %04x, data: %02x\n", offset, data);
// this pcb is subject to bus conflict
data = account_bus_conflict(offset, data);
@@ -2301,7 +2302,7 @@ void nes_bmc_th2348_device::write_h(offs_t offset, u8 data)
void nes_bmc_tj03_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_tj03 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_tj03 write_h, offset: %04x, data: %02x\n", offset, data);
u8 bank = BIT(offset, 8, 2);
prg32(bank);
chr8(bank, CHRROM);
@@ -2321,7 +2322,7 @@ void nes_bmc_tj03_device::write_h(offs_t offset, u8 data)
void nes_bmc_ws_device::write_m(offs_t offset, uint8_t data)
{
- LOG_MMC(("bmc_ws write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_ws write_m, offset: %04x, data: %02x\n", offset, data);
if (offset < 0x1000)
{
@@ -2359,7 +2360,7 @@ void nes_bmc_ws_device::write_m(offs_t offset, uint8_t data)
void nes_bmc_11160_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_11160 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_11160 write_h, offset: %04x, data: %02x\n", offset, data);
prg32(BIT(data, 4, 2));
chr8(bitswap<4>(data, 5, 4, 1, 0), CHRROM);
@@ -2380,7 +2381,7 @@ void nes_bmc_11160_device::write_h(offs_t offset, u8 data)
void nes_bmc_g146_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_g146 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_g146 write_h, offset: %04x, data: %02x\n", offset, data);
u8 prg_lo = offset & 0x1f;
u8 prg_hi = prg_lo; // default: NROM-128 mode
@@ -2411,7 +2412,7 @@ void nes_bmc_g146_device::write_h(offs_t offset, u8 data)
void nes_bmc_2751_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_2751 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_2751 write_h, offset: %04x, data: %02x\n", offset, data);
u8 bank = BIT(offset, 4, 3);
u8 mode = BIT(offset, 7);
prg16_89ab(bank & ~mode);
@@ -2440,7 +2441,7 @@ void nes_bmc_2751_device::write_h(offs_t offset, u8 data)
void nes_bmc_8157_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_8157 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_8157 write_h, offset: %04x, data: %02x\n", offset, data);
u8 bank = BIT(offset, 2, 5);
prg16_89ab(bank);
@@ -2456,7 +2457,7 @@ void nes_bmc_8157_device::write_h(offs_t offset, u8 data)
u8 nes_bmc_8157_device::read_h(offs_t offset)
{
- LOG_MMC(("bmc_8157 read_h, offset: %04x\n", offset));
+ LOG("bmc_8157 read_h, offset: %04x\n", offset);
if (m_latch)
offset = (offset & ~0x01) | m_jumper->read();
return hi_access_rom(offset);
@@ -2477,13 +2478,13 @@ u8 nes_bmc_8157_device::read_h(offs_t offset)
u8 nes_bmc_hik300_device::read_m(offs_t offset)
{
- LOG_MMC(("bmc_hik300 read_m, offset: %04x, data: %02x\n", offset));
+ LOG("bmc_hik300 read_m, offset: %04x, data: %02x\n", offset);
return get_open_bus() | (!BIT(offset, 4) << 7); // some games have a protection MSB
}
void nes_bmc_hik300_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_hik300 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_hik300 write_h, offset: %04x, data: %02x\n", offset, data);
u8 bank = offset & 0x07;
u8 mode = BIT(offset, 14);
@@ -2517,7 +2518,7 @@ void nes_bmc_hik300_device::write_h(offs_t offset, u8 data)
void nes_bmc_s700_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_s700 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_s700 write_h, offset: %04x, data: %02x\n", offset, data);
u8 bank = (offset & 0x40) | BIT(offset, 8, 6);
u8 mode = !BIT(offset, 5);
@@ -2543,7 +2544,7 @@ void nes_bmc_s700_device::write_h(offs_t offset, u8 data)
u8 nes_bmc_ball11_device::read_m(offs_t offset)
{
- LOG_MMC(("bmc_ball11 read_m, offset: %04x, data: %02x\n", offset));
+ LOG("bmc_ball11 read_m, offset: %04x, data: %02x\n", offset);
u8 bank = m_reg[1] << 2 | (m_reg[0] ? 0x23 : 0x2f);
return m_prg[(bank * 0x2000 + offset) & (m_prg_size - 1)];
@@ -2562,7 +2563,7 @@ void nes_bmc_ball11_device::update_prg()
void nes_bmc_ball11_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_ball11 write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_ball11 write_m, offset: %04x, data: %02x\n", offset, data);
set_nt_mirroring(BIT(data, 4) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
m_reg[0] = data & 0x02;
update_prg();
@@ -2570,7 +2571,7 @@ void nes_bmc_ball11_device::write_m(offs_t offset, u8 data)
void nes_bmc_ball11_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_ball11 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_ball11 write_h, offset: %04x, data: %02x\n", offset, data);
m_reg[1] = data & 0x1f;
update_prg();
}
@@ -2595,7 +2596,7 @@ void nes_bmc_ball11_device::write_h(offs_t offset, u8 data)
void nes_bmc_22games_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_22games write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_22games write_h, offset: %04x, data: %02x\n", offset, data);
if (m_latch)
{
@@ -2638,7 +2639,7 @@ void nes_bmc_64y2k_device::update_banks()
void nes_bmc_64y2k_device::write_l(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_64y2k write_l, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_64y2k write_l, offset: %04x, data: %02x\n", offset, data);
offset += 0x100;
if (offset >= 0x1000)
@@ -2650,7 +2651,7 @@ void nes_bmc_64y2k_device::write_l(offs_t offset, u8 data)
void nes_bmc_64y2k_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_64y2k write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_64y2k write_h, offset: %04x, data: %02x\n", offset, data);
if (!BIT(m_reg[0], 7))
prg16_89ab(((m_reg[1] << 1) & ~0x07) | (data & 0x07));
@@ -2672,7 +2673,7 @@ void nes_bmc_64y2k_device::write_h(offs_t offset, u8 data)
void nes_bmc_420y2k_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_420y2k write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_420y2k write_h, offset: %04x, data: %02x\n", offset, data);
if (BIT(m_latch, 1)) // lock bit
m_reg = (m_reg & ~0x07) | (data & 0x07);
@@ -2692,7 +2693,7 @@ void nes_bmc_420y2k_device::write_h(offs_t offset, u8 data)
u8 nes_bmc_420y2k_device::read_h(offs_t offset)
{
- LOG_MMC(("bmc_420y2k read_h, offset: %04x\n", offset));
+ LOG("bmc_420y2k read_h, offset: %04x\n", offset);
// latch bit 0 is only used to determine the menu, and the behavior of
// this cart seems hardwired to OR $02 (ORing $00-$03 allows four menus)
return hi_access_rom(offset | (m_latch & 1) << 1);
@@ -2731,7 +2732,7 @@ void nes_bmc_12in1_device::update_banks()
void nes_bmc_12in1_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_12in1 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_12in1 write_h, offset: %04x, data: %02x\n", offset, data);
m_reg[BIT(offset, 13, 2)] = data;
update_banks();
@@ -2752,7 +2753,7 @@ void nes_bmc_12in1_device::write_h(offs_t offset, u8 data)
void nes_bmc_20in1_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_20in1 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_20in1 write_h, offset: %04x, data: %02x\n", offset, data);
prg16_89ab(offset & 0x1e);
prg16_cdef((offset & 0x1e) | BIT(offset, 5));
@@ -2774,7 +2775,7 @@ void nes_bmc_20in1_device::write_h(offs_t offset, u8 data)
void nes_bmc_21in1_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_21in1 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_21in1 write_h, offset: %04x, data: %02x\n", offset, data);
prg32(offset & 0x03);
chr8(offset & 0x07, CHRROM);
@@ -2795,7 +2796,7 @@ void nes_bmc_21in1_device::write_h(offs_t offset, u8 data)
void nes_bmc_31in1_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_31in1 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_31in1 write_h, offset: %04x, data: %02x\n", offset, data);
set_nt_mirroring(BIT(offset, 5) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
offset &= 0x1f;
@@ -2825,7 +2826,7 @@ void nes_bmc_31in1_device::write_h(offs_t offset, u8 data)
void nes_bmc_35in1_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_35in1 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_35in1 write_h, offset: %04x, data: %02x\n", offset, data);
u8 bank = BIT(data, 2, 2);
prg16_89ab(bank);
@@ -2842,13 +2843,13 @@ void nes_bmc_35in1_device::write_h(offs_t offset, u8 data)
iNES: mapper 200
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
void nes_bmc_36in1_device::write_h(offs_t offset, uint8_t data)
{
- LOG_MMC(("bmc_36in1 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_36in1 write_h, offset: %04x, data: %02x\n", offset, data);
prg16_89ab(offset & 0x07);
prg16_cdef(offset & 0x07);
@@ -2866,7 +2867,7 @@ void nes_bmc_36in1_device::write_h(offs_t offset, uint8_t data)
iNES: mapper 204
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
@@ -2874,7 +2875,7 @@ void nes_bmc_64in1_device::write_h(offs_t offset, uint8_t data)
{
int bank = (offset >> 1) & (offset >> 2) & 0x01;
- LOG_MMC(("bmc_64in1 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_64in1 write_h, offset: %04x, data: %02x\n", offset, data);
prg16_89ab(offset & ~bank);
prg16_cdef(offset | bank);
@@ -2927,7 +2928,7 @@ void nes_bmc_70in1_device::update_prg(u8 bank)
void nes_bmc_70in1_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("bmc70in1 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc70in1 write_h, offset: %04x, data: %02x\n", offset, data);
m_latch[BIT(offset, 14)] = offset;
update_banks();
set_nt_mirroring(BIT(m_latch[0], 5) ? PPU_MIRROR_HORZ: PPU_MIRROR_VERT);
@@ -2935,7 +2936,7 @@ void nes_bmc_70in1_device::write_h(offs_t offset, u8 data)
uint8_t nes_bmc_70in1_device::read_h(offs_t offset)
{
- LOG_MMC(("bmc70in1 read_h, offset: %04x\n", offset));
+ LOG("bmc70in1 read_h, offset: %04x\n", offset);
if ((m_latch[1] & 0x30) == 0x10)
offset = (offset & ~0x0f) | m_jumper; // TODO: make jumper selectable
@@ -2978,7 +2979,7 @@ void nes_bmc_800in1_device::update_banks()
u8 nes_bmc_72in1_device::read_l(offs_t offset)
{
- LOG_MMC(("bmc_72in1 read_l, offset: %04x\n", offset));
+ LOG("bmc_72in1 read_l, offset: %04x\n", offset);
offset += 0x100;
if (offset >= 0x1800) // 4 nibbles of RAM mirrored above 0x5800
@@ -2989,7 +2990,7 @@ u8 nes_bmc_72in1_device::read_l(offs_t offset)
void nes_bmc_72in1_device::write_l(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_72in1 write_l, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_72in1 write_l, offset: %04x, data: %02x\n", offset, data);
offset += 0x100;
if (offset >= 0x1800) // 4 nibbles of RAM mirrored above 0x5800
@@ -2998,7 +2999,7 @@ void nes_bmc_72in1_device::write_l(offs_t offset, u8 data)
void nes_bmc_72in1_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_72in1 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_72in1 write_h, offset: %04x, data: %02x\n", offset, data);
u8 high = (offset >> 8) & 0x40;
u8 bank = high | BIT(offset, 6, 6);
@@ -3033,7 +3034,7 @@ void nes_bmc_72in1_device::write_h(offs_t offset, u8 data)
void nes_bmc_76in1_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_76in1 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_76in1 write_h, offset: %04x, data: %02x\n", offset, data);
m_reg[offset & 0x01] = data;
u8 bank = m_reg[1] << 6 | (m_reg[0] & 0x80) >> 2 | (m_reg[0] & 0x1f);
@@ -3059,7 +3060,7 @@ void nes_bmc_76in1_device::write_h(offs_t offset, u8 data)
void nes_bmc_150in1_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_150in1 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_150in1 write_h, offset: %04x, data: %02x\n", offset, data);
u8 bank = BIT(offset, 1, 3);
u8 mode = (bank & 0x06) == 0x06;
@@ -3085,7 +3086,7 @@ void nes_bmc_150in1_device::write_h(offs_t offset, u8 data)
void nes_bmc_500in1_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("bmc500in1 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc500in1 write_h, offset: %04x, data: %02x\n", offset, data);
prg32(BIT(offset, 2, 3));
chr8(offset & 0x07, CHRROM);
}
@@ -3099,7 +3100,7 @@ void nes_bmc_500in1_device::write_h(offs_t offset, u8 data)
iNES: mapper 227
- In MESS: Preliminary Supported.
+ In MAME: Preliminary Supported.
-------------------------------------------------*/
@@ -3116,7 +3117,7 @@ void nes_bmc_1200in1_device::write_h(offs_t offset, uint8_t data)
{
int bank = ((offset >> 2) & 0x1f) | ((offset & 0x0100) >> 3);
- LOG_MMC(("bmc_1200in1 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_1200in1 write_h, offset: %04x, data: %02x\n", offset, data);
if (offset & 0x80)
{
@@ -3162,7 +3163,7 @@ void nes_bmc_1200in1_device::write_h(offs_t offset, uint8_t data)
void nes_bmc_gold260_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_gold260 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_gold260 write_h, offset: %04x, data: %02x\n", offset, data);
u8 bank = bitswap<8>(offset, 9, 8, 4, 3, 2, 1, 0, 12);
u8 mode = !BIT(offset, 11);
@@ -3214,7 +3215,7 @@ void nes_bmc_gold260_device::write_h(offs_t offset, u8 data)
void nes_bmc_42in1reset_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_42in1reset write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_42in1reset write_h, offset: %04x, data: %02x\n", offset, data);
u8 bank = m_latch | (data & 0x1f);
u8 mode = !BIT(data, 5);
@@ -3241,7 +3242,7 @@ void nes_bmc_42in1reset_device::write_h(offs_t offset, u8 data)
void nes_bmc_lc160_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_lc160 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_lc160 write_h, offset: %04x, data: %02x\n", offset, data);
if (offset >= 0x4000)
{
u8 bank = BIT(offset, 2, 6);
@@ -3287,14 +3288,14 @@ void nes_bmc_60311c_device::update_banks()
void nes_bmc_60311c_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_60311c write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_60311c write_m, offset: %04x, data: %02x\n", offset, data);
m_reg[offset & 1] = data & 0x7f;
update_banks();
}
void nes_bmc_60311c_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_60311c write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_60311c write_h, offset: %04x, data: %02x\n", offset, data);
m_reg[2] = data & 0x07;
update_banks();
}
@@ -3313,13 +3314,13 @@ void nes_bmc_60311c_device::write_h(offs_t offset, u8 data)
u8 nes_bmc_ctc12in1_device::read_m(offs_t offset)
{
- LOG_MMC(("bmc_ctc12in1 read_m, offset: %04x, data: %02x\n", offset));
+ LOG("bmc_ctc12in1 read_m, offset: %04x, data: %02x\n", offset);
return m_prg[0x01 * 0x2000 + offset]; // fixed to bank 1
}
void nes_bmc_ctc12in1_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_ctc12in1 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_ctc12in1 write_h, offset: %04x, data: %02x\n", offset, data);
m_reg[BIT(offset, 14)] = data;
u8 bank = (m_reg[0] & 0x18) | (m_reg[1] & 0x07);
@@ -3364,7 +3365,7 @@ void nes_bmc_ctc12in1_device::write_h(offs_t offset, u8 data)
void nes_bmc_891227_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_891227 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_891227 write_h, offset: %04x, data: %02x\n", offset, data);
if (offset < 0x4000)
data = bitswap<8>(data, 6, 5, 7, 4, 3, 2, 1, 0);
@@ -3399,7 +3400,7 @@ void nes_bmc_891227_device::write_h(offs_t offset, u8 data)
u8 nes_bmc_fam250_device::read_m(offs_t offset)
{
-// LOG_MMC(("fam250 read_m, offset: %04x\n", offset));
+ LOGMASKED(LOG_HIFREQ, "fam250 read_m, offset: %04x\n", offset);
if (m_latch == 5) // only the Bubble Bobble FDS bootleg uses this
return m_prg[(((m_reg & 0x1f) << 1 | BIT(m_reg, 7)) * 0x2000 + offset) & (m_prg_size - 1)];
@@ -3409,7 +3410,7 @@ u8 nes_bmc_fam250_device::read_m(offs_t offset)
void nes_bmc_fam250_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("fam250 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("fam250 write_h, offset: %04x, data: %02x\n", offset, data);
if (offset >= 0x7000)
{
@@ -3442,7 +3443,7 @@ void nes_bmc_fam250_device::write_h(offs_t offset, u8 data)
void nes_bmc_k1029_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_k1029 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_k1029 write_h, offset: %04x, data: %02x\n", offset, data);
u8 bank = data & 0x3f;
switch (offset & 3)
@@ -3492,7 +3493,7 @@ void nes_bmc_k1029_device::write_h(offs_t offset, u8 data)
void nes_n625092_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("n625092 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("n625092 write_h, offset: %04x, data: %02x\n", offset, data);
m_latch[BIT(offset, 14)] = offset;
@@ -3527,7 +3528,7 @@ void nes_n625092_device::write_h(offs_t offset, u8 data)
void nes_bmc_th22913_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_th22913 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_th22913 write_h, offset: %04x, data: %02x\n", offset, data);
u8 bank = offset >> 2;
u8 mode = BIT(offset, 1);
diff --git a/src/devices/bus/nes/namcot.cpp b/src/devices/bus/nes/namcot.cpp
index 31f72761751..67d321fc137 100644
--- a/src/devices/bus/nes/namcot.cpp
+++ b/src/devices/bus/nes/namcot.cpp
@@ -28,12 +28,11 @@
#include "speaker.h"
#ifdef NES_PCB_DEBUG
-#define VERBOSE 1
+#define VERBOSE (LOG_GENERAL)
#else
-#define VERBOSE 0
+#define VERBOSE (0)
#endif
-
-#define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0)
+#include "logmacro.h"
//-------------------------------------------------
@@ -261,7 +260,7 @@ void nes_namcot163_device::pcb_reset()
void nes_namcot3433_device::dxrom_write(offs_t offset, uint8_t data)
{
- LOG_MMC(("dxrom_write, offset: %04x, data: %02x\n", offset, data));
+ LOG("dxrom_write, offset: %04x, data: %02x\n", offset, data);
if (!(offset & 1) && m_pcb_ctrl_mirror)
set_nt_mirroring(BIT(data, 6) ? PPU_MIRROR_HIGH : PPU_MIRROR_LOW);
@@ -304,7 +303,7 @@ void nes_namcot3433_device::dxrom_write(offs_t offset, uint8_t data)
void nes_namcot3446_device::write_h(offs_t offset, uint8_t data)
{
- LOG_MMC(("namcot3446 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("namcot3446 write_h, offset: %04x, data: %02x\n", offset, data);
if (offset >= 0x2000)
return;
@@ -341,7 +340,7 @@ void nes_namcot3446_device::write_h(offs_t offset, uint8_t data)
void nes_namcot3425_device::write_h(offs_t offset, uint8_t data)
{
uint8_t mode;
- LOG_MMC(("namcot3425 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("namcot3425 write_h, offset: %04x, data: %02x\n", offset, data);
if (offset >= 0x2000)
return;
@@ -393,7 +392,7 @@ void nes_namcot3425_device::write_h(offs_t offset, uint8_t data)
iNES: mapper 210
- In MESS: Supported
+ In MAME: Supported
-------------------------------------------------*/
@@ -410,7 +409,7 @@ TIMER_CALLBACK_MEMBER(nes_namcot340_device::irq_timer_tick)
void nes_namcot340_device::n340_lowrite(offs_t offset, uint8_t data)
{
- LOG_MMC(("n340_lowrite, offset: %04x, data: %02x\n", offset, data));
+ LOG("n340_lowrite, offset: %04x, data: %02x\n", offset, data);
offset += 0x100;
switch (offset & 0x1800)
@@ -429,7 +428,7 @@ void nes_namcot340_device::n340_lowrite(offs_t offset, uint8_t data)
uint8_t nes_namcot340_device::n340_loread(offs_t offset)
{
- LOG_MMC(("n340_loread, offset: %04x\n", offset));
+ LOG("n340_loread, offset: %04x\n", offset);
offset += 0x100;
switch (offset & 0x1800)
@@ -449,7 +448,7 @@ uint8_t nes_namcot340_device::n340_loread(offs_t offset)
void nes_namcot340_device::n340_hiwrite(offs_t offset, uint8_t data)
{
- LOG_MMC(("n340_hiwrite, offset: %04x, data: %02x\n", offset, data));
+ LOG("n340_hiwrite, offset: %04x, data: %02x\n", offset, data);
switch (offset & 0x7800)
{
@@ -504,7 +503,7 @@ void nes_namcot340_device::n340_hiwrite(offs_t offset, uint8_t data)
iNES: mapper 210
- In MESS: Supported
+ In MAME: Supported
-------------------------------------------------*/
@@ -528,7 +527,7 @@ void nes_namcot175_device::write_m(offs_t offset, uint8_t data)
void nes_namcot175_device::write_h(offs_t offset, uint8_t data)
{
- LOG_MMC(("namcot175 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("namcot175 write_h, offset: %04x, data: %02x\n", offset, data);
switch (offset & 0x7800)
{
@@ -557,7 +556,7 @@ void nes_namcot175_device::write_h(offs_t offset, uint8_t data)
iNES: mapper 19
- In MESS: Supported
+ In MAME: Supported
-------------------------------------------------*/
@@ -609,7 +608,7 @@ void nes_namcot163_device::write_m(offs_t offset, uint8_t data)
void nes_namcot163_device::write_l(offs_t offset, uint8_t data)
{
- LOG_MMC(("namcot163 write_l, offset: %04x, data: %02x\n", offset, data));
+ LOG("namcot163 write_l, offset: %04x, data: %02x\n", offset, data);
offset += 0x100;
switch (offset & 0x1800)
@@ -625,7 +624,7 @@ void nes_namcot163_device::write_l(offs_t offset, uint8_t data)
uint8_t nes_namcot163_device::read_l(offs_t offset)
{
- LOG_MMC(("namcot163 read_l, offset: %04x\n", offset));
+ LOG("namcot163 read_l, offset: %04x\n", offset);
offset += 0x100;
switch (offset & 0x1800)
@@ -647,7 +646,7 @@ void nes_namcot163_device::set_mirror(uint8_t page, uint8_t data)
void nes_namcot163_device::write_h(offs_t offset, uint8_t data)
{
- LOG_MMC(("namcot163 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("namcot163 write_h, offset: %04x, data: %02x\n", offset, data);
switch (offset & 0x7800)
{
diff --git a/src/devices/bus/nes/nanjing.cpp b/src/devices/bus/nes/nanjing.cpp
index 6a451b3c59d..d23eed28b53 100644
--- a/src/devices/bus/nes/nanjing.cpp
+++ b/src/devices/bus/nes/nanjing.cpp
@@ -18,12 +18,11 @@
#ifdef NES_PCB_DEBUG
-#define VERBOSE 1
+#define VERBOSE (LOG_GENERAL)
#else
-#define VERBOSE 0
+#define VERBOSE (0)
#endif
-
-#define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0)
+#include "logmacro.h"
//-------------------------------------------------
@@ -87,7 +86,7 @@ void nes_nanjing_device::pcb_reset()
iNES: mapper 163
- In MESS: Unsupported.
+ In MAME: Unsupported.
-------------------------------------------------*/
@@ -112,7 +111,7 @@ void nes_nanjing_device::hblank_irq(int scanline, bool vblank, bool blanked)
void nes_nanjing_device::write_l(offs_t offset, uint8_t data)
{
- LOG_MMC(("nanjing write_l, offset: %04x, data: %02x\n", offset, data));
+ LOG("nanjing write_l, offset: %04x, data: %02x\n", offset, data);
offset += 0x100;
@@ -156,7 +155,7 @@ void nes_nanjing_device::write_l(offs_t offset, uint8_t data)
uint8_t nes_nanjing_device::read_l(offs_t offset)
{
uint8_t value = 0;
- LOG_MMC(("nanjing read_l, offset: %04x\n", offset));
+ LOG("nanjing read_l, offset: %04x\n", offset);
offset += 0x100;
diff --git a/src/devices/bus/nes/nes_ines.hxx b/src/devices/bus/nes/nes_ines.hxx
index 69b01ed120a..95f35e14735 100644
--- a/src/devices/bus/nes/nes_ines.hxx
+++ b/src/devices/bus/nes/nes_ines.hxx
@@ -1104,9 +1104,9 @@ void nes_cart_slot_device::call_load_ines()
// SETUP step 5: allocate pointers for PRG/VROM
if (prg_size)
- m_cart->prg_alloc(prg_size, tag());
+ m_cart->prg_alloc(prg_size);
if (vrom_size)
- m_cart->vrom_alloc(vrom_size, tag());
+ m_cart->vrom_alloc(vrom_size);
// if there is a trainer, skip it for the moment
if (m_cart->get_trainer())
diff --git a/src/devices/bus/nes/nes_pcb.hxx b/src/devices/bus/nes/nes_pcb.hxx
index 600809c121d..d9b63863b04 100644
--- a/src/devices/bus/nes/nes_pcb.hxx
+++ b/src/devices/bus/nes/nes_pcb.hxx
@@ -752,11 +752,11 @@ void nes_cart_slot_device::call_load_pcb()
logerror("-- PRG WRAM: %d\n", prgram_size);
// SETUP steps 5/6: allocate pointers for PRG/VROM and load the data!
- m_cart->prg_alloc(prg_size, tag());
+ m_cart->prg_alloc(prg_size);
memcpy(m_cart->get_prg_base(), get_software_region("prg"), prg_size);
if (vrom_size)
{
- m_cart->vrom_alloc(vrom_size, tag());
+ m_cart->vrom_alloc(vrom_size);
memcpy(m_cart->get_vrom_base(), get_software_region("chr"), vrom_size);
}
@@ -766,7 +766,7 @@ void nes_cart_slot_device::call_load_pcb()
uint32_t dpcm_size = get_software_region_length("dpcm");
if (dpcm_size)
{
- m_cart->misc_rom_alloc(dpcm_size, tag());
+ m_cart->misc_rom_alloc(dpcm_size);
memcpy(m_cart->get_misc_rom_base(), get_software_region("dpcm"), dpcm_size);
}
}
diff --git a/src/devices/bus/nes/nes_slot.cpp b/src/devices/bus/nes/nes_slot.cpp
index 5e9365d97ea..d7df07d7693 100644
--- a/src/devices/bus/nes/nes_slot.cpp
+++ b/src/devices/bus/nes/nes_slot.cpp
@@ -158,11 +158,11 @@ device_nes_cart_interface::~device_nes_cart_interface()
// pointer allocators
//-------------------------------------------------
-void device_nes_cart_interface::prg_alloc(size_t size, const char *tag)
+void device_nes_cart_interface::prg_alloc(size_t size)
{
if (m_prg == nullptr)
{
- m_prg = device().machine().memory().region_alloc(std::string(tag).append(NESSLOT_PRGROM_REGION_TAG).c_str(), size, 1, ENDIANNESS_LITTLE)->base();
+ m_prg = device().machine().memory().region_alloc(device().subtag("^cart:prg_rom"), size, 1, ENDIANNESS_LITTLE)->base();
m_prg_size = size;
m_prg_chunks = size / 0x4000;
if (size % 0x2000)
@@ -223,25 +223,21 @@ void device_nes_cart_interface::prg_alloc(size_t size, const char *tag)
}
}
-void device_nes_cart_interface::vrom_alloc(size_t size, const char *tag)
+void device_nes_cart_interface::vrom_alloc(size_t size)
{
if (m_vrom == nullptr)
{
- std::string tempstring(tag);
- tempstring.append(NESSLOT_CHRROM_REGION_TAG);
- m_vrom = device().machine().memory().region_alloc(tempstring.c_str(), size, 1, ENDIANNESS_LITTLE)->base();
+ m_vrom = device().machine().memory().region_alloc(device().subtag("^cart:chr_rom"), size, 1, ENDIANNESS_LITTLE)->base();
m_vrom_size = size;
m_vrom_chunks = size / 0x2000;
}
}
-void device_nes_cart_interface::misc_rom_alloc(size_t size, const char *tag)
+void device_nes_cart_interface::misc_rom_alloc(size_t size)
{
if (m_misc_rom == nullptr)
{
- std::string tempstring(tag);
- tempstring.append(NESSLOT_MISC_ROM_REGION_TAG);
- m_misc_rom = device().machine().memory().region_alloc(tempstring.c_str(), size, 1, ENDIANNESS_LITTLE)->base();
+ m_misc_rom = device().machine().memory().region_alloc(device().subtag("^cart:misc_rom"), size, 1, ENDIANNESS_LITTLE)->base();
m_misc_rom_size = size;
}
}
@@ -471,7 +467,7 @@ void device_nes_cart_interface::set_nt_mirroring(int mirroring)
// Interrupt helpers
//-------------------------------------------------
-DECLARE_WRITE_LINE_MEMBER(device_nes_cart_interface::set_irq_line)
+void device_nes_cart_interface::set_irq_line(int state)
{
assert(state == ASSERT_LINE || state == CLEAR_LINE);
@@ -729,7 +725,7 @@ void nes_cart_slot_device::pcb_reset()
#include "nes_ines.hxx"
-image_init_result nes_cart_slot_device::call_load()
+std::pair<std::error_condition, std::string> nes_cart_slot_device::call_load()
{
if (m_cart)
{
@@ -744,35 +740,27 @@ image_init_result nes_cart_slot_device::call_load()
if ((magic[0] == 'N') && (magic[1] == 'E') && (magic[2] == 'S')) // If header starts with 'NES' it is iNES
{
if (length() <= 0x10)
- {
- logerror("%s only contains the iNES header and no data.\n", filename());
- return image_init_result::FAIL;
- }
+ return std::make_pair(image_error::INVALIDLENGTH, "File contains iNES header with no data");
call_load_ines();
}
else if ((magic[0] == 'U') && (magic[1] == 'N') && (magic[2] == 'I') && (magic[3] == 'F')) // If header starts with 'UNIF' it is UNIF
{
if (length() <= 0x20)
- {
- logerror("%s only contains the UNIF header and no data.\n", filename());
- return image_init_result::FAIL;
- }
+ return std::make_pair(image_error::INVALIDLENGTH, "File contains UNIF header with no data");
call_load_unif();
}
else
{
- logerror("%s is NOT a file in either iNES or UNIF format.\n", filename());
- seterror(image_error::INVALIDIMAGE, "File is neither iNES or UNIF format");
- return image_init_result::FAIL;
+ return std::make_pair(image_error::INVALIDIMAGE, "File is not an iNES or UNIF cartridge image");
}
}
else
call_load_pcb();
}
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
@@ -811,8 +799,7 @@ std::string nes_cart_slot_device::get_default_card_software(get_default_card_sof
hook.image_file()->length(len); // FIXME: check error return, guard against excessively large files
std::vector<uint8_t> rom(len);
- size_t actual;
- hook.image_file()->read(&rom[0], len, actual); // FIXME: check error return or read returning short
+ read(*hook.image_file(), &rom[0], len); // FIXME: check error return or read returning short
const char *slot_string = "nrom";
if ((rom[0] == 'N') && (rom[1] == 'E') && (rom[2] == 'S'))
diff --git a/src/devices/bus/nes/nes_slot.h b/src/devices/bus/nes/nes_slot.h
index 932bff1d41d..ca2d884c226 100644
--- a/src/devices/bus/nes/nes_slot.h
+++ b/src/devices/bus/nes/nes_slot.h
@@ -205,9 +205,9 @@ public:
// hack until disk system is made modern!
virtual void disk_flip_side() { }
- void prg_alloc(size_t size, const char *tag);
- void vrom_alloc(size_t size, const char *tag);
- void misc_rom_alloc(size_t size, const char *tag);
+ void prg_alloc(size_t size);
+ void vrom_alloc(size_t size);
+ void misc_rom_alloc(size_t size);
void prgram_alloc(size_t size);
void vram_alloc(size_t size);
void battery_alloc(size_t size);
@@ -265,7 +265,7 @@ public:
protected:
device_nes_cart_interface(const machine_config &mconfig, device_t &device);
- DECLARE_WRITE_LINE_MEMBER(set_irq_line);
+ void set_irq_line(int state);
// internal state
uint8_t *m_prg;
@@ -398,8 +398,8 @@ public:
nes_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual ~nes_cart_slot_device();
- // image-level overrides
- virtual image_init_result call_load() override;
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
virtual void call_unload() override;
virtual bool is_reset_on_load() const noexcept override { return true; }
@@ -407,7 +407,7 @@ public:
virtual const char *file_extensions() const noexcept override { return "nes,unf,unif"; }
virtual u32 unhashed_header_length() const noexcept override { return 16; }
- // slot interface overrides
+ // device_slot_interface implementation
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
// reading and writing
@@ -438,7 +438,7 @@ public:
int m_pcb_id;
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
const char * get_default_card_ines(get_default_card_software_hook &hook, const uint8_t *ROM, uint32_t len) const;
@@ -454,13 +454,4 @@ protected:
// device type definition
DECLARE_DEVICE_TYPE(NES_CART_SLOT, nes_cart_slot_device)
-
-/***************************************************************************
- DEVICE CONFIGURATION MACROS
- ***************************************************************************/
-
-#define NESSLOT_PRGROM_REGION_TAG ":cart:prg_rom"
-#define NESSLOT_CHRROM_REGION_TAG ":cart:chr_rom"
-#define NESSLOT_MISC_ROM_REGION_TAG ":cart:misc_rom"
-
#endif // MAME_BUS_NES_NES_SLOT_H
diff --git a/src/devices/bus/nes/nes_unif.hxx b/src/devices/bus/nes/nes_unif.hxx
index 8c153e869a2..b4955cd9b8d 100644
--- a/src/devices/bus/nes/nes_unif.hxx
+++ b/src/devices/bus/nes/nes_unif.hxx
@@ -12,6 +12,7 @@
****************************************************************************************/
#include "corestr.h"
+#include "multibyte.h"
/* Set to generate prg & chr files when the cart is loaded */
#define SPLIT_PRG 0
@@ -220,7 +221,7 @@ void nes_cart_slot_device::call_load_unif()
fseek(4, SEEK_SET);
fread(&buffer, 4);
- unif_ver = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24);
+ unif_ver = get_u32le(buffer);
logerror("Loaded game in UNIF format, version %d\n", unif_ver);
do
@@ -241,7 +242,7 @@ void nes_cart_slot_device::call_load_unif()
mapr_chunk_found = true;
logerror("[MAPR] chunk found: ");
fread(&buffer, 4);
- chunk_length = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24);
+ chunk_length = get_u32le(buffer);
if (chunk_length <= 0x20)
fread(&unif_mapr, chunk_length);
@@ -255,7 +256,7 @@ void nes_cart_slot_device::call_load_unif()
{
logerror("Skip this chunk. We need a [MAPR] chunk before anything else.\n");
fread(&buffer, 4);
- chunk_length = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24);
+ chunk_length = get_u32le(buffer);
read_length += (chunk_length + 8);
}
@@ -269,7 +270,7 @@ void nes_cart_slot_device::call_load_unif()
/* TO DO: it would be nice to check if more than one MAPR chunk is present */
logerror("[MAPR] chunk found (in the 2nd run). Already loaded.\n");
fread(&buffer, 4);
- chunk_length = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24);
+ chunk_length = get_u32le(buffer);
read_length += (chunk_length + 8);
}
@@ -277,7 +278,7 @@ void nes_cart_slot_device::call_load_unif()
{
logerror("[READ] chunk found. No support yet.\n");
fread(&buffer, 4);
- chunk_length = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24);
+ chunk_length = get_u32le(buffer);
read_length += (chunk_length + 8);
}
@@ -285,7 +286,7 @@ void nes_cart_slot_device::call_load_unif()
{
logerror("[NAME] chunk found. No support yet.\n");
fread(&buffer, 4);
- chunk_length = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24);
+ chunk_length = get_u32le(buffer);
read_length += (chunk_length + 8);
}
@@ -293,7 +294,7 @@ void nes_cart_slot_device::call_load_unif()
{
logerror("[WRTR] chunk found. No support yet.\n");
fread(&buffer, 4);
- chunk_length = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24);
+ chunk_length = get_u32le(buffer);
read_length += (chunk_length + 8);
}
@@ -301,7 +302,7 @@ void nes_cart_slot_device::call_load_unif()
{
logerror("[TVCI] chunk found.\n");
fread(&buffer, 4);
- chunk_length = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24);
+ chunk_length = get_u32le(buffer);
fread(&temp_byte, 1);
logerror("Television Standard : %s\n", (temp_byte == 0) ? "NTSC" : (temp_byte == 1) ? "PAL" : "Does not matter");
@@ -312,7 +313,7 @@ void nes_cart_slot_device::call_load_unif()
{
logerror("[TVSC] chunk found. No support yet.\n");
fread(&buffer, 4);
- chunk_length = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24);
+ chunk_length = get_u32le(buffer);
read_length += (chunk_length + 8);
}
@@ -320,7 +321,7 @@ void nes_cart_slot_device::call_load_unif()
{
logerror("[DINF] chunk found. No support yet.\n");
fread(&buffer, 4);
- chunk_length = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24);
+ chunk_length = get_u32le(buffer);
read_length += (chunk_length + 8);
}
@@ -328,7 +329,7 @@ void nes_cart_slot_device::call_load_unif()
{
logerror("[CTRL] chunk found. No support yet.\n");
fread(&buffer, 4);
- chunk_length = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24);
+ chunk_length = get_u32le(buffer);
read_length += (chunk_length + 8);
}
@@ -336,7 +337,7 @@ void nes_cart_slot_device::call_load_unif()
{
logerror("[BATR] chunk found. No support yet.\n");
fread(&buffer, 4);
- chunk_length = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24);
+ chunk_length = get_u32le(buffer);
read_length += (chunk_length + 8);
}
@@ -344,7 +345,7 @@ void nes_cart_slot_device::call_load_unif()
{
logerror("[VROR] chunk found. No support yet.\n");
fread(&buffer, 4);
- chunk_length = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24);
+ chunk_length = get_u32le(buffer);
read_length += (chunk_length + 8);
}
@@ -352,7 +353,7 @@ void nes_cart_slot_device::call_load_unif()
{
logerror("[MIRR] chunk found.\n");
fread(&buffer, 4);
- chunk_length = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24);
+ chunk_length = get_u32le(buffer);
fread(&mirror, 1);
@@ -362,7 +363,7 @@ void nes_cart_slot_device::call_load_unif()
{
logerror("[PCK%c] chunk found. No support yet.\n", magic2[3]);
fread(&buffer, 4);
- chunk_length = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24);
+ chunk_length = get_u32le(buffer);
read_length += (chunk_length + 8);
}
@@ -370,7 +371,7 @@ void nes_cart_slot_device::call_load_unif()
{
logerror("[CCK%c] chunk found. No support yet.\n", magic2[3]);
fread(&buffer, 4);
- chunk_length = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24);
+ chunk_length = get_u32le(buffer);
read_length += (chunk_length + 8);
}
@@ -378,7 +379,7 @@ void nes_cart_slot_device::call_load_unif()
{
logerror("[PRG%c] chunk found. ", magic2[3]);
fread(&buffer, 4);
- chunk_length = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24);
+ chunk_length = get_u32le(buffer);
prg_size += chunk_length;
if (chunk_length / 0x4000)
@@ -399,7 +400,7 @@ void nes_cart_slot_device::call_load_unif()
{
logerror("[CHR%c] chunk found. ", magic2[3]);
fread(&buffer, 4);
- chunk_length = buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24);
+ chunk_length = get_u32le(buffer);
vrom_size += chunk_length;
logerror("It consists of %d 8K-blocks.\n", chunk_length / 0x2000);
@@ -479,13 +480,13 @@ void nes_cart_slot_device::call_load_unif()
// SETUP steps 5/6: allocate pointers for PRG/VROM and load the data!
if (prg_size == 0x4000)
{
- m_cart->prg_alloc(0x8000, tag());
+ m_cart->prg_alloc(0x8000);
memcpy(m_cart->get_prg_base(), &temp_prg[0], 0x4000);
memcpy(m_cart->get_prg_base() + 0x4000, m_cart->get_prg_base(), 0x4000);
}
else
{
- m_cart->prg_alloc(prg_size, tag());
+ m_cart->prg_alloc(prg_size);
memcpy(m_cart->get_prg_base(), &temp_prg[0], prg_size);
}
@@ -494,20 +495,17 @@ void nes_cart_slot_device::call_load_unif()
if (vrom_size)
{
- m_cart->vrom_alloc(vrom_size, tag());
+ m_cart->vrom_alloc(vrom_size);
memcpy(m_cart->get_vrom_base(), &temp_chr[0], vrom_size);
}
#if SPLIT_PRG
{
- FILE *prgout;
- char outname[255];
-
- sprintf(outname, "%s.prg", filename());
- prgout = fopen(outname, "wb");
+ auto outname = std::string(filename()) + ".prg";
+ auto prgout = fopen(outname.c_str(), "wb");
if (prgout)
{
- fwrite(m_cart->get_prg_base(), 1, 0x4000 * m_cart->get_prg_size(), prgout);
+ ::fwrite(m_cart->get_prg_base(), 1, 0x4000 * m_cart->get_prg_size(), prgout);
osd_printf_error("Created PRG chunk\n");
}
@@ -518,19 +516,18 @@ void nes_cart_slot_device::call_load_unif()
#if SPLIT_CHR
if (state->m_chr_chunks > 0)
{
- FILE *chrout;
- char outname[255];
-
- sprintf(outname, "%s.chr", filename());
- chrout= fopen(outname, "wb");
+ auto outname = std::string(filename()) + ".chr";
+ auto chrout = fopen(outname.c_str(), "wb");
if (chrout)
{
- fwrite(m_cart->get_vrom_base(), 1, m_cart->get_vrom_size(), chrout);
+ ::fwrite(m_cart->get_vrom_base(), 1, m_cart->get_vrom_size(), chrout);
osd_printf_error("Created CHR chunk\n");
}
+
fclose(chrout);
}
#endif
+
// SETUP steps 7: allocate the remaining pointer, when needed
if (vram_size)
m_cart->vram_alloc(vram_size);
@@ -566,7 +563,7 @@ const char * nes_cart_slot_device::get_default_card_unif(const uint8_t *ROM, uin
{
if ((ROM[read_length + 0] == 'M') && (ROM[read_length + 1] == 'A') && (ROM[read_length + 2] == 'P') && (ROM[read_length + 3] == 'R'))
{
- chunk_length = ROM[read_length + 4] | (ROM[read_length + 5] << 8) | (ROM[read_length + 6] << 16) | (ROM[read_length + 7] << 24);
+ chunk_length = get_u32le(&ROM[read_length + 4]);
if (chunk_length <= 0x20)
memcpy(unif_mapr, ROM + read_length + 8, chunk_length);
@@ -575,7 +572,7 @@ const char * nes_cart_slot_device::get_default_card_unif(const uint8_t *ROM, uin
}
else
{
- chunk_length = ROM[read_length + 4] | (ROM[read_length + 5] << 8) | (ROM[read_length + 6] << 16) | (ROM[read_length + 7] << 24);
+ chunk_length = get_u32le(&ROM[read_length + 4]);
read_length += (chunk_length + 8);
}
} while (len > read_length);
diff --git a/src/devices/bus/nes/ntdec.cpp b/src/devices/bus/nes/ntdec.cpp
index fd207f20a00..5e95c380ffb 100644
--- a/src/devices/bus/nes/ntdec.cpp
+++ b/src/devices/bus/nes/ntdec.cpp
@@ -23,12 +23,11 @@
#ifdef NES_PCB_DEBUG
-#define VERBOSE 1
+#define VERBOSE (LOG_GENERAL)
#else
-#define VERBOSE 0
+#define VERBOSE (0)
#endif
-
-#define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0)
+#include "logmacro.h"
//-------------------------------------------------
@@ -117,7 +116,7 @@ void nes_ntdec_n715021_device::pcb_reset()
void nes_ntdec_asder_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("ntdec_asder write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("ntdec_asder write_h, offset: %04x, data: %02x\n", offset, data);
switch (offset & 0x6001) // writes only at even addresses?
{
@@ -166,7 +165,7 @@ void nes_ntdec_asder_device::write_h(offs_t offset, u8 data)
void nes_ntdec_fh_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("ntdec_fh write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("ntdec_fh write_m, offset: %04x, data: %02x\n", offset, data);
switch (offset & 0x07)
{
@@ -205,7 +204,7 @@ void nes_ntdec_fh_device::write_m(offs_t offset, u8 data)
void nes_ntdec_n715021_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("ntdec_n715021 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("ntdec_n715021 write_h, offset: %04x, data: %02x\n", offset, data);
prg16_89ab(BIT(offset, 2, 2));
chr8(offset & 0x03, CHRROM);
}
diff --git a/src/devices/bus/nes/nxrom.cpp b/src/devices/bus/nes/nxrom.cpp
index 9f2e35aa0ed..ae377894131 100644
--- a/src/devices/bus/nes/nxrom.cpp
+++ b/src/devices/bus/nes/nxrom.cpp
@@ -31,12 +31,11 @@
#include "nxrom.h"
#ifdef NES_PCB_DEBUG
-#define VERBOSE 1
+#define VERBOSE (LOG_GENERAL)
#else
-#define VERBOSE 0
+#define VERBOSE (0)
#endif
-
-#define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0)
+#include "logmacro.h"
//-------------------------------------------------
@@ -221,7 +220,7 @@ void nes_nochr_device::pcb_reset()
iNES: mapper 0
- In MESS: Supported, no need of specific handlers or IRQ
+ In MAME: Supported, no need of specific handlers or IRQ
-------------------------------------------------*/
@@ -233,13 +232,13 @@ void nes_nochr_device::pcb_reset()
This is an homebrew extension to map linearly 46KB
or PRG in boards with no PRG bankswitch logic
- In MESS: Supported
+ In MAME: Supported
-------------------------------------------------*/
uint8_t nes_nrom368_device::read_l(offs_t offset)
{
- LOG_MMC(("nrom368 read_l, offset: %04x\n", offset));
+ LOG("nrom368 read_l, offset: %04x\n", offset);
offset += 0x100;
if (offset >= 0x800)
return m_prg[offset - 0x800];
@@ -249,13 +248,13 @@ uint8_t nes_nrom368_device::read_l(offs_t offset)
uint8_t nes_nrom368_device::read_m(offs_t offset)
{
- LOG_MMC(("nrom368 read_m, offset: %04x\n", offset));
+ LOG("nrom368 read_m, offset: %04x\n", offset);
return m_prg[0x1800 + (offset & 0x1fff)];
}
uint8_t nes_nrom368_device::read_h(offs_t offset)
{
- LOG_MMC(("nrom368 read_h, offset: %04x\n", offset));
+ LOG("nrom368 read_h, offset: %04x\n", offset);
return m_prg[0x3800 + (offset & 0x7fff)];
}
@@ -276,13 +275,13 @@ uint8_t nes_nrom368_device::read_h(offs_t offset)
iNES: mapper 7
- In MESS: Supported
+ In MAME: Supported
-------------------------------------------------*/
void nes_axrom_device::write_h(offs_t offset, uint8_t data)
{
- LOG_MMC(("axrom write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("axrom write_h, offset: %04x, data: %02x\n", offset, data);
// this pcb is subject to bus conflict
data = account_bus_conflict(offset, data);
@@ -305,7 +304,7 @@ void nes_bxrom_device::write_h(offs_t offset, uint8_t data)
{
/* This portion of the mapper is nearly identical to Mapper 7, except no one-screen mirroring */
/* Deadly Towers is really a BxROM game - the demo screens look wrong using mapper 7. */
- LOG_MMC(("bxrom write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bxrom write_h, offset: %04x, data: %02x\n", offset, data);
// this pcb is subject to bus conflict, but the same is not true for some pirate variants
data = account_bus_conflict(offset, data);
@@ -331,15 +330,15 @@ void nes_bxrom_device::write_h(offs_t offset, uint8_t data)
Notice that BANDAI_PT554 board (Aerobics Studio) uses very
similar hardware but with an additional sound chip which
- gets writes to 0x6000 (currently unemulated in MESS)
+ gets writes to 0x6000 (currently unemulated in MAME)
- In MESS: Supported
+ In MAME: Supported
-------------------------------------------------*/
void nes_cnrom_device::write_h(offs_t offset, uint8_t data)
{
- LOG_MMC(("cxrom write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("cxrom write_h, offset: %04x, data: %02x\n", offset, data);
// this pcb is subject to bus conflict, but the same is not true for some pirate variants
data = account_bus_conflict(offset, data);
@@ -381,13 +380,13 @@ uint8_t nes_cnrom_device::chr_r(offs_t offset)
iNES: mapper 13
- In MESS: Supported
+ In MAME: Supported
-------------------------------------------------*/
void nes_cprom_device::write_h(offs_t offset, uint8_t data)
{
- LOG_MMC(("cprom write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("cprom write_h, offset: %04x, data: %02x\n", offset, data);
// this pcb is subject to bus conflict
data = account_bus_conflict(offset, data);
@@ -408,7 +407,7 @@ void nes_cprom_device::write_h(offs_t offset, uint8_t data)
void nes_gxrom_device::write_h(offs_t offset, uint8_t data)
{
- LOG_MMC(("gxrom write_h, offset %04x, data: %02x\n", offset, data));
+ LOG("gxrom write_h, offset %04x, data: %02x\n", offset, data);
// this pcb is subject to bus conflict
data = account_bus_conflict(offset, data);
@@ -428,13 +427,13 @@ void nes_gxrom_device::write_h(offs_t offset, uint8_t data)
iNES: mapper 2
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
void nes_uxrom_device::write_h(offs_t offset, uint8_t data)
{
- LOG_MMC(("uxrom write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("uxrom write_h, offset: %04x, data: %02x\n", offset, data);
// this pcb is subject to bus conflict
data = account_bus_conflict(offset, data);
@@ -454,13 +453,13 @@ void nes_uxrom_device::write_h(offs_t offset, uint8_t data)
iNES: mapper 180
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
void nes_uxrom_cc_device::write_h(offs_t offset, uint8_t data)
{
- LOG_MMC(("uxrom_cc write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("uxrom_cc write_h, offset: %04x, data: %02x\n", offset, data);
prg16_cdef(data);
}
@@ -475,13 +474,13 @@ void nes_uxrom_cc_device::write_h(offs_t offset, uint8_t data)
iNES: mapper 94
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
void nes_un1rom_device::write_h(offs_t offset, uint8_t data)
{
- LOG_MMC(("un1rom write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("un1rom write_h, offset: %04x, data: %02x\n", offset, data);
// this pcb is subject to bus conflict
data = account_bus_conflict(offset, data);
diff --git a/src/devices/bus/nes/pirate.cpp b/src/devices/bus/nes/pirate.cpp
index 81a06c7d655..44b7c8acf8d 100644
--- a/src/devices/bus/nes/pirate.cpp
+++ b/src/devices/bus/nes/pirate.cpp
@@ -21,12 +21,11 @@
#ifdef NES_PCB_DEBUG
-#define VERBOSE 1
+#define VERBOSE (LOG_GENERAL)
#else
-#define VERBOSE 0
+#define VERBOSE (0)
#endif
-
-#define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0)
+#include "logmacro.h"
//-------------------------------------------------
@@ -269,7 +268,7 @@ void nes_eh8813a_device::pcb_reset()
void nes_agci_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("agci write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("agci write_h, offset: %04x, data: %02x\n", offset, data);
// this pcb is subject to bus conflict
// bit 0 is always determined by the ROM value at the offset due to a resistor on the board
@@ -293,7 +292,7 @@ void nes_agci_device::write_h(offs_t offset, u8 data)
void nes_dreamtech_device::write_l(offs_t offset, u8 data)
{
- LOG_MMC(("dreamtech write_l, offset: %04x, data: %02x\n", offset, data));
+ LOG("dreamtech write_l, offset: %04x, data: %02x\n", offset, data);
offset += 0x100;
if (offset >= 0x1000)
@@ -314,7 +313,7 @@ void nes_dreamtech_device::write_l(offs_t offset, u8 data)
void nes_fukutake_device::write_l(offs_t offset, uint8_t data)
{
- LOG_MMC(("fukutake write_l, offset: %04x, data: %02x\n", offset, data));
+ LOG("fukutake write_l, offset: %04x, data: %02x\n", offset, data);
offset += 0x100;
if (offset >= 0x200 && offset < 0x400)
@@ -330,7 +329,7 @@ void nes_fukutake_device::write_l(offs_t offset, uint8_t data)
uint8_t nes_fukutake_device::read_l(offs_t offset)
{
- LOG_MMC(("fukutake read_l, offset: %04x\n", offset));
+ LOG("fukutake read_l, offset: %04x\n", offset);
offset += 0x100;
if (offset >= 0x200 && offset < 0x400)
@@ -350,13 +349,13 @@ uint8_t nes_fukutake_device::read_l(offs_t offset)
void nes_fukutake_device::write_m(offs_t offset, uint8_t data)
{
- LOG_MMC(("fukutake write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("fukutake write_m, offset: %04x, data: %02x\n", offset, data);
m_prgram[((m_latch * 0x2000) + offset) & (m_prgram.size() - 1)] = data;
}
uint8_t nes_fukutake_device::read_m(offs_t offset)
{
- LOG_MMC(("fukutake read_m, offset: %04x\n", offset));
+ LOG("fukutake read_m, offset: %04x\n", offset);
return m_prgram[((m_latch * 0x2000) + offset) & (m_prgram.size() - 1)];
}
@@ -387,7 +386,7 @@ void nes_futuremedia_device::hblank_irq(int scanline, bool vblank, bool blanked)
void nes_futuremedia_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("futuremedia write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("futuremedia write_h, offset: %04x, data: %02x\n", offset, data);
switch (offset)
{
@@ -443,7 +442,7 @@ void nes_futuremedia_device::write_h(offs_t offset, u8 data)
void nes_magseries_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("magseries write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("magseries write_h, offset: %04x, data: %02x\n", offset, data);
prg32(data >> 1);
chr8(data, CHRROM);
@@ -466,7 +465,7 @@ void nes_magseries_device::write_h(offs_t offset, u8 data)
void nes_daou306_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("daou306 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("daou306 write_h, offset: %04x, data: %02x\n", offset, data);
if (offset >= 0x4000 && offset < 0x4010)
{
@@ -495,7 +494,7 @@ void nes_daou306_device::write_h(offs_t offset, u8 data)
void nes_cc21_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("cc21 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("cc21 write_h, offset: %04x, data: %02x\n", offset, data);
set_nt_mirroring(BIT(offset, 0) ? PPU_MIRROR_HIGH : PPU_MIRROR_LOW);
chr4_0(BIT(offset, 0), CHRROM);
@@ -513,13 +512,13 @@ void nes_cc21_device::write_h(offs_t offset, u8 data)
iNES: mapper 176
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
void nes_xiaozy_device::write_l(offs_t offset, uint8_t data)
{
- LOG_MMC(("xiaozy write_l, offset: %04x, data: %02x\n", offset, data));
+ LOG("xiaozy write_l, offset: %04x, data: %02x\n", offset, data);
switch (offset)
{
@@ -540,7 +539,7 @@ void nes_xiaozy_device::write_l(offs_t offset, uint8_t data)
void nes_edu2k_device::write_h(offs_t offset, uint8_t data)
{
- LOG_MMC(("edu2k write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("edu2k write_h, offset: %04x, data: %02x\n", offset, data);
prg32(data & 0x1f);
m_latch = BIT(data, 6, 2);
@@ -548,13 +547,13 @@ void nes_edu2k_device::write_h(offs_t offset, uint8_t data)
void nes_edu2k_device::write_m(offs_t offset, uint8_t data)
{
- LOG_MMC(("edu2k write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("edu2k write_m, offset: %04x, data: %02x\n", offset, data);
m_prgram[((m_latch * 0x2000) + offset) & (m_prgram.size() - 1)] = data;
}
uint8_t nes_edu2k_device::read_m(offs_t offset)
{
- LOG_MMC(("edu2k read_m, offset: %04x\n", offset));
+ LOG("edu2k read_m, offset: %04x\n", offset);
return m_prgram[((m_latch * 0x2000) + offset) & (m_prgram.size() - 1)];
}
@@ -589,7 +588,7 @@ void nes_jy830623c_device::hblank_irq(int scanline, bool vblank, bool blanked)
if (m_irq_enable && !blanked && !m_irq_count && prior_count)
{
- LOG_MMC(("irq fired, scanline: %d\n", scanline));
+ LOG("irq fired, scanline: %d\n", scanline);
set_irq_line(ASSERT_LINE);
}
}
@@ -607,7 +606,7 @@ void nes_jy830623c_device::update_banks()
void nes_jy830623c_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("jy830623c write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("jy830623c write_m, offset: %04x, data: %02x\n", offset, data);
switch (offset & 0x1003)
{
@@ -634,7 +633,7 @@ void nes_jy830623c_device::write_m(offs_t offset, u8 data)
void nes_jy830623c_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("jy830623c write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("jy830623c write_h, offset: %04x, data: %02x\n", offset, data);
if (offset < 0x2000)
{
@@ -649,13 +648,13 @@ void nes_jy830623c_device::write_h(offs_t offset, u8 data)
Games: Gaau Hok Gwong Cheung
- In MESS: Preliminary Supported
+ In MAME: Preliminary Supported
-------------------------------------------------*/
void nes_43272_device::write_h(offs_t offset, uint8_t data)
{
- LOG_MMC(("unl_43272 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("unl_43272 write_h, offset: %04x, data: %02x\n", offset, data);
if ((m_latch & 0x81) == 0x81)
prg32(BIT(m_latch, 3, 3));
@@ -667,7 +666,7 @@ void nes_43272_device::write_h(offs_t offset, uint8_t data)
uint8_t nes_43272_device::read_h(offs_t offset)
{
uint8_t mask = (m_latch & 0x400) ? 0xfe : 0xff;
- LOG_MMC(("unl_43272 read_h, offset: %04x\n", offset));
+ LOG("unl_43272 read_h, offset: %04x\n", offset);
return hi_access_rom(offset & mask);
}
@@ -687,7 +686,7 @@ uint8_t nes_43272_device::read_h(offs_t offset)
void nes_eh8813a_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("unl_eh8813a write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("unl_eh8813a write_h, offset: %04x, data: %02x\n", offset, data);
if (!BIT(m_latch, 8))
{
@@ -707,7 +706,7 @@ void nes_eh8813a_device::write_h(offs_t offset, u8 data)
u8 nes_eh8813a_device::read_h(offs_t offset)
{
- LOG_MMC(("unl_eh8813a read_h, offset: %04x\n", offset));
+ LOG("unl_eh8813a read_h, offset: %04x\n", offset);
if (BIT(m_latch, 6))
offset = (offset & ~0x0f) | m_jumper; // TODO: jumper setting that controls which menu appears is 0 for now
@@ -742,7 +741,7 @@ void nes_fujiya_device::pcb_reset()
void nes_fujiya_device::write_m(offs_t offset, uint8_t data)
{
- LOG_MMC(("fujiya write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("fujiya write_m, offset: %04x, data: %02x\n", offset, data);
offset += 0x6000;
if (offset == 0x6502 || offset == 0x7000)
@@ -751,7 +750,7 @@ void nes_fujiya_device::write_m(offs_t offset, uint8_t data)
uint8_t nes_fujiya_device::read_m(offs_t offset)
{
- LOG_MMC(("fujiya read_m, offset: %04x\n", offset));
+ LOG("fujiya read_m, offset: %04x\n", offset);
offset += 0x6000;
if (offset == 0x7001 || offset == 0x7777)
diff --git a/src/devices/bus/nes/pt554.cpp b/src/devices/bus/nes/pt554.cpp
index 024da1655a5..fee133f6add 100644
--- a/src/devices/bus/nes/pt554.cpp
+++ b/src/devices/bus/nes/pt554.cpp
@@ -17,12 +17,11 @@
#ifdef NES_PCB_DEBUG
-#define VERBOSE 1
+#define VERBOSE (LOG_GENERAL)
#else
-#define VERBOSE 0
+#define VERBOSE (0)
#endif
-
-#define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0)
+#include "logmacro.h"
//-------------------------------------------------
@@ -58,7 +57,7 @@ nes_bandai_pt554_device::nes_bandai_pt554_device(const machine_config &mconfig,
void nes_bandai_pt554_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("Bandai PT-554 Sound write, data: %02x\n", data));
+ LOG("Bandai PT-554 Sound write, data: %02x\n", data);
// the actual chip starts speech synthesis when SYNC is held low >18µs
if (!BIT(data, 6))
diff --git a/src/devices/bus/nes/racermate.cpp b/src/devices/bus/nes/racermate.cpp
index 6ebc898721f..00524bd47da 100644
--- a/src/devices/bus/nes/racermate.cpp
+++ b/src/devices/bus/nes/racermate.cpp
@@ -20,12 +20,11 @@
#ifdef NES_PCB_DEBUG
-#define VERBOSE 1
+#define VERBOSE (LOG_GENERAL)
#else
-#define VERBOSE 0
+#define VERBOSE (0)
#endif
-
-#define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0)
+#include "logmacro.h"
//-------------------------------------------------
@@ -69,7 +68,7 @@ void nes_racermate_device::pcb_reset()
Board UNL-RACERMATE
- In MESS: *VERY* preliminary support. Also, it seems that this
+ In MAME: *VERY* preliminary support. Also, it seems that this
board saves to battery the CHRRAM!!!
-------------------------------------------------*/
@@ -82,7 +81,7 @@ void nes_racermate_device::update_banks()
void nes_racermate_device::write_h(offs_t offset, uint8_t data)
{
- LOG_MMC(("racermate write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("racermate write_h, offset: %04x, data: %02x\n", offset, data);
if (offset == 0x3000)
{
diff --git a/src/devices/bus/nes/rcm.cpp b/src/devices/bus/nes/rcm.cpp
index 4378d65c4df..73b78644170 100644
--- a/src/devices/bus/nes/rcm.cpp
+++ b/src/devices/bus/nes/rcm.cpp
@@ -21,14 +21,12 @@
#include "rcm.h"
-
#ifdef NES_PCB_DEBUG
-#define VERBOSE 1
+#define VERBOSE (LOG_GENERAL)
#else
-#define VERBOSE 0
+#define VERBOSE (0)
#endif
-
-#define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0)
+#include "logmacro.h"
//-------------------------------------------------
@@ -97,7 +95,7 @@ nes_3dblock_device::nes_3dblock_device(const machine_config &mconfig, const char
void nes_gs2015_device::write_h(offs_t offset, uint8_t data)
{
- LOG_MMC(("gs2015 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("gs2015 write_h, offset: %04x, data: %02x\n", offset, data);
prg32(offset);
chr8(offset >> 1, m_chr_source);
@@ -105,7 +103,7 @@ void nes_gs2015_device::write_h(offs_t offset, uint8_t data)
uint8_t nes_gs2015_device::read_m(offs_t offset)
{
- LOG_MMC(("gs2015 read_m, offset: %04x\n", offset));
+ LOG("gs2015 read_m, offset: %04x\n", offset);
return 0; // Videopoker Bonza needs this (sort of protection? or related to inputs?)
}
@@ -123,13 +121,13 @@ uint8_t nes_gs2015_device::read_m(offs_t offset)
u8 nes_gs2004_device::read_m(offs_t offset)
{
- LOG_MMC(("gs2004 read_m, offset: %04x\n", offset));
+ LOG("gs2004 read_m, offset: %04x\n", offset);
return m_prg[m_base + offset]; // fixed base differs per device
}
void nes_gs2004_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("gs2004 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("gs2004 write_h, offset: %04x, data: %02x\n", offset, data);
prg32(data);
}
@@ -147,7 +145,7 @@ void nes_gs2004_device::write_h(offs_t offset, u8 data)
void nes_tf9_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("tetrisfam write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("tetrisfam write_h, offset: %04x, data: %02x\n", offset, data);
u8 bank = (offset & 0x0f) << 1 | BIT(offset, 5);
u8 mode = !BIT(offset, 4);
diff --git a/src/devices/bus/nes/rexsoft.cpp b/src/devices/bus/nes/rexsoft.cpp
index fdab817e515..76eeb7c8036 100644
--- a/src/devices/bus/nes/rexsoft.cpp
+++ b/src/devices/bus/nes/rexsoft.cpp
@@ -22,12 +22,11 @@
#ifdef NES_PCB_DEBUG
-#define VERBOSE 1
+#define VERBOSE (LOG_GENERAL)
#else
-#define VERBOSE 0
+#define VERBOSE (0)
#endif
-
-#define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0)
+#include "logmacro.h"
//-------------------------------------------------
@@ -109,7 +108,7 @@ void nes_rex_sl1632_device::pcb_reset()
void nes_rex_dbz5_device::write_l(offs_t offset, uint8_t data)
{
- LOG_MMC(("rex_dbz write_l, offset: %04x, data: %02x\n", offset, data));
+ LOG("rex_dbz write_l, offset: %04x, data: %02x\n", offset, data);
m_extra = data;
set_chr(m_chr_source, m_chr_base, m_chr_mask);
@@ -118,7 +117,7 @@ void nes_rex_dbz5_device::write_l(offs_t offset, uint8_t data)
/* we would need to use this read handler in 0x6000-0x7fff as well */
uint8_t nes_rex_dbz5_device::read_l(offs_t offset)
{
- LOG_MMC(("rex_dbz read_l, offset: %04x\n", offset));
+ LOG("rex_dbz read_l, offset: %04x\n", offset);
return 0x01;
}
@@ -170,7 +169,7 @@ void nes_rex_sl1632_device::chr_cb(int start, int bank, int source)
void nes_rex_sl1632_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("rex_sl1632 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("rex_sl1632 write_h, offset: %04x, data: %02x\n", offset, data);
if (offset == 0x2131) // Mode control register at $A131
{
diff --git a/src/devices/bus/nes/sachen.cpp b/src/devices/bus/nes/sachen.cpp
index 8e21943f97f..69934c2b0cd 100644
--- a/src/devices/bus/nes/sachen.cpp
+++ b/src/devices/bus/nes/sachen.cpp
@@ -28,14 +28,14 @@
#include "emu.h"
#include "sachen.h"
+#define LOG_HIFREQ (1U << 1)
#ifdef NES_PCB_DEBUG
-#define VERBOSE 1
+#define VERBOSE (LOG_GENERAL)
#else
-#define VERBOSE 0
+#define VERBOSE (0)
#endif
-
-#define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0)
+#include "logmacro.h"
//-------------------------------------------------
@@ -246,13 +246,13 @@ void nes_sachen_8259d_device::pcb_reset()
iNES: mapper 160
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
void nes_sachen_sa009_device::write_l(offs_t offset, uint8_t data)
{
- LOG_MMC(("SA009 write_l, offset: %04x, data: %02x\n", offset, data));
+ LOG("SA009 write_l, offset: %04x, data: %02x\n", offset, data);
chr8(data, m_chr_source);
}
@@ -271,7 +271,7 @@ void nes_sachen_sa009_device::write_l(offs_t offset, uint8_t data)
void nes_sachen_sa0036_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("sa0036 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("sa0036 write_h, offset: %04x, data: %02x\n", offset, data);
// this pcb is subject to bus conflict
data = account_bus_conflict(offset, data);
@@ -294,7 +294,7 @@ void nes_sachen_sa0036_device::write_h(offs_t offset, u8 data)
void nes_sachen_sa0037_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("sa0037 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("sa0037 write_h, offset: %04x, data: %02x\n", offset, data);
// this pcb is subject to bus conflict
data = account_bus_conflict(offset, data);
@@ -311,13 +311,13 @@ void nes_sachen_sa0037_device::write_h(offs_t offset, u8 data)
iNES: mapper 145
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
void nes_sachen_sa72007_device::write_l(offs_t offset, uint8_t data)
{
- LOG_MMC(("SA72007 write_l, offset: %04x, data: %02x\n", offset, data));
+ LOG("SA72007 write_l, offset: %04x, data: %02x\n", offset, data);
/* only if we are at 0x4100 + k * 0x200, but 0x4100 is offset = 0 */
if (!(offset & 0x100))
@@ -332,13 +332,13 @@ void nes_sachen_sa72007_device::write_l(offs_t offset, uint8_t data)
iNES: mapper 133
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
void nes_sachen_sa72008_device::write_l(offs_t offset, uint8_t data)
{
- LOG_MMC(("SA72008 write_l, offset: %04x, data: %02x\n", offset, data));
+ LOG("SA72008 write_l, offset: %04x, data: %02x\n", offset, data);
prg32(data >> 2);
chr8(data, CHRROM);
@@ -358,7 +358,7 @@ void nes_sachen_sa72008_device::write_l(offs_t offset, uint8_t data)
uint8_t nes_sachen_tca01_device::read_l(offs_t offset)
{
- LOG_MMC(("TCA-01 read_l, offset: %04x\n", offset));
+ LOG("TCA-01 read_l, offset: %04x\n", offset);
/* the address is read only if we are at 0x4100 + k * 0x200, but 0x4100 is offset = 0 */
if (!(offset & 0x100))
@@ -375,13 +375,13 @@ uint8_t nes_sachen_tca01_device::read_l(offs_t offset)
iNES: mapper 147
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
void nes_sachen_tcu01_device::write_l(offs_t offset, uint8_t data)
{
- LOG_MMC(("TCU-01 write_l, offset: %04x, data: %02x\n", offset, data));
+ LOG("TCU-01 write_l, offset: %04x, data: %02x\n", offset, data);
if ((offset & 0x103) == 0x002)
{
@@ -398,13 +398,13 @@ void nes_sachen_tcu01_device::write_l(offs_t offset, uint8_t data)
iNES: mapper 136
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
void nes_sachen_tcu02_device::write_l(offs_t offset, uint8_t data)
{
- LOG_MMC(("TCU-02 write_l, offset: %04x, data: %02x\n", offset, data));
+ LOG("TCU-02 write_l, offset: %04x, data: %02x\n", offset, data);
if ((offset & 0x103) == 0x002)
{
@@ -415,7 +415,7 @@ void nes_sachen_tcu02_device::write_l(offs_t offset, uint8_t data)
uint8_t nes_sachen_tcu02_device::read_l(offs_t offset)
{
- LOG_MMC(("TCU-02 read_l, offset: %04x\n", offset));
+ LOG("TCU-02 read_l, offset: %04x\n", offset);
if ((offset & 0x103) == 0x000)
return m_latch | 0x40;
@@ -463,7 +463,7 @@ u8 nes_sachen_3013_device::read_h(offs_t offset)
void nes_sachen_3014_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("Sachen 3014 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("Sachen 3014 write_h, offset: %04x, data: %02x\n", offset, data);
// this pcb is subject to bus conflict
data = account_bus_conflict(offset, data);
@@ -474,7 +474,7 @@ void nes_sachen_3014_device::write_h(offs_t offset, u8 data)
u8 nes_sachen_3014_device::read_h(offs_t offset)
{
-// LOG_MMC(("Sachen 3014 read_h, offset: %04x\n", offset));
+ LOGMASKED(LOG_HIFREQ, "Sachen 3014 read_h, offset: %04x\n", offset);
u8 temp = hi_access_rom(offset);
if ((offset & 0x7000) == 0x6000)
@@ -511,14 +511,14 @@ void nes_sachen_74x374_device::set_mirror(uint8_t nt) // also used by mappers 13
set_nt_mirroring(PPU_MIRROR_LOW);
break;
default:
- LOG_MMC(("Mapper set NT to invalid value %02x", nt));
+ LOG("Mapper set NT to invalid value %02x", nt);
break;
}
}
void nes_sachen_74x374_device::write_l(offs_t offset, uint8_t data)
{
- LOG_MMC(("Sachen 74*374 write_l, offset: %04x, data: %02x\n", offset, data));
+ LOG("Sachen 74*374 write_l, offset: %04x, data: %02x\n", offset, data);
/* write happens only if we are at 0x4100 + k * 0x200, but 0x4100 is offset = 0 */
if (!(offset & 0x100))
@@ -557,7 +557,7 @@ void nes_sachen_74x374_device::write_l(offs_t offset, uint8_t data)
uint8_t nes_sachen_74x374_device::read_l(offs_t offset)
{
- LOG_MMC(("Sachen 74*374 read_l, offset: %04x", offset));
+ LOG("Sachen 74*374 read_l, offset: %04x", offset);
/* read happens only if we are at 0x4100 + k * 0x200, but 0x4100 is offset = 0 */
if (!(offset & 0x100))
@@ -568,7 +568,7 @@ uint8_t nes_sachen_74x374_device::read_l(offs_t offset)
void nes_sachen_74x374_alt_device::write_l(offs_t offset, uint8_t data)
{
- LOG_MMC(("Sachen 74*374 Alt write_l, offset: %04x, data: %02x\n", offset, data));
+ LOG("Sachen 74*374 Alt write_l, offset: %04x, data: %02x\n", offset, data);
/* write happens only if we are at 0x4100 + k * 0x200, but 0x4100 is offset = 0 */
if (!(offset & 0x100))
@@ -632,7 +632,7 @@ void nes_sachen_8259a_device::chr_update()
void nes_sachen_8259a_device::write_l(offs_t offset, uint8_t data)
{
- LOG_MMC(("Sachen 8259 write_l, offset: %04x, data: %02x\n", offset, data));
+ LOG("Sachen 8259 write_l, offset: %04x, data: %02x\n", offset, data);
/* write happens only if we are at 0x4100 + k * 0x200, but 0x4100 is offset = 0 */
if (!(offset & 0x100))
diff --git a/src/devices/bus/nes/sealie.cpp b/src/devices/bus/nes/sealie.cpp
index 32adda5680c..5c7b42cfe4e 100644
--- a/src/devices/bus/nes/sealie.cpp
+++ b/src/devices/bus/nes/sealie.cpp
@@ -21,12 +21,11 @@
#ifdef NES_PCB_DEBUG
-#define VERBOSE 1
+#define VERBOSE (LOG_GENERAL)
#else
-#define VERBOSE 0
+#define VERBOSE (0)
#endif
-
-#define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0)
+#include "logmacro.h"
//-------------------------------------------------
@@ -129,7 +128,7 @@ void nes_8bitxmas_device::pcb_reset()
void nes_cufrom_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("cufrom write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("cufrom write_h, offset: %04x, data: %02x\n", offset, data);
prg16_89ab(BIT(data, 2, 3));
chr8(data & 0x03, CHRRAM);
@@ -154,7 +153,7 @@ void nes_cufrom_device::write_h(offs_t offset, u8 data)
void nes_dpcmcart_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("dpcmcart write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("dpcmcart write_h, offset: %04x, data: %02x\n", offset, data);
prg16_89ab(offset & 0x0fff);
}
@@ -177,7 +176,7 @@ void nes_dpcmcart_device::write_h(offs_t offset, u8 data)
void nes_unrom512_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("unrom512 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("unrom512 write_h, offset: %04x, data: %02x\n", offset, data);
// this pcb is subject to bus conflict in its nonflashable configuration
data = account_bus_conflict(offset, data);
@@ -230,7 +229,7 @@ void nes_8bitxmas_device::update_led()
void nes_8bitxmas_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("8bitxmas write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("8bitxmas write_h, offset: %04x, data: %02x\n", offset, data);
if (BIT(offset, 14))
nes_unrom512_device::write_h(offset, data);
diff --git a/src/devices/bus/nes/somari.cpp b/src/devices/bus/nes/somari.cpp
index bdf5b21b885..15382d01111 100644
--- a/src/devices/bus/nes/somari.cpp
+++ b/src/devices/bus/nes/somari.cpp
@@ -17,12 +17,11 @@
#ifdef NES_PCB_DEBUG
-#define VERBOSE 1
+#define VERBOSE (LOG_GENERAL)
#else
-#define VERBOSE 0
+#define VERBOSE (0)
#endif
-
-#define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0)
+#include "logmacro.h"
#define SOMARI_VRC2_MODE 0
#define SOMARI_MMC3_MODE 1
@@ -260,7 +259,7 @@ void nes_somari_device::update_mirror()
void nes_somari_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("somari write_h, mode %d, offset: %04x, data: %02x\n", m_board_mode, offset, data));
+ LOG("somari write_h, mode %d, offset: %04x, data: %02x\n", m_board_mode, offset, data);
switch (m_board_mode)
{
@@ -279,7 +278,7 @@ void nes_somari_device::update_all_banks()
void nes_somari_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("somari write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("somari write_m, offset: %04x, data: %02x\n", offset, data);
if (offset & 0x100)
{
diff --git a/src/devices/bus/nes/subor.cpp b/src/devices/bus/nes/subor.cpp
index 2c9daf203ee..109e1625fdd 100644
--- a/src/devices/bus/nes/subor.cpp
+++ b/src/devices/bus/nes/subor.cpp
@@ -17,12 +17,11 @@
#include "subor.h"
#ifdef NES_PCB_DEBUG
-#define VERBOSE 1
+#define VERBOSE (LOG_GENERAL)
#else
-#define VERBOSE 0
+#define VERBOSE (0)
#endif
-
-#define LOG_MMC(...) do { if (VERBOSE) logerror(__VA_ARGS__); } while (0)
+#include "logmacro.h"
//**************************************************************************
// DEVICE DEFINITIONS
@@ -232,7 +231,7 @@ void nes_subor2_device::update_banks()
uint8_t nes_subor2_device::read_l(offs_t offset)
{
- LOG_MMC("subor2 read_l, offset: %04x\n", offset);
+ LOG("subor2 read_l, offset: %04x\n", offset);
if (offset == 0x1200)
{
@@ -248,7 +247,7 @@ uint8_t nes_subor2_device::read_l(offs_t offset)
void nes_subor0_device::write_h(offs_t offset, uint8_t data)
{
uint8_t subor_helper1, subor_helper2;
- LOG_MMC("subor0 write_h, offset: %04x, data: %02x\n", offset, data);
+ LOG("subor0 write_h, offset: %04x, data: %02x\n", offset, data);
m_reg[BIT(offset, 13, 2)] = data;
subor_helper1 = ((m_reg[0] ^ m_reg[1]) << 1) & 0x20;
@@ -278,7 +277,7 @@ void nes_subor0_device::write_h(offs_t offset, uint8_t data)
void nes_subor1_device::write_h(offs_t offset, uint8_t data)
{
uint8_t subor_helper1, subor_helper2;
- LOG_MMC("subor1 write_h, offset: %04x, data: %02x\n", offset, data);
+ LOG("subor1 write_h, offset: %04x, data: %02x\n", offset, data);
m_reg[BIT(offset, 13, 2)] = data;
subor_helper1 = ((m_reg[0] ^ m_reg[1]) << 1) & 0x20;
@@ -307,7 +306,7 @@ void nes_subor1_device::write_h(offs_t offset, uint8_t data)
void nes_subor2_device::write_l(offs_t offset, uint8_t data)
{
- LOG_MMC("subor2 write_l, offset: %04x, data: %02x\n", offset, data);
+ LOG("subor2 write_l, offset: %04x, data: %02x\n", offset, data);
switch (offset)
{
diff --git a/src/devices/bus/nes/sunsoft.cpp b/src/devices/bus/nes/sunsoft.cpp
index ffe5aec9005..14ea2ea83c2 100644
--- a/src/devices/bus/nes/sunsoft.cpp
+++ b/src/devices/bus/nes/sunsoft.cpp
@@ -27,14 +27,14 @@
#include "sound/ay8910.h"
#include "speaker.h"
+#define LOG_UNHANDLED (1U << 1)
#ifdef NES_PCB_DEBUG
-#define VERBOSE 1
+#define VERBOSE (LOG_UNHANDLED | LOG_GENERAL)
#else
-#define VERBOSE 0
+#define VERBOSE (LOG_UNHANDLED)
#endif
-
-#define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0)
+#include "logmacro.h"
//-------------------------------------------------
@@ -191,7 +191,7 @@ void nes_sunsoft_fme7_device::pcb_reset()
void nes_sunsoft_1_device::write_m(offs_t offset, uint8_t data)
{
- LOG_MMC(("Sunsoft 1 write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("Sunsoft 1 write_m, offset: %04x, data: %02x\n", offset, data);
if (m_vrom_chunks)
{
@@ -218,7 +218,7 @@ void nes_sunsoft_1_device::write_m(offs_t offset, uint8_t data)
void nes_sunsoft_2_device::write_h(offs_t offset, uint8_t data)
{
uint8_t helper = (data & 0x07) | ((data & 0x80) ? 0x08 : 0x00);
- LOG_MMC(("Sunsoft 2 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("Sunsoft 2 write_h, offset: %04x, data: %02x\n", offset, data);
// this pcb is subject to bus conflict
data = account_bus_conflict(offset, data);
@@ -253,7 +253,7 @@ TIMER_CALLBACK_MEMBER(nes_sunsoft_3_device::irq_timer_tick)
void nes_sunsoft_3_device::write_h(offs_t offset, uint8_t data)
{
- LOG_MMC(("Sunsoft 3 write_h, offset %04x, data: %02x\n", offset, data));
+ LOG("Sunsoft 3 write_h, offset %04x, data: %02x\n", offset, data);
switch (offset & 0x7800)
{
@@ -328,7 +328,7 @@ void nes_sunsoft_4_device::sun4_mirror()
void nes_sunsoft_4_device::sun4_write(offs_t offset, u8 data)
{
- LOG_MMC(("Sunsoft 4 write_h, offset %04x, data: %02x\n", offset, data));
+ LOG("Sunsoft 4 write_h, offset %04x, data: %02x\n", offset, data);
switch (offset & 0x7000)
{
@@ -353,7 +353,7 @@ void nes_sunsoft_4_device::sun4_write(offs_t offset, u8 data)
void nes_sunsoft_4_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("Sunsoft 4 write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("Sunsoft 4 write_m, offset: %04x, data: %02x\n", offset, data);
if (m_wram_enable)
device_nes_cart_interface::write_m(offset, data);
@@ -361,7 +361,7 @@ void nes_sunsoft_4_device::write_m(offs_t offset, u8 data)
u8 nes_sunsoft_4_device::read_m(offs_t offset)
{
- LOG_MMC(("Sunsoft 4 read_m, offset: %04x\n", offset));
+ LOG("Sunsoft 4 read_m, offset: %04x\n", offset);
if (m_wram_enable)
return device_nes_cart_interface::read_m(offset);
@@ -393,7 +393,7 @@ TIMER_CALLBACK_MEMBER(nes_sunsoft_fme7_device::irq_timer_tick)
void nes_sunsoft_fme7_device::fme7_write(offs_t offset, uint8_t data)
{
- LOG_MMC(("fme7_write, offset %04x, data: %02x\n", offset, data));
+ LOG("fme7_write, offset %04x, data: %02x\n", offset, data);
switch (offset & 0x6000)
{
@@ -443,7 +443,7 @@ void nes_sunsoft_fme7_device::fme7_write(offs_t offset, uint8_t data)
break;
default:
- logerror("Sunsoft FME7 write_h uncaught %04x value: %02x\n", offset + 0x8000, data);
+ LOGMASKED(LOG_UNHANDLED, "Sunsoft FME7 write_h uncaught %04x value: %02x\n", offset + 0x8000, data);
break;
}
}
@@ -451,7 +451,7 @@ void nes_sunsoft_fme7_device::fme7_write(offs_t offset, uint8_t data)
void nes_sunsoft_fme7_device::write_m(offs_t offset, uint8_t data)
{
uint8_t bank = m_wram_bank & 0x3f;
- LOG_MMC(("Sunsoft FME7 write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("Sunsoft FME7 write_m, offset: %04x, data: %02x\n", offset, data);
if (!(m_wram_bank & 0x40)) // is PRG ROM, no write
return;
@@ -467,7 +467,7 @@ void nes_sunsoft_fme7_device::write_m(offs_t offset, uint8_t data)
uint8_t nes_sunsoft_fme7_device::read_m(offs_t offset)
{
uint8_t bank = m_wram_bank & 0x3f;
- LOG_MMC(("Sunsoft FME7 read_m, offset: %04x\n", offset));
+ LOG("Sunsoft FME7 read_m, offset: %04x\n", offset);
if (!(m_wram_bank & 0x40)) // is PRG ROM
return m_prg[((bank * 0x2000) + offset) & (m_prg_size - 1)];
@@ -495,7 +495,7 @@ uint8_t nes_sunsoft_fme7_device::read_m(offs_t offset)
void nes_sunsoft_5_device::write_h(offs_t offset, uint8_t data)
{
- LOG_MMC(("sunsoft 5 write_h, offset %04x, data: %02x\n", offset, data));
+ LOG("sunsoft 5 write_h, offset %04x, data: %02x\n", offset, data);
switch (offset & 0x6000)
{
diff --git a/src/devices/bus/nes/sunsoft_dcs.cpp b/src/devices/bus/nes/sunsoft_dcs.cpp
index 7f291e741ed..188f0a83b32 100644
--- a/src/devices/bus/nes/sunsoft_dcs.cpp
+++ b/src/devices/bus/nes/sunsoft_dcs.cpp
@@ -16,12 +16,11 @@
#include "sunsoft_dcs.h"
#ifdef NES_PCB_DEBUG
-#define VERBOSE 1
+#define VERBOSE (LOG_GENERAL)
#else
-#define VERBOSE 0
+#define VERBOSE (0)
#endif
-
-#define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0)
+#include "logmacro.h"
//-----------------------------------------------
@@ -77,32 +76,31 @@ uint8_t nes_ntb_slot_device::read(offs_t offset)
}
-image_init_result nes_ntb_slot_device::call_load()
+std::pair<std::error_condition, std::string> nes_ntb_slot_device::call_load()
{
if (m_cart)
{
- uint8_t *ROM = m_cart->get_cart_base();
-
+ uint8_t *const ROM = m_cart->get_cart_base();
if (!ROM)
- return image_init_result::FAIL;
+ return std::make_pair(image_error::INTERNAL, std::string());
if (!loaded_through_softlist())
{
if (length() != 0x4000)
- return image_init_result::FAIL;
+ return std::make_pair(image_error::INVALIDLENGTH, "Unsupported cartridge size (must be 16K)");
- fread(&ROM, 0x4000);
+ fread(ROM, 0x4000);
}
else
{
if (get_software_region_length("rom") != 0x4000)
- return image_init_result::FAIL;
+ return std::make_pair(image_error::INVALIDLENGTH, "Unsupported cartridge size (must be 16K)");
memcpy(ROM, get_software_region("rom"), 0x4000);
}
}
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
@@ -203,7 +201,7 @@ void nes_sunsoft_dcs_device::pcb_reset()
void nes_sunsoft_dcs_device::write_h(offs_t offset, uint8_t data)
{
- LOG_MMC(("Sunsoft DCS write_h, offset %04x, data: %02x\n", offset, data));
+ LOG("Sunsoft DCS write_h, offset %04x, data: %02x\n", offset, data);
switch (offset & 0x7000)
{
@@ -220,7 +218,7 @@ void nes_sunsoft_dcs_device::write_h(offs_t offset, uint8_t data)
uint8_t nes_sunsoft_dcs_device::read_h(offs_t offset)
{
- LOG_MMC(("Sunsoft DCS read_h, offset: %04x\n", offset));
+ LOG("Sunsoft DCS read_h, offset: %04x\n", offset);
if (m_exrom_enable && m_subslot->m_cart && offset < 0x4000)
{
@@ -235,7 +233,7 @@ uint8_t nes_sunsoft_dcs_device::read_h(offs_t offset)
void nes_sunsoft_dcs_device::write_m(offs_t offset, uint8_t data)
{
- LOG_MMC(("Sunsoft DCS write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("Sunsoft DCS write_m, offset: %04x, data: %02x\n", offset, data);
if (!m_battery.empty() && m_wram_enable)
m_battery[offset & (m_battery.size() - 1)] = data;
@@ -251,7 +249,7 @@ void nes_sunsoft_dcs_device::write_m(offs_t offset, uint8_t data)
uint8_t nes_sunsoft_dcs_device::read_m(offs_t offset)
{
- LOG_MMC(("Sunsoft DCS read_m, offset: %04x\n", offset));
+ LOG("Sunsoft DCS read_m, offset: %04x\n", offset);
if (!m_battery.empty() && m_wram_enable)
return m_battery[offset & (m_battery.size() - 1)];
diff --git a/src/devices/bus/nes/sunsoft_dcs.h b/src/devices/bus/nes/sunsoft_dcs.h
index e9f6594a452..bb98c1f8081 100644
--- a/src/devices/bus/nes/sunsoft_dcs.h
+++ b/src/devices/bus/nes/sunsoft_dcs.h
@@ -59,23 +59,23 @@ public:
nes_ntb_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual ~nes_ntb_slot_device();
- // image-level overrides
- virtual image_init_result call_load() override;
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
virtual bool is_reset_on_load() const noexcept override { return true; }
virtual const char *image_interface() const noexcept override { return "ntb_cart"; }
virtual const char *file_extensions() const noexcept override { return "bin"; }
- // slot interface overrides
+ // device_slot_interface implementation
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
virtual uint8_t read(offs_t offset);
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
- ntb_cart_interface* m_cart;
+ ntb_cart_interface *m_cart;
};
// device type definition
@@ -97,13 +97,12 @@ public:
// construction/destruction
nes_ntb_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- // optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual uint8_t* get_cart_base();
+ virtual uint8_t *get_cart_base();
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
};
// device type definition
diff --git a/src/devices/bus/nes/taito.cpp b/src/devices/bus/nes/taito.cpp
index a3689c8f4a7..d27b8fb2695 100644
--- a/src/devices/bus/nes/taito.cpp
+++ b/src/devices/bus/nes/taito.cpp
@@ -20,20 +20,19 @@
***********************************************************************************************************/
-
#include "emu.h"
#include "taito.h"
#include "video/ppu2c0x.h" // this has to be included so that IRQ functions can access ppu2c0x_device::BOTTOM_VISIBLE_SCANLINE
+#define LOG_UNHANDLED (1U << 1)
#ifdef NES_PCB_DEBUG
-#define VERBOSE 1
+#define VERBOSE (LOG_UNHANDLED | LOG_GENERAL)
#else
-#define VERBOSE 0
+#define VERBOSE (LOG_UNHANDLED)
#endif
-
-#define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0)
+#include "logmacro.h"
//-------------------------------------------------
@@ -174,7 +173,7 @@ void nes_x1_017_device::pcb_reset()
void nes_tc0190fmc_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("tc0190fmc write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("tc0190fmc write_h, offset: %04x, data: %02x\n", offset, data);
switch (offset & 0x6003)
{
@@ -234,7 +233,7 @@ void nes_tc0190fmc_pal16r4_device::hblank_irq(int scanline, bool vblank, bool bl
void nes_tc0190fmc_pal16r4_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("tc0190fmc pal16r4 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("tc0190fmc pal16r4 write_h, offset: %04x, data: %02x\n", offset, data);
switch (offset & 0x6003)
{
@@ -282,7 +281,7 @@ void nes_tc0190fmc_pal16r4_device::write_h(offs_t offset, u8 data)
void nes_x1_005_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("x1_005 write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("x1_005 write_m, offset: %04x, data: %02x\n", offset, data);
if ((offset & 0x1f70) == 0x1e70) // A7 is not connected
{
@@ -328,12 +327,12 @@ void nes_x1_005_device::write_m(offs_t offset, u8 data)
else if (offset >= 0x1f00 && m_latch == 0xa3)
m_x1_005_ram[offset & 0x7f] = data;
else
- logerror("Taito X1-005 uncaught addr: %04x, value: %02x\n", offset + 0x6000, data);
+ LOGMASKED(LOG_UNHANDLED, "Taito X1-005 uncaught addr: %04x, value: %02x\n", offset + 0x6000, data);
}
u8 nes_x1_005_device::read_m(offs_t offset)
{
- LOG_MMC(("x1_005 read_m, offset: %04x\n", offset));
+ LOG("x1_005 read_m, offset: %04x\n", offset);
if (offset >= 0x1f00 && m_latch == 0xa3)
return m_x1_005_ram[offset & 0x7f];
@@ -379,7 +378,7 @@ void nes_x1_017_device::set_chr()
void nes_x1_017_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("x1017 write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("x1017 write_m, offset: %04x, data: %02x\n", offset, data);
switch (offset)
{
@@ -437,7 +436,7 @@ void nes_x1_017_device::write_m(offs_t offset, u8 data)
u8 nes_x1_017_device::read_m(offs_t offset)
{
- LOG_MMC(("x1017 read_m, offset: %04x\n", offset));
+ LOG("x1017 read_m, offset: %04x\n", offset);
// 2+2+1 KB of Internal RAM can be independently enabled/disabled!
if ((offset < 0x0800 && m_reg[0] == 0xca) ||
diff --git a/src/devices/bus/nes/tengen.cpp b/src/devices/bus/nes/tengen.cpp
index 3b74a13f2cd..2304ee9a201 100644
--- a/src/devices/bus/nes/tengen.cpp
+++ b/src/devices/bus/nes/tengen.cpp
@@ -23,12 +23,11 @@
#ifdef NES_PCB_DEBUG
-#define VERBOSE 1
+#define VERBOSE (LOG_GENERAL)
#else
-#define VERBOSE 0
+#define VERBOSE (0)
#endif
-
-#define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0)
+#include "logmacro.h"
//-------------------------------------------------
@@ -205,7 +204,7 @@ void nes_tengen032_device::set_chr()
void nes_tengen032_device::write_h(offs_t offset, u8 data)
{
u8 helper, cmd;
- LOG_MMC(("tengen032 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("tengen032 write_h, offset: %04x, data: %02x\n", offset, data);
switch (offset & 0x6001)
{
@@ -273,7 +272,7 @@ void nes_tengen032_device::write_h(offs_t offset, u8 data)
break;
default:
- LOG_MMC(("Tengen 800032 write. addr: %04x value: %02x\n", offset + 0x8000, data));
+ LOG("Tengen 800032 write. addr: %04x value: %02x\n", offset + 0x8000, data);
break;
}
}
@@ -309,7 +308,7 @@ void nes_tengen037_device::set_chr()
void nes_tengen037_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("tengen037 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("tengen037 write_h, offset: %04x, data: %02x\n", offset, data);
switch (offset & 0x6001)
{
diff --git a/src/devices/bus/nes/txc.cpp b/src/devices/bus/nes/txc.cpp
index 398adbd17f3..0fbab1a8f12 100644
--- a/src/devices/bus/nes/txc.cpp
+++ b/src/devices/bus/nes/txc.cpp
@@ -25,12 +25,11 @@
#ifdef NES_PCB_DEBUG
-#define VERBOSE 1
+#define VERBOSE (LOG_GENERAL)
#else
-#define VERBOSE 0
+#define VERBOSE (0)
#endif
-
-#define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0)
+#include "logmacro.h"
//-------------------------------------------------
@@ -122,13 +121,13 @@ void nes_txc_strikew_device::pcb_reset()
iNES: mapper 132
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
void nes_txc_22211_device::write_l(offs_t offset, uint8_t data)
{
- LOG_MMC(("TXC 22111 write_l, offset: %04x, data: %02x\n", offset, data));
+ LOG("TXC 22111 write_l, offset: %04x, data: %02x\n", offset, data);
if (offset < 4)
m_reg[offset & 0x03] = data;
@@ -136,7 +135,7 @@ void nes_txc_22211_device::write_l(offs_t offset, uint8_t data)
uint8_t nes_txc_22211_device::read_l(offs_t offset)
{
- LOG_MMC(("TXC 22111 read_l, offset: %04x\n", offset));
+ LOG("TXC 22111 read_l, offset: %04x\n", offset);
if (offset == 0x0000)
return (m_reg[1] ^ m_reg[2]) | 0x40;
@@ -146,7 +145,7 @@ uint8_t nes_txc_22211_device::read_l(offs_t offset)
void nes_txc_22211_device::write_h(offs_t offset, uint8_t data)
{
- LOG_MMC(("TXC 22111 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("TXC 22111 write_h, offset: %04x, data: %02x\n", offset, data);
prg32(m_reg[2] >> 2);
chr8(m_reg[2], CHRROM);
@@ -163,13 +162,13 @@ void nes_txc_22211_device::write_h(offs_t offset, uint8_t data)
iNES: mapper 172
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
void nes_txc_dumarc_device::write_h(offs_t offset, uint8_t data)
{
- LOG_MMC(("TXC Du Ma Racing write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("TXC Du Ma Racing write_h, offset: %04x, data: %02x\n", offset, data);
prg32(m_reg[2] >> 2);
chr8(bitswap<2>(data ^ m_reg[2], 4, 5), CHRROM);
@@ -186,13 +185,13 @@ void nes_txc_dumarc_device::write_h(offs_t offset, uint8_t data)
iNES: mapper 172
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
uint8_t nes_txc_mjblock_device::read_l(offs_t offset)
{
- LOG_MMC(("TXC mjblock read_l, offset: %04x\n", offset));
+ LOG("TXC mjblock read_l, offset: %04x\n", offset);
if (offset == 0x0000)
return (m_reg[1] ^ m_reg[2]) | 0x41;
@@ -215,7 +214,7 @@ uint8_t nes_txc_mjblock_device::read_l(offs_t offset)
u8 nes_txc_strikew_device::read_l(offs_t offset)
{
- LOG_MMC(("TXC 01-22000-400 read_l, offset: %04x\n", offset));
+ LOG("TXC 01-22000-400 read_l, offset: %04x\n", offset);
offset += 0x100;
if (offset & 0x100)
@@ -226,7 +225,7 @@ u8 nes_txc_strikew_device::read_l(offs_t offset)
void nes_txc_strikew_device::write_l(offs_t offset, u8 data)
{
- LOG_MMC(("TXC 01-22000-400 write_l, offset: %04x, data: %02x\n", offset, data));
+ LOG("TXC 01-22000-400 write_l, offset: %04x, data: %02x\n", offset, data);
offset += 0x100;
switch (offset & 0x103)
@@ -252,7 +251,7 @@ void nes_txc_strikew_device::write_l(offs_t offset, u8 data)
void nes_txc_strikew_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("TXC 01-22000-400 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("TXC 01-22000-400 write_h, offset: %04x, data: %02x\n", offset, data);
prg32(m_reg[0]);
}
@@ -269,7 +268,7 @@ void nes_txc_strikew_device::write_h(offs_t offset, u8 data)
iNES: mapper 241
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
@@ -280,7 +279,7 @@ uint8_t nes_txc_commandos_device::read_l(offs_t offset)
void nes_txc_commandos_device::write_h(offs_t offset, uint8_t data)
{
- LOG_MMC(("TXC Commandos write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("TXC Commandos write_h, offset: %04x, data: %02x\n", offset, data);
prg32(data);
}
diff --git a/src/devices/bus/nes/vrc_clones.cpp b/src/devices/bus/nes/vrc_clones.cpp
index 506857df85f..ba358cb164f 100644
--- a/src/devices/bus/nes/vrc_clones.cpp
+++ b/src/devices/bus/nes/vrc_clones.cpp
@@ -14,14 +14,14 @@
#include "emu.h"
#include "vrc_clones.h"
+#define LOG_HIFREQ (1U << 1)
#ifdef NES_PCB_DEBUG
-#define VERBOSE 1
+#define VERBOSE (LOG_GENERAL)
#else
-#define VERBOSE 0
+#define VERBOSE (0)
#endif
-
-#define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0)
+#include "logmacro.h"
//-------------------------------------------------
@@ -333,7 +333,7 @@ TIMER_CALLBACK_MEMBER(nes_900218_device::irq_timer_tick)
void nes_900218_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("900218 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("900218 write_h, offset: %04x, data: %02x\n", offset, data);
if ((offset & 0x7000) == 0x7000)
{
@@ -370,7 +370,7 @@ void nes_900218_device::write_h(offs_t offset, u8 data)
void nes_ax40g_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("ax40g write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("ax40g write_h, offset: %04x, data: %02x\n", offset, data);
nes_konami_vrc2_device::write_h(offset, data);
@@ -397,7 +397,7 @@ void nes_ax40g_device::write_h(offs_t offset, u8 data)
void nes_ax5705_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("ax5705 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("ax5705 write_h, offset: %04x, data: %02x\n", offset, data);
offset = (offset & ~0x1000) | BIT(offset, 3) << 12;
switch (offset & 0x7001)
@@ -430,7 +430,7 @@ void nes_ax5705_device::write_h(offs_t offset, u8 data)
void nes_cityfight_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("unl_cityfight write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("unl_cityfight write_h, offset: %04x, data: %02x\n", offset, data);
offset = (offset & ~0x6000) | bitswap<2>(offset, 13, 14) << 13;
switch (offset & 0x7800)
@@ -444,7 +444,7 @@ void nes_cityfight_device::write_h(offs_t offset, u8 data)
nes_konami_vrc4_device::write_h(offset, data);
break;
case 0x1800:
- LOG_MMC(("Extended Audio write, data %x!", data & 0x0f)); // pcmwrite(0x4011, (V & 0xf) << 3); (etabeta's original comment, FCEUX code)
+ LOG("Extended Audio write, data %x!", data & 0x0f); // pcmwrite(0x4011, (V & 0xf) << 3); (etabeta's original comment, FCEUX code)
break;
default:
nes_konami_vrc4_device::write_h(offset, data);
@@ -468,20 +468,20 @@ void nes_cityfight_device::write_h(offs_t offset, u8 data)
u8 nes_shuiguan_device::read_m(offs_t offset)
{
-// LOG_MMC(("shuiguan read_m, offset: %04x\n", offset));
+ LOGMASKED(LOG_HIFREQ, "shuiguan read_m, offset: %04x\n", offset);
return m_prg[(m_reg * 0x2000 + offset) & (m_prg_size - 1)];
}
void nes_shuiguan_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("shuiguan write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("shuiguan write_m, offset: %04x, data: %02x\n", offset, data);
if ((offset & 0x1800) == 0x800)
m_reg = offset & 0x1f;
}
void nes_shuiguan_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("shuiguan write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("shuiguan write_h, offset: %04x, data: %02x\n", offset, data);
switch (offset & 0x7800)
{
@@ -525,7 +525,7 @@ void nes_shuiguan_device::write_h(offs_t offset, u8 data)
void nes_t230_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("t230 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("t230 write_h, offset: %04x, data: %02x\n", offset, data);
switch (offset & 0x7000)
{
@@ -591,7 +591,7 @@ TIMER_CALLBACK_MEMBER(nes_th21311_device::irq_timer_tick)
void nes_th21311_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("th21311 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("th21311 write_h, offset: %04x, data: %02x\n", offset, data);
if ((offset & 0x7000) == 0x7000)
{
@@ -636,7 +636,7 @@ void nes_th21311_device::write_h(offs_t offset, u8 data)
void nes_waixing_sgz_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("waixing_sgz write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("waixing_sgz write_h, offset: %04x, data: %02x\n", offset, data);
nes_konami_vrc4_device::write_h(offset, data);
@@ -689,7 +689,7 @@ void nes_waixing_sgz_device::chr_w(offs_t offset, u8 data)
void nes_2yudb_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("2yudb write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("2yudb write_h, offset: %04x, data: %02x\n", offset, data);
nes_konami_vrc4_device::write_h(offset, data);
@@ -722,7 +722,7 @@ void nes_bmc_830506c_device::irq_ack_w()
void nes_bmc_830506c_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_830506c write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_830506c write_h, offset: %04x, data: %02x\n", offset, data);
nes_konami_vrc4_device::write_h(offset, data);
@@ -752,17 +752,18 @@ void nes_bmc_830506c_device::write_h(offs_t offset, u8 data)
u8 nes_bmc_831128c_device::read_m(offs_t offset)
{
-// LOG_MMC(("bmc_831128c read_m, offset: %04x, data: %02x\n", offset, data));
-
+ u8 data = 0;
if (m_reg == 1)
- return device_nes_cart_interface::read_m(offset);
+ data = device_nes_cart_interface::read_m(offset);
else
- return m_prg[(m_reg * 0x2000 + offset) & (m_prg_size - 1)];
+ data = m_prg[(m_reg * 0x2000 + offset) & (m_prg_size - 1)];
+ LOGMASKED(LOG_HIFREQ, "bmc_831128c read_m, offset: %04x, data: %02x\n", offset, data);
+ return data;
}
void nes_bmc_831128c_device::write_m(offs_t offset, u8 data)
{
-// LOG_MMC(("bmc_831128c write_m, offset: %04x, data: %02x\n", offset, data));
+ LOGMASKED(LOG_HIFREQ, "bmc_831128c write_m, offset: %04x, data: %02x\n", offset, data);
if (m_reg == 1)
device_nes_cart_interface::write_m(offset, data);
@@ -770,7 +771,7 @@ void nes_bmc_831128c_device::write_m(offs_t offset, u8 data)
void nes_bmc_831128c_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_831128c write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_831128c write_h, offset: %04x, data: %02x\n", offset, data);
u8 page = offset >> 12;
if (page != 2 && page != 4) // ignore writes except $Axxx and $Cxxx
@@ -846,7 +847,7 @@ void nes_bmc_kl06_device::set_prg()
void nes_bmc_kl06_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("bmc_kl06 write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("bmc_kl06 write_m, offset: %04x, data: %02x\n", offset, data);
// 2K RAM for Crisis Force overlays control register
nes_konami_vrc4_device::write_m(offset, data);
diff --git a/src/devices/bus/nes/waixing.cpp b/src/devices/bus/nes/waixing.cpp
index 1f286c00485..b10df1b3f59 100644
--- a/src/devices/bus/nes/waixing.cpp
+++ b/src/devices/bus/nes/waixing.cpp
@@ -17,14 +17,14 @@
#include "emu.h"
#include "waixing.h"
+#define LOG_HIFREQ (1U << 1)
#ifdef NES_PCB_DEBUG
-#define VERBOSE 1
+#define VERBOSE (LOG_GENERAL)
#else
-#define VERBOSE 0
+#define VERBOSE (0)
#endif
-
-#define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0)
+#include "logmacro.h"
//-------------------------------------------------
@@ -314,7 +314,7 @@ void nes_waixing_fs304_device::pcb_reset()
iNES: mapper 74
- In MESS: Supported
+ In MAME: Supported
-------------------------------------------------*/
@@ -334,7 +334,7 @@ void nes_waixing_a_device::set_mirror(uint8_t nt)
set_nt_mirroring(PPU_MIRROR_HIGH);
break;
default:
- LOG_MMC(("Mapper set NT to invalid value %02x", nt));
+ LOG("Mapper set NT to invalid value %02x", nt);
break;
}
}
@@ -355,7 +355,7 @@ void nes_waixing_a1_device::chr_cb(int start, int bank, int source)
void nes_waixing_a_device::waixing_write(offs_t offset, uint8_t data)
{
- LOG_MMC(("waixing_write, offset: %04x, data: %02x\n", offset, data));
+ LOG("waixing_write, offset: %04x, data: %02x\n", offset, data);
switch (offset & 0x6001)
{
@@ -374,7 +374,7 @@ void nes_waixing_a_device::waixing_write(offs_t offset, uint8_t data)
uint8_t nes_waixing_a_device::read_l(offs_t offset)
{
- LOG_MMC(("waixing read_l, offset: %04x\n", offset));
+ LOG("waixing read_l, offset: %04x\n", offset);
offset += 0x100;
if (offset >= 0x1000 && offset < 0x1400)
return mapper_ram[offset & 0x3ff];
@@ -384,7 +384,7 @@ uint8_t nes_waixing_a_device::read_l(offs_t offset)
void nes_waixing_a_device::write_l(offs_t offset, uint8_t data)
{
- LOG_MMC(("waixing write_l, offset: %04x, data: %02x\n", offset, data));
+ LOG("waixing write_l, offset: %04x, data: %02x\n", offset, data);
offset += 0x100;
if (offset >= 0x1000 && offset < 0x1400)
mapper_ram[offset & 0x3ff] = data;
@@ -403,7 +403,7 @@ void nes_waixing_a_device::write_l(offs_t offset, uint8_t data)
iNES: mapper 191
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
@@ -425,7 +425,7 @@ void nes_waixing_b_device::chr_cb(int start, int bank, int source)
iNES: mapper 192
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
@@ -447,7 +447,7 @@ void nes_waixing_c_device::chr_cb(int start, int bank, int source)
iNES: mapper 194
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
@@ -470,7 +470,7 @@ void nes_waixing_d_device::chr_cb(int start, int bank, int source)
iNES: mapper 195
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
@@ -502,7 +502,7 @@ void nes_waixing_e_device::chr_cb(int start, int bank, int source)
u8 nes_waixing_f_device::read_l(offs_t offset)
{
-// LOG_MMC(("waixing_f read_l, offset: %04x\n", offset));
+ LOGMASKED(LOG_HIFREQ, "waixing_f read_l, offset: %04x\n", offset);
offset += 0x100;
if (!m_prgram.empty() && offset >= 0x1000)
@@ -513,7 +513,7 @@ u8 nes_waixing_f_device::read_l(offs_t offset)
void nes_waixing_f_device::write_l(offs_t offset, u8 data)
{
-// LOG_MMC(("waixing_f write_l, offset: %04x, data: %02x\n", offset, data));
+ LOGMASKED(LOG_HIFREQ, "waixing_f write_l, offset: %04x, data: %02x\n", offset, data);
offset += 0x100;
if (!m_prgram.empty() && offset >= 0x1000)
@@ -536,7 +536,7 @@ void nes_waixing_f1_device::set_chr(u8 chr, int chr_base, int chr_mask)
iNES: mapper 199
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
@@ -563,7 +563,7 @@ void nes_waixing_g_device::set_chr(uint8_t chr, int chr_base, int chr_mask)
void nes_waixing_g_device::write_h(offs_t offset, uint8_t data)
{
uint8_t cmd;
- LOG_MMC(("waixing_g write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("waixing_g write_h, offset: %04x, data: %02x\n", offset, data);
switch (offset & 0x6001)
{
@@ -613,7 +613,7 @@ void nes_waixing_g_device::write_h(offs_t offset, uint8_t data)
iNES: mapper 245
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
@@ -626,7 +626,7 @@ void nes_waixing_h_device::chr_cb(int start, int bank, int source)
void nes_waixing_h_device::write_h(offs_t offset, uint8_t data)
{
uint8_t cmd;
- LOG_MMC(("waixing_h write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("waixing_h write_h, offset: %04x, data: %02x\n", offset, data);
switch (offset & 0x6001)
{
@@ -668,7 +668,7 @@ void nes_waixing_h_device::write_h(offs_t offset, uint8_t data)
void nes_waixing_h1_device::write_h(offs_t offset, uint8_t data)
{
uint8_t cmd;
- LOG_MMC(("waixing_h1 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("waixing_h1 write_h, offset: %04x, data: %02x\n", offset, data);
switch (offset & 0x6001)
{
@@ -712,7 +712,7 @@ void nes_waixing_h1_device::write_h(offs_t offset, uint8_t data)
MMC3 clone.
- In MESS: Preliminary support.
+ In MAME: Preliminary support.
-------------------------------------------------*/
@@ -729,7 +729,7 @@ void nes_waixing_j_device::set_prg( int prg_base, int prg_mask )
void nes_waixing_j_device::write_h(offs_t offset, uint8_t data)
{
uint8_t cmd;
- LOG_MMC(("waixing_f write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("waixing_f write_h, offset: %04x, data: %02x\n", offset, data);
switch (offset & 0x6001)
{
@@ -812,7 +812,7 @@ u8 nes_waixing_sh2_device::chr_r(offs_t offset)
iNES: mapper 249
- In MESS: Partially Supported.
+ In MAME: Partially Supported.
-------------------------------------------------*/
@@ -834,7 +834,7 @@ void nes_waixing_sec_device::chr_cb(int start, int bank, int source)
void nes_waixing_sec_device::write_l(offs_t offset, uint8_t data)
{
- LOG_MMC(("waixing_sec write_l, offset: %04x, data: %02x\n", offset, data));
+ LOG("waixing_sec write_l, offset: %04x, data: %02x\n", offset, data);
offset += 0x100;
if (offset == 0x1000)
@@ -854,7 +854,7 @@ void nes_waixing_sec_device::write_l(offs_t offset, uint8_t data)
iNES: mapper 178
- In MESS: Supported.
+ In MAME: Supported.
Implementations wildly vary between emulators, but
Cah4e3's implementation boots up both the games and
@@ -866,7 +866,7 @@ void nes_waixing_sec_device::write_l(offs_t offset, uint8_t data)
void nes_waixing_sgzlz_device::write_l(offs_t offset, uint8_t data)
{
- LOG_MMC(("waixing_sgzlz write_l, offset: %04x, data: %02x\n", offset, data));
+ LOG("waixing_sgzlz write_l, offset: %04x, data: %02x\n", offset, data);
if (offset >= 0x700 && offset <= 0xEFF)
{
m_reg[offset & 0x03] = data;
@@ -925,14 +925,14 @@ void nes_waixing_sgzlz_device::write_l(offs_t offset, uint8_t data)
iNES: mapper 164
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
void nes_waixing_ffv_device::write_l(offs_t offset, uint8_t data)
{
uint8_t helper;
- LOG_MMC(("waixing_ffv write_l, offset: %04x, data: %02x\n", offset, data));
+ LOG("waixing_ffv write_l, offset: %04x, data: %02x\n", offset, data);
offset += 0x100; /* the checks work better on addresses */
if ((offset & 0x1200) == 0x1000)
@@ -974,13 +974,13 @@ void nes_waixing_ffv_device::write_l(offs_t offset, uint8_t data)
iNES: mapper 242
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
void nes_waixing_wxzs_device::write_h(offs_t offset, uint8_t data)
{
- LOG_MMC(("waixing_zs write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("waixing_zs write_h, offset: %04x, data: %02x\n", offset, data);
prg32(offset >> 3);
@@ -1004,13 +1004,13 @@ void nes_waixing_wxzs_device::write_h(offs_t offset, uint8_t data)
iNES: mapper 242
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
void nes_waixing_dq8_device::write_h(offs_t offset, uint8_t data)
{
- LOG_MMC(("waixing_dq8 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("waixing_dq8 write_h, offset: %04x, data: %02x\n", offset, data);
prg32(offset >> 3);
}
@@ -1037,7 +1037,7 @@ void nes_waixing_wxzs2_device::write_h(offs_t offset, uint8_t data)
uint8_t flip = BIT(data, 7);
uint8_t helper = data << 1;
- LOG_MMC(("waixing_wxzs2 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("waixing_wxzs2 write_h, offset: %04x, data: %02x\n", offset, data);
set_nt_mirroring(BIT(data, 6) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
@@ -1081,13 +1081,13 @@ void nes_waixing_wxzs2_device::write_h(offs_t offset, uint8_t data)
iNES: mapper 162? (only found in UNIF format)
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
void nes_waixing_fs304_device::write_l(offs_t offset, uint8_t data)
{
- LOG_MMC(("fs304 write_l, offset: %04x, data: %02x\n", offset, data));
+ LOG("fs304 write_l, offset: %04x, data: %02x\n", offset, data);
offset += 0x100;
if (offset >= 0x1000)
diff --git a/src/devices/bus/nes/zemina.cpp b/src/devices/bus/nes/zemina.cpp
index b46da0e7561..5268a31cb30 100644
--- a/src/devices/bus/nes/zemina.cpp
+++ b/src/devices/bus/nes/zemina.cpp
@@ -10,12 +10,11 @@
#include "zemina.h"
#ifdef NES_PCB_DEBUG
-#define VERBOSE 1
+#define VERBOSE (LOG_GENERAL)
#else
-#define VERBOSE 0
+#define VERBOSE (0)
#endif
-
-#define LOG_MMC(...) do { if (VERBOSE) logerror(__VA_ARGS__); } while (0)
+#include "logmacro.h"
//**************************************************************************
// DEVICE DEFINITIONS
@@ -68,7 +67,7 @@ void nes_zemina_device::pcb_reset()
void nes_zemina_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC("zemina write_h, offset: %04x, data: %02x\n", offset, data);
+ LOG("zemina write_h, offset: %04x, data: %02x\n", offset, data);
switch (offset & 0x6000)
{
diff --git a/src/devices/bus/nes_ctrl/arkpaddle.cpp b/src/devices/bus/nes_ctrl/arkpaddle.cpp
index 67d1d42de7f..48be8990b47 100644
--- a/src/devices/bus/nes_ctrl/arkpaddle.cpp
+++ b/src/devices/bus/nes_ctrl/arkpaddle.cpp
@@ -12,6 +12,14 @@
Known differences: NES and Ark2 paddles have screws to adjust range
of returned values, Ark2 paddle has an extra expansion port.
+ The Ark2 paddle's expansion port is NOT a passthru. OUT0 ($4016 bit 0)
+ is passed along when writing. Pins 13 and 7 (normally read as bit 1
+ from $4016 and $4017) are read from the daisy chained device and passed
+ to the Famicom expansion port pins 5 and 4 (i.e. the Famicom sees them
+ as bits 3,4 at $4017). Due to the limited pin connections the Famicom
+ Keyboard cannot be daisy chained, so the Data Recorder cannot be used
+ simultaneously with the paddle when saving and loading user made levels.
+
All paddles return the ones' complement of a 9-bit value from their
potentiometers, MSB first. The three commercial releases, Arkanoids
and Chase HQ, only read 8-bits, ignoring the LSB.
@@ -25,8 +33,8 @@
// DEVICE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(NES_ARKPADDLE, nes_vaus_device, "nes_vaus", "NES Arkanoid Vaus Controller")
-DEFINE_DEVICE_TYPE(NES_ARKPADDLE_FC, nes_vausfc_device, "nes_vausfc", "FC Arkanoid Vaus Controller")
+DEFINE_DEVICE_TYPE(NES_ARKPADDLE, nes_vaus_device, "nes_vaus", "Taito Arkanoid Vaus Controller (NES)")
+DEFINE_DEVICE_TYPE(NES_ARKPADDLE_FC, nes_vausfc_device, "nes_vausfc", "Taito Arkanoid Vaus Controller (FC)")
static INPUT_PORTS_START( arkanoid_paddle )
@@ -129,8 +137,8 @@ u8 nes_vausfc_device::read_exp(offs_t offset)
{
ret = (m_latch & 0x100) >> 7;
m_latch <<= 1;
- ret |= m_daisychain->read_exp(0) << 2;
- ret |= m_daisychain->read_exp(1) << 3;
+ ret |= (m_daisychain->read_exp(0) & 0x02) << 2;
+ ret |= (m_daisychain->read_exp(1) & 0x02) << 3;
}
return ret;
}
@@ -147,6 +155,6 @@ void nes_vaus_device::write(u8 data)
void nes_vausfc_device::write(u8 data)
{
- m_daisychain->write(data);
+ m_daisychain->write(data & 1);
nes_vaus_device::write(data);
}
diff --git a/src/devices/bus/nes_ctrl/bandaihs.cpp b/src/devices/bus/nes_ctrl/bandaihs.cpp
new file mode 100644
index 00000000000..e77cf7002ab
--- /dev/null
+++ b/src/devices/bus/nes_ctrl/bandaihs.cpp
@@ -0,0 +1,132 @@
+// license:BSD-3-Clause
+// copyright-holders:Fabio Priuli
+/**********************************************************************
+
+ Nintendo Family Computer Bandai Hyper Shot Lightgun
+
+**********************************************************************/
+
+#include "emu.h"
+#include "bandaihs.h"
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(NES_BANDAIHS, nes_bandaihs_device, "nes_bandaihs", "Bandai Hyper Shot Lightgun")
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+static INPUT_PORTS_START( nes_bandaihs )
+ PORT_START("JOYPAD")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED ) // has complete joypad inputs except button A
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("%p B")
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_SELECT )
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_START )
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_8WAY
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_8WAY
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_8WAY
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_8WAY
+
+ PORT_START("GUN_X")
+ PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_X ) PORT_CROSSHAIR(X, 1.0, 0.0, 0) PORT_SENSITIVITY(70) PORT_KEYDELTA(30) PORT_MINMAX(0, 255)
+ PORT_START("GUN_Y")
+ PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_Y ) PORT_CROSSHAIR(Y, 1.0, 0.0, 0) PORT_SENSITIVITY(50) PORT_KEYDELTA(30) PORT_MINMAX(0, 239)
+ PORT_START("GUN_T")
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("Lightgun Trigger")
+INPUT_PORTS_END
+
+ioport_constructor nes_bandaihs_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( nes_bandaihs );
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void nes_bandaihs_device::device_add_mconfig(machine_config &config)
+{
+ NES_ZAPPER_SENSOR(config, m_sensor, 0);
+ if (m_port != nullptr)
+ m_sensor->set_screen_tag(m_port->m_screen);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// constructor
+//-------------------------------------------------
+
+nes_bandaihs_device::nes_bandaihs_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, NES_BANDAIHS, tag, owner, clock)
+ , device_nes_control_port_interface(mconfig, *this)
+ , m_sensor(*this, "sensor")
+ , m_lightx(*this, "GUN_X")
+ , m_lighty(*this, "GUN_Y")
+ , m_trigger(*this, "GUN_T")
+ , m_joypad(*this, "JOYPAD")
+ , m_latch(0)
+{
+}
+
+
+//-------------------------------------------------
+// device_start
+//-------------------------------------------------
+
+void nes_bandaihs_device::device_start()
+{
+ save_item(NAME(m_latch));
+ save_item(NAME(m_strobe));
+}
+
+
+//-------------------------------------------------
+// read
+//-------------------------------------------------
+
+u8 nes_bandaihs_device::read_exp(offs_t offset)
+{
+ u8 ret = 0;
+
+ if (offset == 0) // $4016
+ {
+ if (m_strobe)
+ m_latch = m_joypad->read();
+ ret = (m_latch & 1) << 1;
+ m_latch = (m_latch >> 1) | 0x80;
+ }
+ else // $4017
+ {
+ ret = m_trigger->read();
+ if (!m_sensor->detect_light(m_lightx->read(), m_lighty->read()))
+ ret |= 0x08;
+ }
+
+ return ret;
+}
+
+
+//-------------------------------------------------
+// write
+//-------------------------------------------------
+
+// In addition to bit 0 used here the real Bandai Hyper Shot also responds to
+// bits 1 and 2, neither emulated here. Bit 1 turns on and off a motor, which
+// causes the machine gun to shake as if to simulate recoil. Bit 2 turns on and
+// off an internal speaker in the gun. Videos demostrate that the speaker plays
+// the same audio as the Famicom itself. The analog audio signal of the FC is
+// carried on expansion port pin 2, so there's likely nothing more going on.
+void nes_bandaihs_device::write(u8 data)
+{
+ if (write_strobe(data))
+ m_latch = m_joypad->read();
+}
diff --git a/src/devices/bus/nes_ctrl/bandaihs.h b/src/devices/bus/nes_ctrl/bandaihs.h
new file mode 100644
index 00000000000..3ab57b5a053
--- /dev/null
+++ b/src/devices/bus/nes_ctrl/bandaihs.h
@@ -0,0 +1,53 @@
+// license:BSD-3-Clause
+// copyright-holders:Fabio Priuli
+/**********************************************************************
+
+ Nintendo Family Computer Bandai Hyper Shot Lightgun
+
+**********************************************************************/
+
+#ifndef MAME_BUS_NES_CTRL_BANDAIHS
+#define MAME_BUS_NES_CTRL_BANDAIHS
+
+#pragma once
+
+#include "ctrl.h"
+#include "zapper_sensor.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> nes_bandaihs_device
+
+class nes_bandaihs_device : public device_t,
+ public device_nes_control_port_interface
+{
+public:
+ // construction/destruction
+ nes_bandaihs_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual u8 read_exp(offs_t offset) override;
+ virtual void write(u8 data) override;
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual ioport_constructor device_input_ports() const override;
+
+private:
+ required_device<nes_zapper_sensor_device> m_sensor;
+ required_ioport m_lightx;
+ required_ioport m_lighty;
+ required_ioport m_trigger;
+ required_ioport m_joypad;
+ u8 m_latch;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(NES_BANDAIHS, nes_bandaihs_device)
+
+#endif // MAME_BUS_NES_CTRL_BANDAIHS
diff --git a/src/devices/bus/nes_ctrl/ctrl.cpp b/src/devices/bus/nes_ctrl/ctrl.cpp
index a505b687783..4f508cac556 100644
--- a/src/devices/bus/nes_ctrl/ctrl.cpp
+++ b/src/devices/bus/nes_ctrl/ctrl.cpp
@@ -42,9 +42,11 @@
#include "emu.h"
#include "ctrl.h"
+
// slot devices
#include "4score.h"
#include "arkpaddle.h"
+#include "bandaihs.h"
#include "bcbattle.h"
#include "dorepiano.h"
#include "fckeybrd.h"
@@ -59,6 +61,7 @@
#include "partytap.h"
#include "powerpad.h"
#include "rob.h"
+#include "sharpcass.h"
#include "snesadapter.h"
#include "suborkey.h"
#include "turbofile.h"
@@ -223,6 +226,7 @@ void fc_expansion_devices(device_slot_interface &device)
device.option_add("joypad", NES_FCPAD_EXP);
device.option_add("arcstick", NES_ARCSTICK);
device.option_add("fc_keyboard", NES_FCKEYBOARD);
+ device.option_add("sharp_cassette", NES_SHARPCASS);
device.option_add("zapper", NES_ZAPPER);
device.option_add("bandaihs", NES_BANDAIHS);
device.option_add("vaus", NES_ARKPADDLE_FC);
diff --git a/src/devices/bus/nes_ctrl/fckeybrd.cpp b/src/devices/bus/nes_ctrl/fckeybrd.cpp
index 5633254c8fb..3fd78131bc7 100644
--- a/src/devices/bus/nes_ctrl/fckeybrd.cpp
+++ b/src/devices/bus/nes_ctrl/fckeybrd.cpp
@@ -2,7 +2,7 @@
// copyright-holders:Fabio Priuli
/**********************************************************************
- Nintendo Family Computer Keyboard Component
+ Nintendo Family Computer Keyboard HVC-007 and Data Recorder HVC-008
**********************************************************************/
@@ -13,99 +13,102 @@
// DEVICE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(NES_FCKEYBOARD, nes_fckeybrd_device, "nes_fckeybrd", "Nintendo Family Computer Keyboard Component")
+DEFINE_DEVICE_TYPE(NES_FCKEYBOARD, nes_fckeybrd_device, "nes_fckeybrd", "Nintendo Family Computer Keyboard and Data Recorder")
static INPUT_PORTS_START( fc_keyboard )
PORT_START("FCKEY.0")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F8) PORT_CHAR(UCHAR_MAMEKEY(F8))
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13)
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR('[')
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR(']')
- PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Kana")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F8) PORT_CHAR(UCHAR_MAMEKEY(F8))
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13)
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR('[')
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR(']')
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Kana")
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_RSHIFT)
- PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_BACKSLASH2) PORT_CHAR('\\')
- PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Stop") PORT_CODE(KEYCODE_BACKSPACE)
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_BACKSLASH2) PORT_CHAR('\\')
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_BACKSPACE) PORT_NAME("Stop")
PORT_START("FCKEY.1")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F7) PORT_CHAR(UCHAR_MAMEKEY(F7))
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('@')
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_COLON) PORT_CHAR(':')
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(';')
- PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CHAR('_')
- PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CHAR('/')
- PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-')
- PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('^')
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F7) PORT_CHAR(UCHAR_MAMEKEY(F7))
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('@')
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_COLON) PORT_CHAR(':')
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(';')
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CHAR('_')
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CHAR('/')
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-')
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('^')
PORT_START("FCKEY.2")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F6) PORT_CHAR(UCHAR_MAMEKEY(F6))
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_O) PORT_CHAR('O')
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_L) PORT_CHAR('L')
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_K) PORT_CHAR('K')
- PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.')
- PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',')
- PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_P) PORT_CHAR('P')
- PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_0) PORT_CHAR('0')
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F6) PORT_CHAR(UCHAR_MAMEKEY(F6))
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_O) PORT_CHAR('O')
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_L) PORT_CHAR('L')
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_K) PORT_CHAR('K')
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.')
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',')
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_P) PORT_CHAR('P')
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_0) PORT_CHAR('0')
PORT_START("FCKEY.3")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F5) PORT_CHAR(UCHAR_MAMEKEY(F5))
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_I) PORT_CHAR('I')
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_U) PORT_CHAR('U')
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_J) PORT_CHAR('J')
- PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_M) PORT_CHAR('M')
- PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_N) PORT_CHAR('N')
- PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_9) PORT_CHAR('9')
- PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_8) PORT_CHAR('8')
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F5) PORT_CHAR(UCHAR_MAMEKEY(F5))
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_I) PORT_CHAR('I')
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_U) PORT_CHAR('U')
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_J) PORT_CHAR('J')
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_M) PORT_CHAR('M')
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_N) PORT_CHAR('N')
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_9) PORT_CHAR('9')
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_8) PORT_CHAR('8')
PORT_START("FCKEY.4")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F4) PORT_CHAR(UCHAR_MAMEKEY(F4))
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Y) PORT_CHAR('Y')
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_G) PORT_CHAR('G')
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_H) PORT_CHAR('H')
- PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_B) PORT_CHAR('B')
- PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_V) PORT_CHAR('V')
- PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_7) PORT_CHAR('7')
- PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_6) PORT_CHAR('6')
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F4) PORT_CHAR(UCHAR_MAMEKEY(F4))
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Y) PORT_CHAR('Y')
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_G) PORT_CHAR('G')
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_H) PORT_CHAR('H')
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_B) PORT_CHAR('B')
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_V) PORT_CHAR('V')
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_7) PORT_CHAR('7')
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_6) PORT_CHAR('6')
PORT_START("FCKEY.5")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F3) PORT_CHAR(UCHAR_MAMEKEY(F3))
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_T) PORT_CHAR('T')
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_R) PORT_CHAR('R')
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_D) PORT_CHAR('D')
- PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F) PORT_CHAR('F')
- PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_C) PORT_CHAR('C')
- PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_5) PORT_CHAR('5')
- PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_4) PORT_CHAR('4')
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F3) PORT_CHAR(UCHAR_MAMEKEY(F3))
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_T) PORT_CHAR('T')
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_R) PORT_CHAR('R')
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_D) PORT_CHAR('D')
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F) PORT_CHAR('F')
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_C) PORT_CHAR('C')
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_5) PORT_CHAR('5')
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_4) PORT_CHAR('4')
PORT_START("FCKEY.6")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F2) PORT_CHAR(UCHAR_MAMEKEY(F2))
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_W) PORT_CHAR('W')
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_S) PORT_CHAR('S')
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_A) PORT_CHAR('A')
- PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_X) PORT_CHAR('X')
- PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Z) PORT_CHAR('Z')
- PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_E) PORT_CHAR('E')
- PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_3) PORT_CHAR('3')
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F2) PORT_CHAR(UCHAR_MAMEKEY(F2))
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_W) PORT_CHAR('W')
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_S) PORT_CHAR('S')
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_A) PORT_CHAR('A')
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_X) PORT_CHAR('X')
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Z) PORT_CHAR('Z')
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_E) PORT_CHAR('E')
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_3) PORT_CHAR('3')
PORT_START("FCKEY.7")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F1) PORT_CHAR(UCHAR_MAMEKEY(F1))
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_TAB) PORT_CHAR(UCHAR_MAMEKEY(ESC))
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Q) PORT_CHAR('Q')
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_LCONTROL) PORT_CHAR(UCHAR_SHIFT_2)
- PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_LSHIFT) PORT_CHAR(UCHAR_SHIFT_1)
- PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Grph") PORT_CODE(KEYCODE_LALT)
- PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_1) PORT_CHAR('1')
- PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_2) PORT_CHAR('2')
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F1) PORT_CHAR(UCHAR_MAMEKEY(F1))
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_TAB) PORT_CHAR(UCHAR_MAMEKEY(ESC))
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Q) PORT_CHAR('Q')
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_LCONTROL) PORT_CHAR(UCHAR_SHIFT_2)
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_LSHIFT) PORT_CHAR(UCHAR_SHIFT_1)
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Grph") PORT_CODE(KEYCODE_LALT)
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_1) PORT_CHAR('1')
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_2) PORT_CHAR('2')
PORT_START("FCKEY.8")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Clr")
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP))
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT))
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_LEFT) PORT_CHAR(UCHAR_MAMEKEY(LEFT))
- PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN))
- PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ')
- PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Del") PORT_CODE(KEYCODE_DEL)
- PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Ins") PORT_CODE(KEYCODE_INSERT)
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP))
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT))
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_LEFT) PORT_CHAR(UCHAR_MAMEKEY(LEFT))
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN))
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ')
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_DEL) PORT_NAME("Del")
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_INSERT) PORT_NAME("Ins")
+
+ PORT_START("FCKEY.9")
+ PORT_BIT( 0xff, IP_ACTIVE_HIGH, IPT_UNUSED ) // final dummy row
INPUT_PORTS_END
@@ -139,13 +142,14 @@ void nes_fckeybrd_device::device_add_mconfig(machine_config &config)
// nes_fckeybrd_device - constructor
//-------------------------------------------------
-nes_fckeybrd_device::nes_fckeybrd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_fckeybrd_device::nes_fckeybrd_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: device_t(mconfig, NES_FCKEYBOARD, tag, owner, clock)
, device_nes_control_port_interface(mconfig, *this)
, m_cassette(*this, "tape")
, m_kbd(*this, "FCKEY.%u", 0)
, m_fck_scan(0)
- , m_fck_mode(0)
+ , m_fck_nibble(0)
+ , m_fck_enable(0)
{
}
@@ -157,18 +161,8 @@ nes_fckeybrd_device::nes_fckeybrd_device(const machine_config &mconfig, const ch
void nes_fckeybrd_device::device_start()
{
save_item(NAME(m_fck_scan));
- save_item(NAME(m_fck_mode));
-}
-
-
-//-------------------------------------------------
-// device_reset
-//-------------------------------------------------
-
-void nes_fckeybrd_device::device_reset()
-{
- m_fck_scan = 0;
- m_fck_mode = 0;
+ save_item(NAME(m_fck_nibble));
+ save_item(NAME(m_fck_enable));
}
@@ -176,28 +170,26 @@ void nes_fckeybrd_device::device_reset()
// read
//-------------------------------------------------
-uint8_t nes_fckeybrd_device::read_exp(offs_t offset)
+u8 nes_fckeybrd_device::read_exp(offs_t offset)
{
- uint8_t ret = 0;
- if (offset == 0) //$4016
+ u8 ret = 0;
+
+ if (m_fck_enable)
{
- // FC Keyboard: tape input
- if ((m_cassette->get_state() & CASSETTE_MASK_UISTATE) == CASSETTE_PLAY)
+ if (offset == 0) // $4016
{
- double level = m_cassette->input();
- if (level < 0)
- ret |= 0x00;
- else
- ret |= 0x02;
+ // FC Keyboard: tape input
+ if ((m_cassette->get_state() & CASSETTE_MASK_UISTATE) == CASSETTE_PLAY)
+ {
+ if (m_cassette->input() >= 0)
+ ret |= 0x02;
+ }
+ }
+ else // $4017
+ {
+ // FC Keyboard: rows of the keyboard matrix are read 4-bits at time and returned as bit1->bit4
+ ret |= BIT(~m_kbd[m_fck_scan]->read(), m_fck_nibble * 4, 4) << 1;
}
- }
- else //$4017
- {
- // FC Keyboard: rows of the keyboard matrix are read 4-bits at time and returned as bit1->bit4
- if (m_fck_scan < 9)
- ret |= ~(((m_kbd[m_fck_scan]->read() >> (m_fck_mode * 4)) & 0x0f) << 1) & 0x1e;
- else
- ret |= 0x1e;
}
return ret;
@@ -207,22 +199,19 @@ uint8_t nes_fckeybrd_device::read_exp(offs_t offset)
// write
//-------------------------------------------------
-void nes_fckeybrd_device::write(uint8_t data)
+void nes_fckeybrd_device::write(u8 data)
{
// tape output (not fully tested)
if ((m_cassette->get_state() & CASSETTE_MASK_UISTATE) == CASSETTE_RECORD)
- m_cassette->output(((data & 0x07) == 0x07) ? +1.0 : -1.0);
+ m_cassette->output(BIT(data, 0) ? -1.0 : +1.0); // Arkanoid 2 requires this polarity for saving
- if (BIT(data, 2)) // keyboard active
- {
- uint8_t out = BIT(data, 1); // scan
-
- if (m_fck_mode && !out && ++m_fck_scan > 9)
- m_fck_scan = 0;
+ m_fck_enable = BIT(data, 2);
- m_fck_mode = out; // access lower or upper 4 bits
+ u8 prev = m_fck_nibble;
+ m_fck_nibble = BIT(data, 1);
+ if (prev && !m_fck_nibble)
+ m_fck_scan = (m_fck_scan + 1) % m_kbd.size();
- if (BIT(data, 0)) // reset
- m_fck_scan = 0;
- }
+ if (BIT(data, 0)) // reset
+ m_fck_scan = 0;
}
diff --git a/src/devices/bus/nes_ctrl/fckeybrd.h b/src/devices/bus/nes_ctrl/fckeybrd.h
index b293b4e9b10..137ff90fc1f 100644
--- a/src/devices/bus/nes_ctrl/fckeybrd.h
+++ b/src/devices/bus/nes_ctrl/fckeybrd.h
@@ -2,7 +2,7 @@
// copyright-holders:Fabio Priuli
/**********************************************************************
- Nintendo Family Computer Keyboard Component
+ Nintendo Family Computer Keyboard HVC-007 and Data Recorder HVC-008
**********************************************************************/
@@ -26,23 +26,22 @@ class nes_fckeybrd_device : public device_t,
{
public:
// construction/destruction
- nes_fckeybrd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ nes_fckeybrd_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
- virtual uint8_t read_exp(offs_t offset) override;
- virtual void write(uint8_t data) override;
+ virtual u8 read_exp(offs_t offset) override;
+ virtual void write(u8 data) override;
protected:
// device-level overrides
virtual void device_start() override;
- virtual void device_reset() override;
virtual ioport_constructor device_input_ports() const override;
virtual void device_add_mconfig(machine_config &config) override;
private:
required_device<cassette_image_device> m_cassette;
- required_ioport_array<9> m_kbd;
- uint8_t m_fck_scan, m_fck_mode;
+ required_ioport_array<10> m_kbd;
+ u8 m_fck_scan, m_fck_nibble, m_fck_enable;
};
diff --git a/src/devices/bus/nes_ctrl/rob.cpp b/src/devices/bus/nes_ctrl/rob.cpp
index 24747e6a088..5e101d55042 100644
--- a/src/devices/bus/nes_ctrl/rob.cpp
+++ b/src/devices/bus/nes_ctrl/rob.cpp
@@ -2,14 +2,14 @@
// copyright-holders:hap
/**********************************************************************
- Nintendo HVC-012 Family Computer Robot / Nintendo NES-012 R.O.B.
+Nintendo HVC-012 Family Computer Robot / Nintendo NES-012 R.O.B.
- TODO:
- - does nes_rob have motor sensors? (eg. limit switches, or optical
- sensor to determine position)
- - can't really play anything with nes_rob, because of interaction
- with physical objects (gyromite especially, since it has a gadget
- to make the robot press joypad buttons)
+TODO:
+- does nes_rob have motor sensors? (eg. limit switches, or optical
+ sensor to determine position)
+- can't really play anything with nes_rob, because of interaction
+ with physical objects (gyromite especially, since it has a gadget
+ to make the robot press joypad buttons)
**********************************************************************/
@@ -25,6 +25,10 @@
DEFINE_DEVICE_TYPE(NES_ROB, nes_rob_device, "nes_rob", "Nintendo R.O.B. / Family Computer Robot")
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
static INPUT_PORTS_START( nes_rob )
PORT_START("EYE_X")
PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_X ) PORT_CROSSHAIR(X, 1.0, 0.0, 0) PORT_SENSITIVITY(70) PORT_KEYDELTA(30) PORT_MINMAX(0, 255)
@@ -32,11 +36,6 @@ static INPUT_PORTS_START( nes_rob )
PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_Y ) PORT_CROSSHAIR(Y, 1.0, 0.0, 0) PORT_SENSITIVITY(50) PORT_KEYDELTA(30) PORT_MINMAX(0, 239)
INPUT_PORTS_END
-
-//-------------------------------------------------
-// input_ports - device-specific input ports
-//-------------------------------------------------
-
ioport_constructor nes_rob_device::device_input_ports() const
{
return INPUT_PORTS_NAME( nes_rob );
@@ -83,7 +82,7 @@ void nes_rob_device::device_start()
u8 nes_rob_device::input_r()
{
// R00: lightsensor
- return !m_sensor->detect_light(m_eye_x->read(), m_eye_y->read());
+ return m_sensor->detect_light(m_eye_x->read(), m_eye_y->read()) ? 0 : 1;
}
void nes_rob_device::output_w(offs_t offset, u8 data)
diff --git a/src/devices/bus/nes_ctrl/sharpcass.cpp b/src/devices/bus/nes_ctrl/sharpcass.cpp
new file mode 100644
index 00000000000..5668498bfd0
--- /dev/null
+++ b/src/devices/bus/nes_ctrl/sharpcass.cpp
@@ -0,0 +1,89 @@
+// license:BSD-3-Clause
+// copyright-holders:kmg
+/**********************************************************************
+
+ Nintendo Family Computer Sharp Cassette Interface AN-300SL
+
+ An alternative to the Nintendo released Data Recorder. Unlike the
+ Data Recorder, which plugs into the Famicom Keyboard via audio jacks,
+ this Sharp Cassette Interface plugs directly into the expansion port
+ and connects to any cassette deck via two audio jacks. The Sharp and
+ Nintendo cassette interfaces are software incompatible.
+
+ This device is used by the built-in Graphics/Note program of the
+ Sharp My Computer Terebi C1 for saving/loading. Is there any other
+ use for this device?
+
+ TODO: The menu option of "play" when verifying saved data suggests
+ that the unit autodetects when the play button is pressed on a
+ cassette deck and signals this somehow to the Graphics/Note program.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "sharpcass.h"
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(NES_SHARPCASS, nes_sharpcass_device, "nes_sharpcass", "Sharp Cassette Interface AN-300SL")
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void nes_sharpcass_device::device_add_mconfig(machine_config &config)
+{
+ CASSETTE(config, m_cassette);
+ m_cassette->set_default_state(CASSETTE_STOPPED | CASSETTE_MOTOR_ENABLED | CASSETTE_SPEAKER_ENABLED);
+ m_cassette->set_interface("fc_cass");
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// nes_sharpcass_device - constructor
+//-------------------------------------------------
+
+nes_sharpcass_device::nes_sharpcass_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, NES_SHARPCASS, tag, owner, clock)
+ , device_nes_control_port_interface(mconfig, *this)
+ , m_cassette(*this, "tape")
+{
+}
+
+
+//-------------------------------------------------
+// read
+//-------------------------------------------------
+
+u8 nes_sharpcass_device::read_exp(offs_t offset)
+{
+ u8 ret = 0;
+
+ if (offset == 1) // $4017
+ {
+ if ((m_cassette->get_state() & CASSETTE_MASK_UISTATE) == CASSETTE_PLAY)
+ {
+ if (m_cassette->input() < 0)
+ ret |= 0x04;
+ }
+ }
+
+ return ret;
+}
+
+//-------------------------------------------------
+// write
+//-------------------------------------------------
+
+void nes_sharpcass_device::write(u8 data)
+{
+ if ((m_cassette->get_state() & CASSETTE_MASK_UISTATE) == CASSETTE_RECORD)
+ m_cassette->output(BIT(data, 2) ? +1.0 : -1.0);
+}
diff --git a/src/devices/bus/nes_ctrl/sharpcass.h b/src/devices/bus/nes_ctrl/sharpcass.h
new file mode 100644
index 00000000000..c66b561c066
--- /dev/null
+++ b/src/devices/bus/nes_ctrl/sharpcass.h
@@ -0,0 +1,48 @@
+// license:BSD-3-Clause
+// copyright-holders:kmg
+/**********************************************************************
+
+ Nintendo Family Computer Sharp Cassette Interface AN-300SL
+
+**********************************************************************/
+
+#ifndef MAME_BUS_NES_CTRL_SHARPCASS_H
+#define MAME_BUS_NES_CTRL_SHARPCASS_H
+
+#pragma once
+
+#include "ctrl.h"
+#include "imagedev/cassette.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> nes_sharpcass_device
+
+class nes_sharpcass_device : public device_t,
+ public device_nes_control_port_interface
+{
+public:
+ // construction/destruction
+ nes_sharpcass_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual u8 read_exp(offs_t offset) override;
+ virtual void write(u8 data) override;
+
+protected:
+ // device-level overrides
+ virtual void device_start() override { }
+
+ virtual void device_add_mconfig(machine_config &config) override;
+
+private:
+ required_device<cassette_image_device> m_cassette;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(NES_SHARPCASS, nes_sharpcass_device)
+
+#endif // MAME_BUS_NES_CTRL_SHARPCASS_H
diff --git a/src/devices/bus/nes_ctrl/zapper.cpp b/src/devices/bus/nes_ctrl/zapper.cpp
index 5d55b1f2d3f..8562db41bec 100644
--- a/src/devices/bus/nes_ctrl/zapper.cpp
+++ b/src/devices/bus/nes_ctrl/zapper.cpp
@@ -3,7 +3,6 @@
/**********************************************************************
Nintendo Family Computer & Entertainment System Zapper Lightgun
- Nintendo Family Computer Bandai Hyper Shot Lightgun
**********************************************************************/
@@ -15,48 +14,34 @@
//**************************************************************************
DEFINE_DEVICE_TYPE(NES_ZAPPER, nes_zapper_device, "nes_zapper", "Nintendo Zapper Lightgun")
-DEFINE_DEVICE_TYPE(NES_BANDAIHS, nes_bandaihs_device, "nes_bandaihs", "Bandai Hyper Shot Lightgun")
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
static INPUT_PORTS_START( nes_zapper )
- PORT_START("ZAPPER_X")
+ PORT_START("GUN_X")
PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_X ) PORT_CROSSHAIR(X, 1.0, 0.0, 0) PORT_SENSITIVITY(70) PORT_KEYDELTA(30) PORT_MINMAX(0, 255)
- PORT_START("ZAPPER_Y")
+ PORT_START("GUN_Y")
PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_Y ) PORT_CROSSHAIR(Y, 1.0, 0.0, 0) PORT_SENSITIVITY(50) PORT_KEYDELTA(30) PORT_MINMAX(0, 239)
- PORT_START("ZAPPER_T")
- PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("Lightgun Trigger")
+ PORT_START("GUN_T")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("Lightgun Trigger") PORT_CHANGED_MEMBER(DEVICE_SELF, nes_zapper_device, trigger, 0)
INPUT_PORTS_END
-
-static INPUT_PORTS_START( nes_bandaihs )
- PORT_INCLUDE( nes_zapper )
-
- PORT_START("JOYPAD")
- PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED ) // has complete joypad inputs except button A
- PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("%p B")
- PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_SELECT )
- PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_START )
- PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_8WAY
- PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_8WAY
- PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_8WAY
- PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_8WAY
-INPUT_PORTS_END
-
-
-//-------------------------------------------------
-// input_ports - device-specific input ports
-//-------------------------------------------------
-
ioport_constructor nes_zapper_device::device_input_ports() const
{
return INPUT_PORTS_NAME( nes_zapper );
}
-ioport_constructor nes_bandaihs_device::device_input_ports() const
+INPUT_CHANGED_MEMBER(nes_zapper_device::trigger)
{
- return INPUT_PORTS_NAME( nes_bandaihs );
+ // a trigger pull is active for around 3-4 frames
+ if (newval)
+ m_trigger->adjust(attotime::from_msec(50));
}
+
//-------------------------------------------------
// device_add_mconfig - add device configuration
//-------------------------------------------------
@@ -77,25 +62,12 @@ void nes_zapper_device::device_add_mconfig(machine_config &config)
// constructor
//-------------------------------------------------
-nes_zapper_device::nes_zapper_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
- : device_t(mconfig, type, tag, owner, clock)
+nes_zapper_device::nes_zapper_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, NES_ZAPPER, tag, owner, clock)
, device_nes_control_port_interface(mconfig, *this)
, m_sensor(*this, "sensor")
- , m_lightx(*this, "ZAPPER_X")
- , m_lighty(*this, "ZAPPER_Y")
- , m_trigger(*this, "ZAPPER_T")
-{
-}
-
-nes_zapper_device::nes_zapper_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
- : nes_zapper_device(mconfig, NES_ZAPPER, tag, owner, clock)
-{
-}
-
-nes_bandaihs_device::nes_bandaihs_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
- : nes_zapper_device(mconfig, NES_BANDAIHS, tag, owner, clock)
- , m_joypad(*this, "JOYPAD")
- , m_latch(0)
+ , m_lightx(*this, "GUN_X")
+ , m_lighty(*this, "GUN_Y")
{
}
@@ -106,13 +78,7 @@ nes_bandaihs_device::nes_bandaihs_device(const machine_config &mconfig, const ch
void nes_zapper_device::device_start()
{
-}
-
-void nes_bandaihs_device::device_start()
-{
- nes_zapper_device::device_start();
- save_item(NAME(m_latch));
- save_item(NAME(m_strobe));
+ m_trigger = timer_alloc(timer_expired_delegate());
}
@@ -122,7 +88,7 @@ void nes_bandaihs_device::device_start()
u8 nes_zapper_device::read_bit34()
{
- u8 ret = m_trigger->read();
+ u8 ret = m_trigger->enabled() ? 0x10 : 0;
if (!m_sensor->detect_light(m_lightx->read(), m_lighty->read()))
ret |= 0x08;
@@ -137,32 +103,3 @@ u8 nes_zapper_device::read_exp(offs_t offset)
ret = nes_zapper_device::read_bit34();
return ret;
}
-
-u8 nes_bandaihs_device::read_exp(offs_t offset)
-{
- u8 ret = 0;
-
- if (offset == 0) // $4016
- {
- if (m_strobe)
- m_latch = m_joypad->read();
- ret = (m_latch & 1) << 1;
- m_latch = (m_latch >> 1) | 0x80;
- }
- else // $4017
- ret = nes_zapper_device::read_exp(offset);
-
- return ret;
-}
-
-// In addition to bit 0 used here the real Bandai Hyper Shot also responds to
-// bits 1 and 2, neither emulated here. Bit 1 turns on and off a motor, which
-// causes the machine gun to shake as if to simulate recoil. Bit 2 turns on and
-// off an internal speaker in the gun. Videos demostrate that the speaker plays
-// the same audio as the Famicom itself. The analog audio signal of the FC is
-// carried on expansion port pin 2, so there's likely nothing more going on.
-void nes_bandaihs_device::write(u8 data)
-{
- if (write_strobe(data))
- m_latch = m_joypad->read();
-}
diff --git a/src/devices/bus/nes_ctrl/zapper.h b/src/devices/bus/nes_ctrl/zapper.h
index d3ca9a298bf..232a38cce5b 100644
--- a/src/devices/bus/nes_ctrl/zapper.h
+++ b/src/devices/bus/nes_ctrl/zapper.h
@@ -3,7 +3,6 @@
/**********************************************************************
Nintendo Family Computer & Entertainment System Zapper Lightgun
- Nintendo Family Computer Bandai Hyper Shot Lightgun
**********************************************************************/
@@ -32,10 +31,9 @@ public:
virtual u8 read_bit34() override;
virtual u8 read_exp(offs_t offset) override;
-protected:
- // construction/destruction
- nes_zapper_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+ DECLARE_INPUT_CHANGED_MEMBER(trigger);
+protected:
// device-level overrides
virtual void device_start() override;
virtual void device_add_mconfig(machine_config &config) override;
@@ -45,34 +43,11 @@ private:
required_device<nes_zapper_sensor_device> m_sensor;
required_ioport m_lightx;
required_ioport m_lighty;
- required_ioport m_trigger;
-};
-
-
-// ======================> nes_bandaihs_device
-
-class nes_bandaihs_device : public nes_zapper_device
-{
-public:
- // construction/destruction
- nes_bandaihs_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
-
- virtual u8 read_exp(offs_t offset) override;
- virtual void write(u8 data) override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
- virtual ioport_constructor device_input_ports() const override;
-
-private:
- required_ioport m_joypad;
- u8 m_latch;
+ emu_timer *m_trigger;
};
// device type definition
DECLARE_DEVICE_TYPE(NES_ZAPPER, nes_zapper_device)
-DECLARE_DEVICE_TYPE(NES_BANDAIHS, nes_bandaihs_device)
#endif // MAME_BUS_NES_CTRL_ZAPPER
diff --git a/src/devices/bus/newbrain/eim.cpp b/src/devices/bus/newbrain/eim.cpp
index 7b3685eeea7..9b44f80b55f 100644
--- a/src/devices/bus/newbrain/eim.cpp
+++ b/src/devices/bus/newbrain/eim.cpp
@@ -223,7 +223,7 @@ void newbrain_eim_device::anio_w(uint8_t data)
// adc_eoc_w -
//-------------------------------------------------
-WRITE_LINE_MEMBER( newbrain_eim_device::adc_eoc_w )
+void newbrain_eim_device::adc_eoc_w(int state)
{
m_anint = state;
}
@@ -233,7 +233,7 @@ WRITE_LINE_MEMBER( newbrain_eim_device::adc_eoc_w )
// acia_interrupt -
//-------------------------------------------------
-WRITE_LINE_MEMBER( newbrain_eim_device::acia_interrupt )
+void newbrain_eim_device::acia_interrupt(int state)
{
m_aciaint = state;
}
@@ -243,7 +243,7 @@ WRITE_LINE_MEMBER( newbrain_eim_device::acia_interrupt )
// ctc_z2_w -
//-------------------------------------------------
-WRITE_LINE_MEMBER( newbrain_eim_device::ctc_z2_w )
+void newbrain_eim_device::ctc_z2_w(int state)
{
// connected to CTC channel 0/1 clock inputs
m_ctc->trg0(state);
diff --git a/src/devices/bus/newbrain/eim.h b/src/devices/bus/newbrain/eim.h
index 4241fd4b69a..89551a4bca4 100644
--- a/src/devices/bus/newbrain/eim.h
+++ b/src/devices/bus/newbrain/eim.h
@@ -54,9 +54,9 @@ protected:
virtual void iorq_w(offs_t offset, uint8_t data, bool &prtov) override;
private:
- DECLARE_WRITE_LINE_MEMBER( acia_interrupt );
- DECLARE_WRITE_LINE_MEMBER( ctc_z2_w );
- DECLARE_WRITE_LINE_MEMBER( adc_eoc_w );
+ void acia_interrupt(int state);
+ void ctc_z2_w(int state);
+ void adc_eoc_w(int state);
TIMER_DEVICE_CALLBACK_MEMBER(ctc_c2_tick);
diff --git a/src/devices/bus/newbrain/fdc.cpp b/src/devices/bus/newbrain/fdc.cpp
index fa046e0d5a9..c726a36f020 100644
--- a/src/devices/bus/newbrain/fdc.cpp
+++ b/src/devices/bus/newbrain/fdc.cpp
@@ -231,7 +231,7 @@ void newbrain_fdc_device::moton(int state)
// fdc_int_w -
//-------------------------------------------------
-WRITE_LINE_MEMBER( newbrain_fdc_device::fdc_int_w )
+void newbrain_fdc_device::fdc_int_w(int state)
{
m_fdc_int = state;
}
diff --git a/src/devices/bus/newbrain/fdc.h b/src/devices/bus/newbrain/fdc.h
index 3ac24faffa6..a95d4679d2b 100644
--- a/src/devices/bus/newbrain/fdc.h
+++ b/src/devices/bus/newbrain/fdc.h
@@ -46,7 +46,7 @@ protected:
virtual void iorq_w(offs_t offset, uint8_t data, bool &prtov) override;
private:
- DECLARE_WRITE_LINE_MEMBER( fdc_int_w );
+ void fdc_int_w(int state);
void fdc_auxiliary_w(uint8_t data);
uint8_t fdc_control_r();
diff --git a/src/devices/bus/nscsi/cd.cpp b/src/devices/bus/nscsi/cd.cpp
index 750f7be774a..1aea67056fd 100644
--- a/src/devices/bus/nscsi/cd.cpp
+++ b/src/devices/bus/nscsi/cd.cpp
@@ -3,14 +3,19 @@
#include "emu.h"
#include "bus/nscsi/cd.h"
+#include "coreutil.h"
+#include "multibyte.h"
+
#define VERBOSE 0
#include "logmacro.h"
DEFINE_DEVICE_TYPE(NSCSI_CDROM, nscsi_cdrom_device, "scsi_cdrom", "SCSI CD-ROM")
DEFINE_DEVICE_TYPE(NSCSI_CDROM_SGI, nscsi_cdrom_sgi_device, "scsi_cdrom_sgi", "SCSI CD-ROM SGI")
+DEFINE_DEVICE_TYPE(NSCSI_CDROM_NEWS, nscsi_cdrom_news_device, "scsi_cdrom_news", "SCSI CD-ROM NEWS")
DEFINE_DEVICE_TYPE(NSCSI_RRD45, nscsi_dec_rrd45_device, "nrrd45", "RRD45 CD-ROM (New)")
DEFINE_DEVICE_TYPE(NSCSI_XM3301, nscsi_toshiba_xm3301_device, "nxm3301", "XM-3301TA CD-ROM (New)")
DEFINE_DEVICE_TYPE(NSCSI_XM5301SUN, nscsi_toshiba_xm5301_sun_device, "nxm5301sun", "XM-5301B Sun 4x CD-ROM (New)")
+DEFINE_DEVICE_TYPE(NSCSI_XM5401, nscsi_toshiba_xm5401_device, "nxm5401", "XM-5401B 4x CD-ROM (New)")
DEFINE_DEVICE_TYPE(NSCSI_XM5401SUN, nscsi_toshiba_xm5401_sun_device, "nxm5401sun", "XM-5401B Sun 4x CD-ROM (New)")
DEFINE_DEVICE_TYPE(NSCSI_XM5701, nscsi_toshiba_xm5701_device, "nxm5701", "XM-5701B 12x CD-ROM (New)")
DEFINE_DEVICE_TYPE(NSCSI_XM5701SUN, nscsi_toshiba_xm5701_sun_device, "nxm5701sun", "XM-5701B Sun 12x CD-ROM (New)")
@@ -26,6 +31,11 @@ nscsi_cdrom_sgi_device::nscsi_cdrom_sgi_device(const machine_config &mconfig, co
{
}
+nscsi_cdrom_news_device::nscsi_cdrom_news_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ nscsi_cdrom_device(mconfig, NSCSI_CDROM_NEWS, tag, owner, "Sony", "CD-ROM CDU-541", "1.0A", 0x00, 0x05)
+{
+}
+
nscsi_dec_rrd45_device::nscsi_dec_rrd45_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
nscsi_cdrom_device(mconfig, NSCSI_RRD45, tag, owner, "DEC ", "RRD45 (C) DEC ", "0436", 0x98, 0x02)
{
@@ -41,6 +51,11 @@ nscsi_toshiba_xm5301_sun_device::nscsi_toshiba_xm5301_sun_device(const machine_c
{
}
+nscsi_toshiba_xm5401_device::nscsi_toshiba_xm5401_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ nscsi_cdrom_device(mconfig, NSCSI_XM5401, tag, owner, "TOSHIBA ", "CD-ROM XM-5401TA", "3605", 0x98, 0x02)
+{
+}
+
nscsi_toshiba_xm5401_sun_device::nscsi_toshiba_xm5401_sun_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
nscsi_cdrom_device(mconfig, NSCSI_XM5401SUN, tag, owner, "TOSHIBA ", "XM-5401TASUN4XCD", "1036", 0x98, 0x02)
{
@@ -58,40 +73,47 @@ nscsi_toshiba_xm5701_sun_device::nscsi_toshiba_xm5701_sun_device(const machine_c
// drive identifies as an original Apple CDSC (Sony CDU-8001 with custom firmware)
nscsi_cdrom_apple_device::nscsi_cdrom_apple_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- nscsi_cdrom_device(mconfig, NSCSI_CDROM_APPLE, tag, owner, "Sony", "CD-ROM CDU-8001", "1.0", 0x00, 0x05)
+ nscsi_cdrom_device(mconfig, NSCSI_CDROM_APPLE, tag, owner, "SONY ", "CD-ROM CDU-8002 ", "1.8g", 0x00, 0x05),
+ m_stopped(true),
+ m_stop_position(0)
{
}
nscsi_cdrom_device::nscsi_cdrom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
: nscsi_full_device(mconfig, type, tag, owner, clock)
- , cdrom(nullptr)
+ , image(*this, "image")
+ , cdda(*this, "cdda")
, bytes_per_block(bytes_per_sector)
, lba(0)
, cur_sector(0)
- , image(*this, "image")
{
}
void nscsi_cdrom_device::device_start()
{
nscsi_full_device::device_start();
+
save_item(NAME(sector_buffer));
save_item(NAME(lba));
save_item(NAME(cur_sector));
save_item(NAME(bytes_per_block));
+ save_item(NAME(mode_data_size));
}
void nscsi_cdrom_device::device_reset()
{
nscsi_full_device::device_reset();
- cdrom = image->get_cdrom_file();
+ sequence_counter = image->sequence_counter();
lba = 0;
cur_sector = -1;
+ mode_data_size = 12;
}
void nscsi_cdrom_device::device_add_mconfig(machine_config &config)
{
CDROM(config, image).set_interface("cdrom");
+
+ CDDA(config, cdda).set_cdrom_tag(image);
}
int nscsi_cdrom_device::to_msf(int frame)
@@ -123,7 +145,7 @@ uint8_t nscsi_cdrom_device::scsi_get_data(int id, int pos)
const int extra_pos = (lba * bytes_per_block) % bytes_per_sector;
if(sector != cur_sector) {
cur_sector = sector;
- if(!cdrom->read_data(sector, sector_buffer, cdrom_file::CD_TRACK_MODE1)) {
+ if(!image->read_data(sector, sector_buffer, cdrom_file::CD_TRACK_MODE1)) {
LOG("CD READ ERROR sector %d!\n", sector);
std::fill_n(sector_buffer, sizeof(sector_buffer), 0);
}
@@ -139,14 +161,30 @@ void nscsi_cdrom_device::scsi_put_data(int id, int pos, uint8_t data)
}
// process mode parameter header and one block descriptor
- if(pos < sizeof(mode_data)) {
+ if(pos < mode_data_size) {
mode_data[pos] = data;
// is this the last byte of the mode parameter block descriptor?
- if(pos == sizeof(mode_data) - 1)
+ if(pos == mode_data_size - 1) {
// is there exactly one block descriptor?
if(mode_data[3] == 8)
- set_block_size((mode_data[9] << 16) | (mode_data[10] << 8) | (mode_data[11] << 0));
+ set_block_size(get_u24be(&mode_data[9]));
+
+ // Size of block descriptor should change based on if it's mode select (6) or (10)
+ // TODO: Find a usage of mode select (10) for testing
+ int pagedata_offset = 4 + mode_data[3];
+ switch(mode_data[pagedata_offset] & 0x3f) {
+ case 0x0e: // CD Audio Control Mode Page
+ cdda_sotc = BIT(mode_data[pagedata_offset+2], 1);
+ LOG("Ch 0 route: %x vol: %x\n", mode_data[pagedata_offset+8], mode_data[pagedata_offset+9]);
+ LOG("Ch 1 route: %x vol: %x\n", mode_data[pagedata_offset+10], mode_data[pagedata_offset+11]);
+ LOG("Ch 2 route: %x vol: %x\n", mode_data[pagedata_offset+12], mode_data[pagedata_offset+13]);
+ LOG("Ch 3 route: %x vol: %x\n", mode_data[pagedata_offset+14], mode_data[pagedata_offset+15]);
+ cdda->set_output_gain(0, mode_data[pagedata_offset+9] / 255.0f);
+ cdda->set_output_gain(1, mode_data[pagedata_offset+11] / 255.0f);
+ break;
+ }
+ }
}
}
@@ -161,11 +199,11 @@ void nscsi_cdrom_device::scsi_command()
int blocks;
// check for media change
- if((cdrom != image->get_cdrom_file()) && (scsi_cmdbuf[0] != SC_INQUIRY))
+ if( sequence_counter != image->sequence_counter() && (scsi_cmdbuf[0] != SC_INQUIRY))
{
// clear media change condition
- cdrom = image->get_cdrom_file();
cur_sector = -1;
+ sequence_counter = image->sequence_counter();
// report unit attention condition
sense(false, SK_UNIT_ATTENTION);
@@ -176,19 +214,19 @@ void nscsi_cdrom_device::scsi_command()
switch(scsi_cmdbuf[0]) {
case SC_TEST_UNIT_READY:
LOG("command TEST UNIT READY\n");
- if(cdrom)
+ if(image->exists())
scsi_status_complete(SS_GOOD);
else
return_no_cd();
break;
case SC_READ_6:
- if(!cdrom) {
+ if(!image->exists()) {
return_no_cd();
break;
}
- lba = ((scsi_cmdbuf[1] & 0x1f)<<16) | (scsi_cmdbuf[2]<<8) | scsi_cmdbuf[3];
+ lba = get_u24be(&scsi_cmdbuf[1]) & 0x1fffff;
blocks = scsi_cmdbuf[4];
if(!blocks)
blocks = 256;
@@ -223,7 +261,7 @@ void nscsi_cdrom_device::scsi_command()
int size = scsi_cmdbuf[4];
switch(page) {
case 0:
- std::fill_n(scsi_cmdbuf, 36, 0);
+ std::fill_n(scsi_cmdbuf, size, 0);
if (lun != 0)
scsi_cmdbuf[0] = 0x7f;
@@ -243,8 +281,6 @@ void nscsi_cdrom_device::scsi_command()
if(scsi_cmdbuf[i] == 0)
scsi_cmdbuf[i] = 0x20;
- if(size > 36)
- size = 36;
scsi_data_in(SBUF_MAIN, size);
break;
}
@@ -256,8 +292,9 @@ void nscsi_cdrom_device::scsi_command()
LOG("command MODE SELECT 6 length %d\n", scsi_cmdbuf[4]);
// accept mode select parameter data
- if(scsi_cmdbuf[4])
- scsi_data_out(2, scsi_cmdbuf[4]);
+ mode_data_size = scsi_cmdbuf[4];
+ if(mode_data_size)
+ scsi_data_out(2, mode_data_size);
scsi_status_complete(SS_GOOD);
break;
@@ -268,9 +305,9 @@ void nscsi_cdrom_device::scsi_command()
scsi_status_complete(SS_GOOD);
break;
- case SC_RECIEVE_DIAG_RES: {
- LOG("command RECIEVE DIAGNOSTICS RESULTS");
- int size = (scsi_cmdbuf[3] << 8) | scsi_cmdbuf[4];
+ case SC_RECEIVE_DIAGNOSTIC_RESULTS: {
+ LOG("command RECEIVE DIAGNOSTIC RESULTS");
+ int size = get_u16be(&scsi_cmdbuf[3]);
int pos = 0;
scsi_cmdbuf[pos++] = 0;
scsi_cmdbuf[pos++] = 6;
@@ -286,9 +323,9 @@ void nscsi_cdrom_device::scsi_command()
break;
}
- case SC_SEND_DIAGNOSTICS: {
- LOG("command SEND DIAGNOSTICS");
- int size = (scsi_cmdbuf[3] << 8) | scsi_cmdbuf[4];
+ case SC_SEND_DIAGNOSTIC: {
+ LOG("command SEND DIAGNOSTIC");
+ int size = get_u16be(&scsi_cmdbuf[3]);
if(scsi_cmdbuf[1] & 4) {
// Self-test
scsi_status_complete(SS_GOOD);
@@ -313,22 +350,18 @@ void nscsi_cdrom_device::scsi_command()
case SC_READ_CAPACITY: {
LOG("command READ CAPACITY\n");
- if(!cdrom) {
+ if(!image->exists()) {
return_no_cd();
break;
}
// get the last used block on the disc
- const u32 temp = cdrom->get_track_start(0xaa) * (bytes_per_sector / bytes_per_block) - 1;
+ const u32 temp = image->get_track_start(0xaa) * (bytes_per_sector / bytes_per_block) - 1;
- scsi_cmdbuf[0] = (temp>>24) & 0xff;
- scsi_cmdbuf[1] = (temp>>16) & 0xff;
- scsi_cmdbuf[2] = (temp>>8) & 0xff;
- scsi_cmdbuf[3] = (temp & 0xff);
+ put_u32be(&scsi_cmdbuf[0], temp);
scsi_cmdbuf[4] = 0;
scsi_cmdbuf[5] = 0;
- scsi_cmdbuf[6] = (bytes_per_block>>8)&0xff;
- scsi_cmdbuf[7] = (bytes_per_block & 0xff);
+ put_u16be(&scsi_cmdbuf[6], bytes_per_block);
scsi_data_in(SBUF_MAIN, 8);
scsi_status_complete(SS_GOOD);
@@ -336,11 +369,11 @@ void nscsi_cdrom_device::scsi_command()
}
case SC_READ_10:
- lba = (scsi_cmdbuf[2]<<24) | (scsi_cmdbuf[3]<<16) | (scsi_cmdbuf[4]<<8) | scsi_cmdbuf[5];
- blocks = (scsi_cmdbuf[7] << 8) | scsi_cmdbuf[8];
+ lba = get_u32be(&scsi_cmdbuf[2]);
+ blocks = get_u16be(&scsi_cmdbuf[7]);
LOG("command READ EXTENDED start=%08x blocks=%04x\n", lba, blocks);
- if(!cdrom) {
+ if(!image->exists()) {
return_no_cd();
break;
}
@@ -365,17 +398,16 @@ void nscsi_cdrom_device::scsi_command()
scsi_cmdbuf[pos++] = 0x80; // WP, cache
// get the last used block on the disc
- const u32 temp = cdrom ? cdrom->get_track_start(0xaa) * (bytes_per_sector / bytes_per_block) - 1 : 0;
+ const u32 temp = image->exists() ? image->get_track_start(0xaa) * (bytes_per_sector / bytes_per_block) - 1 : 0;
scsi_cmdbuf[pos++] = 0x08; // Block descriptor length
scsi_cmdbuf[pos++] = 0x00; // density code
- scsi_cmdbuf[pos++] = (temp>>16) & 0xff;
- scsi_cmdbuf[pos++] = (temp>>8) & 0xff;
- scsi_cmdbuf[pos++] = (temp & 0xff);
+ put_u24be(&scsi_cmdbuf[pos], temp);
+ pos += 3;
scsi_cmdbuf[pos++] = 0;
scsi_cmdbuf[pos++] = 0;
- scsi_cmdbuf[pos++] = (bytes_per_block>>8)&0xff;
- scsi_cmdbuf[pos++] = (bytes_per_block & 0xff);
+ put_u16be(&scsi_cmdbuf[pos], bytes_per_block);
+ pos += 2;
bool fail = false;
int pmax = page == 0x3f ? 0x3e : page;
@@ -424,6 +456,25 @@ void nscsi_cdrom_device::scsi_command()
scsi_cmdbuf[pos++] = 0x00; // Reserved
break;
+ case 0x0e: // CD Audio control page
+ scsi_cmdbuf[pos++] = 0x8e; // PS, page id
+ scsi_cmdbuf[pos++] = 0x0e; // Page length
+ scsi_cmdbuf[pos++] = (1 << 2) | (cdda_sotc << 1); // IMMED = 1
+ scsi_cmdbuf[pos++] = 0x00; // Reserved
+ scsi_cmdbuf[pos++] = 0x00;
+ scsi_cmdbuf[pos++] = 0x00;
+ scsi_cmdbuf[pos++] = 0x00;
+ scsi_cmdbuf[pos++] = 0x00;
+ scsi_cmdbuf[pos++] = 0x01; // Ch 1 connected
+ scsi_cmdbuf[pos++] = 0xff; // Ch 1 max volume
+ scsi_cmdbuf[pos++] = 0x02; // Ch 2 connected
+ scsi_cmdbuf[pos++] = 0xff; // Ch 2 max volume
+ scsi_cmdbuf[pos++] = 0x04; // Ch 3 connected
+ scsi_cmdbuf[pos++] = 0xff; // Ch 3 max volume
+ scsi_cmdbuf[pos++] = 0x08; // Ch 4 connected
+ scsi_cmdbuf[pos++] = 0xff; // Ch 4 max volume
+ break;
+
case 0x30: // magic Apple page
{
static const u8 apple_magic[0x17] =
@@ -463,7 +514,7 @@ void nscsi_cdrom_device::scsi_command()
case SC_READ_DISC_INFORMATION:
LOG("command READ DISC INFORMATION\n");
- if(!cdrom) {
+ if(!image->exists()) {
return_no_cd();
break;
}
@@ -474,27 +525,21 @@ void nscsi_cdrom_device::scsi_command()
scsi_cmdbuf[3] = 1; // first track
scsi_cmdbuf[4] = 1; // number of sessions (TODO: session support for CHDv6)
scsi_cmdbuf[5] = 1; // first track in last session
- scsi_cmdbuf[6] = cdrom->get_last_track(); // last track in last session
+ scsi_cmdbuf[6] = image->get_last_track(); // last track in last session
scsi_cmdbuf[8] = 0; // CD-ROM, not XA
// lead in start time in MSF
{
- u32 tstart = cdrom->get_track_start(0);
+ u32 tstart = image->get_track_start(0);
tstart = to_msf(tstart + 150);
- scsi_cmdbuf[16] = (tstart >> 24) & 0xff;
- scsi_cmdbuf[17] = (tstart >> 16) & 0xff;
- scsi_cmdbuf[18] = (tstart >> 8) & 0xff;
- scsi_cmdbuf[19] = (tstart & 0xff);
+ put_u32be(&scsi_cmdbuf[16], tstart);
// lead-out start time in MSF
- tstart = cdrom->get_track_start(0xaa);
+ tstart = image->get_track_start(0xaa);
tstart = to_msf(tstart + 150);
- scsi_cmdbuf[20] = (tstart >> 24) & 0xff;
- scsi_cmdbuf[21] = (tstart >> 16) & 0xff;
- scsi_cmdbuf[22] = (tstart >> 8) & 0xff;
- scsi_cmdbuf[23] = (tstart & 0xff);
+ put_u32be(&scsi_cmdbuf[20], tstart);
}
scsi_data_in(0, 34);
@@ -507,6 +552,77 @@ void nscsi_cdrom_device::scsi_command()
scsi_status_complete(SS_GOOD);
break;
+ case SC_READ_SUB_CHANNEL: {
+ const bool msf = BIT(scsi_cmdbuf[1], 1) != 0;
+ const bool subq = BIT(scsi_cmdbuf[2], 6);
+ const int param = scsi_cmdbuf[3];
+ const int track = scsi_cmdbuf[6];
+ const int alloc_length = get_u16be(&scsi_cmdbuf[7]);
+
+ LOG("command READ SUB CHANNEL Param = %d, Track = %d, MSF = %d, SUBQ = %d\n", param, track, msf, subq);
+
+ if(!image->exists()) {
+ return_no_cd();
+ break;
+ }
+
+ std::fill_n(scsi_cmdbuf, alloc_length, 0);
+
+ scsi_cmdbuf[0] = 0x00; // Reserved
+
+ int audio_active = cdda->audio_active();
+ if(audio_active) {
+ if(cdda->audio_paused())
+ scsi_cmdbuf[1] = 0x12; // Audio play operation paused
+ else
+ scsi_cmdbuf[1] = 0x11; // Audio play operation in progress
+ } else {
+ if(cdda->audio_ended())
+ scsi_cmdbuf[1] = 0x13; // Audio play operation successfully completed
+ else
+ scsi_cmdbuf[1] = 0x15; // No current audio status to return
+ }
+
+ if(subq) {
+ switch(param) {
+ case 1: { // CD current position
+ int m_last_lba = audio_active ? cdda->get_audio_lba() : 0;
+
+ scsi_cmdbuf[2] = 0; // Sub-channel Data Length
+ scsi_cmdbuf[3] = 12;
+
+ scsi_cmdbuf[4] = 0x01; // Sub-channel Data Format Code
+ scsi_cmdbuf[5] = (audio_active ? 0 : 4) | 0x10; // Q Sub-channel encodes current position data
+ scsi_cmdbuf[6] = image->get_track(m_last_lba) + 1; // Track Number
+ scsi_cmdbuf[7] = 0x00; // Index Number
+
+ uint32_t frame = m_last_lba;
+ if(msf)
+ frame = to_msf(frame);
+
+ put_u32be(&scsi_cmdbuf[8], frame); // Absolute CD Address
+
+ frame = m_last_lba - image->get_track_start(scsi_cmdbuf[6] - 1);
+ if(msf)
+ frame = to_msf(frame);
+
+ put_u32be(&scsi_cmdbuf[12], frame); // Track Relative CD Address
+ break;
+ }
+
+ case 0x02: // Media Catalog number (UPC/bar code)
+ case 0x03: // Track International standard recording code (ISRC)
+ default:
+ LOG("Unknown subchannel type %d requested\n", scsi_cmdbuf[3]);
+ break;
+ }
+ }
+
+ scsi_data_in(0, alloc_length);
+ scsi_status_complete(SS_GOOD);
+ break;
+ }
+
case SC_READ_TOC_PMA_ATIP: {
/*
Track numbers are problematic here: 0 = lead-in, 0xaa = lead-out.
@@ -534,7 +650,7 @@ void nscsi_cdrom_device::scsi_command()
};
bool msf = (scsi_cmdbuf[1] & 0x2) != 0;
- u16 size = (scsi_cmdbuf[7] << 7) | scsi_cmdbuf[8];
+ u16 size = get_u16be(&scsi_cmdbuf[7]);
u8 format = scsi_cmdbuf[2] & 15;
/// SFF8020 legacy format field (see T10/1836-D Revision 2g page 643)
@@ -543,7 +659,7 @@ void nscsi_cdrom_device::scsi_command()
LOG("command READ TOC PMA ATIP, format %s msf=%d size=%d\n", format_names[format], msf, size);
- if(!cdrom) {
+ if(!image->exists()) {
return_no_cd();
break;
}
@@ -552,7 +668,7 @@ void nscsi_cdrom_device::scsi_command()
switch (format) {
case 0: {
int start_track = scsi_cmdbuf[6];
- int end_track = cdrom->get_last_track();
+ int end_track = image->get_last_track();
int tracks;
if(start_track == 0)
@@ -568,10 +684,10 @@ void nscsi_cdrom_device::scsi_command()
// the returned TOC DATA LENGTH must be the full amount,
// regardless of how much we're able to pass back due to size
- scsi_cmdbuf[pos++] = (len>>8) & 0xff;
- scsi_cmdbuf[pos++] = (len & 0xff);
+ put_u16be(&scsi_cmdbuf[pos], len);
+ pos += 2;
scsi_cmdbuf[pos++] = 1;
- scsi_cmdbuf[pos++] = cdrom->get_last_track();
+ scsi_cmdbuf[pos++] = image->get_last_track();
if (start_track == 0)
start_track = 1;
@@ -585,19 +701,17 @@ void nscsi_cdrom_device::scsi_command()
}
scsi_cmdbuf[pos++] = 0;
- scsi_cmdbuf[pos++] = cdrom->get_adr_control(cdrom_track);
+ scsi_cmdbuf[pos++] = image->get_adr_control(cdrom_track);
scsi_cmdbuf[pos++] = track;
scsi_cmdbuf[pos++] = 0;
- u32 tstart = cdrom->get_track_start(cdrom_track);
+ u32 tstart = image->get_track_start(cdrom_track);
if(msf)
tstart = to_msf(tstart+150);
- scsi_cmdbuf[pos++] = (tstart>>24) & 0xff;
- scsi_cmdbuf[pos++] = (tstart>>16) & 0xff;
- scsi_cmdbuf[pos++] = (tstart>>8) & 0xff;
- scsi_cmdbuf[pos++] = (tstart & 0xff);
+ put_u32be(&scsi_cmdbuf[pos], tstart);
+ pos += 4;
}
break;
}
@@ -605,25 +719,23 @@ void nscsi_cdrom_device::scsi_command()
case 1: {
int len = 2 + (8 * 1);
- scsi_cmdbuf[pos++] = (len>>8) & 0xff;
- scsi_cmdbuf[pos++] = (len & 0xff);
+ put_u16be(&scsi_cmdbuf[pos], len);
+ pos += 2;
scsi_cmdbuf[pos++] = 1;
scsi_cmdbuf[pos++] = 1;
scsi_cmdbuf[pos++] = 0;
- scsi_cmdbuf[pos++] = cdrom->get_adr_control(0);
+ scsi_cmdbuf[pos++] = image->get_adr_control(0);
scsi_cmdbuf[pos++] = 1;
scsi_cmdbuf[pos++] = 0;
- u32 tstart = cdrom->get_track_start(0);
+ u32 tstart = image->get_track_start(0);
if (msf)
tstart = to_msf(tstart+150);
- scsi_cmdbuf[pos++] = (tstart>>24) & 0xff;
- scsi_cmdbuf[pos++] = (tstart>>16) & 0xff;
- scsi_cmdbuf[pos++] = (tstart>>8) & 0xff;
- scsi_cmdbuf[pos++] = (tstart & 0xff);
+ put_u32be(&scsi_cmdbuf[pos], tstart);
+ pos += 4;
break;
}
@@ -647,6 +759,44 @@ void nscsi_cdrom_device::scsi_command()
break;
}
+ case SC_PLAY_AUDIO_TRACK_INDEX: {
+ LOG("command PLAY AUDIO TRACK INDEX tr %d/idx %d to tr %d/idx %d\n", scsi_cmdbuf[4], scsi_cmdbuf[5], scsi_cmdbuf[7], scsi_cmdbuf[8]);
+
+ if(scsi_cmdbuf[4] > scsi_cmdbuf[7]) {
+ scsi_status_complete(SS_CHECK_CONDITION);
+ sense(false, SK_ILLEGAL_REQUEST, 0x00, 0x14);
+ break;
+ }
+
+ // TODO: Index isn't accounted for at all
+ const uint32_t start_track = scsi_cmdbuf[4];
+ const uint32_t end_track = cdda_sotc ? start_track : std::min(image->get_last_track(), (int)scsi_cmdbuf[7]);
+ const uint32_t lba = image->get_track_start(start_track - 1);
+ const uint32_t blocks = image->get_track_start(end_track) - lba;
+ const uint32_t track = image->get_track(lba);
+
+ if(image->get_track_type(track) == cdrom_file::CD_TRACK_AUDIO) {
+ LOG("Playing %d blocks from track %d (lba %d)\n", blocks, start_track, lba);
+
+ cdda->start_audio(lba, blocks);
+ scsi_status_complete(SS_GOOD);
+ sense(false, SK_NO_SENSE, 0x00, 0x11);
+ } else {
+ LOG("Track %d is not audio\n", start_track);
+
+ scsi_status_complete(SS_CHECK_CONDITION);
+ sense(false, SK_ILLEGAL_REQUEST, 0x64, 0x00);
+ }
+ break;
+ }
+
+ case SC_PAUSE_RESUME:
+ if (image->exists())
+ cdda->pause_audio(BIT(scsi_cmdbuf[8], 0) ^ 1);
+
+ scsi_status_complete(SS_GOOD);
+ break;
+
default:
nscsi_full_device::scsi_command();
break;
@@ -708,6 +858,30 @@ bool nscsi_cdrom_sgi_device::scsi_command_done(uint8_t command, uint8_t length)
return nscsi_full_device::scsi_command_done(command, length);
}
}
+
+// Apple CDSC commands, from AppleCDSC.aii in IIgs System 6.0.1.
+// These are related to the Sony CDU-541 commands but customized by Apple.
+enum apple_scsi_command_e : uint8_t {
+ APPLE_EJECT = 0xc0,
+ APPLE_READ_TOC = 0xc1,
+ APPLE_READ_SUB_CHANNEL = 0xc2,
+ APPLE_AUDIO_PLAY = 0xc8,
+ APPLE_AUDIO_PLAY_TRACK = 0xc9,
+ APPLE_AUDIO_PAUSE = 0xca,
+ APPLE_AUDIO_STOP = 0xcb,
+ APPLE_AUDIO_STATUS = 0xcc,
+ APPLE_AUDIO_SCAN = 0xcd,
+ APPLE_AUDIO_CONTROL = 0xce
+};
+
+void nscsi_cdrom_apple_device::device_start()
+{
+ nscsi_cdrom_device::device_start();
+
+ save_item(NAME(m_stopped));
+ save_item(NAME(m_stop_position));
+}
+
/*
The Apple II SCSI Card firmware demands that ASC on a failing TEST_UNIT_READY be either 0x28 or 0xb0.
0x28 is MEDIA_CHANGED, 0xb0 is vendor-specific. If the drive returns the normal 0x3A for disc-not-present,
@@ -716,10 +890,19 @@ bool nscsi_cdrom_sgi_device::scsi_command_done(uint8_t command, uint8_t length)
*/
void nscsi_cdrom_apple_device::scsi_command()
{
+ if (scsi_cmdbuf[0] != 8 && scsi_cmdbuf[0] != 0x28 && scsi_cmdbuf[0] != 0 && scsi_cmdbuf[0] != 0x03)
+ {
+ LOG("CD command: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
+ scsi_cmdbuf[0], scsi_cmdbuf[1], scsi_cmdbuf[2],
+ scsi_cmdbuf[3], scsi_cmdbuf[4], scsi_cmdbuf[5],
+ scsi_cmdbuf[6], scsi_cmdbuf[7], scsi_cmdbuf[8],
+ scsi_cmdbuf[9]);
+ }
+
switch (scsi_cmdbuf[0]) {
case SC_TEST_UNIT_READY:
LOG("command TEST UNIT READY (AppleCD)\n");
- if(cdrom)
+ if(image->exists())
{
scsi_status_complete(SS_GOOD);
}
@@ -730,8 +913,455 @@ void nscsi_cdrom_apple_device::scsi_command()
}
break;
+ case SC_INQUIRY:
+ {
+ int lun = get_lun(scsi_cmdbuf[1] >> 5);
+ LOG("command INQUIRY lun=%d EVPD=%d page=%d alloc=%02x link=%02x\n",
+ lun, scsi_cmdbuf[1] & 1, scsi_cmdbuf[2], scsi_cmdbuf[4], scsi_cmdbuf[5]);
+
+ int page = scsi_cmdbuf[2];
+ int size = scsi_cmdbuf[4];
+ switch (page)
+ {
+ case 0:
+ std::fill_n(scsi_cmdbuf, size, 0);
+
+ // data taken from the ROM of an AppleCD 150
+ scsi_cmdbuf[0] = 0x05; // device is present, device is CD/DVD (MMC-3)
+ scsi_cmdbuf[1] = 0x80; // media is removable
+ scsi_cmdbuf[2] = 0x01;
+ scsi_cmdbuf[3] = 0x01;
+ scsi_cmdbuf[4] = 0x31; // additional length
+ memcpy((char *)&scsi_cmdbuf[8], "SONY ", 8);
+ memcpy((char *)&scsi_cmdbuf[16], "CD-ROM CDU-8002 ", 16);
+ memcpy((char *)&scsi_cmdbuf[32], "1.8g", 4);
+ scsi_cmdbuf[39] = 0xd0;
+ scsi_cmdbuf[40] = 0x90;
+ scsi_cmdbuf[41] = 0x27;
+ scsi_cmdbuf[42] = 0x3e;
+ scsi_cmdbuf[43] = 0x01;
+ scsi_cmdbuf[44] = 0x04;
+ scsi_cmdbuf[45] = 0x91;
+ scsi_cmdbuf[47] = 0x18;
+ scsi_cmdbuf[48] = 0x06;
+ scsi_cmdbuf[49] = 0xf0;
+ scsi_cmdbuf[50] = 0xfe;
+
+ scsi_data_in(SBUF_MAIN, size);
+ break;
+ }
+ scsi_status_complete(SS_GOOD);
+ }
+ break;
+
+ case APPLE_READ_TOC:
+ {
+ if (!image->exists())
+ {
+ return_no_cd();
+ break;
+ }
+
+ u16 size = get_u16be(&scsi_cmdbuf[7]);
+ LOG("command READ TOC (AppleCD), size=%d, track=%d, type1=%02x type2=%02x\n", size, scsi_cmdbuf[2], scsi_cmdbuf[9], scsi_cmdbuf[5]);
+
+ if (scsi_cmdbuf[9] == 0x80)
+ {
+ // get TOC info for 1 or more tracks from a specified starting track
+ assert(scsi_cmdbuf[5] > 0);
+
+ const int start_track = scsi_cmdbuf[5] - 1;
+ const int num_trks = size / 4;
+ int pos = 0;
+
+ for (int trk = 0; trk < num_trks; trk++)
+ {
+ // Coverity: The emulated program could conceivably request a buffer size for
+ // more tracks than exist, but we must still return the requested amount of data.
+ if ((trk + start_track) < image->get_last_track())
+ {
+ const uint32_t start_lba = image->get_track_start(trk + start_track);
+ const uint32_t start_frame = to_msf(start_lba);
+
+ scsi_cmdbuf[pos++] = image->get_adr_control(trk + start_track);
+ scsi_cmdbuf[pos++] = dec_2_bcd(BIT(start_frame, 16, 8)); // minutes
+ scsi_cmdbuf[pos++] = dec_2_bcd(BIT(start_frame, 8, 8)); // seconds
+ scsi_cmdbuf[pos++] = dec_2_bcd(BIT(start_frame, 0, 8)); // frames
+ }
+ else // keep returning the last track if necessary
+ {
+ const uint32_t start_lba = image->get_track_start(image->get_last_track());
+ const uint32_t start_frame = to_msf(start_lba);
+
+ scsi_cmdbuf[pos++] = image->get_adr_control(image->get_last_track());
+ scsi_cmdbuf[pos++] = dec_2_bcd(BIT(start_frame, 16, 8)); // minutes
+ scsi_cmdbuf[pos++] = dec_2_bcd(BIT(start_frame, 8, 8)); // seconds
+ scsi_cmdbuf[pos++] = dec_2_bcd(BIT(start_frame, 0, 8)); // frames
+ }
+ }
+
+ scsi_data_in(SBUF_MAIN, pos);
+ scsi_status_complete(SS_GOOD);
+ }
+ else if (scsi_cmdbuf[9] == 0x40) // get MSF of the start of the leadout
+ {
+ const int track = image->get_last_track();
+ const uint32_t frame = to_msf(image->get_track_start(track));
+ scsi_cmdbuf[0] = dec_2_bcd(BIT(frame, 16, 8)); // minutes
+ scsi_cmdbuf[1] = dec_2_bcd(BIT(frame, 8, 8)); // seconds
+ scsi_cmdbuf[2] = dec_2_bcd(BIT(frame, 0, 8)); // frames
+ scsi_cmdbuf[3] = 0;
+
+ scsi_data_in(SBUF_MAIN, 4);
+ scsi_status_complete(SS_GOOD);
+ }
+ else
+ {
+ switch (scsi_cmdbuf[5])
+ {
+ case 0x00: // get start and end track numbers
+ scsi_cmdbuf[0] = 1;
+ scsi_cmdbuf[1] = dec_2_bcd(image->get_last_track());
+ scsi_cmdbuf[2] = 0;
+ scsi_cmdbuf[3] = 0;
+
+ scsi_data_in(SBUF_MAIN, 4);
+ scsi_status_complete(SS_GOOD);
+ break;
+
+ case 0x40: // get first frame of lead-out (one past end of last track)
+ {
+ const uint32_t leadout_lba = image->get_track_start(0xaa);
+ const uint32_t leadout_frame = to_msf(leadout_lba);
+ scsi_cmdbuf[0] = dec_2_bcd(BIT(leadout_frame, 16, 8)); // minutes
+ scsi_cmdbuf[1] = dec_2_bcd(BIT(leadout_frame, 8, 8)); // seconds
+ scsi_cmdbuf[2] = dec_2_bcd(BIT(leadout_frame, 0, 8)); // frames
+ scsi_cmdbuf[3] = 0;
+
+ scsi_data_in(SBUF_MAIN, 4);
+ scsi_status_complete(SS_GOOD);
+ }
+ break;
+
+ case 0x80: // get track info
+ {
+ const uint32_t start_lba = image->get_track_start(scsi_cmdbuf[2]);
+ const uint32_t start_frame = to_msf(start_lba);
+
+ scsi_cmdbuf[0] = image->get_adr_control(scsi_cmdbuf[2]);
+ scsi_cmdbuf[1] = dec_2_bcd(BIT(start_frame, 16, 8)); // minutes
+ scsi_cmdbuf[2] = dec_2_bcd(BIT(start_frame, 8, 8)); // seconds
+ scsi_cmdbuf[3] = dec_2_bcd(BIT(start_frame, 0, 8)); // frames
+ scsi_data_in(SBUF_MAIN, 4);
+ scsi_status_complete(SS_GOOD);
+ }
+ break;
+
+ default:
+ logerror("APPLE READ TOC: Unhandled type %02x\n", scsi_cmdbuf[5]);
+ break;
+ }
+ }
+ }
+ break;
+
+ case APPLE_AUDIO_STATUS:
+ LOG("command APPLE AUDIO STATUS, type %02x, want %d bytes\n", scsi_cmdbuf[3], scsi_cmdbuf[8]);
+
+ if (!image->exists())
+ {
+ return_no_cd();
+ break;
+ }
+
+ // Audio status codes, adapted from CDRemote.equ in GS/OS 6.0.1 (matches CDU-541 as well)
+ enum cd_status_t: u8
+ {
+ PLAYING = 0, // Audio is playing
+ PAUSED, // Audio is paused
+ PLAYING_MUTED, // Playing, but muted
+ REACHED_END, // Playback reached the end successfully
+ ERROR, // an error occured
+ VOID // really "idle"
+ };
+
+ {
+ const int type = scsi_cmdbuf[3];
+
+ scsi_cmdbuf[2] = image->get_adr_control(image->get_track(cdda->get_audio_lba()));
+
+ const uint32_t frame = to_msf(cdda->get_audio_lba());
+ scsi_cmdbuf[3] = dec_2_bcd(BIT(frame, 16, 8)); // minute
+ scsi_cmdbuf[4] = dec_2_bcd(BIT(frame, 8, 8)); // second
+ scsi_cmdbuf[5] = dec_2_bcd(BIT(frame, 0, 8)); // frame
+
+ // TODO: When you pause, both 7.1's CD Remote and 7.6+'s more modern player still see the
+ // status as "playing" even though it's definitely returning "paused". I've tried returning
+ // every code and nothing works.
+ if (type == 0)
+ {
+ scsi_cmdbuf[1] = 0;
+ if (m_stopped)
+ {
+ scsi_cmdbuf[0] = VOID;
+ }
+ else
+ {
+ if (cdda->audio_ended())
+ {
+ scsi_cmdbuf[0] = REACHED_END;
+ }
+ else
+ {
+ if (cdda->audio_active())
+ {
+ if (cdda->audio_paused())
+ {
+ scsi_cmdbuf[0] = PAUSED;
+ }
+ else
+ {
+ scsi_cmdbuf[0] = PLAYING;
+ }
+ }
+ else
+ {
+ scsi_cmdbuf[0] = VOID;
+ }
+ }
+ }
+ }
+ else if (type == 1) // "volume status"
+ {
+ scsi_cmdbuf[0] = (u8)(cdda->output_gain(0) * 255.0f);
+ scsi_cmdbuf[1] = (u8)(cdda->output_gain(1) * 255.0f);
+
+ // Other 4 bytes unknown in this mode, going with the same as type 0 for now
+ }
+ }
+ //printf("status => %02x %02x %02x %02x %02x %02x\n", scsi_cmdbuf[0], scsi_cmdbuf[1], scsi_cmdbuf[2], scsi_cmdbuf[3], scsi_cmdbuf[4], scsi_cmdbuf[5]);
+ scsi_cmdbuf[0] = 0;
+ scsi_data_in(SBUF_MAIN, 6);
+ scsi_status_complete(SS_GOOD);
+ break;
+
+ case APPLE_READ_SUB_CHANNEL:
+ LOG("command READ SUB CHANNEL\n");
+
+ scsi_cmdbuf[0] = 0; // Control nibble
+ scsi_cmdbuf[1] = 0; // Track
+ scsi_cmdbuf[2] = 0; // Index
+ scsi_cmdbuf[3] = 0; // Relative Minute
+ scsi_cmdbuf[4] = 0; // Relative Second
+ scsi_cmdbuf[5] = 0; // Relative Frame
+ scsi_cmdbuf[6] = 0; // AMinute
+ scsi_cmdbuf[7] = 0; // ASecond
+ scsi_cmdbuf[8] = 0; // AFrame
+
+ if (cdda->audio_active())
+ {
+ int track = image->get_track(cdda->get_audio_lba());
+ scsi_cmdbuf[1] = dec_2_bcd(track+1);
+ scsi_cmdbuf[2] = 1; // Index
+
+ const uint32_t track_start = image->get_track_start(track);
+ uint32_t cur_lba = cdda->get_audio_lba();
+
+ if (cur_lba < track_start)
+ {
+ cur_lba = track_start;
+ }
+
+ const uint32_t relframe = to_msf(cur_lba - track_start);
+ scsi_cmdbuf[3] = dec_2_bcd(BIT(relframe, 16, 8)); // minute
+ scsi_cmdbuf[4] = dec_2_bcd(BIT(relframe, 8, 8)); // second
+ scsi_cmdbuf[5] = dec_2_bcd(BIT(relframe, 0, 8)); // frame
+
+ const uint32_t frame = to_msf(cur_lba);
+ scsi_cmdbuf[6] = dec_2_bcd(BIT(frame, 16, 8)); // minute
+ scsi_cmdbuf[7] = dec_2_bcd(BIT(frame, 8, 8)); // second
+ scsi_cmdbuf[8] = dec_2_bcd(BIT(frame, 0, 8)); // frame
+ }
+
+ scsi_data_in(SBUF_MAIN, 9);
+ scsi_status_complete(SS_GOOD);
+ break;
+
+ case APPLE_AUDIO_PLAY:
+ case APPLE_AUDIO_PLAY_TRACK:
+ {
+ const uint8_t val = scsi_cmdbuf[5];
+ const uint8_t start_track = (((val & 0xf0) >> 4) * 10) + (val & 0x0f);
+
+ uint32_t start_lba = 0;
+
+ if (scsi_cmdbuf[0] == APPLE_AUDIO_PLAY)
+ {
+ if (scsi_cmdbuf[9] == 0x40)
+ {
+ LOG("command APPLE AUDIO PLAY MSF = %02x:%02x:%02x\n", scsi_cmdbuf[5], scsi_cmdbuf[6], scsi_cmdbuf[7]);
+ const uint32_t msf = (bcd_2_dec(scsi_cmdbuf[5]) << 16) | (bcd_2_dec(scsi_cmdbuf[6]) << 8) | bcd_2_dec(scsi_cmdbuf[7]);
+ start_lba = cdrom_file::msf_to_lba(msf);
+ }
+ else if (scsi_cmdbuf[9] == 0x80)
+ {
+ LOG("command APPLE AUDIO PLAY track = %d\n", start_track);
+ if (start_track == 0)
+ {
+ cdda->stop_audio();
+ scsi_status_complete(SS_GOOD);
+ return;
+ }
+ else
+ {
+ start_lba = image->get_track_start(start_track - 1);
+ }
+ }
+ else
+ {
+ logerror("nscsi_cdrom_apple_device: Unknown APPLE AUDIO PLAY address mode %02x\n", scsi_cmdbuf[9]);
+ }
+ }
+ else // APPLE_AUDIO_PLAY_TRACK
+ {
+ LOG("command APPLE AUDIO PLAY TRACK track = %d\n", start_track);
+
+ // The Mac version of Apple CD-ROM Explorer issues PLAY on track 0 to stop
+ if (start_track == 0)
+ {
+ cdda->stop_audio();
+ m_stopped = true;
+ scsi_status_complete(SS_GOOD);
+ return;
+ }
+ else
+ {
+ start_lba = image->get_track_start(start_track - 1);
+ m_stop_position = image->get_track_start(start_track);
+ }
+ }
+
+ m_stopped = false;
+ cdda->start_audio(start_lba, m_stop_position - start_lba);
+ scsi_status_complete(SS_GOOD);
+ }
+ break;
+
+ case APPLE_AUDIO_SCAN:
+ LOG("command APPLE_AUDIO_SCAN: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
+ scsi_cmdbuf[0], scsi_cmdbuf[1], scsi_cmdbuf[2],
+ scsi_cmdbuf[3], scsi_cmdbuf[4], scsi_cmdbuf[5],
+ scsi_cmdbuf[6], scsi_cmdbuf[7], scsi_cmdbuf[8],
+ scsi_cmdbuf[9]);
+ scsi_status_complete(SS_GOOD);
+ break;
+
+ case APPLE_AUDIO_PAUSE:
+ LOG("command APPLE AUDIO PAUSE, on/off=%02x\n", scsi_cmdbuf[1]);
+ if (scsi_cmdbuf[1] == 0x10)
+ {
+ // set pause
+ if (!cdda->audio_paused())
+ {
+ cdda->pause_audio(1);
+ }
+ }
+ else
+ {
+ // release pause
+ if (cdda->audio_paused())
+ {
+ cdda->pause_audio(0);
+ }
+ }
+ scsi_status_complete(SS_GOOD);
+ break;
+
+ case APPLE_AUDIO_STOP:
+ LOG("command APPLE AUDIO STOP\n");
+ switch (scsi_cmdbuf[9])
+ {
+ case 0x00: // stop immediately
+ m_stop_position = 0;
+ m_stopped = true;
+ cdda->stop_audio();
+ break;
+
+ case 0x40: // stop at MSF
+ {
+ const uint32_t msf = (bcd_2_dec(scsi_cmdbuf[5]) << 16) | (bcd_2_dec(scsi_cmdbuf[6]) << 8) | bcd_2_dec(scsi_cmdbuf[7]);
+ m_stop_position = cdrom_file::msf_to_lba(msf);
+ }
+ break;
+
+ case 0x80: // stop at track number
+ {
+ const uint8_t val = scsi_cmdbuf[5];
+ const uint8_t start_track = (((val & 0xf0) >> 4) * 10) + (val & 0x0f);
+ m_stop_position = image->get_track_start(start_track);
+ }
+ break;
+
+ default:
+ logerror("nscsi_cdrom_apple_device: Unknown APPLE AUDIO STOPO address mode %02x\n", scsi_cmdbuf[9]);
+ break;
+ }
+ scsi_status_complete(SS_GOOD);
+ break;
+
+ case APPLE_AUDIO_CONTROL:
+ LOG("command APPLE AUDIO CONTROL, size %d\n", scsi_cmdbuf[8]);
+
+ scsi_data_out(3, scsi_cmdbuf[8]);
+ scsi_status_complete(SS_GOOD);
+ break;
+
+ case APPLE_EJECT:
+ LOG("command APPLE EJECT\n");
+ cdda->stop_audio();
+ m_stopped = true;
+ scsi_status_complete(SS_GOOD);
+ break;
+
+ case SC_READ_6:
+ case SC_READ_10:
+ case SC_READ_12:
+ cdda->stop_audio();
+ [[fallthrough]];
+
default:
nscsi_cdrom_device::scsi_command();
break;
}
}
+
+bool nscsi_cdrom_apple_device::scsi_command_done(uint8_t command, uint8_t length)
+{
+ switch (command & 0xf0)
+ {
+ case 0xc0:
+ return length == 10;
+
+ default:
+ return nscsi_full_device::scsi_command_done(command, length);
+ }
+}
+
+void nscsi_cdrom_apple_device::scsi_put_data(int id, int pos, uint8_t data)
+{
+ if (id != 3)
+ {
+ nscsi_cdrom_device::scsi_put_data(id, pos, data);
+ return;
+ }
+
+ if (pos == 0)
+ {
+ cdda->set_output_gain(0, data / 255.0f);
+ }
+ else if (pos == 1)
+ {
+ cdda->set_output_gain(1, data / 255.0f);
+ }
+
+}
diff --git a/src/devices/bus/nscsi/cd.h b/src/devices/bus/nscsi/cd.h
index 1a87e150b13..274e19f9ab5 100644
--- a/src/devices/bus/nscsi/cd.h
+++ b/src/devices/bus/nscsi/cd.h
@@ -5,10 +5,13 @@
#pragma once
+#include "imagedev/cdromimg.h"
#include "machine/nscsi_bus.h"
-#include "imagedev/chd_cd.h"
+#include "sound/cdda.h"
+
#include "cdrom.h"
+
class nscsi_cdrom_device : public nscsi_full_device
{
public:
@@ -17,6 +20,9 @@ public:
void set_block_size(u32 block_size);
protected:
+ required_device<cdrom_image_device> image;
+ required_device<cdda_device> cdda;
+
nscsi_cdrom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock = 0);
nscsi_cdrom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, const char *mfr, const char *product, const char *rev, uint8_t inq_data, uint8_t compliance)
@@ -37,16 +43,18 @@ protected:
virtual uint8_t scsi_get_data(int id, int pos) override;
virtual void scsi_put_data(int buf, int offset, uint8_t data) override;
- cdrom_file *cdrom;
+ void return_no_cd();
+ static int to_msf(int frame);
private:
static constexpr uint32_t bytes_per_sector = 2048;
+ u32 sequence_counter;
uint8_t sector_buffer[bytes_per_sector];
uint32_t bytes_per_block;
int lba, cur_sector;
- required_device<cdrom_image_device> image;
- uint8_t mode_data[12];
+ uint8_t mode_data[256];
+ uint8_t mode_data_size;
char manufacturer[8];
char product[16];
@@ -54,8 +62,7 @@ private:
uint8_t inquiry_data;
uint8_t compliance;
- void return_no_cd();
- static int to_msf(int frame);
+ uint8_t cdda_sotc;
};
class nscsi_cdrom_sgi_device : public nscsi_cdrom_device
@@ -68,6 +75,12 @@ protected:
virtual bool scsi_command_done(uint8_t command, uint8_t length) override;
};
+class nscsi_cdrom_news_device : public nscsi_cdrom_device
+{
+public:
+ nscsi_cdrom_news_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
+};
+
class nscsi_dec_rrd45_device : public nscsi_cdrom_device
{
public:
@@ -86,6 +99,12 @@ public:
nscsi_toshiba_xm5301_sun_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
};
+class nscsi_toshiba_xm5401_device : public nscsi_cdrom_device
+{
+public:
+ nscsi_toshiba_xm5401_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
+};
+
class nscsi_toshiba_xm5401_sun_device : public nscsi_cdrom_device
{
public:
@@ -108,16 +127,25 @@ class nscsi_cdrom_apple_device : public nscsi_cdrom_device
{
public:
nscsi_cdrom_apple_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
+ virtual void device_start() override;
protected:
virtual void scsi_command() override;
+ virtual bool scsi_command_done(uint8_t command, uint8_t length) override;
+ virtual void scsi_put_data(int buf, int offset, uint8_t data) override;
+
+private:
+ bool m_stopped;
+ uint32_t m_stop_position;
};
DECLARE_DEVICE_TYPE(NSCSI_CDROM, nscsi_cdrom_device)
DECLARE_DEVICE_TYPE(NSCSI_CDROM_SGI, nscsi_cdrom_sgi_device)
+DECLARE_DEVICE_TYPE(NSCSI_CDROM_NEWS, nscsi_cdrom_news_device)
DECLARE_DEVICE_TYPE(NSCSI_RRD45, nscsi_dec_rrd45_device)
DECLARE_DEVICE_TYPE(NSCSI_XM3301, nscsi_toshiba_xm3301_device)
DECLARE_DEVICE_TYPE(NSCSI_XM5301SUN, nscsi_toshiba_xm5301_sun_device)
+DECLARE_DEVICE_TYPE(NSCSI_XM5401, nscsi_toshiba_xm5401_device)
DECLARE_DEVICE_TYPE(NSCSI_XM5401SUN, nscsi_toshiba_xm5401_sun_device)
DECLARE_DEVICE_TYPE(NSCSI_XM5701, nscsi_toshiba_xm5701_device)
DECLARE_DEVICE_TYPE(NSCSI_XM5701SUN, nscsi_toshiba_xm5701_sun_device)
diff --git a/src/devices/bus/nscsi/cdd2000.cpp b/src/devices/bus/nscsi/cdd2000.cpp
index 4a2e9c57811..ed2dece8a9b 100644
--- a/src/devices/bus/nscsi/cdd2000.cpp
+++ b/src/devices/bus/nscsi/cdd2000.cpp
@@ -9,7 +9,7 @@
#include "emu.h"
#include "bus/nscsi/cdd2000.h"
#include "cpu/mc68hc11/mc68hc11.h"
-#include "machine/ncr5390.h"
+#include "machine/ncr53c90.h"
DEFINE_DEVICE_TYPE(CDD2000, cdd2000_device, "cdd2000", "Philips CDD2000 CD-R")
@@ -17,18 +17,25 @@ cdd2000_device::cdd2000_device(const machine_config &mconfig, const char *tag, d
: device_t(mconfig, CDD2000, tag, owner, clock)
, nscsi_slot_card_interface(mconfig, *this, "scsic")
, m_cdcpu(*this, "cdcpu")
+ , m_rombank(*this, "bank")
{
}
void cdd2000_device::device_start()
{
+ m_rombank->configure_entries(0, 4, memregion("flash")->base() + 0x1000, 0x10000);
+}
+
+void cdd2000_device::device_reset()
+{
+ m_rombank->set_entry(3); // FIXME: MC68HC11 core should take care of this
}
void cdd2000_device::mem_map(address_map &map)
{
map(0x0400, 0x040f).m("scsic", FUNC(ncr53cf94_device::map));
// 0x0800, 0x080f is another device
- map(0x1000, 0xffff).rom().region("flash", 0x31000); // TODO: banking
+ map(0x1000, 0xffff).bankr(m_rombank);
map(0x2000, 0x3fff).ram();
}
@@ -37,8 +44,10 @@ void cdd2000_device::device_add_mconfig(machine_config &config)
mc68hc11f1_device &cdcpu(MC68HC11F1(config, m_cdcpu, 8'000'000)); // type and clock guessed
cdcpu.set_addrmap(AS_PROGRAM, &cdd2000_device::mem_map);
cdcpu.set_default_config(0x0b);
+ cdcpu.out_pa_callback().set_membank(m_rombank).mask(0x60).rshift(5);
- NCR53CF94(config, "scsic", 25'000'000); // type and clock guessed
+ ncr53cf94_device &scsic(NCR53CF94(config, "scsic", 25'000'000)); // type and clock guessed
+ scsic.irq_handler_cb().set_inputline(m_cdcpu, MC68HC11_IRQ_LINE);
}
ROM_START(cdd2000)
diff --git a/src/devices/bus/nscsi/cdd2000.h b/src/devices/bus/nscsi/cdd2000.h
index 8f2b6eb6a20..546e4dfa96f 100644
--- a/src/devices/bus/nscsi/cdd2000.h
+++ b/src/devices/bus/nscsi/cdd2000.h
@@ -17,6 +17,7 @@ public:
protected:
virtual void device_start() override;
+ virtual void device_reset() override;
virtual void device_add_mconfig(machine_config &config) override;
virtual const tiny_rom_entry *device_rom_region() const override;
@@ -24,6 +25,7 @@ private:
void mem_map(address_map &map);
required_device<cpu_device> m_cdcpu;
+ required_memory_bank m_rombank;
};
DECLARE_DEVICE_TYPE(CDD2000, cdd2000_device)
diff --git a/src/devices/bus/nscsi/cdu415.cpp b/src/devices/bus/nscsi/cdu415.cpp
index a3b733b01d7..5b69a7d3c46 100644
--- a/src/devices/bus/nscsi/cdu415.cpp
+++ b/src/devices/bus/nscsi/cdu415.cpp
@@ -40,15 +40,10 @@ void cdu415_device::mem_map(address_map &map)
map(0x20000, 0x2ffff).rom().region("mcu", 0x10000);
}
-void cdu415_device::io_map(address_map &map)
-{
-}
-
void cdu415_device::device_add_mconfig(machine_config &config)
{
H83032(config, m_mcu, 10000000);
m_mcu->set_addrmap(AS_PROGRAM, &cdu415_device::mem_map);
- m_mcu->set_addrmap(AS_IO, &cdu415_device::io_map);
NCR53C94(config, m_scsi, 25'000'000); // Temporary placeholder
}
diff --git a/src/devices/bus/nscsi/cdu415.h b/src/devices/bus/nscsi/cdu415.h
index 2874c69a8cf..11ccab36a2c 100644
--- a/src/devices/bus/nscsi/cdu415.h
+++ b/src/devices/bus/nscsi/cdu415.h
@@ -8,7 +8,7 @@
#include "machine/nscsi_bus.h"
#include "cpu/h8/h83032.h"
-#include "machine/ncr5390.h"
+#include "machine/ncr53c90.h"
class cdu415_device : public device_t, public nscsi_slot_card_interface
{
@@ -24,7 +24,6 @@ protected:
private:
void mem_map(address_map &map);
- void io_map(address_map &map);
required_device<h83032_device> m_mcu;
required_device<ncr53c94_device> m_scsi;
diff --git a/src/devices/bus/nscsi/cdu75s.cpp b/src/devices/bus/nscsi/cdu75s.cpp
index 40fd92c72fc..601b849f36a 100644
--- a/src/devices/bus/nscsi/cdu75s.cpp
+++ b/src/devices/bus/nscsi/cdu75s.cpp
@@ -51,15 +51,10 @@ void cdu75s_device::mem_map(address_map &map)
map(0xc0000, 0xc003f); // CXD1808AQ
}
-void cdu75s_device::io_map(address_map &map)
-{
-}
-
void cdu75s_device::device_add_mconfig(machine_config &config)
{
H83032(config, m_mcu, 33.8688_MHz_XTAL/2);
m_mcu->set_addrmap(AS_PROGRAM, &cdu75s_device::mem_map);
- m_mcu->set_addrmap(AS_IO, &cdu75s_device::io_map);
NCR53C94(config, m_scsi, 25'000'000); // FAS204, compatible
}
diff --git a/src/devices/bus/nscsi/cdu75s.h b/src/devices/bus/nscsi/cdu75s.h
index b57550f9033..5fd64d0d889 100644
--- a/src/devices/bus/nscsi/cdu75s.h
+++ b/src/devices/bus/nscsi/cdu75s.h
@@ -8,7 +8,7 @@
#include "machine/nscsi_bus.h"
#include "cpu/h8/h83032.h"
-#include "machine/ncr5390.h"
+#include "machine/ncr53c90.h"
class cdu75s_device : public device_t, public nscsi_slot_card_interface
{
@@ -24,7 +24,6 @@ protected:
private:
void mem_map(address_map &map);
- void io_map(address_map &map);
required_device<h83032_device> m_mcu;
required_device<ncr53c94_device> m_scsi;
diff --git a/src/devices/bus/nscsi/crd254sh.cpp b/src/devices/bus/nscsi/crd254sh.cpp
index 80fc5fae740..7561f94cb6e 100644
--- a/src/devices/bus/nscsi/crd254sh.cpp
+++ b/src/devices/bus/nscsi/crd254sh.cpp
@@ -44,15 +44,10 @@ void crd254sh_device::mem_map(address_map &map)
map(0x00000, 0x0ffff).rom().region("mcu", 0);
}
-void crd254sh_device::io_map(address_map &map)
-{
-}
-
void crd254sh_device::device_add_mconfig(machine_config &config)
{
H83040(config, m_mcu, 20_MHz_XTAL);
m_mcu->set_addrmap(AS_PROGRAM, &crd254sh_device::mem_map);
- m_mcu->set_addrmap(AS_IO, &crd254sh_device::io_map);
NCR53C94(config, m_scsi, 25_MHz_XTAL); // Placeholder until we implement the real chip
}
diff --git a/src/devices/bus/nscsi/crd254sh.h b/src/devices/bus/nscsi/crd254sh.h
index c1ac2e4123d..3aacce43669 100644
--- a/src/devices/bus/nscsi/crd254sh.h
+++ b/src/devices/bus/nscsi/crd254sh.h
@@ -8,7 +8,7 @@
#include "machine/nscsi_bus.h"
#include "cpu/h8/h83042.h"
-#include "machine/ncr5390.h"
+#include "machine/ncr53c90.h"
class crd254sh_device : public device_t, public nscsi_slot_card_interface
{
@@ -24,7 +24,6 @@ protected:
private:
void mem_map(address_map &map);
- void io_map(address_map &map);
required_device<h83040_device> m_mcu;
required_device<ncr53c94_device> m_scsi;
diff --git a/src/devices/bus/nscsi/cw7501.cpp b/src/devices/bus/nscsi/cw7501.cpp
index c3ff2286f57..6e1af52e4d5 100644
--- a/src/devices/bus/nscsi/cw7501.cpp
+++ b/src/devices/bus/nscsi/cw7501.cpp
@@ -8,7 +8,7 @@
#include "emu.h"
#include "bus/nscsi/cw7501.h"
-#include "machine/ncr5390.h"
+#include "machine/ncr53c90.h"
DEFINE_DEVICE_TYPE(CW7501, cw7501_device, "cw7501", "Panasonic CW-7501 CD-R")
DEFINE_DEVICE_TYPE(CDR4210, cdr4210_device, "cdr4210", "Creative Technology Blaster CD-R 4210")
diff --git a/src/devices/bus/nscsi/devices.cpp b/src/devices/bus/nscsi/devices.cpp
index fad25440e3b..0ff4b192467 100644
--- a/src/devices/bus/nscsi/devices.cpp
+++ b/src/devices/bus/nscsi/devices.cpp
@@ -16,11 +16,13 @@
#include "bus/nscsi/hd.h"
#include "bus/nscsi/s1410.h"
#include "bus/nscsi/smoc501.h"
+#include "bus/nscsi/tape.h"
void default_scsi_devices(device_slot_interface &device)
{
device.option_add("cdrom", NSCSI_CDROM);
device.option_add("harddisk", NSCSI_HARDDISK);
+ device.option_add("tape", NSCSI_TAPE);
device.option_add("s1410", NSCSI_S1410);
device.option_add("cw7501", CW7501);
device.option_add("cdr4210", CDR4210);
diff --git a/src/devices/bus/nscsi/hd.cpp b/src/devices/bus/nscsi/hd.cpp
index 7e0f48730a8..8e210e22d10 100644
--- a/src/devices/bus/nscsi/hd.cpp
+++ b/src/devices/bus/nscsi/hd.cpp
@@ -4,9 +4,10 @@
#include "bus/nscsi/hd.h"
#include "imagedev/harddriv.h"
-#define LOG_GENERAL (1U << 0)
-#define LOG_COMMAND (1U << 1)
-#define LOG_DATA (1U << 2)
+#include "multibyte.h"
+
+#define LOG_COMMAND (1U << 1)
+#define LOG_DATA (1U << 2)
#define LOG_UNSUPPORTED (1U << 3)
#define VERBOSE 0
@@ -21,7 +22,7 @@ nscsi_harddisk_device::nscsi_harddisk_device(const machine_config &mconfig, cons
}
nscsi_harddisk_device::nscsi_harddisk_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
- nscsi_full_device(mconfig, type, tag, owner, clock), image(*this, "image"), harddisk(nullptr), lba(0), cur_lba(0), blocks(0), bytes_per_sector(0)
+ nscsi_full_device(mconfig, type, tag, owner, clock), image(*this, "image"), lba(0), cur_lba(0), blocks(0), bytes_per_sector(0)
{
}
@@ -38,21 +39,20 @@ void nscsi_harddisk_device::device_start()
void nscsi_harddisk_device::device_reset()
{
nscsi_full_device::device_reset();
- harddisk = image->get_hard_disk_file();
- if(!harddisk) {
+ if(!image->exists()) {
scsi_id = -1;
bytes_per_sector = 0;
} else {
- const auto &hdinfo = harddisk->get_info();
+ const auto &hdinfo = image->get_info();
bytes_per_sector = hdinfo.sectorbytes;
- harddisk->get_inquiry_data(m_inquiry_data);
+ image->get_inquiry_data(m_inquiry_data);
}
cur_lba = -1;
}
void nscsi_harddisk_device::device_add_mconfig(machine_config &config)
{
- HARDDISK(config, image).set_interface("scsi_hdd");
+ HARDDISK(config, image).set_interface("scsi_hdd,hdd");
}
uint8_t nscsi_harddisk_device::scsi_get_data(int id, int pos)
@@ -67,7 +67,7 @@ uint8_t nscsi_harddisk_device::scsi_get_data(int id, int pos)
int clba = lba + pos / bytes_per_sector;
if(clba != cur_lba) {
cur_lba = clba;
- if(!harddisk->read(cur_lba, block)) {
+ if(!image->read(cur_lba, block)) {
LOG("HD READ ERROR !\n");
memset(block, 0, sizeof(block));
}
@@ -90,7 +90,7 @@ void nscsi_harddisk_device::scsi_put_data(int id, int pos, uint8_t data)
block[offset] = data;
cur_lba = lba + pos / bytes_per_sector;
if(offset == bytes_per_sector-1) {
- if(!harddisk->write(cur_lba, block))
+ if(!image->write(cur_lba, block))
LOG("HD WRITE ERROR !\n");
}
}
@@ -110,14 +110,14 @@ void nscsi_harddisk_device::scsi_command()
break;
case SC_READ_6:
- lba = ((scsi_cmdbuf[1] & 0x1f)<<16) | (scsi_cmdbuf[2]<<8) | scsi_cmdbuf[3];
+ lba = get_u24be(&scsi_cmdbuf[1]) & 0x1fffff;
blocks = scsi_cmdbuf[4];
if(!blocks)
blocks = 256;
LOG("command READ start=%08x blocks=%04x\n", lba, blocks);
- if(harddisk->read(lba, block)) {
+ if(image->read(lba, block)) {
scsi_data_in(2, blocks*bytes_per_sector);
scsi_status_complete(SS_GOOD);
}
@@ -129,7 +129,7 @@ void nscsi_harddisk_device::scsi_command()
break;
case SC_WRITE_6:
- lba = ((scsi_cmdbuf[1] & 0x1f)<<16) | (scsi_cmdbuf[2]<<8) | scsi_cmdbuf[3];
+ lba = get_u24be(&scsi_cmdbuf[1]) & 0x1fffff;
blocks = scsi_cmdbuf[4];
if(!blocks)
blocks = 256;
@@ -219,17 +219,15 @@ void nscsi_harddisk_device::scsi_command()
scsi_cmdbuf[pos++] = 0x00; // medium type
scsi_cmdbuf[pos++] = 0x00; // WP, cache
- const auto &info = harddisk->get_info();
+ const auto &info = image->get_info();
uint32_t dsize = info.cylinders * info.heads * info.sectors - 1;
scsi_cmdbuf[pos++] = 0x08; // Block descriptor length
scsi_cmdbuf[pos++] = 0x00;
- scsi_cmdbuf[pos++] = (dsize>>16) & 0xff;
- scsi_cmdbuf[pos++] = (dsize>>8) & 0xff;
- scsi_cmdbuf[pos++] = (dsize & 0xff);
+ put_u24be(&scsi_cmdbuf[pos], dsize);
+ pos += 3;
scsi_cmdbuf[pos++] = 0x00;
- scsi_cmdbuf[pos++] = (info.sectorbytes>>16)&0xff;
- scsi_cmdbuf[pos++] = (info.sectorbytes>>8)&0xff;
- scsi_cmdbuf[pos++] = (info.sectorbytes & 0xff);
+ put_u24be(&scsi_cmdbuf[pos], info.sectorbytes);
+ pos += 3;
int pmax = page == 0x3f ? 0x3e : page;
int pmin = page == 0x3f ? 0x00 : page;
@@ -281,18 +279,18 @@ void nscsi_harddisk_device::scsi_command()
case 0x03: { // Format parameters page
scsi_cmdbuf[pos++] = 0x83; // PS, page id
scsi_cmdbuf[pos++] = 0x16; // Page length
- scsi_cmdbuf[pos++] = (info.cylinders * info.heads) >> 8; // Track/zone
- scsi_cmdbuf[pos++] = info.cylinders * info.heads; // Track/zone
+ put_u16be(&scsi_cmdbuf[pos], info.cylinders * info.heads); // Track/zone
+ pos += 2;
scsi_cmdbuf[pos++] = 0x00; // Alt sect/zone
scsi_cmdbuf[pos++] = 0x00; // Alt sect/zone
scsi_cmdbuf[pos++] = 0x00; // Alt track/zone
scsi_cmdbuf[pos++] = 0x00; // Alt track/zone
scsi_cmdbuf[pos++] = 0x00; // Alt track/volume
scsi_cmdbuf[pos++] = 0x00; // Alt track/volume
- scsi_cmdbuf[pos++] = info.sectors >> 8; // Sectors/track
- scsi_cmdbuf[pos++] = info.sectors; // Sectors/track
- scsi_cmdbuf[pos++] = info.sectorbytes >> 8; // Bytes/sector
- scsi_cmdbuf[pos++] = info.sectorbytes; // Bytes/sector
+ put_u16be(&scsi_cmdbuf[pos], info.sectors); // Sectors/track
+ pos += 2;
+ put_u16be(&scsi_cmdbuf[pos], info.sectorbytes); // Bytes/sector
+ pos += 2;
scsi_cmdbuf[pos++] = 0x00; // Interleave
scsi_cmdbuf[pos++] = 0x00; // Interleave
scsi_cmdbuf[pos++] = 0x00; // Track skew
@@ -309,28 +307,27 @@ void nscsi_harddisk_device::scsi_command()
case 0x04: { // Rigid drive geometry page
scsi_cmdbuf[pos++] = 0x84; // PS, page id
scsi_cmdbuf[pos++] = 0x16; // Page length
- scsi_cmdbuf[pos++] = info.cylinders >> 16; // Cylinders
- scsi_cmdbuf[pos++] = info.cylinders >> 8; // Cylinders
- scsi_cmdbuf[pos++] = info.cylinders; // Cylinders
- scsi_cmdbuf[pos++] = info.heads; // Heads
- scsi_cmdbuf[pos++] = 0x00; // Starting cylinder - write precomp
- scsi_cmdbuf[pos++] = 0x00; // Starting cylinder - write precomp
- scsi_cmdbuf[pos++] = 0x00; // Starting cylinder - write precomp
- scsi_cmdbuf[pos++] = 0x00; // Starting cylinder - reduced write current
- scsi_cmdbuf[pos++] = 0x00; // Starting cylinder - reduced write current
- scsi_cmdbuf[pos++] = 0x00; // Starting cylinder - reduced write current
- scsi_cmdbuf[pos++] = 0x00; // Drive step rate
- scsi_cmdbuf[pos++] = 0x00; // Drive step rate
- scsi_cmdbuf[pos++] = 0x00; // Landing zone cylinder
- scsi_cmdbuf[pos++] = 0x00; // Landing zone cylinder
- scsi_cmdbuf[pos++] = 0x00; // Landing zone cylinder
- scsi_cmdbuf[pos++] = 0x00; // RPL
- scsi_cmdbuf[pos++] = 0x00; // Rotational offset
- scsi_cmdbuf[pos++] = 0x00; // Reserved
- scsi_cmdbuf[pos++] = uint8_t(10000 >> 8); // Medium rotation rate
- scsi_cmdbuf[pos++] = uint8_t(10000); // Medium rotation rate
- scsi_cmdbuf[pos++] = 0x00; // Reserved
- scsi_cmdbuf[pos++] = 0x00; // Reserved
+ put_u24be(&scsi_cmdbuf[pos], info.cylinders); // Cylinders
+ pos += 3;
+ scsi_cmdbuf[pos++] = info.heads; // Heads
+ scsi_cmdbuf[pos++] = 0x00; // Starting cylinder - write precomp
+ scsi_cmdbuf[pos++] = 0x00; // Starting cylinder - write precomp
+ scsi_cmdbuf[pos++] = 0x00; // Starting cylinder - write precomp
+ scsi_cmdbuf[pos++] = 0x00; // Starting cylinder - reduced write current
+ scsi_cmdbuf[pos++] = 0x00; // Starting cylinder - reduced write current
+ scsi_cmdbuf[pos++] = 0x00; // Starting cylinder - reduced write current
+ scsi_cmdbuf[pos++] = 0x00; // Drive step rate
+ scsi_cmdbuf[pos++] = 0x00; // Drive step rate
+ scsi_cmdbuf[pos++] = 0x00; // Landing zone cylinder
+ scsi_cmdbuf[pos++] = 0x00; // Landing zone cylinder
+ scsi_cmdbuf[pos++] = 0x00; // Landing zone cylinder
+ scsi_cmdbuf[pos++] = 0x00; // RPL
+ scsi_cmdbuf[pos++] = 0x00; // Rotational offset
+ scsi_cmdbuf[pos++] = 0x00; // Reserved
+ put_u16be(&scsi_cmdbuf[pos], 10000); // Medium rotation rate
+ pos += 2;
+ scsi_cmdbuf[pos++] = 0x00; // Reserved
+ scsi_cmdbuf[pos++] = 0x00; // Reserved
break;
}
@@ -405,9 +402,9 @@ void nscsi_harddisk_device::scsi_command()
scsi_status_complete(SS_GOOD);
break;
- case SC_RECIEVE_DIAG_RES: {
- LOG("command RECIEVE DIAGNOSTICS RESULTS\n");
- int size = (scsi_cmdbuf[3] << 8) | scsi_cmdbuf[4];
+ case SC_RECEIVE_DIAGNOSTIC_RESULTS: {
+ LOG("command RECEIVE DIAGNOSTIC RESULTS\n");
+ int size = get_u16be(&scsi_cmdbuf[3]);
int pos = 0;
scsi_cmdbuf[pos++] = 0;
scsi_cmdbuf[pos++] = 6;
@@ -423,9 +420,9 @@ void nscsi_harddisk_device::scsi_command()
break;
}
- case SC_SEND_DIAGNOSTICS: {
- LOG("command SEND DIAGNOSTICS\n");
- int size = (scsi_cmdbuf[3] << 8) | scsi_cmdbuf[4];
+ case SC_SEND_DIAGNOSTIC: {
+ LOG("command SEND DIAGNOSTIC\n");
+ int size = get_u16be(&scsi_cmdbuf[3]);
if(scsi_cmdbuf[1] & 4) {
// Self-test
scsi_status_complete(SS_GOOD);
@@ -450,17 +447,11 @@ void nscsi_harddisk_device::scsi_command()
case SC_READ_CAPACITY: {
LOG("command READ CAPACITY\n");
- const auto &info = harddisk->get_info();
+ const auto &info = image->get_info();
uint32_t size = info.cylinders * info.heads * info.sectors - 1;
- scsi_cmdbuf[0] = (size>>24) & 0xff;
- scsi_cmdbuf[1] = (size>>16) & 0xff;
- scsi_cmdbuf[2] = (size>>8) & 0xff;
- scsi_cmdbuf[3] = (size & 0xff);
- scsi_cmdbuf[4] = (info.sectorbytes>>24)&0xff;
- scsi_cmdbuf[5] = (info.sectorbytes>>16)&0xff;
- scsi_cmdbuf[6] = (info.sectorbytes>>8)&0xff;
- scsi_cmdbuf[7] = (info.sectorbytes & 0xff);
+ put_u32be(&scsi_cmdbuf[0], size);
+ put_u32be(&scsi_cmdbuf[4], info.sectorbytes);
scsi_data_in(0, 8);
scsi_status_complete(SS_GOOD);
@@ -468,12 +459,12 @@ void nscsi_harddisk_device::scsi_command()
}
case SC_READ_10:
- lba = (scsi_cmdbuf[2]<<24) | (scsi_cmdbuf[3]<<16) | (scsi_cmdbuf[4]<<8) | scsi_cmdbuf[5];
- blocks = (scsi_cmdbuf[7] << 8) | scsi_cmdbuf[8];
+ lba = get_u32be(&scsi_cmdbuf[2]);
+ blocks = get_u16be(&scsi_cmdbuf[7]);
LOG("command READ EXTENDED start=%08x blocks=%04x\n",lba, blocks);
- if(harddisk->read(lba, block)) {
+ if(image->read(lba, block)) {
scsi_data_in(2, blocks*bytes_per_sector);
scsi_status_complete(SS_GOOD);
}
@@ -485,8 +476,8 @@ void nscsi_harddisk_device::scsi_command()
break;
case SC_WRITE_10:
- lba = (scsi_cmdbuf[2]<<24) | (scsi_cmdbuf[3]<<16) | (scsi_cmdbuf[4]<<8) | scsi_cmdbuf[5];
- blocks = (scsi_cmdbuf[7] << 8) | scsi_cmdbuf[8];
+ lba = get_u32be(&scsi_cmdbuf[2]);
+ blocks = get_u16be(&scsi_cmdbuf[7]);
LOG("command WRITE EXTENDED start=%08x blocks=%04x\n", lba, blocks);
@@ -502,12 +493,12 @@ void nscsi_harddisk_device::scsi_command()
(scsi_cmdbuf[1] & 0x10) ? " FMTDATA" : "",
(scsi_cmdbuf[1] & 0x08) ? " CMPLIST" : "");
{
- const auto &info = harddisk->get_info();
+ const auto &info = image->get_info();
auto block = std::make_unique<uint8_t[]>(info.sectorbytes);
for(int cyl = 0; cyl < info.cylinders; cyl++) {
for(int head = 0; head < info.heads; head++) {
for(int sector = 0; sector < info.sectors; sector++) {
- harddisk->write(cyl * head * sector, block.get());
+ image->write(cyl * head * sector, block.get());
}
}
}
@@ -525,7 +516,7 @@ void nscsi_harddisk_device::scsi_command()
scsi_status_complete(SS_GOOD);
break;
- case SC_VERIFY:
+ case SC_VERIFY_10:
LOG("command VERIFY BytChk %d\n", !!(scsi_cmdbuf[1] & 0x02));
if (!(scsi_cmdbuf[1] & 0x02))
scsi_status_complete(SS_GOOD);
diff --git a/src/devices/bus/nscsi/hd.h b/src/devices/bus/nscsi/hd.h
index 7ee1f851d26..3dc2060099c 100644
--- a/src/devices/bus/nscsi/hd.h
+++ b/src/devices/bus/nscsi/hd.h
@@ -26,7 +26,6 @@ protected:
required_device<harddisk_image_device> image;
uint8_t block[512];
- hard_disk_file *harddisk;
int lba, cur_lba, blocks;
int bytes_per_sector;
diff --git a/src/devices/bus/nscsi/s1410.cpp b/src/devices/bus/nscsi/s1410.cpp
index 4667ce04b98..52358d7e851 100644
--- a/src/devices/bus/nscsi/s1410.cpp
+++ b/src/devices/bus/nscsi/s1410.cpp
@@ -3,7 +3,8 @@
#include "emu.h"
#include "bus/nscsi/s1410.h"
-#define LOG_GENERAL (1U << 0)
+#include "multibyte.h"
+
#define LOG_COMMAND (1U << 1)
#define LOG_DATA (1U << 2)
@@ -33,22 +34,50 @@ void nscsi_s1410_device::device_reset()
params[7] = 11;
}
+bool nscsi_s1410_device::scsi_command_done(uint8_t command, uint8_t length)
+{
+ if(!length)
+ return false;
+ switch(command >> 5) {
+ case 0: return length == 6;
+ case 1: return true;
+ case 2: return true;
+ case 3: return true;
+ case 4: return true;
+ case 5: return true;
+ case 6: return true;
+ case 7: return length == 6;
+ }
+ return true;
+}
+
void nscsi_s1410_device::scsi_command()
{
+ memset(scsi_sense_buffer, 0, sizeof(scsi_sense_buffer));
+
switch(scsi_cmdbuf[0]) {
case SC_TEST_UNIT_READY:
- case SC_REZERO:
+ case SC_REZERO_UNIT:
case SC_REASSIGN_BLOCKS:
case SC_READ:
case SC_WRITE:
- case SC_SEEK:
if (scsi_cmdbuf[1] >> 5) {
scsi_status_complete(SS_NOT_READY);
+ scsi_sense_buffer[0] = SK_DRIVE_NOT_READY;
} else {
nscsi_harddisk_device::scsi_command();
}
break;
+ case SC_SEEK:
+ if (scsi_cmdbuf[1] >> 5) {
+ scsi_status_complete(SS_NOT_READY);
+ scsi_sense_buffer[0] = SK_DRIVE_NOT_READY;
+ } else {
+ scsi_status_complete(SS_GOOD);
+ }
+ break;
+
case SC_REQUEST_SENSE:
scsi_data_in(SBUF_SENSE, 4);
scsi_status_complete(SS_GOOD);
@@ -57,12 +86,12 @@ void nscsi_s1410_device::scsi_command()
case SC_FORMAT_UNIT:
LOG("command FORMAT UNIT\n");
{
- const auto &info = harddisk->get_info();
+ const auto &info = image->get_info();
auto block = std::make_unique<uint8_t[]>(info.sectorbytes);
memset(&block[0], 0x6c, info.sectorbytes);
- lba = ((scsi_cmdbuf[1] & 0x1f)<<16) | (scsi_cmdbuf[2]<<8) | scsi_cmdbuf[3];
+ lba = get_u24be(&scsi_cmdbuf[1]) & 0x1fffff;
for(; lba < (info.cylinders * info.heads * info.sectors); lba++) {
- harddisk->write(lba, block.get());
+ image->write(lba, block.get());
}
}
scsi_status_complete(SS_GOOD);
@@ -71,19 +100,21 @@ void nscsi_s1410_device::scsi_command()
case SC_FORMAT_TRACK: {
if (scsi_cmdbuf[1] >> 5) {
scsi_status_complete(SS_NOT_READY);
+ scsi_sense_buffer[0] = SK_DRIVE_NOT_READY;
return;
}
- lba = ((scsi_cmdbuf[1] & 0x1f)<<16) | (scsi_cmdbuf[2]<<8) | scsi_cmdbuf[3];
+ lba = get_u24be(&scsi_cmdbuf[1]) & 0x1fffff;
blocks = (bytes_per_sector == 256) ? 32 : 17;
int track_length = blocks*bytes_per_sector;
auto block = std::make_unique<uint8_t[]>(track_length);
memset(&block[0], 0x6c, track_length);
- if(!harddisk->write(lba, &block[0])) {
+ if(!image->write(lba, &block[0])) {
logerror("%s: HD WRITE ERROR !\n", tag());
scsi_status_complete(SS_FORMAT_ERROR);
+ scsi_sense_buffer[0] = SK_FORMAT_ERROR;
} else {
scsi_status_complete(SS_GOOD);
}
@@ -93,6 +124,7 @@ void nscsi_s1410_device::scsi_command()
case SC_FORMAT_ALT_TRACK:
if (scsi_cmdbuf[1] >> 5) {
scsi_status_complete(SS_NOT_READY);
+ scsi_sense_buffer[0] = SK_DRIVE_NOT_READY;
return;
}
@@ -118,6 +150,7 @@ void nscsi_s1410_device::scsi_command()
case SC_CHECK_TRACK_FORMAT:
if (scsi_cmdbuf[1] >> 5) {
scsi_status_complete(SS_NOT_READY);
+ scsi_sense_buffer[0] = SK_DRIVE_NOT_READY;
return;
}
scsi_status_complete(SS_GOOD);
@@ -174,3 +207,24 @@ void nscsi_s1410_device::scsi_put_data(int id, int pos, uint8_t data)
return nscsi_harddisk_device::scsi_put_data(id, pos, data);
}
}
+
+// Byte transfer rate (5Mb/s)
+attotime nscsi_s1410_device::scsi_data_byte_period()
+{
+ return attotime::from_nsec(1600);
+}
+
+// Command execution delay
+attotime nscsi_s1410_device::scsi_data_command_delay()
+{
+ switch(scsi_cmdbuf[0]) {
+ case SC_READ:
+ case SC_WRITE:
+ case SC_SEEK:
+ // average seek time of NEC D5126A hard disk
+ return attotime::from_msec(85);
+
+ default:
+ return attotime::zero;
+ }
+}
diff --git a/src/devices/bus/nscsi/s1410.h b/src/devices/bus/nscsi/s1410.h
index bd44a53c830..c3341357a63 100644
--- a/src/devices/bus/nscsi/s1410.h
+++ b/src/devices/bus/nscsi/s1410.h
@@ -43,7 +43,7 @@ protected:
// SCSI commands
enum {
SC_TEST_UNIT_READY = 0x00,
- SC_REZERO = 0x01,
+ SC_REZERO_UNIT = 0x01,
SC_REQUEST_SENSE = 0x03,
SC_FORMAT_UNIT = 0x04,
SC_CHECK_TRACK_FORMAT = 0x05,
@@ -64,11 +64,21 @@ protected:
SC_WRITE_LONG = 0xe6
};
+ // SCSI sense keys
+ enum {
+ SK_NO_ERROR = 0x00,
+ SK_DRIVE_NOT_READY = 0x04,
+ SK_FORMAT_ERROR = 0x1a
+ };
+
virtual void device_reset() override;
+ virtual bool scsi_command_done(uint8_t command, uint8_t length) override;
virtual void scsi_command() override;
virtual uint8_t scsi_get_data(int id, int pos) override;
virtual void scsi_put_data(int buf, int offset, uint8_t data) override;
+ virtual attotime scsi_data_byte_period() override;
+ virtual attotime scsi_data_command_delay() override;
uint8_t params[8];
};
diff --git a/src/devices/bus/nscsi/tape.cpp b/src/devices/bus/nscsi/tape.cpp
new file mode 100644
index 00000000000..e23bbf56939
--- /dev/null
+++ b/src/devices/bus/nscsi/tape.cpp
@@ -0,0 +1,899 @@
+// license:BSD-3-Clause
+// copyright-holders:Mietek Bak
+
+// best read together with SCSI-2 draft spec (rev 10L 7-SEP-93)
+// https://www.staff.uni-mainz.de/tacke/scsi/SCSI2.html
+
+#include "emu.h"
+
+#include "tape.h"
+
+#include "util/multibyte.h"
+#include "util/tape_file_interface.h"
+
+#include <cassert>
+#include <cstring>
+
+// #define VERBOSE LOG_GENERAL
+// #define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+DEFINE_DEVICE_TYPE(NSCSI_TAPE, nscsi_tape_device, "scsi_tape", "SCSI tape");
+
+//////////////////////////////////////////////////////////////////////////////
+
+// constants
+
+static constexpr u32 TAPE_DEFAULT_FIXED_BLOCK_LEN = 512;
+
+static constexpr int TAPE_RW_BUF_ID = 2;
+static constexpr int TAPE_PL_BUF_ID = 3;
+
+//////////////////////////////////////////////////////////////////////////////
+
+// construction
+
+nscsi_tape_device::nscsi_tape_device(const machine_config &config, device_type type, const char *tag, device_t *owner, u32 clock)
+ : nscsi_full_device(config, type, tag, owner, clock)
+ , m_image(*this, "image")
+ , m_sequence_counter(0)
+ , m_has_tape(false)
+ , m_tape_changed(false)
+ , m_fixed_block_len(TAPE_DEFAULT_FIXED_BLOCK_LEN)
+ , m_rw_buf_size(m_fixed_block_len)
+ , m_rw_pending(false)
+{
+}
+
+nscsi_tape_device::nscsi_tape_device(const machine_config &config, const char *tag, device_t *owner, u32 clock)
+ : nscsi_tape_device(config, NSCSI_TAPE, tag, owner, clock)
+{
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+// device_t implementation
+
+void nscsi_tape_device::device_add_mconfig(machine_config &config)
+{
+ SIMH_TAPE_IMAGE(config, m_image).set_interface("tape");
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+// nscsi_full_device implementation
+
+void nscsi_tape_device::device_start()
+{
+ nscsi_full_device::device_start();
+ m_sequence_counter = m_image->sequence_counter();
+ m_has_tape = m_image->get_file();
+ m_rw_buf = std::make_unique<u8[]>(m_rw_buf_size);
+ save_item(NAME(m_sequence_counter));
+ save_item(NAME(m_has_tape));
+ save_item(NAME(m_tape_changed));
+ save_item(NAME(m_fixed_block_len));
+ save_item(NAME(m_rw_buf_size));
+ save_pointer(NAME(m_rw_buf), m_rw_buf_size);
+ save_item(NAME(m_rw_pending));
+ save_item(NAME(m_rw_len));
+ save_item(NAME(m_rw_blocks_num));
+ save_item(NAME(m_rw_req_blocks_num));
+ save_item(NAME(m_rw_req_block_len));
+ save_item(NAME(m_rw_fixed_blocks));
+ save_item(NAME(m_r_suppress_bad_len));
+ save_item(NAME(m_pl_buf));
+ save_item(NAME(m_pl_len));
+}
+
+void nscsi_tape_device::device_reset()
+{
+ nscsi_full_device::device_reset();
+ m_sequence_counter = m_image->sequence_counter();
+ m_has_tape = m_image->get_file();
+ m_tape_changed = false;
+ m_fixed_block_len = TAPE_DEFAULT_FIXED_BLOCK_LEN;
+ m_rw_pending = false;
+}
+
+void nscsi_tape_device::scsi_command()
+{
+ const u8 cmd = scsi_cmdbuf[0];
+ const u8 lun = get_lun(scsi_cmdbuf[1] >> 5); // LUN may be overridden by IDENTIFY, per SCSI-2 section 7.2.2
+ switch (cmd) { // these commands must be handled here, before tape changing logic
+ case SC_INQUIRY: return handle_inquiry(lun);
+ case SC_REQUEST_SENSE: return handle_request_sense(lun);
+ }
+ if (m_sequence_counter != m_image->sequence_counter()) { // tape just changed
+ m_sequence_counter = m_image->sequence_counter();
+ const bool had_tape = m_has_tape;
+ m_has_tape = m_image->get_file();
+ m_tape_changed = true;
+ m_rw_pending = false;
+ if (had_tape) { // we report no tape to let initiator know old tape has been removed
+ LOG("command %s (ignored)\n", command_names[cmd], cmd);
+ return report_no_medium();
+ }
+ }
+ if (m_tape_changed) { // tape changed earlier
+ m_tape_changed = false;
+ if (m_has_tape) { // we report tape changed to let initiator know new tape has been inserted
+ LOG("command %s (ignored)\n", command_names[cmd], cmd);
+ return report_medium_changed();
+ }
+ }
+ if (lun) // error: we don't support LUNs other than 0 for other commands
+ return report_bad_lun(cmd, lun);
+
+ assert(m_has_tape == (bool)m_image->get_file());
+ switch (cmd) {
+ case SC_MODE_SELECT_6: return handle_mode_select_6();
+ case SC_MODE_SENSE_6: return handle_mode_sense_6();
+ case SC_SEND_DIAGNOSTIC: return handle_send_diagnostic();
+ case SC_TEST_UNIT_READY: return handle_test_unit_ready();
+ case SC_PREVENT_ALLOW_MEDIUM_REMOVAL: return handle_prevent_allow_medium_removal();
+ case SC_ERASE: return handle_erase();
+ case SC_LOAD_UNLOAD: return handle_load_unload();
+ case SC_LOCATE: return handle_locate();
+ case SC_READ_6: return handle_read_6();
+ case SC_READ_BLOCK_LIMITS: return handle_read_block_limits();
+ case SC_READ_POSITION: return handle_read_position();
+ case SC_RELEASE_UNIT: return handle_release_unit();
+ case SC_RESERVE_UNIT: return handle_reserve_unit();
+ case SC_REWIND: return handle_rewind();
+ case SC_SPACE: return handle_space();
+ case SC_WRITE_6: return handle_write_6();
+ case SC_WRITE_FILEMARKS: return handle_write_filemarks();
+ // TODO: support more optional commands
+ case SC_CHANGE_DEFINITION:
+ case SC_COMPARE:
+ case SC_COPY:
+ case SC_COPY_AND_VERIFY:
+ case SC_LOG_SELECT:
+ case SC_LOG_SENSE:
+ case SC_MODE_SELECT_10:
+ case SC_MODE_SENSE_10:
+ case SC_READ_BUFFER:
+ case SC_READ_REVERSE:
+ case SC_RECEIVE_DIAGNOSTIC_RESULTS:
+ case SC_RECOVER_BUFFERED_DATA:
+ case SC_VERIFY_6:
+ case SC_WRITE_BUFFER:
+ default:
+ nscsi_full_device::scsi_command();
+ }
+}
+
+u8 nscsi_tape_device::scsi_get_data(int id, int pos)
+{
+ switch (id) {
+ // we're handling READ(6); pos = 0 .. (m_rw_req_blocks_num * m_rw_req_block_len - 1)
+ case TAPE_RW_BUF_ID: {
+ const int relative_pos = pos % m_rw_req_block_len;
+ if (m_rw_pending && relative_pos == 0) { // we need to fill buffer by reading another block
+ assert(m_rw_len == 0);
+ continue_handling_read_6();
+ }
+ if (m_rw_len == 0) // buffer is still empty, so reading block failed; condition has already been reported; all we can do here is pretend to read 0 from buffer
+ return 0;
+
+ m_rw_len--;
+ return m_rw_buf[relative_pos];
+ }
+ default:
+ return nscsi_full_device::scsi_get_data(id, pos);
+ }
+}
+
+void nscsi_tape_device::scsi_put_data(int id, int pos, u8 data)
+{
+ switch (id) {
+ // we're handling WRITE(6); pos == 0 .. (m_rw_req_blocks_num * m_rw_req_block_len - 1)
+ case TAPE_RW_BUF_ID: {
+ if (m_rw_len == m_rw_req_block_len) // buffer is still full, so writing block failed; condition has already been reported; all we can do is pretend to write to buffer
+ return;
+
+ const int relative_pos = pos % m_rw_req_block_len;
+ m_rw_buf[relative_pos] = data;
+ m_rw_len++;
+ if (m_rw_pending && relative_pos == m_rw_req_block_len - 1) { // we need to empty buffer by writing another block
+ assert(m_rw_len == m_rw_req_block_len);
+ continue_handling_write_6();
+ }
+ return;
+ }
+ // we're handling MODE SELECT(6); pos == 0 .. (m_pl_len - 1)
+ case TAPE_PL_BUF_ID:
+ m_pl_buf[pos] = data;
+ if (pos == m_pl_len - 1)
+ continue_handling_mode_select_6();
+ return;
+
+ default:
+ return nscsi_full_device::scsi_put_data(id, pos, data);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+// command handling
+
+void nscsi_tape_device::handle_inquiry(const u8 lun) // mandatory; SCSI-2 section 8.2.5
+{
+ const bool vpd_enable = scsi_cmdbuf[1] & 0x01; // should we respond with vital product data
+ const u8 page_code = scsi_cmdbuf[2];
+ const u8 alloc_len = scsi_cmdbuf[4]; // allocation length
+ LOG("command INQUIRY lun=%d vpd_enable=%d page_code=0x%02x alloc_len=%d\n", lun, vpd_enable, page_code, alloc_len);
+ if ((scsi_cmdbuf[1] & 0x1e) || scsi_cmdbuf[3]) // error: reserved bits set
+ return report_bad_cdb_field();
+
+ if (vpd_enable || page_code) // error: we don't support vital product data or pages other than 0
+ return report_bad_cdb_field();
+
+ assert(sizeof(scsi_cmdbuf) >= 36);
+ memset(scsi_cmdbuf, 0, 36);
+ scsi_cmdbuf[0] = (lun == 0) ? 0x01 : 0x7f; // we support tape device on LUN 0 only, per 7.5.3(a)
+ scsi_cmdbuf[1] = 0x80; // we support removing tape
+ scsi_cmdbuf[2] = 0x02; // we're compliant with SCSI-2 only
+ scsi_cmdbuf[3] = 0x02; // we use SCSI-2 response format
+ scsi_cmdbuf[4] = 32; // additional length
+ strncpy((char *)&scsi_cmdbuf[8], "MAME", 8); // vendor
+ strncpy((char *)&scsi_cmdbuf[16], "SCSI tape drive", 16); // product
+ strncpy((char *)&scsi_cmdbuf[32], "1.0", 4); // revision
+ for (u32 i = 8; i < 36; i++) {
+ if (scsi_cmdbuf[i] == 0)
+ scsi_cmdbuf[i] = ' '; // pad strings with spaces
+ }
+ scsi_data_in(SBUF_MAIN, std::min(36, (const int)alloc_len));
+ scsi_status_complete(SS_GOOD);
+}
+
+void nscsi_tape_device::handle_mode_select_6() // mandatory; SCSI-2 sections 8.2.8, 8.3.3, 10.3.3
+{
+ const bool page_format = scsi_cmdbuf[1] & 0x10; // ignored; we always treat pages according to SCSI-2
+ const bool save_pages = scsi_cmdbuf[1] & 0x01;
+ const u8 pl_len = scsi_cmdbuf[4]; // parameter list length
+ LOG("command MODE SELECT(6) page_format=%d save_pages=%d pl_len=%d\n", page_format, save_pages, pl_len);
+ if ((scsi_cmdbuf[1] & 0x0e) || scsi_cmdbuf[2] || scsi_cmdbuf[3]) // error: reserved bits set
+ return report_bad_cdb_field();
+
+ if (save_pages) // error: we don't support saving pages
+ return report_bad_cdb_field();
+
+ if (pl_len == 0) // success: we have nothing to do
+ return scsi_status_complete(SS_GOOD);
+
+ m_pl_len = pl_len;
+ scsi_data_out(TAPE_PL_BUF_ID, pl_len);
+ // we continue in continue_handling_mode_select_6 through scsi_put_data
+}
+
+void nscsi_tape_device::continue_handling_mode_select_6()
+{
+ // this function is called by scsi_put_data when parameter list buffer is filled
+ if (m_pl_len < 4) // error: truncated header
+ return report_bad_pl_len();
+
+ const u8 buf_mode = (m_pl_buf[2] & 0x70) >> 4; // ignored; we don't support buffering
+ const u8 speed = m_pl_buf[2] & 0x0f; // ignored; we're always fast
+ const u8 bd_len = m_pl_buf[3]; // block descriptor length
+ LOG(" buf_mode=0x%02x speed=0x%02x bd_len=%d\n", buf_mode, speed, bd_len);
+ if (m_pl_len < 4 + bd_len) // error: truncated block descriptor
+ return report_bad_pl_len();
+
+ if (bd_len && bd_len != 8) // error: we don't accept more than 1 block descriptor
+ return report_bad_pl_field();
+
+ if (bd_len == 8) { // 1 block descriptor
+ const u8 density_code = m_pl_buf[4];
+ const u32 blocks_num = get_u24be(&m_pl_buf[5]); // number of blocks
+ const u32 block_len = get_u24be(&m_pl_buf[9]); // block length
+ LOG(" density_code=0x%02x blocks_num=%d block_len=%d\n", density_code, blocks_num, block_len);
+ if (density_code) // error: we don't support changing density
+ return report_bad_pl_field();
+
+ if (blocks_num) // error: we don't support changing block length for only some amount of blocks
+ return report_bad_pl_field();
+
+ if (block_len == 0) // error: requested block length is bad
+ return report_bad_pl_field();
+
+ m_fixed_block_len = block_len;
+ if (m_fixed_block_len > m_rw_buf_size) {
+ m_rw_buf_size = m_fixed_block_len;
+ m_rw_buf = std::make_unique<u8[]>(m_rw_buf_size);
+ }
+ }
+ u32 page_num = 0;
+ u32 page_pos = 4 + bd_len;
+ while (page_pos < m_pl_len) { // we accept any number of pages
+ if (m_pl_len < page_pos + 2) // error: truncated page
+ return report_bad_pl_len();
+
+ const u8 page_code = m_pl_buf[page_pos] & 0x3f;
+ const u8 page_len = m_pl_buf[page_pos + 1];
+ LOG(" page_num=%d page_code=0x%02x page_len=%d\n", page_num, page_code, page_len);
+ if (m_pl_len < page_pos + 2 + page_len) // error: truncated page
+ return report_bad_pl_len();
+
+ switch (page_code) {
+ case SPC_MEDIUM_PARTITION_PAGE_1: { // TODO: test more software and see if these pages need to be accommodated
+ if (page_len < 6 || page_len % 2) // error: malformed page
+ return report_bad_pl_field();
+
+ const u8 map = m_pl_buf[page_pos + 2]; // "maximum additional partitions"
+ const u8 apd = m_pl_buf[page_pos + 3]; // "additional partitions defined"
+ const bool fdp = m_pl_buf[page_pos + 4] & 0x80; // "fixed data partitions"
+ const bool sdp = m_pl_buf[page_pos + 4] & 0x40; // "select data partitions"
+ const bool idp = m_pl_buf[page_pos + 4] & 0x20; // "initiator-defined partitions"
+ const u8 psum = (m_pl_buf[page_pos + 4] & 0x18) >> 3; // "partition size unit of measure"
+ const u8 mfr = m_pl_buf[page_pos + 5]; // "medium format recognition"
+ LOG(" map=%d apd=%d fdp=%d sdp=%d idp=%d psum=0x%x mfr=0x%02x\n", map, apd, fdp, sdp, idp, psum, mfr);
+ u32 psd_num = 0; // partition size descriptor number
+ u32 psd_pos = 8; // partition size descriptor position
+ while (psd_pos < page_len) {
+ const u16 ps = get_u16be(&m_pl_buf[page_pos + psd_pos]); // "partition size"
+ LOG(" psd_num=%d ps=%d\n", psd_num, ps);
+ psd_num++;
+ psd_pos += 2;
+ }
+ break;
+ }
+ default:
+ LOG(" *** BAD PAGE\n");
+ }
+ page_num++;
+ page_pos += 2 + page_len;
+ }
+ scsi_status_complete(SS_GOOD);
+}
+
+void nscsi_tape_device::handle_mode_sense_6() // mandatory; SCSI-2 sections 8.2.10, 8.3.3, 10.3.3
+{
+ const bool bd_disable = scsi_cmdbuf[1] & 0x80; // should we not respond with block descriptor
+ const u8 page_control = scsi_cmdbuf[2] >> 6;
+ const u8 page_code = scsi_cmdbuf[2] & 0x3f;
+ LOG("command MODE SENSE(6) bd_disable=%d page_control=0x%02x page_code=0x%02x\n", bd_disable, page_control, page_code);
+ if ((scsi_cmdbuf[1] & 0x17) || scsi_cmdbuf[3]) // error: reserved bits set
+ return report_bad_cdb_field();
+
+ if (page_code && page_code != SPC_RETURN_ALL_MODE_PAGES) // error: we don't support pages other than 0
+ return report_bad_cdb_field();
+
+ // TODO: support more pages, such as SPC_DATA_COMPRESSION_PAGE, and SPC_DEVICE_CONFIGURATION_PAGE with BIS bit set to indicate we support reporting block addresses in response to READ POSITION
+ if (page_control == SPC_SAVED_VALUES) // error: we don't support saving parameters
+ return report_no_saving_params();
+
+ const u8 resp_len = bd_disable ? 4 : 12; // response length
+ assert(sizeof(scsi_cmdbuf) >= resp_len);
+ memset(scsi_cmdbuf, 0, resp_len);
+ scsi_cmdbuf[0] = resp_len - 1; // mode data length does not include itself, per SCSI-2 section 8.3.3
+ scsi_cmdbuf[2] = (m_has_tape && m_image->get_file()->is_read_only()) ? 0x80 : 0; // device-specific parameter
+ scsi_cmdbuf[3] = bd_disable ? 0 : 8; // block descriptor length
+ if (!bd_disable) { // respond with block descriptor
+ scsi_cmdbuf[4] = m_has_tape ? m_image->get_file()->get_density_code() : 0; // density code
+ put_u24be(&scsi_cmdbuf[9], m_fixed_block_len); // block length
+ }
+ scsi_data_in(SBUF_MAIN, resp_len);
+ scsi_status_complete(SS_GOOD);
+}
+
+void nscsi_tape_device::handle_send_diagnostic() // mandatory; SCSI-2 section 8.2.15
+{
+ const bool page_format = scsi_cmdbuf[1] & 0x10;
+ const bool self_test = scsi_cmdbuf[1] & 0x04;
+ const bool device_offline = scsi_cmdbuf[1] & 0x02;
+ const bool unit_offline = scsi_cmdbuf[1] & 0x01;
+ const u16 pl_len = get_u16be(&scsi_cmdbuf[3]); // parameter list length
+ LOG("command SEND DIAGNOSTIC page_format=%d self_test=%d device_offline=%d unit_offline=%d pl_len=%d\n", page_format, self_test, device_offline, unit_offline, pl_len);
+ if ((scsi_cmdbuf[1] & 0x08) || scsi_cmdbuf[2]) // error: reserved bits set
+ return report_bad_cdb_field();
+
+ if (pl_len) // error: we don't support any parameters
+ return report_bad_cdb_field();
+
+ scsi_status_complete(SS_GOOD);
+}
+
+void nscsi_tape_device::handle_test_unit_ready() // mandatory; SCSI-2 section 8.2.16
+{
+ LOG("command TEST UNIT READY\n");
+ if ((scsi_cmdbuf[1] & 0x1f) || scsi_cmdbuf[2] || scsi_cmdbuf[3] || scsi_cmdbuf[4]) // error: reserved bits set
+ return report_bad_cdb_field();
+
+ if (!m_has_tape) // error: no tape
+ return report_no_medium();
+
+ scsi_status_complete(SS_GOOD);
+}
+
+void nscsi_tape_device::handle_prevent_allow_medium_removal() // optional; SCSI-2 section 9.2.4
+{
+ const bool prevent = scsi_cmdbuf[4] & 0x01; // should we prevent or allow removing tape
+ LOG("command %s MEDIUM REMOVAL\n", prevent ? "PREVENT" : "ALLOW");
+ if ((scsi_cmdbuf[1] & 0x1f) || scsi_cmdbuf[2] || scsi_cmdbuf[3] || (scsi_cmdbuf[4] & 0xfe)) // error: reserved bits set
+ return report_bad_cdb_field();
+
+ if (prevent) {
+ if (!m_has_tape) // error: no tape
+ return report_no_medium();
+
+ // TODO: prevent removing tape, once MAME supports it
+ return scsi_status_complete(SS_GOOD);
+ }
+ else { // allow
+ // TODO: allow removing tape, once MAME supports it
+ return scsi_status_complete(SS_GOOD);
+ }
+}
+
+void nscsi_tape_device::handle_erase() // mandatory; SCSI-2 section 10.2.1
+{
+ const bool immed = scsi_cmdbuf[1] & 0x02; // ignored; we don't support buffering
+ const bool eom = scsi_cmdbuf[1] & 0x01; // should we erase to EOM instead of 1 block; "long"
+ LOG("command ERASE immed=%d eom=%d\n", immed, eom);
+ if ((scsi_cmdbuf[1] & 0x1c) || scsi_cmdbuf[2] || scsi_cmdbuf[3] || scsi_cmdbuf[4]) // error: reserved bits set
+ return report_bad_cdb_field();
+
+ if (!m_has_tape) // error: no tape
+ return report_no_medium();
+
+ if (m_image->get_file()->is_read_only()) // error: tape is read-only
+ return report_read_only();
+
+ try {
+ m_image->get_file()->erase(eom);
+ return scsi_status_complete(SS_GOOD);
+ }
+ catch (std::exception &e) { // error: writing to tape failed
+ osd_printf_error("ERASE FAILURE: nscsi_tape_device::handle_erase: %s\n", e.what());
+ return report_erase_failure();
+ }
+}
+
+void nscsi_tape_device::handle_load_unload() // optional; SCSI-2 section 10.2.2
+{
+ const bool immed = scsi_cmdbuf[1] & 0x01; // ignored; we don't support buffering
+ const bool eom = scsi_cmdbuf[4] & 0x04; // should we rewind to EOM instead of BOM on unload
+ const bool retension = scsi_cmdbuf[4] & 0x02; // ignored; we're always tense
+ const bool load = scsi_cmdbuf[4] & 0x01; // should we load or unload tape
+ LOG("command %s immed=%d eom=%d retension=%d\n", load ? "LOAD" : "UNLOAD", immed, eom, retension);
+ if ((scsi_cmdbuf[1] & 0x1e) || scsi_cmdbuf[2] || scsi_cmdbuf[3] || (scsi_cmdbuf[4] & 0xf8)) // error: reserved bits set
+ return report_bad_cdb_field();
+
+ if (load && eom) // error: invalid combination of command options
+ return report_bad_cdb_field();
+
+ if (load) {
+ if (!m_has_tape) // error: no tape
+ return report_no_medium();
+
+ m_image->get_file()->rewind(false);
+ return scsi_status_complete(SS_GOOD);
+ }
+ else { // unload
+ if (m_has_tape) // rewind tape if it's there
+ m_image->get_file()->rewind(eom);
+ return scsi_status_complete(SS_GOOD);
+ }
+}
+
+void nscsi_tape_device::handle_locate() // optional; SCSI-2 section 10.2.3
+{
+ const bool block_addr_type = scsi_cmdbuf[1] & 0x04; // ignored; we always use logical block addresses
+ const bool change_partition = scsi_cmdbuf[1] & 0x02;
+ const bool immed = scsi_cmdbuf[1] & 0x01; // ignored; we don't support buffering
+ const u32 req_block_addr = get_u32be(&scsi_cmdbuf[3]); // requested block address to locate
+ const u8 partition = scsi_cmdbuf[8];
+ LOG("command LOCATE block_addr_type=%d change_partition=%d immed=%d req_block_addr=%d partition=0x%02x\n", block_addr_type, change_partition, immed, req_block_addr, partition);
+ if ((scsi_cmdbuf[1] & 0x18) || scsi_cmdbuf[2] || scsi_cmdbuf[7]) // error: reserved bits set
+ return report_bad_cdb_field();
+
+ if (change_partition) // error: we don't support partitions other than 0
+ return report_bad_cdb_field();
+
+ if (!m_has_tape) // error: no tape
+ return report_no_medium();
+
+ try {
+ const auto status = m_image->get_file()->locate_block(req_block_addr);
+ switch (status) {
+ case tape_status::OK: // success: we located requested block
+ return scsi_status_complete(SS_GOOD);
+
+ case tape_status::EOD: // error: we reached EOD
+ case tape_status::EOD_EW: // error: we reached EOD and we're also between EW and EOM
+ return report_eod(0, status == tape_status::EOD_EW);
+
+ case tape_status::EOM: // error: we reached EOM
+ return report_eom(false);
+
+ default:
+ assert(false);
+ }
+ }
+ catch (std::exception &e) { // error: reading from tape failed
+ osd_printf_error("READ FAILURE: nscsi_tape_device::handle_locate: %s\n", e.what());
+ return report_read_failure();
+ }
+}
+
+void nscsi_tape_device::handle_read_6() // mandatory; SCSI-2 section 10.2.4
+{
+ const bool suppress = scsi_cmdbuf[1] & 0x02; // should we suppress indicating incorrect length
+ const bool fixed = scsi_cmdbuf[1] & 0x01; // should we read many fixed-length blocks instead of 1 variable-length block
+ const u32 req_items_num = get_u24be(&scsi_cmdbuf[2]); // requested number of blocks or bytes to read; "transfer length"
+ LOG("command READ(6) suppress=%d fixed=%d req_items_num=%d\n", suppress, fixed, req_items_num);
+ if (scsi_cmdbuf[1] & 0x1c) // error: reserved bits set
+ return report_bad_cdb_field();
+
+ if (fixed && suppress) // error: invalid combination of command options
+ return report_bad_cdb_field();
+
+ if (!m_has_tape) // error: no tape
+ return report_no_medium();
+
+ if (req_items_num == 0) // success: we have nothing to do
+ return scsi_status_complete(SS_GOOD);
+
+ if (!fixed && req_items_num > m_rw_buf_size) {
+ m_rw_buf_size = req_items_num;
+ m_rw_buf = std::make_unique<u8[]>(m_rw_buf_size);
+ }
+ m_rw_pending = true;
+ m_rw_len = 0;
+ m_rw_blocks_num = 0;
+ m_rw_req_blocks_num = fixed ? req_items_num : 1;
+ m_rw_req_block_len = fixed ? m_fixed_block_len : req_items_num;
+ m_rw_fixed_blocks = fixed;
+ m_r_suppress_bad_len = suppress;
+ assert(m_rw_req_block_len <= m_rw_buf_size);
+ scsi_data_in(TAPE_RW_BUF_ID, m_rw_req_blocks_num * m_rw_req_block_len);
+ // we continue in continue_handling_read_6 through scsi_get_data
+}
+
+void nscsi_tape_device::continue_handling_read_6()
+{
+ // this function is called by scsi_get_data every time read/write buffer is emptied
+ assert(m_has_tape);
+ assert(m_rw_len == 0);
+ try {
+ const auto result = m_image->get_file()->read_block(m_rw_buf.get(), m_rw_buf_size);
+ const auto status = result.first;
+ const u32 block_len = result.second;
+ switch (status) {
+ case tape_status::OK: { // success: we read another block
+ const bool over = block_len > m_rw_req_block_len;
+ const bool under = block_len < m_rw_req_block_len;
+ if (over || (under && !m_r_suppress_bad_len)) { // error: we read block of incorrect length
+ m_rw_pending = false;
+ return report_bad_len(over, m_rw_fixed_blocks ? (m_rw_req_blocks_num - m_rw_blocks_num) : (m_rw_req_block_len - block_len));
+ }
+ if (under && m_r_suppress_bad_len)
+ LOG(" *** UNDERLENGTH\n");
+ m_rw_len = block_len;
+ m_rw_blocks_num++;
+ if (m_rw_blocks_num == m_rw_req_blocks_num) { // success: we're done
+ m_rw_pending = false;
+ return scsi_status_complete(SS_GOOD);
+ }
+ return; // we should read some more blocks
+ }
+ case tape_status::FILEMARK: // error: we reached filemark
+ case tape_status::FILEMARK_EW: // error: we reached filemark and we're also between EW and EOM
+ m_rw_pending = false;
+ assert(block_len == 0);
+ return report_filemark(m_rw_fixed_blocks ? (m_rw_req_blocks_num - m_rw_blocks_num) : m_rw_req_block_len, status == tape_status::FILEMARK_EW);
+
+ case tape_status::EOD: // error: we reached EOD
+ case tape_status::EOD_EW: // error: we reached EOD and we're also between EW and EOM
+ m_rw_pending = false;
+ assert(block_len == 0);
+ return report_eod(m_rw_fixed_blocks ? (m_rw_req_blocks_num - m_rw_blocks_num) : m_rw_req_block_len, status == tape_status::EOD_EW);
+
+ case tape_status::EOM: // error: we reached EOM
+ m_rw_pending = false;
+ assert(block_len == 0);
+ return report_eom(false, m_rw_fixed_blocks ? (m_rw_req_blocks_num - m_rw_blocks_num) : m_rw_req_block_len);
+
+ default:
+ assert(false);
+ }
+ }
+ catch (std::exception &e) { // error: reading from tape failed
+ osd_printf_error("READ FAILURE: nscsi_tape_device::continue_handling_read_6: %s\n", e.what());
+ return report_read_failure();
+ }
+}
+
+void nscsi_tape_device::handle_read_block_limits() // mandatory; SCSI-2 section 10.2.5
+{
+ LOG("command READ BLOCK LIMITS\n");
+ if ((scsi_cmdbuf[1] & 0x1f) || scsi_cmdbuf[2] || scsi_cmdbuf[3] || scsi_cmdbuf[4]) // error: reserved bits set
+ return report_bad_cdb_field();
+
+ assert(sizeof(scsi_cmdbuf) >= 6);
+ memset(scsi_cmdbuf, 0, 6);
+ put_u24be(&scsi_cmdbuf[1], 0xffffff); // 16MB; "maximum block length limit"
+ put_u16be(&scsi_cmdbuf[4], m_fixed_block_len); // "minimum block length limit"
+ scsi_data_in(SBUF_MAIN, 6);
+ scsi_status_complete(SS_GOOD);
+}
+
+void nscsi_tape_device::handle_read_position() // optional; SCSI-2 section 10.2.6
+{
+ const bool block_addr_type = scsi_cmdbuf[1] & 0x01; // ignored; we always use logical block addresses
+ LOG("command READ POSITION block_addr_type=%d\n", block_addr_type);
+ if ((scsi_cmdbuf[1] & 0x1e) || scsi_cmdbuf[2] || scsi_cmdbuf[3] || scsi_cmdbuf[4] || scsi_cmdbuf[5] || scsi_cmdbuf[6] || scsi_cmdbuf[7] || scsi_cmdbuf[8]) // error: reserved bits set
+ return report_bad_cdb_field();
+
+ if (!m_has_tape) // error: no tape
+ return report_no_medium();
+
+ try {
+ const auto result = m_image->get_file()->read_position();
+ const auto status = result.first;
+ const u32 block_addr = result.second;
+ switch (status) {
+ case tape_status::OK: // we're right after some block (at EOD, or at filemark, or at another block); block address is valid
+ LOG(" block_addr=%d\n", block_addr);
+ break;
+ case tape_status::BOM: // we're at BOM; block address is valid and 0
+ LOG(" BOM block_addr=%d\n", block_addr);
+ assert(block_addr == 0);
+ break;
+ case tape_status::EW: // we're between EW and EOM; block address is valid
+ LOG(" EW block_addr=%d\n", block_addr);
+ break;
+ case tape_status::UNKNOWN: // we're after EOD or inside some block; block address is not valid
+ case tape_status::UNKNOWN_EW: // we're after EOD or inside some block and also between EW and EOM; block address is not valid
+ LOG(" UNKNOWN%s block_addr=%d\n", status == tape_status::UNKNOWN_EW ? " EW" : " ", block_addr);
+ assert(block_addr == 0);
+ break;
+ case tape_status::EOM: // we're at EOM; block address is not valid
+ LOG(" EOM block_addr=%d\n", block_addr);
+ assert(block_addr == 0);
+ break;
+ default:
+ assert(false);
+ }
+ const bool bom = status == tape_status::BOM;
+ const bool eom = status == tape_status::EW
+ || status == tape_status::UNKNOWN_EW
+ || status == tape_status::EOM;
+ const bool bpu = status == tape_status::UNKNOWN
+ || status == tape_status::UNKNOWN_EW
+ || status == tape_status::EOM;
+ assert(sizeof(scsi_cmdbuf) >= 20);
+ memset(scsi_cmdbuf, 0, 20);
+ scsi_cmdbuf[0] = (bom ? 0x80 : 0) // is position at BOM
+ | (eom ? 0x40 : 0) // is position between EW and EOM
+ | (bpu ? 0x04 : 0); // is next block address invalid; "block position unknown"
+ put_u32be(&scsi_cmdbuf[4], block_addr); // address of next block to be read/written; "first block location"
+ put_u32be(&scsi_cmdbuf[8], block_addr); // address of last buffered block; we don't support buffering, so we set it to next block address; "last block location"
+ scsi_data_in(SBUF_MAIN, 20);
+ scsi_status_complete(SS_GOOD);
+ }
+ catch (std::exception &e) { // error: reading from tape failed
+ osd_printf_error("READ FAILURE: nscsi_tape_device::handle_read_position: %s\n", e.what());
+ return report_read_failure();
+ }
+}
+
+void nscsi_tape_device::handle_release_unit() // mandatory; SCSI-2 section 10.2.9
+{
+ const bool tpr = scsi_cmdbuf[1] & 0x10; // "third-party release"
+ const u8 tpdi = (scsi_cmdbuf[1] & 0x0e) >> 1; // "third-party device id"
+ LOG("command RELEASE UNIT tpr=%d tpdi=%d\n", tpr, tpdi);
+ if ((scsi_cmdbuf[1] & 0x01) || scsi_cmdbuf[2] || scsi_cmdbuf[3] || scsi_cmdbuf[4]) // error: reserved bits set
+ return report_bad_cdb_field();
+
+ // TODO: release unit, once MAME supports multiple initiators
+ scsi_status_complete(SS_GOOD);
+}
+
+void nscsi_tape_device::handle_reserve_unit() // mandatory; SCSI-2 section 10.2.10
+{
+ const bool tpr = scsi_cmdbuf[1] & 0x10; // "third-party release"
+ const u8 tpdi = (scsi_cmdbuf[1] & 0x0e) >> 1; // "third-party device id"
+ LOG("command RESERVE UNIT tpr=%d tpdi=%d\n", tpr, tpdi);
+ if ((scsi_cmdbuf[1] & 0x01) || scsi_cmdbuf[2] || scsi_cmdbuf[3] || scsi_cmdbuf[4]) // error: reserved bits set
+ return report_bad_cdb_field();
+
+ // TODO: reserve unit, once MAME supports multiple initiators
+ scsi_status_complete(SS_GOOD);
+}
+
+void nscsi_tape_device::handle_rewind() // mandatory; SCSI-2 section 10.2.11
+{
+ const bool immed = scsi_cmdbuf[1] & 0x01; // ignored; we don't support buffering
+ LOG("command REWIND immed=%d\n", immed);
+ if ((scsi_cmdbuf[1] & 0x1e) || scsi_cmdbuf[2] || scsi_cmdbuf[3] || scsi_cmdbuf[4]) // error: reserved bits set
+ return report_bad_cdb_field();
+
+ if (!m_has_tape) // error: no tape
+ return report_no_medium();
+
+ m_image->get_file()->rewind(false);
+ scsi_status_complete(SS_GOOD);
+}
+
+void nscsi_tape_device::handle_space() // mandatory; SCSI-2 section 10.2.12
+{
+ const u8 items_type = scsi_cmdbuf[1] & 0x07; // what type of items should we space over
+ const u32 req_dir_items_num = get_s24be(&scsi_cmdbuf[2]); // requested direction and number of items to space over; "count"
+ LOG("command SPACE items_type=0x%02x req_dir_items_num=%d\n", items_type, req_dir_items_num);
+ if (scsi_cmdbuf[1] & 0x18) // error: reserved bits set
+ return report_bad_cdb_field();
+
+ if (items_type != STC_BLOCKS && items_type != STC_FILEMARKS && items_type != STC_END_OF_DATA) // error: we don't support spacing over setmarks or sequential filemarks
+ return report_bad_cdb_field();
+
+ if (!m_has_tape) // error: no tape
+ return report_no_medium();
+
+ try {
+ if (items_type == STC_END_OF_DATA) { // spacing EOD needs special handling
+ const auto status = m_image->get_file()->space_eod();
+ switch (status) {
+ case tape_status::OK: // success: we reached EOD
+ return scsi_status_complete(SS_GOOD);
+
+ case tape_status::EOM: // error: we reached EOM
+ return report_eom(false, 0, true);
+
+ default:
+ assert(false);
+ }
+ }
+ if (req_dir_items_num == 0) // success: we have nothing to do
+ return scsi_status_complete(SS_GOOD);
+
+ const bool marks = items_type == STC_FILEMARKS;
+ const bool reverse = req_dir_items_num < 0;
+ const u32 req_items_num = reverse ? -req_dir_items_num : req_dir_items_num;
+ const auto result = marks ? (reverse ? m_image->get_file()->space_filemarks_reverse(req_items_num)
+ : m_image->get_file()->space_filemarks(req_items_num))
+ : (reverse ? m_image->get_file()->space_blocks_reverse(req_items_num)
+ : m_image->get_file()->space_blocks(req_items_num));
+ const auto status = result.first;
+ const u32 items_num = result.second;
+ switch (status) {
+ case tape_status::OK: // success: we reached requested item
+ assert(items_num == req_items_num);
+ return scsi_status_complete(SS_GOOD);
+
+ case tape_status::BOM: // error: we reached BOM
+ return report_bom(req_items_num - items_num);
+
+ case tape_status::FILEMARK: // error: we reached filemark
+ case tape_status::FILEMARK_EW: // error: we reached filemark and we're also between EW and EOM
+ return report_filemark(req_items_num - items_num, status == tape_status::FILEMARK_EW);
+
+ case tape_status::EOD: // error: we reached EOD
+ case tape_status::EOD_EW: // error: we reached EOD and we're also between EW and EOM
+ return report_eod(req_items_num - items_num, status == tape_status::EOD_EW);
+
+ case tape_status::EOM: // error: we reached EOM
+ return report_eom(false, req_items_num - items_num);
+
+ default:
+ assert(false);
+ }
+ }
+ catch (std::exception &e) { // error: reading from tape failed
+ osd_printf_error("READ FAILURE: nscsi_tape_device::handle_space: %s\n", e.what());
+ return report_read_failure();
+ }
+}
+
+void nscsi_tape_device::handle_write_6() // mandatory; SCSI-2 section 10.2.14
+{
+ const bool fixed = scsi_cmdbuf[1] & 0x01; // should we write many fixed-length blocks instead of 1 variable-length block
+ const u32 req_items_num = get_u24be(&scsi_cmdbuf[2]); // requested number of blocks or bytes to write; "transfer length"
+ LOG("command WRITE(6) fixed=%d req_items_num=%d\n", fixed, req_items_num);
+ if (scsi_cmdbuf[1] & 0x1e) // error: reserved bits set
+ return report_bad_cdb_field();
+
+ if (!m_has_tape) // error: no tape
+ return report_no_medium();
+
+ if (m_image->get_file()->is_read_only()) // error: tape is read-only
+ return report_read_only();
+
+ if (req_items_num == 0) // success: we have nothing to do
+ return scsi_status_complete(SS_GOOD);
+
+ if (!fixed && req_items_num > m_rw_buf_size) {
+ m_rw_buf_size = req_items_num;
+ m_rw_buf = std::make_unique<u8[]>(m_rw_buf_size);
+ }
+ m_rw_pending = true;
+ m_rw_len = 0;
+ m_rw_blocks_num = 0;
+ m_rw_req_blocks_num = fixed ? req_items_num : 1;
+ m_rw_req_block_len = fixed ? m_fixed_block_len : req_items_num;
+ m_rw_fixed_blocks = fixed;
+ assert(m_rw_req_block_len <= m_rw_buf_size);
+ scsi_data_out(TAPE_RW_BUF_ID, m_rw_req_blocks_num * m_rw_req_block_len);
+ // we continue in continue_handling_write_6 through scsi_put_data
+}
+
+void nscsi_tape_device::continue_handling_write_6()
+{
+ // this function is called by scsi_put_data every time read/write buffer is filled
+ assert(m_has_tape);
+ assert(m_rw_len == m_rw_req_block_len);
+ try {
+ const auto status = m_image->get_file()->write_block(m_rw_buf.get(), m_rw_req_block_len);
+ switch (status) {
+ case tape_status::OK: // success: we wrote another block
+ m_rw_len = 0;
+ m_rw_blocks_num++;
+ if (m_rw_blocks_num == m_rw_req_blocks_num) { // success: we're done
+ m_rw_pending = false;
+ return scsi_status_complete(SS_GOOD);
+ }
+ return; // we should write some more blocks
+
+ case tape_status::EW: // success: we wrote another block, but we're between EW and EOM
+ m_rw_len = 0;
+ m_rw_blocks_num++;
+ m_rw_pending = false;
+ return report_ew(m_rw_fixed_blocks ? (m_rw_req_blocks_num - m_rw_blocks_num) : m_rw_req_block_len);
+
+ case tape_status::EOM: // error: we reached EOM
+ m_rw_pending = false;
+ return report_eom(true, m_rw_fixed_blocks ? (m_rw_req_blocks_num - m_rw_blocks_num) : m_rw_req_block_len);
+
+ default:
+ assert(false);
+ }
+ }
+ catch (std::exception &e) { // error: writing to tape failed
+ osd_printf_error("WRITE FAILURE: nscsi_tape_device::continue_handling_write_6: %s\n", e.what());
+ return report_write_failure();
+ }
+}
+
+void nscsi_tape_device::handle_write_filemarks() // mandatory; SCSI-2 section 10.2.15
+{
+ const bool setmarks = scsi_cmdbuf[1] & 0x02; // should we write setmarks instead of filemarks
+ const bool immed = scsi_cmdbuf[1] & 0x01; // ignored; we don't support buffering
+ const u32 req_marks_num = get_u24be(&scsi_cmdbuf[2]); // requested number of marks to write; "transfer length"
+ LOG("command WRITE FILEMARKS setmarks=%d immed=%d req_marks_num=%d\n", setmarks, immed, req_marks_num);
+ if (scsi_cmdbuf[1] & 0x1c) // error: reserved bits set
+ return report_bad_cdb_field();
+
+ if (setmarks) // error: we don't support writing setmarks
+ return report_bad_cdb_field();
+
+ if (!m_has_tape) // error: no tape
+ return report_no_medium();
+
+ if (m_image->get_file()->is_read_only()) // error: tape is read-only
+ return report_read_only();
+
+ try {
+ const auto status = m_image->get_file()->write_filemarks(req_marks_num);
+ switch (status) {
+ case tape_status::OK: // success: we wrote all filemarks
+ return scsi_status_complete(SS_GOOD);
+
+ case tape_status::EW: // success: we wrote all filemarks, but we're between EW and EOM
+ return report_ew();
+
+ case tape_status::EOM: // error: we reached EOM
+ return report_eom(true, req_marks_num);
+
+ default:
+ assert(false);
+ }
+ }
+ catch (std::exception &e) { // error: writing to tape failed
+ osd_printf_error("WRITE FAILURE: nscsi_tape_device::handle_write_filemarks: %s\n", e.what());
+ return report_write_failure();
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
diff --git a/src/devices/bus/nscsi/tape.h b/src/devices/bus/nscsi/tape.h
new file mode 100644
index 00000000000..b3758252fa7
--- /dev/null
+++ b/src/devices/bus/nscsi/tape.h
@@ -0,0 +1,83 @@
+// license:BSD-3-Clause
+// copyright-holders:Mietek Bak
+
+#ifndef MAME_BUS_NSCSI_TAPE_H
+#define MAME_BUS_NSCSI_TAPE_H
+
+#pragma once
+
+#include "imagedev/simh_tape_image.h"
+#include "machine/nscsi_bus.h"
+
+DECLARE_DEVICE_TYPE(NSCSI_TAPE, nscsi_tape_device);
+
+//////////////////////////////////////////////////////////////////////////////
+
+class nscsi_tape_device : public nscsi_full_device
+{
+public:
+ // construction
+ nscsi_tape_device(const machine_config &config, const char *tag, device_t *owner, u32 clock = 0);
+
+protected:
+ nscsi_tape_device(const machine_config &config, device_type type, const char *tag, device_t *owner, u32 clock);
+
+ // device_t implementation
+ virtual void device_add_mconfig(machine_config &config) override;
+
+ // nscsi_full_device implementation
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void scsi_command() override;
+ virtual u8 scsi_get_data(int id, int pos) override;
+ virtual void scsi_put_data(int id, int pos, u8 data) override;
+
+ // command handling
+ void handle_inquiry(const u8 lun);
+ void handle_mode_select_6();
+ void continue_handling_mode_select_6();
+ void handle_mode_sense_6();
+ void handle_send_diagnostic();
+ void handle_test_unit_ready();
+ void handle_prevent_allow_medium_removal();
+ void handle_erase();
+ void handle_load_unload();
+ void handle_locate();
+ void handle_read_6();
+ void continue_handling_read_6();
+ void handle_read_block_limits();
+ void handle_read_position();
+ void handle_release_unit();
+ void handle_reserve_unit();
+ void handle_rewind();
+ void handle_space();
+ void handle_write_6();
+ void continue_handling_write_6();
+ void handle_write_filemarks();
+
+ // basic state
+ required_device<simh_tape_image_device> m_image; // tape image
+ u32 m_sequence_counter; // tape image identifier
+ bool m_has_tape; // is tape image file available; cached value of m_image->get_file()
+ bool m_tape_changed; // should we report medium changed next time we receive command
+ u32 m_fixed_block_len; // fixed-length block length
+
+ // state for READ and WRITE
+ u32 m_rw_buf_size; // size of read/write buffer
+ std::unique_ptr<u8[]> m_rw_buf; // read/write buffer
+ bool m_rw_pending; // should we try to read/write additional blocks
+ u32 m_rw_len; // length of valid data in read/write buffer
+ u32 m_rw_blocks_num; // number of blocks read/written so far
+ u32 m_rw_req_blocks_num; // requested number of blocks to read/write
+ u32 m_rw_req_block_len; // requested block length
+ bool m_rw_fixed_blocks; // should we read/write many fixed-length blocks instead of 1 variable-length block
+ bool m_r_suppress_bad_len; // should we suppress indicating incorrect length for read blocks
+
+ // state for MODE SELECT
+ u8 m_pl_buf[256]; // parameter list buffer
+ u32 m_pl_len; // length of valid data in parameter list buffer
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+#endif // MAME_BUS_NSCSI_TAPE_H
diff --git a/src/devices/bus/nubus/8lc.cpp b/src/devices/bus/nubus/8lc.cpp
new file mode 100644
index 00000000000..2e326def9d0
--- /dev/null
+++ b/src/devices/bus/nubus/8lc.cpp
@@ -0,0 +1,421 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+/***************************************************************************
+
+ RasterOps ColorVue 8LC
+ 1, 2, 4, and 8 bpp at 1024x768 for the Macintosh LC
+
+ This is the same hardware as the ClearVueGS/LC board, which shows grayscale.
+ Both cards are documented to only work with the original LC due to some shortcuts
+ taken in how they map the address space.
+
+ Note: the current ROM is a prototype from a former ROPS employee.
+ RasterOps' graphics driver software doesn't recognize it to enable the pan/zoom functionality.
+ ROM dumps from a retail card would resolve several questions.
+
+ Map:
+ 0xXXX00000: VRAM (768K)
+ 0xXXXC0000: TMS34061 registers
+ 0xXXXD0000: Control register + DIP switches
+
+ Control register layout:
+ bits 0-1: oscillator select (0 = 80.0 MHz, 1 = 57.2832 MHz, 2/3 unused)
+ bits 2-3: mode select (0 = 1 bpp, 1 = 2 bpp, 2 = 4 bpp, 3 = 8 bpp)
+ bits 4-5: X zoom amount (0 = 1x, 1 = 2x, 2 = 4x, 3 = 8x)
+ bit 6: Vblank status, negative logic (0 = active)
+ bit 7: Display status (0 = disabled, 1 = enabled)
+ bit 8: monitor sense (1 = connected)
+ bit 11: Display enable switch on the 708+/SE this is derived from
+
+ TODO:
+ - Get real declaration ROMs for 8LC and ClearVueGS/LC and other related cards
+ - Implement pan/zoom functionality if supported, which likely requires VRAM to go through the TMS34061
+
+***************************************************************************/
+
+#include "emu.h"
+#include "8lc.h"
+
+#include "video/tms34061.h"
+
+#include "emupal.h"
+#include "screen.h"
+
+#define LOG_REGISTERS (1U << 1)
+#define LOG_RAMDAC (1U << 2)
+
+#define VERBOSE (0)
+#include "logmacro.h"
+
+namespace {
+
+static constexpr u32 VRAM_SIZE = 0xc0000;
+
+class lcpds_cv8lc_device : public device_t,
+ public device_nubus_card_interface
+{
+public:
+ // construction/destruction
+ lcpds_cv8lc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ lcpds_cv8lc_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
+ required_device<tms34061_device> m_tms34061;
+ required_device<screen_device> m_screen;
+ required_device<palette_device> m_palette;
+ required_ioport m_monitor_config;
+
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual ioport_constructor device_input_ports() const override;
+
+ u32 registers_r(offs_t offset, u32 mem_mask);
+ void registers_w(offs_t offset, u32 data, u32 mem_mask);
+ u32 ramdac_r(offs_t offset, u32 mem_mask);
+ void ramdac_w(offs_t offset, u32 data, u32 mem_mask);
+
+private:
+ u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
+ void vblank_w(int state);
+
+ std::unique_ptr<u32[]> m_vram;
+ u32 m_mode, m_irq_control;
+ u32 m_pal_idx, m_pal_address;
+ u32 m_hres, m_vres, m_stride, m_htotal, m_vtotal, m_pixel_clock;
+ u32 m_display_enable;
+ u32 m_crtc[12];
+};
+
+ROM_START( cb708plc )
+ ROM_REGION(0x8000, "declrom", 0)
+ ROM_LOAD( "8lc_prototype.bin", 0x000000, 0x008000, CRC(6f47e0f2) SHA1(a8552315d9127aee92416aa22893551851f42e5c) )
+ROM_END
+
+static INPUT_PORTS_START(monitor_config)
+ PORT_START("monitor")
+ PORT_CONFNAME(0x0100, 0x0000, "Monitor presence")
+ PORT_CONFSETTING(0x0000, u8"19\" 1024\u00d7768 RGB");
+ PORT_CONFSETTING(0x0100, u8"No monitor")
+INPUT_PORTS_END
+
+void lcpds_cv8lc_device::device_add_mconfig(machine_config &config)
+{
+ SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
+ m_screen->set_raw(80'000'000, 1312, 0, 1024, 802, 0, 768);
+ m_screen->set_screen_update(FUNC(lcpds_cv8lc_device::screen_update));
+
+ PALETTE(config, m_palette).set_entries(256);
+
+ TMS34061(config, m_tms34061, 0);
+ m_tms34061->set_rowshift(10); // VRAM address is (row << rowshift) | col
+ m_tms34061->set_vram_size(0xc0000);
+ m_tms34061->set_screen(m_screen);
+ m_tms34061->int_callback().set(FUNC(lcpds_cv8lc_device::vblank_w));
+}
+
+const tiny_rom_entry *lcpds_cv8lc_device::device_rom_region() const
+{
+ return ROM_NAME( cb708plc );
+}
+
+ioport_constructor lcpds_cv8lc_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(monitor_config);
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+lcpds_cv8lc_device::lcpds_cv8lc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ lcpds_cv8lc_device(mconfig, PDSLC_COLORVUE8LC, tag, owner, clock)
+{
+}
+
+lcpds_cv8lc_device::lcpds_cv8lc_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, type, tag, owner, clock),
+ device_nubus_card_interface(mconfig, *this),
+ m_tms34061(*this, "tms34061"),
+ m_screen(*this, "screen"),
+ m_palette(*this, "palette"),
+ m_monitor_config(*this, "monitor"),
+ m_mode(0), m_irq_control(0), m_pal_idx(0), m_pal_address(0),
+ m_hres(1024), m_vres(768), m_stride(1024), m_htotal(0), m_vtotal(0),
+ m_pixel_clock(80'000'000), m_display_enable(0)
+{
+ std::fill(std::begin(m_crtc), std::end(m_crtc), 0);
+}
+
+void lcpds_cv8lc_device::device_start()
+{
+ set_pds_slot(0xe);
+
+ const u32 slotspace = get_slotspace();
+
+ install_declaration_rom("declrom");
+
+ m_vram = std::make_unique<u32[]>(VRAM_SIZE/4);
+
+ save_item(NAME(m_mode));
+ save_item(NAME(m_irq_control));
+ save_item(NAME(m_pal_idx));
+ save_item(NAME(m_pal_address));
+ save_item(NAME(m_stride));
+ save_item(NAME(m_hres));
+ save_item(NAME(m_vres));
+ save_item(NAME(m_htotal));
+ save_item(NAME(m_vtotal));
+ save_item(NAME(m_display_enable));
+ save_pointer(NAME(m_vram), VRAM_SIZE/4);
+
+ install_bank(0xe00000 + slotspace, 0xe00000 + slotspace + VRAM_SIZE - 1, &m_vram[0]);
+ nubus().install_device(slotspace + 0xec0000, slotspace + 0xedffff, emu::rw_delegate(*this, FUNC(lcpds_cv8lc_device::registers_r)), emu::rw_delegate(*this, FUNC(lcpds_cv8lc_device::registers_w)));
+ nubus().install_device(slotspace + 0xee0000, slotspace + 0xee00ff, emu::rw_delegate(*this, FUNC(lcpds_cv8lc_device::ramdac_r)), emu::rw_delegate(*this, FUNC(lcpds_cv8lc_device::ramdac_w)));
+
+ // The real card appears to ignore A31 (reminder: on the LC and LC II, A24-A30 are not decoded) so we need this extra
+ // mapping as well.
+ install_bank(0xe00000, 0xe00000 + VRAM_SIZE - 1, &m_vram[0]);
+ nubus().install_device(0xec0000, 0xedffff, emu::rw_delegate(*this, FUNC(lcpds_cv8lc_device::registers_r)), emu::rw_delegate(*this, FUNC(lcpds_cv8lc_device::registers_w)));
+ nubus().install_device(0xee0000, 0xee00ff, emu::rw_delegate(*this, FUNC(lcpds_cv8lc_device::ramdac_r)), emu::rw_delegate(*this, FUNC(lcpds_cv8lc_device::ramdac_w)));
+}
+
+void lcpds_cv8lc_device::device_reset()
+{
+ m_pal_idx = 0;
+ m_pal_address = 0;
+ m_irq_control = 0;
+ m_mode = 0;
+ m_display_enable = 0;
+}
+
+uint32_t lcpds_cv8lc_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
+{
+ auto const vram8 = util::big_endian_cast<uint8_t const>(&m_vram[0]);
+ const pen_t *pens = m_palette->pens();
+
+ m_tms34061->get_display_state();
+ if (m_tms34061->blanked())
+ {
+ bitmap.fill(rgb_t::black(), cliprect);
+ return 0;
+ }
+
+ switch (m_mode)
+ {
+ case 0: // 1bpp
+ for (int y = 0; y < m_vres; y++)
+ {
+ u32 *scanline = &bitmap.pix(y);
+ for (int x = 0; x < m_hres/8; x++)
+ {
+ u8 const pixels = vram8[(y * m_stride) + x];
+
+ *scanline++ = pens[pixels&0x80];
+ *scanline++ = pens[(pixels<<1)&0x80];
+ *scanline++ = pens[(pixels<<2)&0x80];
+ *scanline++ = pens[(pixels<<3)&0x80];
+ *scanline++ = pens[(pixels<<4)&0x80];
+ *scanline++ = pens[(pixels<<5)&0x80];
+ *scanline++ = pens[(pixels<<6)&0x80];
+ *scanline++ = pens[(pixels<<7)&0x80];
+ }
+ }
+ break;
+
+ case 1: // 2bpp
+ for (int y = 0; y < m_vres; y++)
+ {
+ u32 *scanline = &bitmap.pix(y);
+ for (int x = 0; x < m_hres / 4; x++)
+ {
+ u8 const pixels = vram8[(y * m_stride) + x];
+
+ *scanline++ = pens[(pixels & 0xc0)];
+ *scanline++ = pens[((pixels << 2) & 0xc0)];
+ *scanline++ = pens[((pixels << 4) & 0xc0)];
+ *scanline++ = pens[(pixels << 6) & 0xc0];
+ }
+ }
+ break;
+
+ case 2: // 4bpp
+ for (int y = 0; y < m_vres; y++)
+ {
+ u32 *scanline = &bitmap.pix(y);
+ for (int x = 0; x < m_hres/2; x++)
+ {
+ u8 const pixels = vram8[(y * m_stride) + x];
+
+ *scanline++ = pens[((pixels << 0) & 0xf0)];
+ *scanline++ = pens[((pixels << 4) & 0xf0)];
+ }
+ }
+ break;
+
+ case 3: // 8bpp
+ for (int y = 0; y < m_vres; y++)
+ {
+ u32 *scanline = &bitmap.pix(y);
+ for (int x = 0; x < m_hres; x++)
+ {
+ u8 const pixels = vram8[(y * m_stride) + x];
+
+ *scanline++ = pens[pixels];
+ }
+ }
+ break;
+ }
+
+ return 0;
+}
+
+void lcpds_cv8lc_device::vblank_w(int state)
+{
+ if (state)
+ {
+ raise_slot_irq();
+ }
+ else
+ {
+ lower_slot_irq();
+ }
+}
+
+u32 lcpds_cv8lc_device::registers_r(offs_t offset, u32 mem_mask)
+{
+ if (offset != 0x34)
+ {
+ LOGMASKED(LOG_REGISTERS, "Read @ Cxxxx: offset %x (mask %x)\n", offset, mem_mask);
+ }
+
+ if (offset == 0x4000)
+ {
+ u32 result = m_monitor_config->read();
+ result |= (m_screen->vblank() ? 0 : 0x0040);
+ return result;
+ }
+ else if (offset < 0x40)
+ {
+ return m_tms34061->read(offset, 0, 0)<<24;
+ }
+ else if (offset == 0x44)
+ {
+ return m_screen->vpos() & 0xff;
+ }
+ else if (offset == 0x46)
+ {
+ return (m_screen->vpos() >> 8) & 0xff;
+ }
+
+ return 0;
+}
+
+void lcpds_cv8lc_device::registers_w(offs_t offset, u32 data, u32 mem_mask)
+{
+ LOGMASKED(LOG_REGISTERS, "Write @ Cxxxx: %x to reg %x (mask %x)\n", data, offset, mem_mask);
+ if (offset == 0x4000)
+ {
+ m_mode = (data >> 2) & 3;
+
+ u32 new_clock;
+ switch (data & 3)
+ {
+ case 0:
+ new_clock = 80'000'000;
+ break;
+
+ case 1:
+ new_clock = 57'283'200;
+ break;
+
+ default:
+ fatalerror("colorboard708: invalid crystal select %d\n", data & 3);
+ break;
+ }
+
+ if (m_pixel_clock != new_clock)
+ {
+ m_pixel_clock = new_clock;
+ m_hres = m_tms34061->hvisible();
+ m_htotal = m_tms34061->htotal();
+ m_vres = m_tms34061->vvisible();
+ m_vtotal = m_tms34061->vtotal();
+
+ if ((m_hres != 0) && (m_vres != 0) && (m_htotal != 0) && (m_vtotal != 0))
+ {
+ rectangle visarea(0, m_hres - 1, 0, m_vres - 1);
+ m_screen->configure(m_htotal, m_vtotal, visarea, attotime::from_ticks(m_htotal * m_vtotal, m_pixel_clock).as_attoseconds());
+ }
+ }
+ }
+ else
+ {
+ if (mem_mask == 0xff000000)
+ {
+ m_tms34061->write(offset, 0, 0, data >> 24);
+ }
+ else
+ {
+ m_tms34061->write(offset, 0, 0, data & 0xff);
+ }
+ }
+}
+
+u32 lcpds_cv8lc_device::ramdac_r(offs_t offset, u32 mem_mask)
+{
+ LOGMASKED(LOG_RAMDAC, "Read DAC @ %08x (mask %08x)\n", offset, mem_mask);
+ return 0;
+}
+
+void lcpds_cv8lc_device::ramdac_w(offs_t offset, u32 data, u32 mem_mask)
+{
+ u8 writedata = (mem_mask == 0xff000000) ? (data >> 24) : (data & 0xff);
+ LOGMASKED(LOG_RAMDAC, "%08x (write %02x) to DAC at %x (mask %08x)\n", data, writedata, offset, mem_mask);
+ switch (offset)
+ {
+ case 0:
+ m_pal_address = writedata;
+ m_pal_idx = 0;
+ break;
+
+ case 1:
+ switch (m_pal_idx)
+ {
+ case 0:
+ m_palette->set_pen_red_level(m_pal_address, writedata);
+ break;
+
+ case 1:
+ m_palette->set_pen_green_level(m_pal_address, writedata);
+ break;
+
+ case 2:
+ m_palette->set_pen_blue_level(m_pal_address, writedata);
+ break;
+ }
+
+ m_pal_idx++;
+ if (m_pal_idx == 3)
+ {
+ m_pal_address++;
+ m_pal_address &= 0xff;
+ m_pal_idx = 0;
+ }
+ break;
+
+ default:
+ LOGMASKED(LOG_REGISTERS, "%08x to DAC @ %x\n", data & mem_mask, offset);
+ break;
+ }
+}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(PDSLC_COLORVUE8LC, device_nubus_card_interface, lcpds_cv8lc_device, "cv8lc", "RasterOps ColorVue 8LC video card")
+
diff --git a/src/devices/bus/nubus/8lc.h b/src/devices/bus/nubus/8lc.h
new file mode 100644
index 00000000000..afbb9523433
--- /dev/null
+++ b/src/devices/bus/nubus/8lc.h
@@ -0,0 +1,12 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+#ifndef MAME_BUS_NUBUS_COLORVUE8LC_H
+#define MAME_BUS_NUBUS_COLORVUE8LC_H
+
+#pragma once
+
+#include "nubus.h"
+
+DECLARE_DEVICE_TYPE(PDSLC_COLORVUE8LC, device_nubus_card_interface)
+
+#endif // MAME_BUS_NUBUS_COLORVUE8LC_H
diff --git a/src/devices/bus/nubus/cards.cpp b/src/devices/bus/nubus/cards.cpp
index 4501754bc21..a16f3e48497 100644
--- a/src/devices/bus/nubus/cards.cpp
+++ b/src/devices/bus/nubus/cards.cpp
@@ -2,13 +2,14 @@
// copyright-holders:R. Belmont
/***************************************************************************
- NuBus and SE/30 PDS slot cards
+ NuBus, SE/30 PDS, and LC slot cards
***************************************************************************/
#include "emu.h"
#include "cards.h"
+#include "8lc.h"
#include "bootbug.h"
#include "laserview.h"
#include "nubus_48gc.h"
@@ -28,7 +29,7 @@
#include "pds30_procolor816.h"
#include "pds30_sigmalview.h"
#include "quadralink.h"
-
+#include "thunder4gx.h"
void mac_nubus_cards(device_slot_interface &device)
{
@@ -41,7 +42,6 @@ void mac_nubus_cards(device_slot_interface &device)
device.option_add("specpdq", NUBUS_SPECPDQ); // SuperMac Spectrum PDQ
device.option_add("m2hires", NUBUS_M2HIRES); // Apple Macintosh II Hi-Resolution Card
device.option_add("spec8s3", NUBUS_SPEC8S3); // SuperMac Spectrum/8 Series III
-// device.option_add("thundergx", NUBUS_THUNDERGX); // Radius Thunder GX (not yet)
device.option_add("radiustpd", NUBUS_RADIUSTPD); // Radius Two Page Display
device.option_add("asmc3nb", NUBUS_ASNTMC3NB); // Asante MC3NB Ethernet card
device.option_add("portrait", NUBUS_WSPORTRAIT); // Apple Macintosh II Portrait video card
@@ -49,14 +49,57 @@ void mac_nubus_cards(device_slot_interface &device)
device.option_add("bootbug", NUBUS_BOOTBUG); // Brigent BootBug debugger card
device.option_add("quadralink", NUBUS_QUADRALINK); // AE Quadralink serial card
device.option_add("laserview", NUBUS_LASERVIEW); // Sigma Designs LaserView monochrome video card
+ device.option_add("thunder4gx", NUBUS_THUNDERIVGX); // Radius Thunder IV GX video card
}
void mac_pds030_cards(device_slot_interface &device)
{
- device.option_add("cb264", PDS030_CB264SE30); // RasterOps Colorboard 264/SE30
+ device.option_add("cb264se30", PDS030_CB264SE30); // RasterOps Colorboard 264/SE30
device.option_add("pc816", PDS030_PROCOLOR816); // Lapis ProColor Server 8*16 PDS
device.option_add("lview", PDS030_LVIEW); // Sigma Designs L-View
device.option_add("30hr", PDS030_XCEED30HR); // Micron/XCEED Technology Color 30HR
device.option_add("mc30", PDS030_XCEEDMC30); // Micron/XCEED Technology MacroColor 30
+ device.option_add("ethermac30", PDS030_ETHERMAC30I); // Farallon EtherMac 30i Ethernet card
+}
+
+void mac_pdslc_cards(device_slot_interface &device)
+{
+ device.option_add("macconilc", PDSLC_MACCONILC); // Asante MacCON i LC Ethernet card
+}
+
+// cards for the LC PDS slot that only work in the original LC
+void mac_pdslc_orig_cards(device_slot_interface &device)
+{
+ device.option_add("macconilc", PDSLC_MACCONILC); // Asante MacCON i LC Ethernet card
+ device.option_add("ro8lc", PDSLC_COLORVUE8LC); // RasterOps ColorVue 8LC
+}
+
+// IIsi can take either one SE/30 PDS or one NuBus card
+void mac_iisi_cards(device_slot_interface &device)
+{
+ device.option_add("m2video", NUBUS_M2VIDEO); // Apple Macintosh II Video Card
+ device.option_add("mdc48", NUBUS_MDC48); // Apple Macintosh Display Card 4•8
+ device.option_add("mdc824", NUBUS_MDC824); // Apple Macintosh Display Card 8•24
+ device.option_add("cb264", NUBUS_CB264); // RasterOps ColorBoard 264
+ device.option_add("vikbw", NUBUS_VIKBW); // Moniterm Viking board
+ device.option_add("image", NUBUS_IMAGE); // Disk Image Pseudo-Card
+ device.option_add("specpdq", NUBUS_SPECPDQ); // SuperMac Spectrum PDQ
+ device.option_add("m2hires", NUBUS_M2HIRES); // Apple Macintosh II Hi-Resolution Card
+ device.option_add("spec8s3", NUBUS_SPEC8S3); // SuperMac Spectrum/8 Series III
+ device.option_add("radiustpd", NUBUS_RADIUSTPD); // Radius Two Page Display
+ device.option_add("asmc3nb", NUBUS_ASNTMC3NB); // Asante MC3NB Ethernet card
+ device.option_add("portrait", NUBUS_WSPORTRAIT); // Apple Macintosh II Portrait video card
+ device.option_add("enetnb", NUBUS_APPLEENET); // Apple NuBus Ethernet
+ device.option_add("bootbug", NUBUS_BOOTBUG); // Brigent BootBug debugger card
+ device.option_add("quadralink", NUBUS_QUADRALINK); // AE Quadralink serial card
+ device.option_add("laserview", NUBUS_LASERVIEW); // Sigma Designs LaserView monochrome video card
+ device.option_add("thunder4gx", NUBUS_THUNDERIVGX); // Radius Thunder IV GX video card
+
+ device.option_add("cb264se30", PDS030_CB264SE30); // RasterOps Colorboard 264/SE30
+ device.option_add("pc816", PDS030_PROCOLOR816); // Lapis ProColor Server 8*16 PDS
+ device.option_add("lview", PDS030_LVIEW); // Sigma Designs L-View
+ device.option_add("30hr", PDS030_XCEED30HR); // Micron/XCEED Technology Color 30HR
+ device.option_add("mc30", PDS030_XCEEDMC30); // Micron/XCEED Technology MacroColor 30
+ device.option_add("ethermac30", PDS030_ETHERMAC30I); // Farallon EtherMac 30i Ethernet card
}
diff --git a/src/devices/bus/nubus/cards.h b/src/devices/bus/nubus/cards.h
index 3b484be3cdc..498e9b0e07c 100644
--- a/src/devices/bus/nubus/cards.h
+++ b/src/devices/bus/nubus/cards.h
@@ -2,7 +2,7 @@
// copyright-holders:R. Belmont
/***************************************************************************
- NuBus and SE/30 PDS slot cards
+ NuBus, SE/30 PDS, and LC PDS slot cards
***************************************************************************/
@@ -13,5 +13,8 @@
void mac_nubus_cards(device_slot_interface &device) ATTR_COLD;
void mac_pds030_cards(device_slot_interface &device) ATTR_COLD;
+void mac_pdslc_cards(device_slot_interface &device) ATTR_COLD;
+void mac_pdslc_orig_cards(device_slot_interface &device) ATTR_COLD;
+void mac_iisi_cards(device_slot_interface &device) ATTR_COLD;
#endif // MAME_BUS_NUBUS_CARDS_H
diff --git a/src/devices/bus/nubus/laserview.cpp b/src/devices/bus/nubus/laserview.cpp
index 9e9d8ef131b..e4804b55547 100644
--- a/src/devices/bus/nubus/laserview.cpp
+++ b/src/devices/bus/nubus/laserview.cpp
@@ -3,48 +3,86 @@
/***************************************************************************
Sigma Designs fixed-resolution monochrome video card
- 1664x1200 or 832x600 according to the ad, can't find the 1664 mode.
+ 1664x1200 or 832x600 according to the ad, and exist as mode entries
+ in the declaration ROM.
VRAM at Fs000000, mirrored at Fs900000.
Fs0BFFEC: write 0x04 to enable VBL, 0x01 to ack VBL
+ Card has one ASIC, a Sigma Designs 53C280A. This is shared with the PC ISA
+ "LaserView Plus" card.
+
+ Crystals:
+ 160.00 MHz
+ 122.925 MHz
+ 99.108 MHz
+ 16.0 MHz
+
+ CRTC parameters are always programmed for 1664x1200, the card apparently
+ doubles up the output for the 832x600 mode.
+
+ TODO: Find what makes it sense the higher resolution mode.
+
***************************************************************************/
#include "emu.h"
+
#include "laserview.h"
+
+#include "emupal.h"
#include "screen.h"
#include <algorithm>
+static constexpr u32 VRAM_SIZE = 0x40000; // ROM tests for 512K, but card has 8x uPD41264 (64K x 4 bit) = 256 KiB
+namespace {
-#define LASERVIEW_SCREEN_NAME "laserview_screen"
-#define LASERVIEW_ROM_REGION "laserview_rom"
+ class nubus_laserview_device : public device_t,
+ public device_nubus_card_interface
+ {
+ public:
+ // construction/destruction
+ nubus_laserview_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
-#define VRAM_SIZE (0x40000)
+ protected:
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
-ROM_START( laserview )
- ROM_REGION(0x8000, LASERVIEW_ROM_REGION, 0)
- ROM_LOAD( "lva-m2-00020_v3.00.bin", 0x000000, 0x008000, CRC(569d1fb7) SHA1(fd505505226abb5fea7c10ed14e8841077ef1be6) )
-ROM_END
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
-//**************************************************************************
-// GLOBAL VARIABLES
-//**************************************************************************
+ private:
+ u8 regs_r(offs_t offset);
+ void regs_w(offs_t offset, u8 data);
-DEFINE_DEVICE_TYPE(NUBUS_LASERVIEW, nubus_laserview_device, "nb_laserview", "Sigma Designs LaserView video card")
+ u32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
+ void vbl_w(int state);
-//-------------------------------------------------
-// device_add_mconfig - add device configuration
-//-------------------------------------------------
+ required_device<screen_device> m_screen;
+
+ std::unique_ptr<u32[]> m_vram;
+ u16 m_htotal, m_hvis, m_vtotal, m_vvis;
+ u32 m_vbl_disable;
+ u8 m_prot_latch;
+ };
+
+ROM_START( laserview )
+ ROM_REGION(0x8000, "declrom", 0)
+ ROM_LOAD( "lva-m2-00020_v3.00.bin", 0x000000, 0x008000, CRC(569d1fb7) SHA1(fd505505226abb5fea7c10ed14e8841077ef1be6) )
+ROM_END
void nubus_laserview_device::device_add_mconfig(machine_config &config)
{
- screen_device &screen(SCREEN(config, LASERVIEW_SCREEN_NAME, SCREEN_TYPE_RASTER));
- screen.set_screen_update(FUNC(nubus_laserview_device::screen_update));
- screen.set_size(832,600);
- screen.set_visarea(0, 832-1, 0, 600-1);
- screen.set_refresh_hz(70);
+ SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
+ m_screen->set_screen_update(FUNC(nubus_laserview_device::screen_update));
+ m_screen->set_raw(99108000/2, 1008, 0, 832, 622, 0, 600);
+ m_screen->set_palette("palette");
+ m_screen->screen_vblank().set(FUNC(nubus_laserview_device::vbl_w));
+
+ PALETTE(config, "palette", palette_device::MONOCHROME_INVERTED);
}
//-------------------------------------------------
@@ -56,109 +94,131 @@ const tiny_rom_entry *nubus_laserview_device::device_rom_region() const
return ROM_NAME( laserview );
}
-//**************************************************************************
-// LIVE DEVICE
-//**************************************************************************
-
-//-------------------------------------------------
-// nubus_laserview_device - constructor
-//-------------------------------------------------
-
-nubus_laserview_device::nubus_laserview_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- nubus_laserview_device(mconfig, NUBUS_LASERVIEW, tag, owner, clock)
-{
-}
-
-nubus_laserview_device::nubus_laserview_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, type, tag, owner, clock),
+nubus_laserview_device::nubus_laserview_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ device_t(mconfig, NUBUS_LASERVIEW, tag, owner, clock),
device_nubus_card_interface(mconfig, *this),
- m_vbl_disable(0)
+ m_screen(*this, "screen"),
+ m_htotal(0), m_hvis(0), m_vtotal(0), m_vvis(0),
+ m_vbl_disable(1), m_prot_latch(0)
{
}
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-
void nubus_laserview_device::device_start()
{
- uint32_t slotspace;
-
- install_declaration_rom(LASERVIEW_ROM_REGION, true);
-
- slotspace = get_slotspace();
+ const u32 slotspace = get_slotspace();
-// printf("[laserview %p] slotspace = %x\n", this, slotspace);
+ install_declaration_rom("declrom", true);
- m_vram.resize(VRAM_SIZE / sizeof(uint32_t));
- install_bank(slotspace, slotspace+VRAM_SIZE-1, &m_vram[0]);
+ m_vram = std::make_unique<u32[]>(VRAM_SIZE / sizeof(u32));
+ install_bank(slotspace, slotspace + VRAM_SIZE - 1, &m_vram[0]);
install_bank(slotspace+0x900000, slotspace+0x900000+VRAM_SIZE-1, &m_vram[0]);
- nubus().install_device(slotspace+0xB0000, slotspace+0xBFFFF, read32s_delegate(*this, FUNC(nubus_laserview_device::regs_r)), write32s_delegate(*this, FUNC(nubus_laserview_device::regs_w)));
-}
+ nubus().install_device(slotspace+0xB0000, slotspace+0xBFFFF, emu::rw_delegate(*this, FUNC(nubus_laserview_device::regs_r)), emu::rw_delegate(*this, FUNC(nubus_laserview_device::regs_w)));
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
+ save_item(NAME(m_htotal));
+ save_item(NAME(m_hvis));
+ save_item(NAME(m_vtotal));
+ save_item(NAME(m_vvis));
+ save_item(NAME(m_vbl_disable));
+ save_item(NAME(m_prot_latch));
+ save_pointer(NAME(m_vram), VRAM_SIZE / sizeof(u32));
+}
void nubus_laserview_device::device_reset()
{
m_vbl_disable = 1;
- m_prot_state = 0;
- m_toggle = 0;
- std::fill(m_vram.begin(), m_vram.end(), 0);
-
- m_palette[0] = rgb_t(255, 255, 255);
- m_palette[1] = rgb_t(0, 0, 0);
+ std::fill_n(&m_vram[0], VRAM_SIZE / sizeof(u32), 0);
}
-/***************************************************************************
-
- Viking 1024x768 B&W card section
-
-***************************************************************************/
-
-uint32_t nubus_laserview_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
+u32 nubus_laserview_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
- if (!m_vbl_disable)
- {
- raise_slot_irq();
- }
-
- auto const vram8 = util::big_endian_cast<uint8_t const>(&m_vram[0]);
+ auto const vram8 = util::big_endian_cast<u8 const>(&m_vram[0]);
for (int y = 0; y < 600; y++)
{
- uint32_t *scanline = &bitmap.pix(y);
+ u16 *scanline = &bitmap.pix(y);
for (int x = 0; x < 832/8; x++)
{
- uint8_t const pixels = vram8[(y * 104) + x + 0x20];
-
- *scanline++ = m_palette[BIT(pixels, 7)];
- *scanline++ = m_palette[BIT(pixels, 6)];
- *scanline++ = m_palette[BIT(pixels, 5)];
- *scanline++ = m_palette[BIT(pixels, 4)];
- *scanline++ = m_palette[BIT(pixels, 3)];
- *scanline++ = m_palette[BIT(pixels, 2)];
- *scanline++ = m_palette[BIT(pixels, 1)];
- *scanline++ = m_palette[BIT(pixels, 0)];
+ u8 const pixels = vram8[(y * 104) + x + 0x20];
+
+ *scanline++ = BIT(pixels, 7);
+ *scanline++ = BIT(pixels, 6);
+ *scanline++ = BIT(pixels, 5);
+ *scanline++ = BIT(pixels, 4);
+ *scanline++ = BIT(pixels, 3);
+ *scanline++ = BIT(pixels, 2);
+ *scanline++ = BIT(pixels, 1);
+ *scanline++ = BIT(pixels, 0);
}
}
-
return 0;
}
-void nubus_laserview_device::regs_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+void nubus_laserview_device::vbl_w(int state)
{
-// printf("%08x to regs @ %x mask %08x\n", data, offset, mem_mask);
+ if ((state) && (!m_vbl_disable))
+ {
+ raise_slot_irq();
+ }
+}
+void nubus_laserview_device::regs_w(offs_t offset, u8 data)
+{
switch (offset)
{
- case 0x3ffb:
+ case 0x00f9:
+ m_prot_latch = ~data;
+ break;
+
+ case 0x0493:
+ m_vvis = (m_vvis & 0xff) | (data << 8);
+ break;
+
+ case 0x0687:
+ m_hvis = (m_hvis & 0xff) | (data << 8);
+ break;
+
+ case 0x078f:
+ m_vtotal = (m_vtotal & 0xff) | (data << 8);
+ break;
+
+ case 0x0883:
+ m_htotal = (m_htotal & 0xff) | (data<<8);
+ break;
+
+ case 0x08ff:
+ if (data == 0xc1)
+ {
+ const rectangle visarea(0, (m_hvis / 2) - 1, 0, (m_vvis / 2) - 1);
+ m_screen->configure(m_htotal / 2, m_vtotal / 2, visarea, attotime::from_ticks((m_htotal / 2) * (m_vtotal / 2), 160000000 / 2).as_attoseconds());
+ }
+ break;
+
+ case 0x20f9:
+ m_prot_latch = ~data ^ 0xff;
+ break;
+
+ case 0xb095:
+ m_vvis = (m_vvis & 0xff00) | data;
+ break;
+
+ case 0xdd91:
+ m_vtotal = (m_vtotal & 0xff00) | data;
+ break;
+
+ case 0x8085:
+ m_htotal = (m_htotal & 0xff00) | data;
+ break;
+
+ case 0x8089:
+ m_hvis = (m_hvis & 0xff00) | data;
+ break;
+
+ case 0xffef:
if ((data & 0xff) == 0x04)
{
m_vbl_disable = 0;
}
- else if ((data & 0xff) == 01)
+ else if ((data & 0xff) == 1)
{
lower_slot_irq();
}
@@ -172,38 +232,23 @@ void nubus_laserview_device::regs_w(offs_t offset, uint32_t data, uint32_t mem_m
}
-uint32_t nubus_laserview_device::regs_r(offs_t offset, uint32_t mem_mask)
+u8 nubus_laserview_device::regs_r(offs_t offset)
{
- //f (offset != 0x3fc1) printf("Read regs_r @ %x mask %08x\n", offset, mem_mask);
-
switch (offset)
{
- case 0x3fc1:
- m_toggle ^= 1;
- if (m_toggle)
- {
- return 0x01010101;
- }
- else
- {
- return 0;
- }
- machine().debug_break();
- break;
+ case 0xff04: // vblank status
+ return m_screen->vblank();
- case 0x3fc2:
- if (m_prot_state == 0)
- {
- m_prot_state = 1;
- return 0;
- }
- return 0x02000000;
+ case 0xff08:
+ return m_prot_latch;
- case 0x3fff:
- m_prot_state = 0;
- return 0xfeffffff;
+ case 0xfffc:
+ return 0xe4;
}
- return 0xffffffff;
+ return 0xff;
}
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(NUBUS_LASERVIEW, device_nubus_card_interface, nubus_laserview_device, "nb_laserview", "Sigma Designs LaserView video card")
diff --git a/src/devices/bus/nubus/laserview.h b/src/devices/bus/nubus/laserview.h
index a2d99227566..22e283c2391 100644
--- a/src/devices/bus/nubus/laserview.h
+++ b/src/devices/bus/nubus/laserview.h
@@ -7,44 +7,6 @@
#include "nubus.h"
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-// ======================> nubus_laserview_device
-
-class nubus_laserview_device :
- public device_t,
- public device_nubus_card_interface
-{
-public:
- // construction/destruction
- nubus_laserview_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- nubus_laserview_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
-
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
-
- // optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
-
-private:
- uint32_t regs_r(offs_t offset, uint32_t mem_mask = ~0);
- void regs_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
-
- uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
-
- std::vector<uint32_t> m_vram;
- uint32_t m_vbl_disable, m_palette[2];
- int m_prot_state;
- int m_toggle;
-};
-
-// device type definition
-DECLARE_DEVICE_TYPE(NUBUS_LASERVIEW, nubus_laserview_device)
+DECLARE_DEVICE_TYPE(NUBUS_LASERVIEW, device_nubus_card_interface)
#endif // MAME_BUS_NUBUS_LASERVIEW_H
diff --git a/src/devices/bus/nubus/nubus.cpp b/src/devices/bus/nubus/nubus.cpp
index 8ac4ea719b9..0ca41acf8a6 100644
--- a/src/devices/bus/nubus/nubus.cpp
+++ b/src/devices/bus/nubus/nubus.cpp
@@ -53,7 +53,7 @@ void nubus_slot_device::device_resolve_objects()
if (dev)
{
dev->set_nubus_tag(m_nubus.target(), m_nubus_slottag);
- m_nubus->add_nubus_card(dev);
+ m_nubus->add_nubus_card(*dev);
}
}
@@ -94,23 +94,11 @@ nubus_device::nubus_device(const machine_config &mconfig, device_type type, cons
m_out_irqd_cb(*this),
m_out_irqe_cb(*this)
{
+ m_addr_mask = 0xffffffff;
}
-//-------------------------------------------------
-// device_resolve_objects - resolve objects that
-// may be needed for other devices to set
-// initial conditions at start time
-//-------------------------------------------------
-
-void nubus_device::device_resolve_objects()
+nubus_device::~nubus_device()
{
- // resolve callbacks
- m_out_irq9_cb.resolve_safe();
- m_out_irqa_cb.resolve_safe();
- m_out_irqb_cb.resolve_safe();
- m_out_irqc_cb.resolve_safe();
- m_out_irqd_cb.resolve_safe();
- m_out_irqe_cb.resolve_safe();
}
//-------------------------------------------------
@@ -121,15 +109,17 @@ void nubus_device::device_start()
{
}
-void nubus_device::add_nubus_card(device_nubus_card_interface *card)
+void nubus_device::add_nubus_card(device_nubus_card_interface &card)
{
- m_device_list.append(*card);
+ m_device_list.emplace_back(card);
}
template <typename R, typename W>
void nubus_device::install_device(offs_t start, offs_t end, R rhandler, W whandler, uint32_t mask)
{
- int buswidth = m_space->data_width();
+ const int buswidth = m_space->data_width();
+ start &= m_addr_mask;
+ end &= m_addr_mask;
switch(buswidth)
{
case 32:
@@ -159,7 +149,9 @@ template void nubus_device::install_device<read32smo_delegate, write32smo_delega
template <typename R>
void nubus_device::install_readonly_device(offs_t start, offs_t end, R rhandler, uint32_t mask)
{
- int buswidth = m_space->data_width();
+ const int buswidth = m_space->data_width();
+ start &= m_addr_mask;
+ end &= m_addr_mask;
switch(buswidth)
{
case 32:
@@ -189,7 +181,9 @@ template void nubus_device::install_readonly_device<read32smo_delegate>(offs_t s
template <typename W>
void nubus_device::install_writeonly_device(offs_t start, offs_t end, W whandler, uint32_t mask)
{
- int buswidth = m_space->data_width();
+ const int buswidth = m_space->data_width();
+ start &= m_addr_mask;
+ end &= m_addr_mask;
switch(buswidth)
{
case 32:
@@ -218,13 +212,15 @@ template void nubus_device::install_writeonly_device<write32smo_delegate>(offs_t
void nubus_device::install_bank(offs_t start, offs_t end, void *data)
{
-// printf("install_bank: %s @ %x->%x\n", tag, start, end);
+ start &= m_addr_mask;
+ end &= m_addr_mask;
m_space->install_ram(start, end, data);
}
void nubus_device::install_view(offs_t start, offs_t end, memory_view &view)
{
-// printf("install_view: %s @ %x->%x\n", tag, start, end);
+ start &= m_addr_mask;
+ end &= m_addr_mask;
m_space->install_view(start, end, view);
}
@@ -242,12 +238,12 @@ void nubus_device::set_irq_line(int slot, int state)
}
// interrupt request from nubus card
-WRITE_LINE_MEMBER( nubus_device::irq9_w ) { m_out_irq9_cb(state); }
-WRITE_LINE_MEMBER( nubus_device::irqa_w ) { m_out_irqa_cb(state); }
-WRITE_LINE_MEMBER( nubus_device::irqb_w ) { m_out_irqb_cb(state); }
-WRITE_LINE_MEMBER( nubus_device::irqc_w ) { m_out_irqc_cb(state); }
-WRITE_LINE_MEMBER( nubus_device::irqd_w ) { m_out_irqd_cb(state); }
-WRITE_LINE_MEMBER( nubus_device::irqe_w ) { m_out_irqe_cb(state); }
+void nubus_device::irq9_w(int state) { m_out_irq9_cb(state); }
+void nubus_device::irqa_w(int state) { m_out_irqa_cb(state); }
+void nubus_device::irqb_w(int state) { m_out_irqb_cb(state); }
+void nubus_device::irqc_w(int state) { m_out_irqc_cb(state); }
+void nubus_device::irqd_w(int state) { m_out_irqd_cb(state); }
+void nubus_device::irqe_w(int state) { m_out_irqe_cb(state); }
//**************************************************************************
// DEVICE CONFIG NUBUS CARD INTERFACE
@@ -262,10 +258,11 @@ WRITE_LINE_MEMBER( nubus_device::irqe_w ) { m_out_irqe_cb(state); }
// device_nubus_card_interface - constructor
//-------------------------------------------------
-device_nubus_card_interface::device_nubus_card_interface(const machine_config &mconfig, device_t &device)
- : device_interface(device, "nubus"),
- m_nubus(nullptr),
- m_nubus_slottag(nullptr), m_slot(0), m_next(nullptr)
+device_nubus_card_interface::device_nubus_card_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "nubus"),
+ m_nubus(nullptr),
+ m_nubus_slottag(nullptr),
+ m_slot(0)
{
}
@@ -280,13 +277,13 @@ device_nubus_card_interface::~device_nubus_card_interface()
void device_nubus_card_interface::interface_pre_start()
{
- if (!strncmp(m_nubus_slottag, "pds030", 6))
+ if ((!strncmp(m_nubus_slottag, "pds030", 6)) || (!strcmp(m_nubus_slottag, "siexp")))
{
- m_slot = 0x9; // '030 PDS slots phantom slot as NuBus slots $9, $A, and $B
+ m_slot = 0x9; // '030 PDS slots phantom slot as whatever they want but default to 9
}
else if (!strncmp(m_nubus_slottag, "lcpds", 6))
{
- m_slot = 0xe; // LC PDS slots phantom slot as NuBus slot $E
+ m_slot = 0xe; // LC PDS phantom slots as slot $E in most cases
}
else
{
@@ -456,7 +453,6 @@ void device_nubus_card_interface::install_declaration_rom(const char *romregion,
// now install the ROM
uint32_t addr = get_slotspace() + 0x01000000;
addr -= romlen;
-// printf("Installing ROM at %x, length %x\n", addr, romlen);
if (mirror_all_mb) // mirror the declaration ROM across all 16 megs of the slot space
{
uint32_t off = 0;
diff --git a/src/devices/bus/nubus/nubus.h b/src/devices/bus/nubus/nubus.h
index c99f25b33d6..68ba2aca96a 100644
--- a/src/devices/bus/nubus/nubus.h
+++ b/src/devices/bus/nubus/nubus.h
@@ -13,6 +13,10 @@
#pragma once
+#include <functional>
+#include <utility>
+#include <vector>
+
//**************************************************************************
// TYPE DEFINITIONS
@@ -26,15 +30,10 @@ class nubus_device;
class device_nubus_card_interface : public device_interface
{
friend class nubus_device;
- template <class ElementType> friend class simple_list;
public:
// construction/destruction
virtual ~device_nubus_card_interface();
- device_nubus_card_interface *next() const { return m_next; }
-
- void set_nubus_device();
-
// helper functions for card devices
void install_declaration_rom(const char *romregion, bool mirror_all_mb = false, bool reverse_rom = false);
void install_bank(offs_t start, offs_t end, void *data);
@@ -46,6 +45,8 @@ public:
void raise_slot_irq();
void lower_slot_irq();
+ void set_pds_slot(int slot) { m_slot = slot; }
+
// inline configuration
void set_nubus_tag(nubus_device *nubus, const char *slottag) { m_nubus = nubus; m_nubus_slottag = slottag; }
@@ -61,7 +62,6 @@ private:
const char *m_nubus_slottag;
int m_slot;
std::vector<uint8_t> m_declaration_rom;
- device_nubus_card_interface *m_next;
};
class nubus_slot_device : public device_t, public device_single_card_slot_interface<device_nubus_card_interface>
@@ -91,7 +91,7 @@ public:
protected:
nubus_slot_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
- // device-level overrides
+ // device_t implementation
virtual void device_resolve_objects() override;
virtual void device_start() override;
@@ -111,7 +111,7 @@ class nubus_device : public device_t
public:
// construction/destruction
nubus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- ~nubus_device() { m_device_list.detach_all(); }
+ ~nubus_device();
// inline configuration
template <typename T> void set_space(T &&tag, int spacenum) { m_space.set_tag(std::forward<T>(tag), spacenum); }
@@ -122,26 +122,26 @@ public:
auto out_irqd_callback() { return m_out_irqd_cb.bind(); }
auto out_irqe_callback() { return m_out_irqe_cb.bind(); }
- void add_nubus_card(device_nubus_card_interface *card);
+ void add_nubus_card(device_nubus_card_interface &card);
template <typename R, typename W> void install_device(offs_t start, offs_t end, R rhandler, W whandler, uint32_t mask=0xffffffff);
template <typename R> void install_readonly_device(offs_t start, offs_t end, R rhandler, uint32_t mask=0xffffffff);
template <typename W> void install_writeonly_device(offs_t start, offs_t end, W whandler, uint32_t mask=0xffffffff);
void install_bank(offs_t start, offs_t end, void *data);
void install_view(offs_t start, offs_t end, memory_view &view);
void set_irq_line(int slot, int state);
+ void set_address_mask(uint32_t mask) { m_addr_mask = mask; }
- DECLARE_WRITE_LINE_MEMBER( irq9_w );
- DECLARE_WRITE_LINE_MEMBER( irqa_w );
- DECLARE_WRITE_LINE_MEMBER( irqb_w );
- DECLARE_WRITE_LINE_MEMBER( irqc_w );
- DECLARE_WRITE_LINE_MEMBER( irqd_w );
- DECLARE_WRITE_LINE_MEMBER( irqe_w );
+ void irq9_w(int state);
+ void irqa_w(int state);
+ void irqb_w(int state);
+ void irqc_w(int state);
+ void irqd_w(int state);
+ void irqe_w(int state);
protected:
nubus_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
- // device-level overrides
- virtual void device_resolve_objects() override;
+ // device_t implementation
virtual void device_start() override;
// internal state
@@ -154,7 +154,9 @@ protected:
devcb_write_line m_out_irqd_cb;
devcb_write_line m_out_irqe_cb;
- simple_list<device_nubus_card_interface> m_device_list;
+ std::vector<std::reference_wrapper<device_nubus_card_interface> > m_device_list;
+
+ uint32_t m_addr_mask;
};
inline void device_nubus_card_interface::raise_slot_irq()
diff --git a/src/devices/bus/nubus/nubus_48gc.cpp b/src/devices/bus/nubus/nubus_48gc.cpp
index 60a28c513e6..9237b893150 100644
--- a/src/devices/bus/nubus/nubus_48gc.cpp
+++ b/src/devices/bus/nubus/nubus_48gc.cpp
@@ -99,7 +99,7 @@ protected:
virtual void device_add_mconfig(machine_config &config) override;
// palette implementation
- uint32_t palette_entries() const override;
+ uint32_t palette_entries() const noexcept override;
private:
static constexpr offs_t VRAM_MAX = 0x10'0000 / 4; // chip supports 2M but card can only use 1M
@@ -309,7 +309,7 @@ ioport_constructor nubus_824gc_device::device_input_ports() const
// palette_entries - entries in color palette
//-------------------------------------------------
-uint32_t jmfb_device::palette_entries() const
+uint32_t jmfb_device::palette_entries() const noexcept
{
return 256;
}
diff --git a/src/devices/bus/nubus/nubus_asntmc3b.cpp b/src/devices/bus/nubus/nubus_asntmc3b.cpp
index 2a45e2f2f3f..1a384e4bd81 100644
--- a/src/devices/bus/nubus/nubus_asntmc3b.cpp
+++ b/src/devices/bus/nubus/nubus_asntmc3b.cpp
@@ -2,12 +2,21 @@
// copyright-holders:R. Belmont
/***************************************************************************
- Asante MC3NB NuBus Ethernet card (DP83902)
- Apple NuBus Ethernet Card (DP8390)
+ Asante MC3NB NuBus Ethernet card (DP83902) (NuBus)
+ Apple NuBus Ethernet Card (DP8390) (NuBus)
+ Farallon EtherMac 30i-TH (DP83901) (SE/30 and IIsi PDS)
- Based on National Semiconductor DP8390 family chips
+ The declaration ROM calls the Farallon PDS card "EtherMac 30i-TH", but that
+ full name doesn't appear anywhere user-visible unless you're using software
+ such as TattleTech or TechTool that can show declaration ROM names.
- FssD0000 - 64k RAM buffer (used as DP83902 DMA target)
+ These cards are all a Mac adaptation of the ISA NE2000, with a DP8390
+ or DP8390x Ethernet controller plus 16K or more of on-card RAM. There
+ is no DMA, the CPU must read/write packets to the on-card RAM and the
+ DP839* chip can DMA to and from that RAM (but not the host system).
+
+ FssD0000 - RAM buffer (16K on Apple cards expandable to 64K,
+ 64K stock on Farallon and Asante cards)
FssE0000 - DP83902 registers
***************************************************************************/
@@ -15,9 +24,13 @@
#include "emu.h"
#include "nubus_asntmc3b.h"
+#include "machine/dp8390.h"
+
+#include "multibyte.h"
+
#define MAC8390_ROM_REGION "asntm3b_rom"
-#define MAC8390_839X "dp83902"
+namespace {
ROM_START( asntm3nb )
ROM_REGION(0x4000, MAC8390_ROM_REGION, 0)
@@ -29,17 +42,79 @@ ROM_START( appleenet )
ROM_LOAD( "aenet1", 0x000000, 0x004000, CRC(e3ae8c26) SHA1(01ddc15ee84b17128203cb812f29bac6b20fd642) )
ROM_END
-//**************************************************************************
-// GLOBAL VARIABLES
-//**************************************************************************
+ROM_START( ethermac30i )
+ ROM_REGION(0x4000, MAC8390_ROM_REGION, 0)
+ ROM_LOAD( "5000118-00-01.bin", 0x000000, 0x004000, CRC(49a602ec) SHA1(65a8e87180a793cd54d30930cc030b95723369f1) )
+ROM_END
+
+ROM_START( macconilc )
+ ROM_REGION(0x4000, MAC8390_ROM_REGION, 0)
+ ROM_LOAD( "asante_maccon_lc_mcilc_1.1.bin", 0x000000, 0x004000, CRC(b95940be) SHA1(317255bcb552ef43f43f85109706ed860baaf6dc) )
+ROM_END
+
+class nubus_mac8390_device : public device_t,
+ public device_nubus_card_interface
+{
+protected:
+ // construction/destruction
+ nubus_mac8390_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
-DEFINE_DEVICE_TYPE(NUBUS_ASNTMC3NB, nubus_asntmc3nb_device, "nb_amc3b", "Asante MC3NB Ethernet card")
-DEFINE_DEVICE_TYPE(NUBUS_APPLEENET, nubus_appleenet_device, "nb_aenet", "Apple NuBus Ethernet card")
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+ u8 asntm3b_ram_r(offs_t offset);
+ void asntm3b_ram_w(offs_t offset, u8 data);
+ u32 dp_r(offs_t offset, u32 mem_mask = ~0);
+ void dp_w(offs_t offset, u32 data, u32 mem_mask = ~0);
-//-------------------------------------------------
-// device_add_mconfig - add device configuration
-//-------------------------------------------------
+ required_device<dp8390_device> m_dp83902;
+
+private:
+ void dp_irq_w(int state);
+ u8 dp_mem_read(offs_t offset);
+ void dp_mem_write(offs_t offset, u8 data);
+
+ std::unique_ptr<u8[]> m_ram;
+ u8 m_prom[16];
+};
+
+class nubus_asntmc3nb_device : public nubus_mac8390_device
+{
+public:
+ nubus_asntmc3nb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+};
+
+class nubus_appleenet_device : public nubus_mac8390_device
+{
+public:
+ nubus_appleenet_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+ virtual const tiny_rom_entry *device_rom_region() const override;
+};
+
+class pds030_ethermac30i_device : public nubus_mac8390_device
+{
+public:
+ pds030_ethermac30i_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+protected:
+ virtual void device_start() override;
+};
+
+class pdslc_macconilc_device : public nubus_mac8390_device
+{
+public:
+ pdslc_macconilc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+protected:
+ virtual void device_start() override;
+};
void nubus_mac8390_device::device_add_mconfig(machine_config &config)
{
@@ -49,10 +124,6 @@ void nubus_mac8390_device::device_add_mconfig(machine_config &config)
m_dp83902->mem_write_callback().set(FUNC(nubus_mac8390_device::dp_mem_write));
}
-//-------------------------------------------------
-// rom_region - device-specific ROM region
-//-------------------------------------------------
-
const tiny_rom_entry *nubus_mac8390_device::device_rom_region() const
{
return ROM_NAME( asntm3nb );
@@ -63,83 +134,103 @@ const tiny_rom_entry *nubus_appleenet_device::device_rom_region() const
return ROM_NAME( appleenet );
}
-//**************************************************************************
-// LIVE DEVICE
-//**************************************************************************
+const tiny_rom_entry *pds030_ethermac30i_device::device_rom_region() const
+{
+ return ROM_NAME( ethermac30i );
+}
-//-------------------------------------------------
-// nubus_mac8390_device - constructor
-//-------------------------------------------------
+const tiny_rom_entry *pdslc_macconilc_device::device_rom_region() const
+{
+ return ROM_NAME(macconilc);
+}
-nubus_mac8390_device::nubus_mac8390_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
+nubus_mac8390_device::nubus_mac8390_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock) :
device_t(mconfig, type, tag, owner, clock),
device_nubus_card_interface(mconfig, *this),
- m_dp83902(*this, MAC8390_839X)
+ m_dp83902(*this, "dp83902")
{
}
-nubus_asntmc3nb_device::nubus_asntmc3nb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+nubus_asntmc3nb_device::nubus_asntmc3nb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
nubus_mac8390_device(mconfig, NUBUS_ASNTMC3NB, tag, owner, clock)
{
}
-nubus_appleenet_device::nubus_appleenet_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+nubus_appleenet_device::nubus_appleenet_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
nubus_mac8390_device(mconfig, NUBUS_APPLEENET, tag, owner, clock)
{
}
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
+pds030_ethermac30i_device::pds030_ethermac30i_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ nubus_mac8390_device(mconfig, PDS030_ETHERMAC30I, tag, owner, clock)
+{
+}
+
+pdslc_macconilc_device::pdslc_macconilc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ nubus_mac8390_device(mconfig, PDSLC_MACCONILC, tag, owner, clock)
+{
+}
void nubus_mac8390_device::device_start()
{
- uint32_t slotspace;
- char mac[7];
- uint32_t num = machine().rand();
+ const u32 slotspace = get_slotspace();
+ u8 mac[6];
+ u32 num = machine().rand();
memset(m_prom, 0x57, 16);
- sprintf(mac+2, "\x1b%c%c%c", (num >> 16) & 0xff, (num >> 8) & 0xff, num & 0xff);
+ mac[2] = 0x1b;
+ put_u24be(mac+3, num);
mac[0] = mac[1] = 0; // avoid gcc warning
memcpy(m_prom, mac, 6);
m_dp83902->set_mac(mac);
- install_declaration_rom(MAC8390_ROM_REGION, true);
+ m_ram = std::make_unique<u8[]>(0x10000);
+ save_pointer(NAME(m_ram), 0x10000);
- slotspace = get_slotspace();
+ install_declaration_rom(MAC8390_ROM_REGION);
// printf("[ASNTMC3NB %p] slotspace = %x\n", this, slotspace);
- // TODO: move 24-bit mirroring down into nubus.c
- uint32_t ofs_24bit = slotno()<<20;
+ // TODO: move 24-bit mirroring down into nubus.cpp
+ u32 ofs_24bit = slotno()<<20;
nubus().install_device(slotspace+0xd0000, slotspace+0xdffff, read8sm_delegate(*this, FUNC(nubus_mac8390_device::asntm3b_ram_r)), write8sm_delegate(*this, FUNC(nubus_mac8390_device::asntm3b_ram_w)));
- nubus().install_device(slotspace+0xe0000, slotspace+0xe003f, read32s_delegate(*this, FUNC(nubus_mac8390_device::en_r)), write32s_delegate(*this, FUNC(nubus_mac8390_device::en_w)));
+ nubus().install_device(slotspace+0xe0000, slotspace+0xe003f, read32s_delegate(*this, FUNC(nubus_mac8390_device::dp_r)), write32s_delegate(*this, FUNC(nubus_mac8390_device::dp_w)));
nubus().install_device(slotspace+0xd0000+ofs_24bit, slotspace+0xdffff+ofs_24bit, read8sm_delegate(*this, FUNC(nubus_mac8390_device::asntm3b_ram_r)), write8sm_delegate(*this, FUNC(nubus_mac8390_device::asntm3b_ram_w)));
- nubus().install_device(slotspace+0xe0000+ofs_24bit, slotspace+0xe003f+ofs_24bit, read32s_delegate(*this, FUNC(nubus_mac8390_device::en_r)), write32s_delegate(*this, FUNC(nubus_mac8390_device::en_w)));
+ nubus().install_device(slotspace+0xe0000+ofs_24bit, slotspace+0xe003f+ofs_24bit, read32s_delegate(*this, FUNC(nubus_mac8390_device::dp_r)), write32s_delegate(*this, FUNC(nubus_mac8390_device::dp_w)));
+}
+
+void pds030_ethermac30i_device::device_start()
+{
+ // this card is hardwired to slot 9 and the driver looks for it there
+ set_pds_slot(0x9);
+ nubus_mac8390_device::device_start();
}
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
+void pdslc_macconilc_device::device_start()
+{
+ // this card is hardwired to slot E and the driver looks for it there
+ set_pds_slot(0xe);
+ nubus_mac8390_device::device_start();
+}
void nubus_mac8390_device::device_reset()
{
m_dp83902->dp8390_reset(0);
- memcpy(m_prom, m_dp83902->get_mac(), 6);
+ memcpy(m_prom, &m_dp83902->get_mac()[0], 6);
}
-void nubus_mac8390_device::asntm3b_ram_w(offs_t offset, uint8_t data)
+void nubus_mac8390_device::asntm3b_ram_w(offs_t offset, u8 data)
{
// printf("MC3NB: CPU wrote %02x to RAM @ %x\n", data, offset);
m_ram[offset] = data;
}
-uint8_t nubus_mac8390_device::asntm3b_ram_r(offs_t offset)
+u8 nubus_mac8390_device::asntm3b_ram_r(offs_t offset)
{
// printf("MC3NB: CPU read %02x @ RAM %x\n", m_ram[offset], offset);
return m_ram[offset];
}
-void nubus_mac8390_device::en_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+void nubus_mac8390_device::dp_w(offs_t offset, u32 data, u32 mem_mask)
{
if (mem_mask == 0xff000000)
{
@@ -156,7 +247,7 @@ void nubus_mac8390_device::en_w(offs_t offset, uint32_t data, uint32_t mem_mask)
}
}
-uint32_t nubus_mac8390_device::en_r(offs_t offset, uint32_t mem_mask)
+u32 nubus_mac8390_device::dp_r(offs_t offset, u32 mem_mask)
{
if (mem_mask == 0xff000000)
{
@@ -174,7 +265,7 @@ uint32_t nubus_mac8390_device::en_r(offs_t offset, uint32_t mem_mask)
return 0;
}
-WRITE_LINE_MEMBER( nubus_mac8390_device::dp_irq_w )
+void nubus_mac8390_device::dp_irq_w(int state)
{
if (state)
{
@@ -186,14 +277,21 @@ WRITE_LINE_MEMBER( nubus_mac8390_device::dp_irq_w )
}
}
-uint8_t nubus_mac8390_device::dp_mem_read(offs_t offset)
+u8 nubus_mac8390_device::dp_mem_read(offs_t offset)
{
// printf("MC3NB: 8390 read RAM @ %x = %02x\n", offset, m_ram[offset]);
return m_ram[offset];
}
-void nubus_mac8390_device::dp_mem_write(offs_t offset, uint8_t data)
+void nubus_mac8390_device::dp_mem_write(offs_t offset, u8 data)
{
// printf("MC3NB: 8390 wrote %02x to RAM @ %x\n", data, offset);
m_ram[offset] = data;
}
+
+}
+
+DEFINE_DEVICE_TYPE_PRIVATE(NUBUS_ASNTMC3NB, device_nubus_card_interface, nubus_asntmc3nb_device, "nb_amc3b", "Asante MC3NB Ethernet card")
+DEFINE_DEVICE_TYPE_PRIVATE(NUBUS_APPLEENET, device_nubus_card_interface, nubus_appleenet_device, "nb_aenet", "Apple NuBus Ethernet card")
+DEFINE_DEVICE_TYPE_PRIVATE(PDS030_ETHERMAC30I, device_nubus_card_interface, pds030_ethermac30i_device, "pds30_emac", "Farallon EtherMac 30i-TH Ethernet card")
+DEFINE_DEVICE_TYPE_PRIVATE(PDSLC_MACCONILC, device_nubus_card_interface, pdslc_macconilc_device, "pdslc_macconlc", "Asante MacCON i LC Ethernet card")
diff --git a/src/devices/bus/nubus/nubus_asntmc3b.h b/src/devices/bus/nubus/nubus_asntmc3b.h
index 20b3cbe0190..229fbecbcc0 100644
--- a/src/devices/bus/nubus/nubus_asntmc3b.h
+++ b/src/devices/bus/nubus/nubus_asntmc3b.h
@@ -6,61 +6,11 @@
#pragma once
#include "nubus.h"
-#include "machine/dp8390.h"
-
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-// ======================> nubus_mac8390_device
-
-class nubus_mac8390_device :
- public device_t,
- public device_nubus_card_interface
-{
-protected:
- // construction/destruction
- nubus_mac8390_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
-
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
-
- // optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
-
- uint8_t asntm3b_ram_r(offs_t offset);
- void asntm3b_ram_w(offs_t offset, uint8_t data);
- uint32_t en_r(offs_t offset, uint32_t mem_mask = ~0);
- void en_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
-
- required_device<dp8390_device> m_dp83902;
-
-private:
- void dp_irq_w(int state);
- uint8_t dp_mem_read(offs_t offset);
- void dp_mem_write(offs_t offset, uint8_t data);
-
- uint8_t m_ram[0x20000];
- uint8_t m_prom[16];
-};
-
-class nubus_asntmc3nb_device : public nubus_mac8390_device
-{
-public:
- nubus_asntmc3nb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-};
-
-class nubus_appleenet_device : public nubus_mac8390_device
-{
-public:
- nubus_appleenet_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual const tiny_rom_entry *device_rom_region() const override;
-};
// device type definition
-DECLARE_DEVICE_TYPE(NUBUS_ASNTMC3NB, nubus_asntmc3nb_device)
-DECLARE_DEVICE_TYPE(NUBUS_APPLEENET, nubus_appleenet_device)
+DECLARE_DEVICE_TYPE(NUBUS_ASNTMC3NB, device_nubus_card_interface)
+DECLARE_DEVICE_TYPE(NUBUS_APPLEENET, device_nubus_card_interface)
+DECLARE_DEVICE_TYPE(PDS030_ETHERMAC30I, device_nubus_card_interface)
+DECLARE_DEVICE_TYPE(PDSLC_MACCONILC, device_nubus_card_interface)
#endif // MAME_BUS_NUBUS_NUBUS_ASNTMC3B_H
diff --git a/src/devices/bus/nubus/nubus_cb264.cpp b/src/devices/bus/nubus/nubus_cb264.cpp
index bc9f436e6bf..e0ef3750ae1 100644
--- a/src/devices/bus/nubus/nubus_cb264.cpp
+++ b/src/devices/bus/nubus/nubus_cb264.cpp
@@ -4,71 +4,89 @@
RasterOps ColorBoard 264 NuBus video card emulation
- fixed resolution 640x480 NuBus video card, 1/4/8/16/24 bit color
- 1.5? MB of VRAM (tests up to 0x1fffff), Bt473 RAMDAC, and two custom gate arrays.
+ fixed resolution 640x480 NuBus video card, 1/2/4/8/24 bit color
+ 1.5 MiB of VRAM, Bt473KPJ35 RAMDAC, and two custom gate arrays.
0xfsff6004 is color depth: 0 for 1bpp, 1 for 2bpp, 2 for 4bpp, 3 for 8bpp, 4 for 24bpp
0xfsff6014 is VBL ack: write 1 to ack
0xfsff603c is VBL disable: write 1 to disable, 0 to enable
+ Crystal (pixel clock) is 30.24 MHz. A 12.3356 MHz crystal is also present,
+ likely used only for 30 Hz interlaced NTSC output.
+
+ TODO:
+ - Figure out the vertical part of the CRTC registers and make the mode dynamic.
+ - Figure out how 24 bpp mode fits in 1.5 MiB. Stride is 4096 bytes, each
+ scanline is 640 pixels at 4 bytes each, which comes to just below 2 MiB.
+
***************************************************************************/
#include "emu.h"
+
#include "nubus_cb264.h"
+
+#include "emupal.h"
#include "screen.h"
#include <algorithm>
+namespace {
-#define CB264_SCREEN_NAME "cb264_screen"
-#define CB264_ROM_REGION "cb264_rom"
+static constexpr u32 VRAM_SIZE = 0x200000; // 12x TC524256J (256K x 4 bit VRAM), so 1.5 MiB total
-#define VRAM_SIZE (0x200000) // 2 megs, maxed out
+class nubus_cb264_device : public device_t,
+ public device_nubus_card_interface
+{
+public:
+ // construction/destruction
+ nubus_cb264_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+protected:
+ nubus_cb264_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
-ROM_START( cb264 )
- ROM_REGION(0x4000, CB264_ROM_REGION, 0)
- ROM_LOAD16_BYTE( "264-1915.bin", 0x000000, 0x002000, CRC(26c19ee5) SHA1(2b2853d04cc6b0258e85eccd23ebfd4f4f63a084) )
- ROM_LOAD16_BYTE( "264-1914.bin", 0x000001, 0x002000, CRC(d5fbd5ad) SHA1(98d35ed3fb0bca4a9bee1cdb2af0d3f22b379386) )
-ROM_END
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
-//**************************************************************************
-// GLOBAL VARIABLES
-//**************************************************************************
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
-DEFINE_DEVICE_TYPE(NUBUS_CB264, nubus_cb264_device, "nb_c264", "RasterOps ColorBoard 264 video card")
+ uint32_t cb264_r(offs_t offset, uint32_t mem_mask = ~0);
+ void cb264_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
+ uint32_t cb264_ramdac_r(offs_t offset);
+ void cb264_ramdac_w(offs_t offset, uint32_t data);
+private:
+ uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
-//-------------------------------------------------
-// device_add_mconfig - add device configuration
-//-------------------------------------------------
+ required_device<screen_device> m_screen;
+ required_device<palette_device> m_palette;
+ std::unique_ptr<u32[]> m_vram;
+ uint32_t m_cb264_mode, m_cb264_vbl_disable;
+ uint32_t m_colors[3], m_count, m_clutoffs;
+};
+
+ROM_START( cb264 )
+ ROM_REGION(0x4000, "cb264_rom", 0)
+ ROM_LOAD16_BYTE( "264-1915.bin", 0x000000, 0x002000, CRC(26c19ee5) SHA1(2b2853d04cc6b0258e85eccd23ebfd4f4f63a084) )
+ ROM_LOAD16_BYTE( "264-1914.bin", 0x000001, 0x002000, CRC(d5fbd5ad) SHA1(98d35ed3fb0bca4a9bee1cdb2af0d3f22b379386) )
+ROM_END
void nubus_cb264_device::device_add_mconfig(machine_config &config)
{
- screen_device &screen(SCREEN(config, CB264_SCREEN_NAME, SCREEN_TYPE_RASTER));
+ screen_device &screen(SCREEN(config, "cb264_screen", SCREEN_TYPE_RASTER));
screen.set_screen_update(FUNC(nubus_cb264_device::screen_update));
- screen.set_raw(25175000, 800, 0, 640, 525, 0, 480);
- screen.set_size(1024, 768);
- screen.set_visarea(0, 640-1, 0, 480-1);
-}
+ screen.set_raw(30.24_MHz_XTAL, 864, 0, 640, 525, 0, 480); // 35 kHz horizontal rate, 66.67 Hz vertical rate
-//-------------------------------------------------
-// rom_region - device-specific ROM region
-//-------------------------------------------------
+ PALETTE(config, m_palette).set_entries(256);
+}
const tiny_rom_entry *nubus_cb264_device::device_rom_region() const
{
return ROM_NAME( cb264 );
}
-//**************************************************************************
-// LIVE DEVICE
-//**************************************************************************
-
-//-------------------------------------------------
-// nubus_cb264_device - constructor
-//-------------------------------------------------
-
nubus_cb264_device::nubus_cb264_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
nubus_cb264_device(mconfig, NUBUS_CB264, tag, owner, clock)
{
@@ -77,7 +95,9 @@ nubus_cb264_device::nubus_cb264_device(const machine_config &mconfig, const char
nubus_cb264_device::nubus_cb264_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, type, tag, owner, clock),
device_nubus_card_interface(mconfig, *this),
- m_cb264_mode(0), m_cb264_vbl_disable(0), m_cb264_toggle(0), m_count(0), m_clutoffs(0)
+ m_screen(*this, "cb264_screen"),
+ m_palette(*this, "cb264_palette"),
+ m_cb264_mode(0), m_cb264_vbl_disable(0), m_count(0), m_clutoffs(0)
{
}
@@ -87,19 +107,22 @@ nubus_cb264_device::nubus_cb264_device(const machine_config &mconfig, device_typ
void nubus_cb264_device::device_start()
{
- uint32_t slotspace;
-
- install_declaration_rom(CB264_ROM_REGION);
+ u32 slotspace = get_slotspace();
- slotspace = get_slotspace();
+ install_declaration_rom("cb264_rom");
-// printf("[cb264 %p] slotspace = %x\n", this, slotspace);
-
- m_vram.resize(VRAM_SIZE / sizeof(uint32_t));
- install_bank(slotspace, slotspace+VRAM_SIZE-1, &m_vram[0]);
+ m_vram = std::make_unique<u32[]>(VRAM_SIZE / sizeof(u32));
+ install_bank(slotspace, slotspace + VRAM_SIZE - 1, &m_vram[0]);
nubus().install_device(slotspace+0xff6000, slotspace+0xff60ff, read32s_delegate(*this, FUNC(nubus_cb264_device::cb264_r)), write32s_delegate(*this, FUNC(nubus_cb264_device::cb264_w)));
nubus().install_device(slotspace+0xff7000, slotspace+0xff70ff, read32sm_delegate(*this, FUNC(nubus_cb264_device::cb264_ramdac_r)), write32sm_delegate(*this, FUNC(nubus_cb264_device::cb264_ramdac_w)));
+
+ save_item(NAME(m_cb264_mode));
+ save_item(NAME(m_cb264_vbl_disable));
+ save_item(NAME(m_colors));
+ save_item(NAME(m_count));
+ save_item(NAME(m_clutoffs));
+ save_pointer(NAME(m_vram), VRAM_SIZE / sizeof(u32));
}
//-------------------------------------------------
@@ -108,21 +131,13 @@ void nubus_cb264_device::device_start()
void nubus_cb264_device::device_reset()
{
- m_cb264_toggle = 0;
m_count = 0;
m_clutoffs = 0;
m_cb264_vbl_disable = 1;
m_cb264_mode = 0;
- std::fill(m_vram.begin(), m_vram.end(), 0);
- memset(m_palette, 0, sizeof(m_palette));
+ std::fill_n(&m_vram[0], VRAM_SIZE / sizeof(u32), 0);
}
-/***************************************************************************
-
- ColorBoard 264 section
-
-***************************************************************************/
-
uint32_t nubus_cb264_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
if (!m_cb264_vbl_disable)
@@ -130,25 +145,27 @@ uint32_t nubus_cb264_device::screen_update(screen_device &screen, bitmap_rgb32 &
raise_slot_irq();
}
- auto const vram8 = util::big_endian_cast<uint8_t const>(&m_vram[0]);
+ auto const vram8 = util::big_endian_cast<u8 const>(&m_vram[0]);
+ const pen_t *pens = m_palette->pens();
+
switch (m_cb264_mode)
{
case 0: // 1 bpp
for (int y = 0; y < 480; y++)
{
- uint32_t *scanline = &bitmap.pix(y);
+ u32 *scanline = &bitmap.pix(y);
for (int x = 0; x < 640/8; x++)
{
- uint8_t const pixels = vram8[(y * 1024) + x];
-
- *scanline++ = m_palette[pixels&0x80];
- *scanline++ = m_palette[(pixels<<1)&0x80];
- *scanline++ = m_palette[(pixels<<2)&0x80];
- *scanline++ = m_palette[(pixels<<3)&0x80];
- *scanline++ = m_palette[(pixels<<4)&0x80];
- *scanline++ = m_palette[(pixels<<5)&0x80];
- *scanline++ = m_palette[(pixels<<6)&0x80];
- *scanline++ = m_palette[(pixels<<7)&0x80];
+ u8 const pixels = vram8[(y * 1024) + x];
+
+ *scanline++ = pens[pixels&0x80];
+ *scanline++ = pens[(pixels<<1)&0x80];
+ *scanline++ = pens[(pixels<<2)&0x80];
+ *scanline++ = pens[(pixels<<3)&0x80];
+ *scanline++ = pens[(pixels<<4)&0x80];
+ *scanline++ = pens[(pixels<<5)&0x80];
+ *scanline++ = pens[(pixels<<6)&0x80];
+ *scanline++ = pens[(pixels<<7)&0x80];
}
}
break;
@@ -156,15 +173,15 @@ uint32_t nubus_cb264_device::screen_update(screen_device &screen, bitmap_rgb32 &
case 1: // 2 bpp (3f/7f/bf/ff)
for (int y = 0; y < 480; y++)
{
- uint32_t *scanline = &bitmap.pix(y);
+ u32 *scanline = &bitmap.pix(y);
for (int x = 0; x < 640/4; x++)
{
- uint8_t const pixels = vram8[(y * 1024) + x];
+ u8 const pixels = vram8[(y * 1024) + x];
- *scanline++ = m_palette[pixels&0xc0];
- *scanline++ = m_palette[(pixels<<2)&0xc0];
- *scanline++ = m_palette[(pixels<<4)&0xc0];
- *scanline++ = m_palette[(pixels<<6)&0xc0];
+ *scanline++ = pens[pixels&0xc0];
+ *scanline++ = pens[(pixels<<2)&0xc0];
+ *scanline++ = pens[(pixels<<4)&0xc0];
+ *scanline++ = pens[(pixels<<6)&0xc0];
}
}
break;
@@ -172,13 +189,13 @@ uint32_t nubus_cb264_device::screen_update(screen_device &screen, bitmap_rgb32 &
case 2: // 4 bpp
for (int y = 0; y < 480; y++)
{
- uint32_t *scanline = &bitmap.pix(y);
+ u32 *scanline = &bitmap.pix(y);
for (int x = 0; x < 640/2; x++)
{
- uint8_t const pixels = vram8[(y * 1024) + x];
+ u8 const pixels = vram8[(y * 1024) + x];
- *scanline++ = m_palette[pixels&0xf0];
- *scanline++ = m_palette[(pixels<<4)&0xf0];
+ *scanline++ = pens[pixels&0xf0];
+ *scanline++ = pens[(pixels<<4)&0xf0];
}
}
break;
@@ -186,11 +203,11 @@ uint32_t nubus_cb264_device::screen_update(screen_device &screen, bitmap_rgb32 &
case 3: // 8 bpp
for (int y = 0; y < 480; y++)
{
- uint32_t *scanline = &bitmap.pix(y);
+ u32 *scanline = &bitmap.pix(y);
for (int x = 0; x < 640; x++)
{
- uint8_t const pixels = vram8[(y * 1024) + x];
- *scanline++ = m_palette[pixels];
+ u8 const pixels = vram8[(y * 1024) + x];
+ *scanline++ = pens[pixels];
}
}
break;
@@ -210,7 +227,7 @@ uint32_t nubus_cb264_device::screen_update(screen_device &screen, bitmap_rgb32 &
return 0;
}
-void nubus_cb264_device::cb264_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+void nubus_cb264_device::cb264_w(offs_t offset, u32 data, u32 mem_mask)
{
switch (offset)
{
@@ -226,13 +243,28 @@ void nubus_cb264_device::cb264_w(offs_t offset, uint32_t data, uint32_t mem_mask
m_cb264_vbl_disable = data;
break;
+ /*
+ CRTC, but vertical doesn't make sense.
+ Vertical:
+ 40: 2 - first line of active display?
+ 44: 209 - last line of active display?
+ 48: 20c - vtotal - 1? (525)
+ 4c: f
+
+ Horizontal:
+ 50: 27 - start of active display
+ 54: c7 - end of active display (0xc7 - 0x27 = 160, 160 * 4 = 640)
+ 58: d7 - htotal/4 - 1? (864)
+ 5c: 6b
+ */
+
default:
-// printf("%s cb264_w: %x to reg %x (mask %x)\n", machine().describe_context().c_str(), data, offset*4, mem_mask);
+ //printf("%s cb264_w: %x to reg %x (mask %x)\n", machine().describe_context().c_str(), data, offset*4, mem_mask);
break;
}
}
-uint32_t nubus_cb264_device::cb264_r(offs_t offset, uint32_t mem_mask)
+u32 nubus_cb264_device::cb264_r(offs_t offset, u32 mem_mask)
{
switch (offset)
{
@@ -241,8 +273,7 @@ uint32_t nubus_cb264_device::cb264_r(offs_t offset, uint32_t mem_mask)
break;
case 0x34/4:
- m_cb264_toggle ^= 1;
- return m_cb264_toggle; // bit 0 is vblank?
+ return m_screen->vblank(); // bit 0 is vblank
default:
logerror("cb264_r: reg %x (mask %x %s)\n", offset*4, mem_mask, machine().describe_context());
@@ -252,7 +283,7 @@ uint32_t nubus_cb264_device::cb264_r(offs_t offset, uint32_t mem_mask)
return 0;
}
-void nubus_cb264_device::cb264_ramdac_w(offs_t offset, uint32_t data)
+void nubus_cb264_device::cb264_ramdac_w(offs_t offset, u32 data)
{
switch (offset)
{
@@ -266,7 +297,9 @@ void nubus_cb264_device::cb264_ramdac_w(offs_t offset, uint32_t data)
if (m_count == 3)
{
- m_palette[m_clutoffs] = rgb_t(m_colors[0], m_colors[1], m_colors[2]);
+ m_palette->set_pen_red_level(m_clutoffs, m_colors[0]);
+ m_palette->set_pen_green_level(m_clutoffs, m_colors[1]);
+ m_palette->set_pen_blue_level(m_clutoffs, m_colors[2]);
m_clutoffs++;
m_count = 0;
}
@@ -278,7 +311,11 @@ void nubus_cb264_device::cb264_ramdac_w(offs_t offset, uint32_t data)
}
}
-uint32_t nubus_cb264_device::cb264_ramdac_r(offs_t offset)
+u32 nubus_cb264_device::cb264_ramdac_r(offs_t offset)
{
return 0;
}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(NUBUS_CB264, device_nubus_card_interface, nubus_cb264_device, "nb_c264", "RasterOps ColorBoard 264 video card")
diff --git a/src/devices/bus/nubus/nubus_cb264.h b/src/devices/bus/nubus/nubus_cb264.h
index bb7d0e3ac98..78c3aa6476c 100644
--- a/src/devices/bus/nubus/nubus_cb264.h
+++ b/src/devices/bus/nubus/nubus_cb264.h
@@ -7,46 +7,6 @@
#include "nubus.h"
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-// ======================> nubus_cb264_device
-
-class nubus_cb264_device :
- public device_t,
- public device_nubus_card_interface
-{
-public:
- // construction/destruction
- nubus_cb264_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- nubus_cb264_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
-
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
-
- // optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
-
- uint32_t cb264_r(offs_t offset, uint32_t mem_mask = ~0);
- void cb264_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
- uint32_t cb264_ramdac_r(offs_t offset);
- void cb264_ramdac_w(offs_t offset, uint32_t data);
-
-private:
- uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
-
- std::vector<uint32_t> m_vram;
- uint32_t m_cb264_mode, m_cb264_vbl_disable, m_cb264_toggle;
- uint32_t m_palette[256], m_colors[3], m_count, m_clutoffs;
-};
-
-
-// device type definition
-DECLARE_DEVICE_TYPE(NUBUS_CB264, nubus_cb264_device)
+DECLARE_DEVICE_TYPE(NUBUS_CB264, device_nubus_card_interface)
#endif // MAME_BUS_NUBUS_NUBUS_CB264_H
diff --git a/src/devices/bus/nubus/nubus_image.cpp b/src/devices/bus/nubus/nubus_image.cpp
index b3c741cb3a9..3d17b2500a1 100644
--- a/src/devices/bus/nubus/nubus_image.cpp
+++ b/src/devices/bus/nubus/nubus_image.cpp
@@ -40,7 +40,7 @@ public:
// construction/destruction
messimg_disk_image_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- // image-level overrides
+ // device_image_interface implementation
virtual bool is_readable() const noexcept override { return true; }
virtual bool is_writeable() const noexcept override { return true; }
virtual bool is_creatable() const noexcept override { return false; }
@@ -49,7 +49,7 @@ public:
virtual const char *image_type_name() const noexcept override { return "disk"; }
virtual const char *image_brief_type_name() const noexcept override { return "disk"; }
- virtual image_init_result call_load() override;
+ virtual std::pair<std::error_condition, std::string> call_load() override;
virtual void call_unload() override;
protected:
@@ -89,22 +89,24 @@ void nubus_image_device::messimg_disk_image_device::device_start()
}
}
-image_init_result nubus_image_device::messimg_disk_image_device::call_load()
+std::pair<std::error_condition, std::string> nubus_image_device::messimg_disk_image_device::call_load()
{
- fseek(0, SEEK_END);
- m_size = uint32_t(ftell());
+ m_size = length();
if (m_size > (256*1024*1024))
{
- osd_printf_error("Mac image too large: must be 256MB or less!\n");
m_size = 0;
- return image_init_result::FAIL;
+ return std::make_pair(image_error::INVALIDLENGTH, "Image file is too large (must be no more than 256MB)");
}
+ m_data.reset(new (std::nothrow) uint8_t [m_size]);
+ if (!m_data)
+ return std::make_pair(std::errc::not_enough_memory, "Error allocating memory for volume image");
+
fseek(0, SEEK_SET);
- fread(m_data, m_size);
+ fread(m_data.get(), m_size);
m_ejected = false;
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
void nubus_image_device::messimg_disk_image_device::call_unload()
@@ -242,8 +244,8 @@ uint32_t nubus_image_device::image_r()
void nubus_image_device::image_super_w(offs_t offset, uint32_t data, uint32_t mem_mask)
{
uint32_t *image = (uint32_t*)m_image->m_data.get();
- data = ((data & 0xff) << 24) | ((data & 0xff00) << 8) | ((data & 0xff0000) >> 8) | ((data & 0xff000000) >> 24);
- mem_mask = ((mem_mask & 0xff) << 24) | ((mem_mask & 0xff00) << 8) | ((mem_mask & 0xff0000) >> 8) | ((mem_mask & 0xff000000) >> 24);
+ data = swapendian_int32(data);
+ mem_mask = swapendian_int32(mem_mask);
COMBINE_DATA(&image[offset]);
}
@@ -251,13 +253,12 @@ void nubus_image_device::image_super_w(offs_t offset, uint32_t data, uint32_t me
uint32_t nubus_image_device::image_super_r(offs_t offset, uint32_t mem_mask)
{
uint32_t *image = (uint32_t*)m_image->m_data.get();
- uint32_t data = image[offset];
- return ((data & 0xff) << 24) | ((data & 0xff00) << 8) | ((data & 0xff0000) >> 8) | ((data & 0xff000000) >> 24);
+ return swapendian_int32(image[offset]);
}
void nubus_image_device::file_cmd_w(uint32_t data)
{
-// data = ((data & 0xff) << 24) | ((data & 0xff00) << 8) | ((data & 0xff0000) >> 8) | ((data & 0xff000000) >> 24);
+// data = swapendian_int32(data);
filectx.curcmd = data;
switch (data) {
case kFileCmdGetDir:
diff --git a/src/devices/bus/nubus/nubus_spec8.cpp b/src/devices/bus/nubus/nubus_spec8.cpp
index 1e55c907928..e85430b0f17 100644
--- a/src/devices/bus/nubus/nubus_spec8.cpp
+++ b/src/devices/bus/nubus/nubus_spec8.cpp
@@ -94,7 +94,7 @@ protected:
virtual ioport_constructor device_input_ports() const override;
// palette implementation
- virtual uint32_t palette_entries() const override;
+ virtual uint32_t palette_entries() const noexcept override;
TIMER_CALLBACK_MEMBER(vbl_tick);
@@ -184,7 +184,7 @@ ioport_constructor nubus_spec8s3_device::device_input_ports() const
// palette_entries - entries in color palette
//-------------------------------------------------
-uint32_t nubus_spec8s3_device::palette_entries() const
+uint32_t nubus_spec8s3_device::palette_entries() const noexcept
{
return 256;
}
diff --git a/src/devices/bus/nubus/nubus_specpdq.cpp b/src/devices/bus/nubus/nubus_specpdq.cpp
index c6b71b7b1f1..c496fa77d05 100644
--- a/src/devices/bus/nubus/nubus_specpdq.cpp
+++ b/src/devices/bus/nubus/nubus_specpdq.cpp
@@ -78,7 +78,7 @@ protected:
virtual ioport_constructor device_input_ports() const override;
// palette implementation
- virtual uint32_t palette_entries() const override;
+ virtual uint32_t palette_entries() const noexcept override;
TIMER_CALLBACK_MEMBER(vbl_tick);
@@ -171,7 +171,7 @@ ioport_constructor nubus_specpdq_device::device_input_ports() const
// palette_entries - entries in color palette
//-------------------------------------------------
-uint32_t nubus_specpdq_device::palette_entries() const
+uint32_t nubus_specpdq_device::palette_entries() const noexcept
{
return 256;
}
diff --git a/src/devices/bus/nubus/nubus_vikbw.cpp b/src/devices/bus/nubus/nubus_vikbw.cpp
index af61f6dc45f..88f3ef5a5d4 100644
--- a/src/devices/bus/nubus/nubus_vikbw.cpp
+++ b/src/devices/bus/nubus/nubus_vikbw.cpp
@@ -2,165 +2,169 @@
// copyright-holders:R. Belmont
/***************************************************************************
- Viking 1024x768 fixed-resolution monochrome board
+ Moniterm MacViking II 1024x768 fixed-resolution monochrome board
- VRAM from Fs040000 to Fs0517FF
+ https://wiki.preterhuman.net/Moniterm_MACVIKING_II
+
+ VRAM from Fs040000 to Fs05FFFF (RAM test goes up to Fs065800 for some reason)
Read from Fs000000 enables VBL, write to Fs000000 disables VBL
Write to Fs080000 acks VBL
+ Crystal (pixel clock) is 72 MHz.
+
+ TODO: Actual raster parameters are unknown. We've gone with the Apple 19"
+ 1024x768 monitor's htotal/vtotal but this used a custom monitor. There are
+ no register writes other than the IRQ enable/ack so tracing, the CRTC is
+ pure TTL.
+
***************************************************************************/
#include "emu.h"
+#include "emupal.h"
#include "nubus_vikbw.h"
#include "screen.h"
-#define VIKBW_SCREEN_NAME "vikbw_screen"
-#define VIKBW_ROM_REGION "vikbw_rom"
+namespace {
-#define VRAM_SIZE (0x18000) // 1024x768 @ 1bpp is 98,304 bytes (0x18000)
+static constexpr u32 VRAM_SIZE = 0x20000; // 4x HM53461 VRAMs (64K x 4 bit)
+class nubus_vikbw_device : public device_t,
+ public device_nubus_card_interface
+{
+public:
+ // construction/destruction
+ nubus_vikbw_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
-ROM_START( vikbw )
- ROM_REGION(0x2000, VIKBW_ROM_REGION, 0)
- ROM_LOAD( "viking.bin", 0x000000, 0x002000, CRC(92cf04d1) SHA1(d08349edfc82a0bd5ea848e053e1712092308f74) )
-ROM_END
+protected:
+ nubus_vikbw_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
-//**************************************************************************
-// GLOBAL VARIABLES
-//**************************************************************************
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
-DEFINE_DEVICE_TYPE(NUBUS_VIKBW, nubus_vikbw_device, "nb_vikbw", "Moniterm Viking video card")
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+private:
+ u32 viking_ack_r();
+ void viking_ack_w(u32 data);
+ u32 viking_enable_r();
+ void viking_disable_w(u32 data);
-//-------------------------------------------------
-// device_add_mconfig - add device configuration
-//-------------------------------------------------
+ u32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
+
+ std::unique_ptr<u32[]> m_vram;
+ u32 m_vbl_disable;
+};
+
+ROM_START( vikbw )
+ ROM_REGION(0x2000, "vikingrom", 0)
+ ROM_LOAD( "viking.bin", 0x000000, 0x002000, CRC(92cf04d1) SHA1(d08349edfc82a0bd5ea848e053e1712092308f74) )
+ROM_END
void nubus_vikbw_device::device_add_mconfig(machine_config &config)
{
- screen_device &screen(SCREEN(config, VIKBW_SCREEN_NAME, SCREEN_TYPE_RASTER));
+ screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
screen.set_screen_update(FUNC(nubus_vikbw_device::screen_update));
- screen.set_size(1024, 768);
- screen.set_visarea(0, 1024-1, 0, 768-1);
- screen.set_refresh_hz(70);
-}
+ screen.set_raw(72000000, 1324, 0, 1024, 803, 0, 768);
+ screen.set_palette("palette");
-//-------------------------------------------------
-// rom_region - device-specific ROM region
-//-------------------------------------------------
+ PALETTE(config, "palette", palette_device::MONOCHROME_INVERTED);
+}
const tiny_rom_entry *nubus_vikbw_device::device_rom_region() const
{
return ROM_NAME( vikbw );
}
-//**************************************************************************
-// LIVE DEVICE
-//**************************************************************************
-
-//-------------------------------------------------
-// nubus_vikbw_device - constructor
-//-------------------------------------------------
-
-nubus_vikbw_device::nubus_vikbw_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+nubus_vikbw_device::nubus_vikbw_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
nubus_vikbw_device(mconfig, NUBUS_VIKBW, tag, owner, clock)
{
}
-nubus_vikbw_device::nubus_vikbw_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
+nubus_vikbw_device::nubus_vikbw_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock) :
device_t(mconfig, type, tag, owner, clock),
device_nubus_card_interface(mconfig, *this),
m_vbl_disable(0)
{
}
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-
void nubus_vikbw_device::device_start()
{
- uint32_t slotspace;
+ u32 slotspace;
- install_declaration_rom(VIKBW_ROM_REGION, true);
+ install_declaration_rom("vikingrom", true);
slotspace = get_slotspace();
-// printf("[vikbw %p] slotspace = %x\n", this, slotspace);
-
- m_vram.resize(VRAM_SIZE / sizeof(uint32_t));
- install_bank(slotspace+0x40000, slotspace+0x40000+VRAM_SIZE-1, &m_vram[0]);
+ m_vram = std::make_unique<u32[]>(VRAM_SIZE / sizeof(u32));
+ install_bank(slotspace + 0x40000, slotspace + 0x40000 + VRAM_SIZE - 1, &m_vram[0]);
install_bank(slotspace+0x940000, slotspace+0x940000+VRAM_SIZE-1, &m_vram[0]);
nubus().install_device(slotspace, slotspace+3, read32smo_delegate(*this, FUNC(nubus_vikbw_device::viking_enable_r)), write32smo_delegate(*this, FUNC(nubus_vikbw_device::viking_disable_w)));
nubus().install_device(slotspace+0x80000, slotspace+0x80000+3, read32smo_delegate(*this, FUNC(nubus_vikbw_device::viking_ack_r)), write32smo_delegate(*this, FUNC(nubus_vikbw_device::viking_ack_w)));
-}
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
+ save_item(NAME(m_vbl_disable));
+ save_pointer(NAME(m_vram), VRAM_SIZE / sizeof(u32));
+}
void nubus_vikbw_device::device_reset()
{
m_vbl_disable = 1;
- std::fill(m_vram.begin(), m_vram.end(), 0);
-
- m_palette[0] = rgb_t(255, 255, 255);
- m_palette[1] = rgb_t(0, 0, 0);
+ std::fill_n(&m_vram[0], VRAM_SIZE / sizeof(u32), 0);
}
-/***************************************************************************
-
- Viking 1024x768 B&W card section
-
-***************************************************************************/
-
-uint32_t nubus_vikbw_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
+u32 nubus_vikbw_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
if (!m_vbl_disable)
{
raise_slot_irq();
}
- auto const vram8 = util::big_endian_cast<uint8_t const>(&m_vram[0]);
+ auto const vram8 = util::big_endian_cast<u8 const>(&m_vram[0]);
for (int y = 0; y < 768; y++)
{
- uint32_t *scanline = &bitmap.pix(y);
+ u16 *scanline = &bitmap.pix(y);
for (int x = 0; x < 1024/8; x++)
{
- uint8_t const pixels = vram8[(y * 128) + x];
-
- *scanline++ = m_palette[BIT(pixels, 7)];
- *scanline++ = m_palette[BIT(pixels, 6)];
- *scanline++ = m_palette[BIT(pixels, 5)];
- *scanline++ = m_palette[BIT(pixels, 4)];
- *scanline++ = m_palette[BIT(pixels, 3)];
- *scanline++ = m_palette[BIT(pixels, 2)];
- *scanline++ = m_palette[BIT(pixels, 1)];
- *scanline++ = m_palette[BIT(pixels, 0)];
+ u8 const pixels = vram8[(y * 128) + x];
+
+ *scanline++ = BIT(pixels, 7);
+ *scanline++ = BIT(pixels, 6);
+ *scanline++ = BIT(pixels, 5);
+ *scanline++ = BIT(pixels, 4);
+ *scanline++ = BIT(pixels, 3);
+ *scanline++ = BIT(pixels, 2);
+ *scanline++ = BIT(pixels, 1);
+ *scanline++ = BIT(pixels, 0);
}
}
return 0;
}
-void nubus_vikbw_device::viking_ack_w(uint32_t data)
+void nubus_vikbw_device::viking_ack_w(u32 data)
{
lower_slot_irq();
}
-uint32_t nubus_vikbw_device::viking_ack_r()
+u32 nubus_vikbw_device::viking_ack_r()
{
return 0;
}
-void nubus_vikbw_device::viking_disable_w(uint32_t data)
+void nubus_vikbw_device::viking_disable_w(u32 data)
{
m_vbl_disable = 1;
}
-uint32_t nubus_vikbw_device::viking_enable_r()
+u32 nubus_vikbw_device::viking_enable_r()
{
m_vbl_disable = 0;
return 0;
}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(NUBUS_VIKBW, device_nubus_card_interface, nubus_vikbw_device, "nb_vikbw", "Moniterm MacViking II video card")
diff --git a/src/devices/bus/nubus/nubus_vikbw.h b/src/devices/bus/nubus/nubus_vikbw.h
index 9cd8a0f295a..4e4bc038cc8 100644
--- a/src/devices/bus/nubus/nubus_vikbw.h
+++ b/src/devices/bus/nubus/nubus_vikbw.h
@@ -7,44 +7,6 @@
#include "nubus.h"
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-// ======================> nubus_vikbw_device
-
-class nubus_vikbw_device :
- public device_t,
- public device_nubus_card_interface
-{
-public:
- // construction/destruction
- nubus_vikbw_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- nubus_vikbw_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
-
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
-
- // optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
-
-private:
- uint32_t viking_ack_r();
- void viking_ack_w(uint32_t data);
- uint32_t viking_enable_r();
- void viking_disable_w(uint32_t data);
-
- uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
-
- std::vector<uint32_t> m_vram;
- uint32_t m_vbl_disable, m_palette[2];
-};
-
-// device type definition
-DECLARE_DEVICE_TYPE(NUBUS_VIKBW, nubus_vikbw_device)
+DECLARE_DEVICE_TYPE(NUBUS_VIKBW, device_nubus_card_interface)
#endif // MAME_BUS_NUBUS_VIKBW_H
diff --git a/src/devices/bus/nubus/nubus_wsportrait.cpp b/src/devices/bus/nubus/nubus_wsportrait.cpp
index 41d96442987..77b6b43fda8 100644
--- a/src/devices/bus/nubus/nubus_wsportrait.cpp
+++ b/src/devices/bus/nubus/nubus_wsportrait.cpp
@@ -6,6 +6,11 @@
PCB is marked "Workstation/Portrait Card"
640x870, 1, 2 or 4bpp grayscale
+ Raster parameters, from an archived copy of Apple's spec sheet:
+ Horizontal 68.85 kHz
+ Vertical 75.0 Hz
+ Dot Clock 57.2832 MHz
+
Fs0900e0 = DAC control
Fs0900e4 = DAC data
Fs0A0000 = enable / ack VBL IRQ
@@ -14,89 +19,101 @@
***************************************************************************/
#include "emu.h"
+
#include "nubus_wsportrait.h"
+
+#include "emupal.h"
#include "screen.h"
#include <algorithm>
-#define WSPORTRAIT_SCREEN_NAME "wsport_screen"
-#define WSPORTRAIT_ROM_REGION "wsport_rom"
+namespace {
-#define VRAM_SIZE (0x80000) // 512k max
+static constexpr u32 VRAM_SIZE = 0x80000;
+class nubus_wsportrait_device : public device_t,
+ public device_video_interface,
+ public device_nubus_card_interface
+{
+public:
+ // construction/destruction
+ nubus_wsportrait_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
-ROM_START( wsportrait )
- ROM_REGION(0x1000, WSPORTRAIT_ROM_REGION, 0)
- ROM_LOAD( "341-0732.bin", 0x000000, 0x001000, CRC(ddc35b78) SHA1(ce2bf2374bb994c17962dba8f3d11bc1260e2644) )
-ROM_END
+protected:
+ nubus_wsportrait_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
-//**************************************************************************
-// GLOBAL VARIABLES
-//**************************************************************************
+ TIMER_CALLBACK_MEMBER(vbl_tick);
-DEFINE_DEVICE_TYPE(NUBUS_WSPORTRAIT, nubus_wsportrait_device, "nb_wspt", "Macintosh II Portrait Video Card")
+private:
+ u32 wsportrait_r(offs_t offset, u32 mem_mask = ~0);
+ void wsportrait_w(offs_t offset, u32 data, u32 mem_mask = ~0);
+ u32 vram_r(offs_t offset, u32 mem_mask = ~0);
+ void vram_w(offs_t offset, u32 data, u32 mem_mask = ~0);
+ u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
-//-------------------------------------------------
-// device_add_mconfig - add device configuration
-//-------------------------------------------------
+ required_device<screen_device> m_screen;
+ required_device<palette_device> m_palette;
+
+ std::unique_ptr<u32[]> m_vram;
+ u32 m_mode, m_vbl_disable;
+ u32 m_colors[3], m_count, m_clutoffs;
+ emu_timer *m_timer;
+};
+
+ROM_START( wsportrait )
+ ROM_REGION(0x1000, "declrom", 0)
+ ROM_LOAD( "341-0732.bin", 0x000000, 0x001000, CRC(ddc35b78) SHA1(ce2bf2374bb994c17962dba8f3d11bc1260e2644) )
+ROM_END
void nubus_wsportrait_device::device_add_mconfig(machine_config &config)
{
- screen_device &screen(SCREEN(config, WSPORTRAIT_SCREEN_NAME, SCREEN_TYPE_RASTER));
- screen.set_screen_update(FUNC(nubus_wsportrait_device::screen_update));
- screen.set_size(1024, 960);
- screen.set_refresh_hz(75.0);
- screen.set_visarea(0, 640-1, 0, 870-1);
- screen.set_physical_aspect(3, 4);
-}
+ SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
+ m_screen->set_screen_update(FUNC(nubus_wsportrait_device::screen_update));
+ m_screen->set_raw(57.2832_MHz_XTAL, 832, 0, 640, 918, 0, 832);
+ m_screen->set_physical_aspect(3, 4);
-//-------------------------------------------------
-// rom_region - device-specific ROM region
-//-------------------------------------------------
+ PALETTE(config, m_palette).set_entries(256);
+}
const tiny_rom_entry *nubus_wsportrait_device::device_rom_region() const
{
return ROM_NAME( wsportrait );
}
-//**************************************************************************
-// LIVE DEVICE
-//**************************************************************************
-
-//-------------------------------------------------
-// nubus_wsportrait_device - constructor
-//-------------------------------------------------
-
-nubus_wsportrait_device::nubus_wsportrait_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+nubus_wsportrait_device::nubus_wsportrait_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
nubus_wsportrait_device(mconfig, NUBUS_WSPORTRAIT, tag, owner, clock)
{
}
-nubus_wsportrait_device::nubus_wsportrait_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
+nubus_wsportrait_device::nubus_wsportrait_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock) :
device_t(mconfig, type, tag, owner, clock),
device_video_interface(mconfig, *this),
device_nubus_card_interface(mconfig, *this),
- m_mode(0), m_vbl_disable(0), m_toggle(0), m_count(0), m_clutoffs(0), m_timer(nullptr)
+ m_screen(*this, "screen"),
+ m_palette(*this, "palette"),
+ m_mode(0), m_vbl_disable(0), m_count(0), m_clutoffs(0), m_timer(nullptr)
{
- set_screen(*this, WSPORTRAIT_SCREEN_NAME);
+ set_screen(*this, "screen");
}
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-
void nubus_wsportrait_device::device_start()
{
- uint32_t slotspace;
+ u32 slotspace;
- install_declaration_rom(WSPORTRAIT_ROM_REGION, true);
+ install_declaration_rom("declrom", true);
slotspace = get_slotspace();
-// printf("[wsportrait %p] slotspace = %x\n", (void *)this, slotspace);
-
- m_vram.resize(VRAM_SIZE / sizeof(uint32_t));
+ m_vram = std::make_unique<u32[]>(VRAM_SIZE / sizeof(u32));
nubus().install_device(slotspace, slotspace+VRAM_SIZE-1, read32s_delegate(*this, FUNC(nubus_wsportrait_device::vram_r)), write32s_delegate(*this, FUNC(nubus_wsportrait_device::vram_w)));
nubus().install_device(slotspace+0x900000, slotspace+0x900000+VRAM_SIZE-1, read32s_delegate(*this, FUNC(nubus_wsportrait_device::vram_r)), write32s_delegate(*this, FUNC(nubus_wsportrait_device::vram_w)));
@@ -104,11 +121,14 @@ void nubus_wsportrait_device::device_start()
m_timer = timer_alloc(FUNC(nubus_wsportrait_device::vbl_tick), this);
m_timer->adjust(screen().time_until_pos(869, 0), 0);
-}
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
+ save_item(NAME(m_mode));
+ save_item(NAME(m_vbl_disable));
+ save_item(NAME(m_colors));
+ save_item(NAME(m_count));
+ save_item(NAME(m_clutoffs));
+ save_pointer(NAME(m_vram), VRAM_SIZE / sizeof(u32));
+}
void nubus_wsportrait_device::device_reset()
{
@@ -116,11 +136,9 @@ void nubus_wsportrait_device::device_reset()
m_clutoffs = 0;
m_vbl_disable = 1;
m_mode = 0;
- std::fill(m_vram.begin(), m_vram.end(), 0);
- memset(m_palette, 0, sizeof(m_palette));
+ std::fill_n(&m_vram[0], VRAM_SIZE / sizeof(u32), 0);
}
-
TIMER_CALLBACK_MEMBER(nubus_wsportrait_device::vbl_tick)
{
if (!m_vbl_disable)
@@ -131,65 +149,59 @@ TIMER_CALLBACK_MEMBER(nubus_wsportrait_device::vbl_tick)
m_timer->adjust(screen().time_until_pos(869, 0), 0);
}
-/***************************************************************************
-
- Workstation/Portrait emulation
-
-***************************************************************************/
-
-uint32_t nubus_wsportrait_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
+u32 nubus_wsportrait_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
- // first time? kick off the VBL timer
- auto const vram8 = util::big_endian_cast<uint8_t const>(&m_vram[0]) + 0x80;
+ auto const vram8 = util::big_endian_cast<u8 const>(&m_vram[0]) + 0x80;
+ const pen_t *pens = m_palette->pens();
switch (m_mode)
{
case 0: // 1 bpp?
for (int y = 0; y < 870; y++)
{
- uint32_t *scanline = &bitmap.pix(y);
+ u32 *scanline = &bitmap.pix(y);
for (int x = 0; x < 640/8; x++)
{
- uint8_t const pixels = vram8[(y * 128) + x];
-
- *scanline++ = m_palette[BIT(pixels, 7)];
- *scanline++ = m_palette[BIT(pixels, 6)];
- *scanline++ = m_palette[BIT(pixels, 5)];
- *scanline++ = m_palette[BIT(pixels, 4)];
- *scanline++ = m_palette[BIT(pixels, 3)];
- *scanline++ = m_palette[BIT(pixels, 2)];
- *scanline++ = m_palette[BIT(pixels, 1)];
- *scanline++ = m_palette[BIT(pixels, 0)];
+ u8 const pixels = vram8[(y * 128) + x];
+
+ *scanline++ = pens[BIT(pixels, 7)];
+ *scanline++ = pens[BIT(pixels, 6)];
+ *scanline++ = pens[BIT(pixels, 5)];
+ *scanline++ = pens[BIT(pixels, 4)];
+ *scanline++ = pens[BIT(pixels, 3)];
+ *scanline++ = pens[BIT(pixels, 2)];
+ *scanline++ = pens[BIT(pixels, 1)];
+ *scanline++ = pens[BIT(pixels, 0)];
}
}
break;
case 1: // 2 bpp
- for (int y = 0; y < 480; y++)
+ for (int y = 0; y < 870; y++)
{
- uint32_t *scanline = &bitmap.pix(y);
+ u32 *scanline = &bitmap.pix(y);
for (int x = 0; x < 640/4; x++)
{
- uint8_t const pixels = vram8[(y * 256) + x];
+ u8 const pixels = vram8[(y * 256) + x];
- *scanline++ = m_palette[((pixels>>6)&3)];
- *scanline++ = m_palette[((pixels>>4)&3)];
- *scanline++ = m_palette[((pixels>>2)&3)];
- *scanline++ = m_palette[(pixels&3)];
+ *scanline++ = pens[((pixels>>6)&3)];
+ *scanline++ = pens[((pixels>>4)&3)];
+ *scanline++ = pens[((pixels>>2)&3)];
+ *scanline++ = pens[(pixels&3)];
}
}
break;
case 2: // 4 bpp
- for (int y = 0; y < 480; y++)
+ for (int y = 0; y < 870; y++)
{
- uint32_t *scanline = &bitmap.pix(y);
+ u32 *scanline = &bitmap.pix(y);
for (int x = 0; x < 640/2; x++)
{
- uint8_t const pixels = vram8[(y * 512) + x];
+ u8 const pixels = vram8[(y * 512) + x];
- *scanline++ = m_palette[((pixels&0xf0)>>4)];
- *scanline++ = m_palette[(pixels&0xf)];
+ *scanline++ = pens[((pixels&0xf0)>>4)];
+ *scanline++ = pens[(pixels&0xf)];
}
}
break;
@@ -200,7 +212,7 @@ uint32_t nubus_wsportrait_device::screen_update(screen_device &screen, bitmap_rg
return 0;
}
-void nubus_wsportrait_device::wsportrait_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+void nubus_wsportrait_device::wsportrait_w(offs_t offset, u32 data, u32 mem_mask)
{
data ^= 0xffffffff;
// if (offset != 0x8000) printf("wsportrait: Write %08x @ %x, mask %08x\n", data, offset, mem_mask);
@@ -208,7 +220,6 @@ void nubus_wsportrait_device::wsportrait_w(offs_t offset, uint32_t data, uint32_
switch (offset)
{
case 1: // mode control
-// printf("%08x to mode 1\n", data);
switch (data & 0xff000000)
{
case 0x20000000:
@@ -229,6 +240,7 @@ void nubus_wsportrait_device::wsportrait_w(offs_t offset, uint32_t data, uint32_
case 0x4038: // DAC control
m_clutoffs = (data>>24)&0xff;
+ m_count = 0;
break;
case 0x4039: // DAC data - only 4 bits per component!
@@ -238,8 +250,9 @@ void nubus_wsportrait_device::wsportrait_w(offs_t offset, uint32_t data, uint32_
if (m_count == 3)
{
-// logerror("RAMDAC: color %d = %02x %02x %02x %s\n", m_clutoffs, m_colors[0], m_colors[1], m_colors[2], machine().describe_context());
- m_palette[m_clutoffs] = rgb_t(m_colors[2], m_colors[2], m_colors[2]);
+ m_palette->set_pen_red_level(m_clutoffs, m_colors[2]);
+ m_palette->set_pen_green_level(m_clutoffs, m_colors[2]);
+ m_palette->set_pen_blue_level(m_clutoffs, m_colors[2]);
m_clutoffs++;
if (m_clutoffs > 255)
{
@@ -260,39 +273,27 @@ void nubus_wsportrait_device::wsportrait_w(offs_t offset, uint32_t data, uint32_
}
}
-uint32_t nubus_wsportrait_device::wsportrait_r(offs_t offset, uint32_t mem_mask)
+u32 nubus_wsportrait_device::wsportrait_r(offs_t offset, u32 mem_mask)
{
-// printf("wsportrait: Read @ %x, mask %08x\n", offset, mem_mask);
-
- /*
- monitor types
-
- 0x0 = invalid
- 0x2 = invalid
- 0x4 = color: 640x870 1bpp, 640x480 2bpp and 4bpp
- 0x6 = 1bpp 640x384? and sets weird mode controls
- 0x8 = really odd (bitplaned?)
- 0xa = invalid
- 0xc = 640x480 grayscale
- 0xe = same as 0x6
- */
-
switch (offset)
{
case 0x4004:
- m_toggle ^= 0x00010000;
- return m_toggle | 0xfffc0000; // bit 0 = vbl status, bits 1-3 = monitor type
+ return (m_screen->vblank() << 16) | 0xfffc0000; // bit 16 = vbl status, bits 17-20 = monitor type
}
return 0;
}
-void nubus_wsportrait_device::vram_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+void nubus_wsportrait_device::vram_w(offs_t offset, u32 data, u32 mem_mask)
{
data ^= 0xffffffff;
COMBINE_DATA(&m_vram[offset]);
}
-uint32_t nubus_wsportrait_device::vram_r(offs_t offset, uint32_t mem_mask)
+u32 nubus_wsportrait_device::vram_r(offs_t offset, u32 mem_mask)
{
return m_vram[offset] ^ 0xffffffff;
}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(NUBUS_WSPORTRAIT, device_nubus_card_interface, nubus_wsportrait_device, "nb_wspt", "Macintosh II Portrait Video Card")
diff --git a/src/devices/bus/nubus/nubus_wsportrait.h b/src/devices/bus/nubus/nubus_wsportrait.h
index e25292c792d..3b3546eb721 100644
--- a/src/devices/bus/nubus/nubus_wsportrait.h
+++ b/src/devices/bus/nubus/nubus_wsportrait.h
@@ -7,50 +7,6 @@
#include "nubus.h"
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-// ======================> nubus_wsportrait_device
-
-class nubus_wsportrait_device :
- public device_t,
- public device_video_interface,
- public device_nubus_card_interface
-{
-public:
- // construction/destruction
- nubus_wsportrait_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- nubus_wsportrait_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
-
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
-
- // optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
-
- TIMER_CALLBACK_MEMBER(vbl_tick);
-
-private:
- uint32_t wsportrait_r(offs_t offset, uint32_t mem_mask = ~0);
- void wsportrait_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
- uint32_t vram_r(offs_t offset, uint32_t mem_mask = ~0);
- void vram_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
-
- uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
-
- std::vector<uint32_t> m_vram;
- uint32_t m_mode, m_vbl_disable, m_toggle;
- uint32_t m_palette[256], m_colors[3], m_count, m_clutoffs;
- emu_timer *m_timer;
-};
-
-
-// device type definition
-DECLARE_DEVICE_TYPE(NUBUS_WSPORTRAIT, nubus_wsportrait_device)
+DECLARE_DEVICE_TYPE(NUBUS_WSPORTRAIT, device_nubus_card_interface)
#endif // MAME_BUS_NUBUS_WSPORTRAIT_H
diff --git a/src/devices/bus/nubus/pds30_cb264.cpp b/src/devices/bus/nubus/pds30_cb264.cpp
index c485772c843..692ebc18c51 100644
--- a/src/devices/bus/nubus/pds30_cb264.cpp
+++ b/src/devices/bus/nubus/pds30_cb264.cpp
@@ -28,7 +28,7 @@ ROM_END
// GLOBAL VARIABLES
//**************************************************************************
-DEFINE_DEVICE_TYPE(PDS030_CB264SE30, nubus_cb264se30_device, "pd3_c264", "RasterOps Colorboard 264/SE30")
+DEFINE_DEVICE_TYPE(PDS030_CB264SE30, nubus_cb264se30_device, "pd3_c264", "RasterOps ColorBoard 264/SE30")
//-------------------------------------------------
@@ -39,9 +39,7 @@ void nubus_cb264se30_device::device_add_mconfig(machine_config &config)
{
screen_device &screen(SCREEN(config, CB264SE30_SCREEN_NAME, SCREEN_TYPE_RASTER));
screen.set_screen_update(FUNC(nubus_cb264se30_device::screen_update));
- screen.set_raw(25175000, 800, 0, 640, 525, 0, 480);
- screen.set_size(1024, 768);
- screen.set_visarea(0, 640-1, 0, 480-1);
+ screen.set_raw(30.24_MHz_XTAL, 864, 0, 640, 525, 0, 480);
}
//-------------------------------------------------
diff --git a/src/devices/bus/nubus/thunder4gx.cpp b/src/devices/bus/nubus/thunder4gx.cpp
new file mode 100644
index 00000000000..0d092d1707d
--- /dev/null
+++ b/src/devices/bus/nubus/thunder4gx.cpp
@@ -0,0 +1,807 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+/***************************************************************************
+
+ Radius Thunder IV GX video card emulation
+
+ NuBus video card, 1/4/8/24 bit color, works up to at least MacOS 9.1.
+ Emulation by R. Belmont, with hat tips to Vas Crabb and Al Kossow.
+
+ This is Radius branded, but it was released shortly after the Radius/SuperMac
+ merger and the hardware is distinctly SuperMac flavored. So it's likely a
+ finished/near finished SuperMac design that was just rebranded. The accelerator
+ registers look a lot like an evolved version of the blitter in the Spectrum PDQ,
+ and the CRTC is similar to the SuperMac CRTC in nubus/supermac.cpp.
+
+ Usage:
+ - Hold down "T" when the Radius screen appears after the beep, and keep it
+ held down until you see the video mode you want. Many more options are
+ available if you install RadiusWare 3.4.1 (earlier versions may not
+ support this card).
+ - Do NOT enable acceleration in RadiusWare, however. The emulation isn't there yet.
+
+ TODO:
+ - Monitor sensing (working for standard Apple monitors, but there are others)
+ - Sub-model sensing (We're IDing as the 1366, the 1600 is the top-end model)
+ - Acceleration/blitter (it's part-way there but not fully)
+ - Photoshop acceleration DSPs. These didn't work past MacOS 7.6 on hardware
+ and the PPC-native version of Photoshop was as fast for cheaper, but it'd
+ still be fun.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "thunder4gx.h"
+
+#include "emupal.h"
+#include "screen.h"
+
+#define LOG_BLITTER (1U << 1)
+#define LOG_CLOCKGEN (1U << 2)
+#define LOG_MONSENSE (1U << 3)
+#define LOG_RAMDAC (1U << 4)
+
+#define VERBOSE (0)
+#include "logmacro.h"
+
+namespace {
+
+static constexpr u32 VRAM_SIZE = 0x600000;
+
+class nubus_thunder4gx_device : public device_t,
+ public device_nubus_card_interface
+{
+public:
+ // construction/destruction
+ nubus_thunder4gx_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ nubus_thunder4gx_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
+ required_device<screen_device> m_screen;
+ required_device<palette_device> m_palette;
+ required_ioport m_monitor_config;
+
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual ioport_constructor device_input_ports() const override;
+
+ u32 registers_r(offs_t offset, u32 mem_mask);
+ void registers_w(offs_t offset, u32 data, u32 mem_mask);
+ u32 ramdac_r(offs_t offset, u32 mem_mask);
+ void ramdac_w(offs_t offset, u32 data, u32 mem_mask);
+ u32 accel_r(offs_t offset, u32 mem_mask);
+ void accel_w(offs_t offset, u32 data, u32 mem_mask);
+ void clockgen_w(offs_t offset, u32 data, u32 mem_mask);
+
+private:
+ u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
+ void vblank_w(int state);
+
+ std::unique_ptr<u32[]> m_vram;
+ u32 m_mode, m_irq_control;
+ u32 m_pal_idx, m_pal_address;
+ u32 m_hres, m_vres, m_stride, m_htotal, m_vtotal;
+ u32 m_display_enable;
+ u32 m_pixel_clock;
+ u32 m_crtc[12];
+ u32 m_accel_regs[0x2000/4];
+ u32 m_monitor_id;
+
+ u32 m_blitter_dest_address, m_blitter_src_address, m_blitter_param1, m_blitter_param2, m_blitter_small_pattern, m_blitter_mask;
+ u32 m_blitter_medium_pattern[16];
+ u32 m_blitter_large_pattern[64];
+};
+
+ROM_START( thundergx )
+ ROM_REGION(0x10000, "declrom", 0)
+ ROM_LOAD("radius thunder gx v1.2.3.rom", 0x000000, 0x010000, CRC(b8e035b6) SHA1(c5a1eab749b76aaf3e0ede2120fa99dd7f720196))
+ROM_END
+
+static constexpr u8 ext(u8 bc, u8 ac, u8 ab)
+{
+ return 0x40 | (bc << 4) | (ac << 2) | ab;
+}
+
+static constexpr u8 ext6(u8 bc, u8 ac, u8 ab)
+{
+ return 0xc0 | (bc << 4) | (ac << 2) | ab;
+}
+
+static INPUT_PORTS_START(monitor_config)
+ PORT_START("monitor")
+ PORT_CONFNAME(0x1ff, ext6(0, 2, 3), "Monitor type")
+ PORT_CONFSETTING(0x00, u8"Mac 21\" Color Display (1152\u00d7870)") // "RGB 2 Page" or "Kong"
+ PORT_CONFSETTING(0x01, u8"Mac Portrait Display (B&W 15\" 640\u00d7870)") // "Full Page" or "Portrait"
+ PORT_CONFSETTING(0x02, u8"Mac RGB Display (12\" 512\u00d7384)") // "Rubik" (modified IIgs AppleColor RGB)
+ PORT_CONFSETTING(0x03, u8"Mac Two-Page Display (B&W 21\" 1152\u00d7870)") // "2 Page"
+ PORT_CONFSETTING(0x06, u8"Mac Hi-Res Display (12-14\" 640\u00d7480)") // "High Res"
+ PORT_CONFSETTING(ext(1, 1, 3), "640\u00d7480 VGA")
+ PORT_CONFSETTING(ext(2, 3, 1), "832\u00d7624 16\" RGB") // "Goldfish" or "16 inch RGB"
+ PORT_CONFSETTING(ext(3, 2, 2), "1024x\u00d7768 19\" RGB")
+ PORT_CONFSETTING(ext6(0, 0, 3), "Multiple Scan 14\"")
+ PORT_CONFSETTING(ext6(0, 2, 3), "Multiple Scan 16\"")
+ PORT_CONFSETTING(ext6(2, 0, 3), "Multiple Scan 21\"")
+INPUT_PORTS_END
+
+void nubus_thunder4gx_device::device_add_mconfig(machine_config &config)
+{
+ SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
+ m_screen->set_screen_update(FUNC(nubus_thunder4gx_device::screen_update));
+ m_screen->set_size(1600, 1200);
+ m_screen->set_visarea(0, 1152 - 1, 0, 870 - 1);
+ m_screen->set_refresh_hz(60);
+ m_screen->screen_vblank().set(FUNC(nubus_thunder4gx_device::vblank_w));
+
+ PALETTE(config, m_palette).set_entries(256);
+}
+
+const tiny_rom_entry *nubus_thunder4gx_device::device_rom_region() const
+{
+ return ROM_NAME( thundergx );
+}
+
+ioport_constructor nubus_thunder4gx_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(monitor_config);
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+nubus_thunder4gx_device::nubus_thunder4gx_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ nubus_thunder4gx_device(mconfig, NUBUS_THUNDERIVGX, tag, owner, clock)
+{
+}
+
+nubus_thunder4gx_device::nubus_thunder4gx_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock) :
+ device_t(mconfig, type, tag, owner, clock),
+ device_nubus_card_interface(mconfig, *this),
+ m_screen(*this, "screen"),
+ m_palette(*this, "palette"),
+ m_monitor_config(*this, "monitor"),
+ m_mode(0), m_irq_control(0), m_pal_idx(0), m_pal_address(0),
+ m_hres(0), m_vres(0), m_stride(128), m_htotal(0), m_vtotal(0),
+ m_display_enable(0), m_pixel_clock(30282182), m_monitor_id(0xffff),
+ m_blitter_dest_address(0), m_blitter_src_address(0), m_blitter_param1(0),
+ m_blitter_param2(0), m_blitter_small_pattern(0), m_blitter_mask(0)
+{
+ std::fill(std::begin(m_crtc), std::end(m_crtc), 0);
+ std::fill(std::begin(m_blitter_medium_pattern), std::end(m_blitter_medium_pattern), 0);
+ std::fill(std::begin(m_blitter_large_pattern), std::end(m_blitter_large_pattern), 0);}
+
+void nubus_thunder4gx_device::device_start()
+{
+ const u32 slotspace = get_slotspace();
+
+ install_declaration_rom("declrom");
+
+ m_vram = std::make_unique<u32[]>(VRAM_SIZE);
+
+ save_item(NAME(m_mode));
+ save_item(NAME(m_irq_control));
+ save_item(NAME(m_pal_idx));
+ save_item(NAME(m_pal_address));
+ save_item(NAME(m_stride));
+ save_item(NAME(m_hres));
+ save_item(NAME(m_vres));
+ save_item(NAME(m_htotal));
+ save_item(NAME(m_vtotal));
+ save_item(NAME(m_pixel_clock));
+ save_item(NAME(m_display_enable));
+ save_pointer(NAME(m_vram), VRAM_SIZE);
+
+ install_bank(slotspace, slotspace+VRAM_SIZE-1, &m_vram[0]);
+
+ nubus().install_writeonly_device(slotspace+0xc00000, slotspace+0xc0000f, emu::rw_delegate(*this, FUNC(nubus_thunder4gx_device::clockgen_w)));
+ nubus().install_device(slotspace+0xc40000, slotspace+0xc8ffff, emu::rw_delegate(*this, FUNC(nubus_thunder4gx_device::registers_r)), emu::rw_delegate(*this, FUNC(nubus_thunder4gx_device::registers_w)));
+ nubus().install_device(slotspace+0xcc0000, slotspace+0xcc1fff, emu::rw_delegate(*this, FUNC(nubus_thunder4gx_device::accel_r)), emu::rw_delegate(*this, FUNC(nubus_thunder4gx_device::accel_w)));
+ nubus().install_device(slotspace+0xd00000, slotspace+0xd000ff, emu::rw_delegate(*this, FUNC(nubus_thunder4gx_device::ramdac_r)), emu::rw_delegate(*this, FUNC(nubus_thunder4gx_device::ramdac_w)));
+}
+
+void nubus_thunder4gx_device::device_reset()
+{
+ m_pal_idx = 0;
+ m_pal_address = 0;
+ m_irq_control = 0;
+ m_mode = 0;
+ m_display_enable = 0;
+}
+
+u32 nubus_thunder4gx_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
+{
+ auto const vram8 = util::big_endian_cast<u8 const>(&m_vram[0]);
+ const pen_t *pens = m_palette->pens();
+
+ if ((m_display_enable != 0xffff) || (m_hres == 0) || (m_vres == 0))
+ {
+ return 0;
+ }
+
+ switch (m_mode)
+ {
+ case 0: // 1bpp
+ for (int y = 0; y < m_vres; y++)
+ {
+ u32 *scanline = &bitmap.pix(y);
+ for (int x = 0; x < m_hres/8; x++)
+ {
+ u8 const pixels = vram8[(y * m_stride) + x];
+
+ *scanline++ = pens[pixels&0x80];
+ *scanline++ = pens[(pixels<<1)&0x80];
+ *scanline++ = pens[(pixels<<2)&0x80];
+ *scanline++ = pens[(pixels<<3)&0x80];
+ *scanline++ = pens[(pixels<<4)&0x80];
+ *scanline++ = pens[(pixels<<5)&0x80];
+ *scanline++ = pens[(pixels<<6)&0x80];
+ *scanline++ = pens[(pixels<<7)&0x80];
+ }
+ }
+ break;
+
+ case 2: // 4bpp
+ for (int y = 0; y < m_vres; y++)
+ {
+ u32 *scanline = &bitmap.pix(y);
+ for (int x = 0; x < m_hres/2; x++)
+ {
+ u8 const pixels = vram8[(y * m_stride) + x];
+
+ *scanline++ = pens[((pixels << 0) & 0xf0)];
+ *scanline++ = pens[((pixels << 4) & 0xf0)];
+ }
+ }
+ break;
+
+ case 3: // 8bpp
+ for (int y = 0; y < m_vres; y++)
+ {
+ u32 *scanline = &bitmap.pix(y);
+ for (int x = 0; x < m_hres; x++)
+ {
+ u8 const pixels = vram8[(y * m_stride) + x];
+
+ *scanline++ = pens[pixels];
+ }
+ }
+ break;
+
+ case 6: // 16bpp x555
+ for (int y = 0; y < m_vres; y++)
+ {
+ u32 *scanline = &bitmap.pix(y);
+ for (int x = 0; x < m_hres; x++)
+ {
+ u16 const pixels = (vram8[(y * m_stride) + (x << 1)] << 8) | vram8[(y * m_stride) + (x << 1) + 1];
+ *scanline++ = rgb_t(((pixels >> 10) & 0x1f) << 3, ((pixels >> 5) & 0x1f) << 3, (pixels & 0x1f) << 3);
+ }
+ }
+ break;
+
+ case 7: // 24bpp (arranged as 32 bits, so there's a wasted byte per pixel)
+ for (int y = 0; y < m_vres; y++)
+ {
+ u32 *scanline = &bitmap.pix(y);
+ u32 const *base = &m_vram[(y * (m_stride >> 2))];
+ for (int x = 0; x < m_hres; x++)
+ {
+ *scanline++ = *base++;
+ }
+ }
+ break;
+ }
+
+ return 0;
+}
+
+void nubus_thunder4gx_device::vblank_w(int state)
+{
+ if ((state) && (BIT(m_irq_control, 1)))
+ {
+ raise_slot_irq();
+ }
+}
+
+u32 nubus_thunder4gx_device::registers_r(offs_t offset, u32 mem_mask)
+{
+ switch (offset)
+ {
+ case 0:
+ return 0x6;
+
+ // bit 16 = accelerator ready flag (or active-low busy)
+ // bit 17 = vblank
+ case 1:
+ return m_screen->vblank() ? 0x30000 : 0x10000;
+
+ case 2:
+ return m_irq_control;
+
+ case 3: // IRQ routine reads this immediately after writing to ack the IRQ (or does reading this ack it?)
+ return 0;
+
+ case 9:
+ // 0a0028 = RadiusColor Twin
+ return 0x0a0028;
+
+ case 0x10000: // mode
+ return m_mode;
+
+ case 0x10002: // monitor sense
+ {
+ u8 mon = m_monitor_config->read();
+ u8 monitor_id = ((m_monitor_id >> 2) ^ 7) & 0x7;
+ u8 res;
+ if (mon & 0x40)
+ {
+ res = 7;
+
+ if (mon & 0x80)
+ {
+ res = 6;
+ }
+
+ if (monitor_id == 0x4)
+ {
+ res &= 4 | (BIT(mon, 5) << 1) | BIT(mon, 4);
+ }
+ if (monitor_id == 0x2)
+ {
+ res &= (BIT(mon, 3) << 2) | 2 | BIT(mon, 2);
+ }
+ if (monitor_id == 0x1)
+ {
+ res &= (BIT(mon, 1) << 2) | (BIT(mon, 0) << 1) | 1;
+ }
+ }
+ else
+ {
+ res = mon;
+ }
+
+ LOGMASKED(LOG_MONSENSE, "Sense result = %x\n", res);
+ return (res << 2) | 0x3;
+ }
+
+ default:
+ LOGMASKED(LOG_GENERAL, "Read @ C4xxxx %08x mask %08x\n", offset, mem_mask);
+ break;
+ }
+ return 0;
+}
+
+void nubus_thunder4gx_device::registers_w(offs_t offset, u32 data, u32 mem_mask)
+{
+ data &= mem_mask;
+ switch (offset)
+ {
+ case 1:
+ if (data & 2)
+ {
+ lower_slot_irq();
+ }
+ break;
+
+ case 2:
+ m_irq_control = data;
+ break;
+
+ case 9:
+ LOGMASKED(LOG_MONSENSE, "Write %08x to extended sense, mask %08x\n", data, mem_mask);
+ break;
+
+ case 0x10000:
+ m_mode = data & 0xf;
+ LOGMASKED(LOG_GENERAL, "%x to mode\n", data);
+ break;
+
+ case 0x10002:
+ LOGMASKED(LOG_MONSENSE, "%x to monitor drive\n", data);
+ m_monitor_id = data;
+ break;
+
+ case 0x10005: case 0x10006: case 0x10007: case 0x10008: case 0x10009: case 0x1000a:
+ case 0x1000b: case 0x1000c: case 0x1000d: case 0x1000e: case 0x1000f:
+ m_crtc[offset - 0x10005] = data & mem_mask;
+ LOGMASKED(LOG_GENERAL, "%04x to CRTC @ %x (%x)\n", data & mem_mask, offset, offset - 0x10005);
+ break;
+
+ default:
+ LOGMASKED(LOG_GENERAL, "%s Write @ C4xxxx: %x to reg %x (mask %x)\n", machine().describe_context(), data & mem_mask, offset, mem_mask);
+ break;
+ }
+}
+
+u32 nubus_thunder4gx_device::ramdac_r(offs_t offset, u32 mem_mask)
+{
+ LOGMASKED(LOG_RAMDAC, "%s: Read DAC @ %08x (mask %08x)\n", machine().describe_context(), offset, mem_mask);
+
+ return 0;
+}
+
+void nubus_thunder4gx_device::ramdac_w(offs_t offset, u32 data, u32 mem_mask)
+{
+ LOGMASKED(LOG_RAMDAC, "%s: %x to DAC at %x\n", machine().describe_context(), data & mem_mask, offset);
+ switch (offset)
+ {
+ case 0:
+ m_pal_address = (data&0xff);
+ m_pal_idx = 0;
+ break;
+
+ case 1:
+ switch (m_pal_idx)
+ {
+ case 0:
+ m_palette->set_pen_red_level(m_pal_address, ((data>>2) & 0xff));
+ break;
+
+ case 1:
+ m_palette->set_pen_green_level(m_pal_address, ((data >> 2) & 0xff));
+ break;
+
+ case 2:
+ m_palette->set_pen_blue_level(m_pal_address, ((data >> 2) & 0xff));
+ break;
+ }
+
+ m_pal_idx++;
+ if (m_pal_idx == 3)
+ {
+ m_pal_address++;
+ m_pal_idx = 0;
+ }
+ break;
+
+ case 2:
+ m_display_enable = data & mem_mask;
+ LOGMASKED(LOG_GENERAL, "%x to display enable\n", m_display_enable);
+ break;
+
+ default:
+ LOGMASKED(LOG_GENERAL, "%08x to DAC @ %x\n", data & mem_mask, offset);
+ break;
+ }
+}
+
+u32 nubus_thunder4gx_device::accel_r(offs_t offset, u32 mem_mask)
+{
+ LOGMASKED(LOG_BLITTER, "Read accelerator @ %08x (mask %08x)\n", offset, mem_mask);
+
+ return m_accel_regs[offset];
+}
+
+void nubus_thunder4gx_device::accel_w(offs_t offset, u32 data, u32 mem_mask)
+{
+ data &= mem_mask;
+
+ switch (offset)
+ {
+ case 2:
+ LOGMASKED(LOG_GENERAL, "%d to stride\n", data);
+ m_stride = data;
+ break;
+
+ case 0x41: // command
+ // 0x1201 is a small pattern fill from the 4 byte pattern in register 0x47
+ // 0x1401 is a medium pattern fill from the 64 bytes of pattern data in registers 0x80-0x8f
+ // 0x1045 is a large pattern fill from the 256 bytes of pattern data in registers 0x100-0x13f
+ // 0x1002 is a copy from the source VRAM address in register 0x42 to the destination VRAM address in register 0x43
+
+ LOGMASKED(LOG_BLITTER, "Blitter opcode %04x\n", data);
+
+ // The blitter is only used in 8, 16, and 32 bpp modes. 1/2/4 bpp are unaccelerated.
+ assert(m_mode >= 3);
+ switch (data)
+ {
+ case 0x1002: // VRAM to VRAM copy
+ switch (m_mode)
+ {
+ case 3: // 8 bpp
+ {
+ u32 vram_src = (m_blitter_src_address & 0x7fffff);
+ u32 vram_dest = (m_blitter_dest_address & 0x7fffff);
+ const u16 width = m_blitter_param1 & 0xffff;
+ const u16 height = m_blitter_param1 >> 16;
+ u8 *vram8 = (u8 *)&m_vram[0];
+ for (int y = 0; y < height; y++)
+ {
+ for (int x = 0; x < width; x++)
+ {
+ vram8[BYTE4_XOR_BE(vram_dest + x)] = vram8[BYTE4_XOR_BE(vram_src + x)];
+ }
+ vram_src += m_stride;
+ vram_dest += m_stride;
+ }
+ }
+ break;
+
+ case 5: // 16 bpp
+ {
+ u32 vram_src = (m_blitter_src_address & 0x7fffff) >> 1;
+ u32 vram_dest = (m_blitter_dest_address & 0x7fffff) >> 1;
+ const u16 width = m_blitter_param1 & 0xffff;
+ const u16 height = m_blitter_param1 >> 16;
+ u16 *vram16 = (u16 *)&m_vram[0];
+ for (int y = 0; y < height; y++)
+ {
+ for (int x = 0; x < width; x++)
+ {
+ vram16[WORD_XOR_BE(vram_dest + x)] = vram16[WORD_XOR_BE(vram_src + x)];
+ }
+ vram_src += (m_stride >> 1);
+ vram_dest += (m_stride >> 1);
+ }
+ }
+ break;
+
+ case 6: // 32 bpp
+ {
+ u32 vram_src = (m_blitter_src_address & 0x7fffff) >> 2;
+ u32 vram_dest = (m_blitter_dest_address & 0x7fffff) >> 2;
+ const u16 width = m_blitter_param1 & 0xffff;
+ const u16 height = m_blitter_param1 >> 16;
+ for (int y = 0; y < height; y++)
+ {
+ for (int x = 0; x < width; x++)
+ {
+ m_vram[vram_dest + x] = m_vram[vram_src + x];
+ }
+ vram_src += (m_stride >> 2);
+ vram_dest += (m_stride >> 2);
+ }
+ }
+ break;
+ }
+ break;
+
+ case 0x1201:
+ switch (m_mode)
+ {
+ case 3: // 8 bpp
+ {
+ u32 vram_offs = (m_blitter_dest_address & 0x7fffff);
+ const u16 width = m_blitter_param1 & 0xffff;
+ const u16 height = m_blitter_param1 >> 16;
+ u8 *vram8 = (u8 *)&m_vram[0];
+ u8 const *const pattern8 = (u8 *)&m_blitter_small_pattern; // FIXME: endianness
+
+ for (int y = 0; y < height; y++)
+ {
+ for (int x = 0; x < width; x++)
+ {
+ vram8[BYTE4_XOR_BE(vram_offs + x)] = pattern8[x % 3]; // is this relative to the start or is the pattern fixed?
+ }
+ vram_offs += m_stride;
+ }
+ }
+ break;
+
+ case 5: // 16 bpp
+ {
+ u32 vram_offs = (m_blitter_dest_address & 0x7fffff) >> 1;
+ const u16 width = m_blitter_param1 & 0xffff;
+ const u16 height = m_blitter_param1 >> 16;
+ u16 *vram16 = (u16 *)&m_vram[0];
+ u16 const *const pattern16 = (u16 *)&m_blitter_small_pattern; // FIXME: endianness
+
+ for (int y = 0; y < height; y++)
+ {
+ for (int x = 0; x < width; x++)
+ {
+ vram16[WORD_XOR_BE(vram_offs + x)] = pattern16[x & 1];
+ }
+ vram_offs += (m_stride >> 1);
+ }
+ }
+ break;
+
+ case 6: // 32 bpp
+ {
+ u32 vram_offs = (m_blitter_dest_address & 0x7fffff) >> 2;
+ const u16 width = m_blitter_param1 & 0xffff;
+ const u16 height = m_blitter_param1 >> 16;
+ for (int y = 0; y < height; y++)
+ {
+ for (int x = 0; x < width; x++)
+ {
+ m_vram[vram_offs + x] = m_blitter_small_pattern;
+ }
+ vram_offs += (m_stride >> 2);
+ }
+ }
+ break;
+ }
+ break;
+
+ case 0x1401:
+ switch (m_mode)
+ {
+ case 3: // 8 bpp
+ {
+ u32 vram_offs = (m_blitter_dest_address & 0x7fffff);
+ const u16 width = (m_blitter_param1 & 0xffff);
+ const u16 height = m_blitter_param1 >> 16;
+ u16 pat_width = (m_blitter_param2 & 0xff);
+ u16 pat_height = (m_blitter_param2 >> 8) & 0xff;
+ u8 *vram8 = (u8 *)&m_vram[0];
+ u8 const *const pattern8 = (u8 *)&m_blitter_medium_pattern; // FIXME: endianness
+
+ if (pat_width == 0)
+ {
+ pat_width = (m_blitter_param2 >> 16) & 0xff;
+ }
+
+ if (pat_height == 0)
+ {
+ pat_height = (m_blitter_param2 >> 24) & 0xff;
+ }
+
+ // is this some kind of indirection or protection or something?
+ if (pat_width == 0)
+ {
+ pat_width = pat_height = 8;
+ }
+
+ LOGMASKED(LOG_BLITTER, "Medium pattern fill 8: offs %08x width %d height %d pat width %d pat height %d\n", vram_offs, width, height, pat_width, pat_height);
+ for (int y = 0; y < height; y++)
+ {
+ const int pat_offs = (y % pat_height) * pat_width;
+ LOGMASKED(LOG_BLITTER, "Line %d vram offs %08x pattern offs %d\n", y, vram_offs, pat_offs % (16 * 4));
+ for (int x = 0; x < width; x++)
+ {
+ vram8[BYTE4_XOR_BE(vram_offs + x)] = pattern8[(pat_offs + (x % pat_width)) % (16 * 4)];
+ }
+ vram_offs += m_stride;
+ }
+ }
+ break;
+
+ case 5: // 16 bpp
+ {
+ u32 vram_offs = (m_blitter_dest_address & 0x7fffff)>>1;
+ const u16 width = (m_blitter_param1 & 0xffff);
+ const u16 height = m_blitter_param1 >> 16;
+ const u16 pat_width = (m_blitter_param2 & 0xff);
+ const u16 pat_height = (m_blitter_param2 >> 8) & 0xff;
+ u16 *vram16 = (u16 *)&m_vram[0];
+ u16 const *const pattern16 = (u16 *)&m_blitter_medium_pattern; // FIXME: endianness
+
+ LOGMASKED(LOG_BLITTER, "Medium pattern fill 16: offs %08x width %d height %d pat width %d pat height %d\n", vram_offs, width, height, pat_width, pat_height);
+ for (int y = 0; y < height; y++)
+ {
+ const int pat_offs = (y % pat_height) * pat_width;
+ LOGMASKED(LOG_BLITTER, "Line %d vram offs %08x pattern offs %d\n", y, vram_offs, pat_offs % (16 * 2));
+ for (int x = 0; x < width; x++)
+ {
+ vram16[WORD_XOR_BE(vram_offs + x)] = pattern16[(pat_offs + (x % pat_width)) % (16 * 2)];
+ }
+ vram_offs += m_stride;
+ }
+ }
+ break;
+
+ case 6: // 32 bpp
+ {
+ u32 vram_offs = (m_blitter_dest_address & 0x7fffff) >> 2; // convert address to offset in 32-bit words
+ const u16 width = (m_blitter_param1 & 0xffff) >> 2;
+ const u16 height = m_blitter_param1 >> 16;
+ const u16 pat_width = (m_blitter_param2 & 0xff) >> 2;
+ const u16 pat_height = (m_blitter_param2 >> 8) & 0xff;
+ LOGMASKED(LOG_BLITTER, "Medium pattern fill 32: offs %08x width %d height %d pat width %d pat height %d\n", vram_offs, width, height, pat_width, pat_height);
+ for (int y = 0; y < height; y++)
+ {
+ const int pat_offs = (y % pat_height) * pat_width;
+ LOGMASKED(LOG_BLITTER, "Line %d vram offs %08x pattern offs %d\n", y, vram_offs, pat_offs);
+ for (int x = 0; x < width; x++)
+ {
+ m_vram[vram_offs + x] = m_blitter_medium_pattern[(pat_offs + (x % pat_width)) % 16];
+ }
+ vram_offs += (m_stride >> 2);
+ }
+ }
+ break;
+ }
+ break;
+ }
+ break;
+
+ case 0x42: // physical source VRAM address (does this mean the card can accelerate cards in other slots?)
+ LOGMASKED(LOG_BLITTER, "%08x to blitter source\n", data);
+ m_blitter_src_address = data;
+ break;
+
+ case 0x43: // physical destination VRAM address (does this mean the card can accelerate cards in other slots?)
+ LOGMASKED(LOG_BLITTER, "%08x to blitter destination\n", data);
+ m_blitter_dest_address = data;
+ break;
+
+ case 0x44: // Blitter parameter 1
+ LOGMASKED(LOG_BLITTER, "%08x to blitter param 1 (mask %08x)\n", data, mem_mask);
+ m_blitter_param1 = data;
+ break;
+
+ case 0x45: // Blitter parameter 2
+ LOGMASKED(LOG_BLITTER, "%08x to blitter param 2 (mask %08x)\n", data, mem_mask);
+ m_blitter_param2 = data;
+ break;
+
+ case 0x49: // Small blitter pattern
+ LOGMASKED(LOG_BLITTER, "%08x to small pattern\n", data);
+ m_blitter_small_pattern = data;
+ break;
+
+ case 0x48: // Blitter mask?
+ LOGMASKED(LOG_BLITTER, "%08x to mask?\n", data);
+ m_blitter_mask = data;
+ break;
+
+ case 0x80: case 0x81: case 0x82: case 0x83: case 0x84: case 0x85: case 0x86: case 0x87:
+ case 0x88: case 0x89: case 0x8a: case 0x8b: case 0x8c: case 0x8d: case 0x8e: case 0x8f:
+ LOGMASKED(LOG_BLITTER, "%08x to medium pattern @ %x\n", data, offset & 0xf);
+ m_blitter_medium_pattern[offset & 0xf] = data;
+ break;
+
+ case 0x100: case 0x101: case 0x102: case 0x103: case 0x104: case 0x105: case 0x106: case 0x107:
+ case 0x108: case 0x109: case 0x10a: case 0x10b: case 0x10c: case 0x10d: case 0x10e: case 0x10f:
+ case 0x110: case 0x111: case 0x112: case 0x113: case 0x114: case 0x115: case 0x116: case 0x117:
+ case 0x118: case 0x119: case 0x11a: case 0x11b: case 0x11c: case 0x11d: case 0x11e: case 0x11f:
+ case 0x120: case 0x121: case 0x122: case 0x123: case 0x124: case 0x125: case 0x126: case 0x127:
+ case 0x128: case 0x129: case 0x12a: case 0x12b: case 0x12c: case 0x12d: case 0x12e: case 0x12f:
+ case 0x130: case 0x131: case 0x132: case 0x133: case 0x134: case 0x135: case 0x136: case 0x137:
+ case 0x138: case 0x139: case 0x13a: case 0x13b: case 0x13c: case 0x13d: case 0x13e: case 0x13f:
+ LOGMASKED(LOG_BLITTER, "%08x to large pattern @ %x\n", data, offset - 0x100);
+ m_blitter_large_pattern[offset - 0x100] = data;
+ break;
+
+ default:
+ LOGMASKED(LOG_BLITTER, "%s: %08x to blitter @ %08x (mask %08x)\n", machine().describe_context(), data, offset, mem_mask);
+ break;
+ }
+
+ m_accel_regs[offset] = data;
+}
+
+// IC Designs ICD2062B frequency synthesizer frontend.
+// The chip has an I2C-style CLK/DATA 2 wire serial interface, but on this card
+// you just write all 21 bits as a longword and the ASIC does it for you.
+void nubus_thunder4gx_device::clockgen_w(offs_t offset, u32 data, u32 mem_mask)
+{
+ const int irange = (data >> 17) & 0xf;
+ const int p = ((data >> 10) & 0x7f) + 3;
+ const int mux = (data >> 7) & 0x7;
+ const int q = (data & 0x7f) + 2;
+
+ LOGMASKED(LOG_CLOCKGEN, "I %d P %d Mux %d Q %d\n", irange, p, mux, q);
+
+ double result = 2.0f * 14.3181818f * (double)p;
+ result /= (double)q;
+ result /= (double)(1 << mux);
+ m_pixel_clock = (int)(result * 1000000 + .5);
+ LOGMASKED(LOG_CLOCKGEN, "result %f, pixel clock %d\n", result, m_pixel_clock);
+
+ m_hres = (m_crtc[2] - m_crtc[1]) << 2;
+ m_vres = (m_crtc[7] - m_crtc[6]);
+ m_htotal = m_crtc[3] << 2;
+ m_vtotal = m_crtc[8];
+
+ if ((m_hres > 0) && (m_vres > 0))
+ {
+ const double refresh = (double)m_pixel_clock / (double)(m_htotal * m_vtotal);
+ LOGMASKED(LOG_CLOCKGEN, "hres %d vres %d htotal %d vtotal %d refresh %f stride %d mode %d\n", m_hres, m_vres, m_htotal, m_vtotal, refresh, m_stride, m_mode);
+
+ rectangle visarea(0, m_hres - 1, 0, m_vres - 1);
+ m_screen->configure(m_htotal, m_vtotal, visarea, attotime::from_ticks(m_htotal * m_vtotal, m_pixel_clock).as_attoseconds());
+ }
+}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(NUBUS_THUNDERIVGX, device_nubus_card_interface, nubus_thunder4gx_device, "nb_thungx", "Radius Thunder IV GX video card")
diff --git a/src/devices/bus/nubus/thunder4gx.h b/src/devices/bus/nubus/thunder4gx.h
new file mode 100644
index 00000000000..625238c0907
--- /dev/null
+++ b/src/devices/bus/nubus/thunder4gx.h
@@ -0,0 +1,12 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+#ifndef MAME_BUS_NUBUS_THUNDER_4_GX_H
+#define MAME_BUS_NUBUS_THUNDER_4_GX_H
+
+#pragma once
+
+#include "nubus.h"
+
+DECLARE_DEVICE_TYPE(NUBUS_THUNDERIVGX, device_nubus_card_interface)
+
+#endif // MAME_BUS_NUBUS_THUNDER_4_GX_H
diff --git a/src/devices/bus/odyssey2/4in1.cpp b/src/devices/bus/odyssey2/4in1.cpp
index c0c3788a05e..30f10d1d1bf 100644
--- a/src/devices/bus/odyssey2/4in1.cpp
+++ b/src/devices/bus/odyssey2/4in1.cpp
@@ -15,13 +15,34 @@ Used in:
#include "emu.h"
#include "4in1.h"
-DEFINE_DEVICE_TYPE(O2_ROM_4IN1, o2_4in1_device, "o2_4in1", "Videopac 40 Cartridge")
-
+namespace {
//-------------------------------------------------
-// o2_4in1_device - constructor
+// initialization
//-------------------------------------------------
+class o2_4in1_device : public device_t, public device_o2_cart_interface
+{
+public:
+ o2_4in1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual void device_start() override;
+
+ virtual void cart_init() override;
+
+ virtual u8 read_rom04(offs_t offset) override { return m_rom[offset + 0x400]; }
+ virtual u8 read_rom0c(offs_t offset) override { return m_rom[offset + 0xc00]; }
+
+ virtual void write_p1(u8 data) override { m_control = data; }
+ virtual void write_p2(u8 data) override { m_bank = data; }
+ virtual u8 io_read(offs_t offset) override;
+
+private:
+ u8 m_control = 0;
+ u8 m_bank = 0;
+};
+
o2_4in1_device::o2_4in1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
device_t(mconfig, O2_ROM_4IN1, tag, owner, clock),
device_o2_cart_interface(mconfig, *this)
@@ -51,3 +72,8 @@ u8 o2_4in1_device::io_read(offs_t offset)
else
return 0xff;
}
+
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(O2_ROM_4IN1, device_o2_cart_interface, o2_4in1_device, "o2_4in1", "Videopac 40 Cartridge")
diff --git a/src/devices/bus/odyssey2/4in1.h b/src/devices/bus/odyssey2/4in1.h
index 2840361bfe0..ad5414345c3 100644
--- a/src/devices/bus/odyssey2/4in1.h
+++ b/src/devices/bus/odyssey2/4in1.h
@@ -13,35 +13,6 @@
#include "slot.h"
-
-// ======================> o2_4in1_device
-
-class o2_4in1_device : public device_t,
- public device_o2_cart_interface
-{
-public:
- // construction/destruction
- o2_4in1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
-
-protected:
- // device-level overrides
- virtual void device_start() override;
-
- virtual void cart_init() override;
-
- virtual u8 read_rom04(offs_t offset) override { return m_rom[offset + 0x400]; }
- virtual u8 read_rom0c(offs_t offset) override { return m_rom[offset + 0xc00]; }
-
- virtual void write_p1(u8 data) override { m_control = data; }
- virtual void write_p2(u8 data) override { m_bank = data; }
- virtual u8 io_read(offs_t offset) override;
-
-private:
- u8 m_control = 0;
- u8 m_bank = 0;
-};
-
-// device type definition
-DECLARE_DEVICE_TYPE(O2_ROM_4IN1, o2_4in1_device)
+DECLARE_DEVICE_TYPE(O2_ROM_4IN1, device_o2_cart_interface)
#endif // MAME_BUS_ODYSSEY2_4IN1_H
diff --git a/src/devices/bus/odyssey2/chess.cpp b/src/devices/bus/odyssey2/chess.cpp
index 3bb5fed470c..1e63062af7a 100644
--- a/src/devices/bus/odyssey2/chess.cpp
+++ b/src/devices/bus/odyssey2/chess.cpp
@@ -14,13 +14,45 @@ Hardware notes:
#include "emu.h"
#include "chess.h"
-DEFINE_DEVICE_TYPE(O2_ROM_CHESS, o2_chess_device, "o2_chess", "Videopac C7010 Cartridge")
+#include "cpu/z80/z80.h"
+#include "machine/gen_latch.h"
+namespace {
//-------------------------------------------------
-// o2_chess_device - constructor
+// initialization
//-------------------------------------------------
+class o2_chess_device : public device_t, public device_o2_cart_interface
+{
+public:
+ o2_chess_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual void device_start() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+
+ virtual void cart_init() override;
+
+ virtual u8 read_rom04(offs_t offset) override { return m_rom[offset]; }
+ virtual u8 read_rom0c(offs_t offset) override { return m_rom[offset + 0x400]; }
+
+ virtual void write_p1(u8 data) override;
+ virtual void io_write(offs_t offset, u8 data) override;
+ virtual u8 io_read(offs_t offset) override;
+
+private:
+ required_device<cpu_device> m_maincpu;
+ required_device_array<generic_latch_8_device, 2> m_latch;
+
+ u8 m_control = 0;
+
+ u8 internal_rom_r(offs_t offset) { return m_exrom[offset]; }
+
+ void chess_io(address_map &map);
+ void chess_mem(address_map &map);
+};
+
o2_chess_device::o2_chess_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
device_t(mconfig, O2_ROM_CHESS, tag, owner, clock),
device_o2_cart_interface(mconfig, *this),
@@ -41,6 +73,34 @@ void o2_chess_device::cart_init()
//-------------------------------------------------
+// mapper specific handlers
+//-------------------------------------------------
+
+void o2_chess_device::write_p1(u8 data)
+{
+ // P11: reset
+ m_maincpu->set_input_line(INPUT_LINE_RESET, (data & 2) ? CLEAR_LINE : ASSERT_LINE);
+
+ // P10,P14: must be low to access latches
+ m_control = data;
+}
+
+u8 o2_chess_device::io_read(offs_t offset)
+{
+ if ((offset & 0xa0) == 0xa0 && (m_control & 0x11) == 0)
+ return m_latch[0]->read();
+ else
+ return 0xff;
+}
+
+void o2_chess_device::io_write(offs_t offset, u8 data)
+{
+ if (offset & 0x80 && (m_control & 0x11) == 0)
+ m_latch[1]->write(data);
+}
+
+
+//-------------------------------------------------
// address maps
//-------------------------------------------------
@@ -72,30 +132,7 @@ void o2_chess_device::device_add_mconfig(machine_config &config)
GENERIC_LATCH_8(config, m_latch[1]);
}
+} // anonymous namespace
-//-------------------------------------------------
-// mapper specific handlers
-//-------------------------------------------------
-
-void o2_chess_device::write_p1(u8 data)
-{
- // P11: reset
- m_maincpu->set_input_line(INPUT_LINE_RESET, (data & 2) ? CLEAR_LINE : ASSERT_LINE);
- // P10,P14: must be low to access latches
- m_control = data;
-}
-
-u8 o2_chess_device::io_read(offs_t offset)
-{
- if ((offset & 0xa0) == 0xa0 && (m_control & 0x11) == 0)
- return m_latch[0]->read();
- else
- return 0xff;
-}
-
-void o2_chess_device::io_write(offs_t offset, u8 data)
-{
- if (offset & 0x80 && (m_control & 0x11) == 0)
- m_latch[1]->write(data);
-}
+DEFINE_DEVICE_TYPE_PRIVATE(O2_ROM_CHESS, device_o2_cart_interface, o2_chess_device, "o2_chess", "Videopac C7010 Cartridge")
diff --git a/src/devices/bus/odyssey2/chess.h b/src/devices/bus/odyssey2/chess.h
index 0b37c50684c..4fddc07dc53 100644
--- a/src/devices/bus/odyssey2/chess.h
+++ b/src/devices/bus/odyssey2/chess.h
@@ -13,46 +13,6 @@
#include "slot.h"
-#include "cpu/z80/z80.h"
-#include "machine/gen_latch.h"
-
-
-// ======================> o2_chess_device
-
-class o2_chess_device : public device_t,
- public device_o2_cart_interface
-{
-public:
- // construction/destruction
- o2_chess_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
-
-protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_add_mconfig(machine_config &config) override;
-
- virtual void cart_init() override;
-
- virtual u8 read_rom04(offs_t offset) override { return m_rom[offset]; }
- virtual u8 read_rom0c(offs_t offset) override { return m_rom[offset]; }
-
- virtual void write_p1(u8 data) override;
- virtual void io_write(offs_t offset, u8 data) override;
- virtual u8 io_read(offs_t offset) override;
-
-private:
- required_device<cpu_device> m_maincpu;
- required_device_array<generic_latch_8_device, 2> m_latch;
-
- u8 internal_rom_r(offs_t offset) { return m_exrom[offset]; }
-
- void chess_io(address_map &map);
- void chess_mem(address_map &map);
-
- u8 m_control = 0;
-};
-
-// device type definition
-DECLARE_DEVICE_TYPE(O2_ROM_CHESS, o2_chess_device)
+DECLARE_DEVICE_TYPE(O2_ROM_CHESS, device_o2_cart_interface)
#endif // MAME_BUS_ODYSSEY2_CHESS_H
diff --git a/src/devices/bus/odyssey2/homecomp.cpp b/src/devices/bus/odyssey2/homecomp.cpp
index 2ab6f45b153..345d9270ca9 100644
--- a/src/devices/bus/odyssey2/homecomp.cpp
+++ b/src/devices/bus/odyssey2/homecomp.cpp
@@ -24,15 +24,57 @@ TODO:
#include "emu.h"
#include "homecomp.h"
-#include "speaker.h"
-DEFINE_DEVICE_TYPE(O2_ROM_HOMECOMP, o2_homecomp_device, "o2_homecomp", "Videopac+ C7420 Cartridge")
+#include "cpu/z80/z80.h"
+#include "imagedev/cassette.h"
+#include "machine/gen_latch.h"
+
+#include "speaker.h"
+namespace {
//-------------------------------------------------
-// o2_homecomp_device - constructor
+// initialization
//-------------------------------------------------
+class o2_homecomp_device : public device_t, public device_o2_cart_interface
+{
+public:
+ o2_homecomp_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual ioport_constructor device_input_ports() const override;
+
+ virtual void cart_init() override;
+
+ virtual u8 read_rom04(offs_t offset) override { return m_rom[offset]; }
+ virtual u8 read_rom0c(offs_t offset) override { return m_rom[offset + 0x400]; }
+
+ virtual void write_p1(u8 data) override;
+ virtual void io_write(offs_t offset, u8 data) override;
+ virtual u8 io_read(offs_t offset) override;
+ virtual int t0_read() override { return m_latch[0]->pending_r(); }
+
+private:
+ required_device<cpu_device> m_maincpu;
+ required_device_array<generic_latch_8_device, 2> m_latch;
+ required_device<cassette_image_device> m_cass;
+
+ std::unique_ptr<u8[]> m_ram;
+ u8 m_control = 0;
+ bool m_installed = false;
+
+ void internal_io_w(offs_t offset, u8 data);
+ u8 internal_io_r(offs_t offset);
+ u8 internal_rom_r(offs_t offset) { return m_exrom[offset]; }
+
+ void homecomp_io(address_map &map);
+ void homecomp_mem(address_map &map);
+};
+
o2_homecomp_device::o2_homecomp_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
device_t(mconfig, O2_ROM_HOMECOMP, tag, owner, clock),
device_o2_cart_interface(mconfig, *this),
@@ -71,19 +113,33 @@ void o2_homecomp_device::cart_init()
//-------------------------------------------------
-// input_ports - device-specific input ports
+// mapper specific handlers
//-------------------------------------------------
-static INPUT_PORTS_START( homecomp )
- PORT_START("RAM")
- PORT_CONFNAME( 0x01, 0x00, "RAM Size" )
- PORT_CONFSETTING( 0x00, "16KB" )
- PORT_CONFSETTING( 0x01, "32KB" ) // unofficial
-INPUT_PORTS_END
+void o2_homecomp_device::write_p1(u8 data)
+{
+ // P10: Z80 INT pin
+ // P10+P11: Z80 RESET pin
+ m_maincpu->set_input_line(INPUT_LINE_IRQ0, (data & 1) ? CLEAR_LINE : ASSERT_LINE);
+ m_maincpu->set_input_line(INPUT_LINE_RESET, (data & 3) ? CLEAR_LINE : ASSERT_LINE);
-ioport_constructor o2_homecomp_device::device_input_ports() const
+ // P11: must be low to access latch 0
+ // P14: must be low to access latch 1
+ m_control = data;
+}
+
+u8 o2_homecomp_device::io_read(offs_t offset)
{
- return INPUT_PORTS_NAME(homecomp);
+ if ((offset & 0xa0) == 0xa0 && ~m_control & 2)
+ return m_latch[0]->read();
+ else
+ return 0xff;
+}
+
+void o2_homecomp_device::io_write(offs_t offset, u8 data)
+{
+ if (offset & 0x80 && ~m_control & 0x10)
+ m_latch[1]->write(data);
}
@@ -154,6 +210,23 @@ void o2_homecomp_device::homecomp_io(address_map &map)
//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+static INPUT_PORTS_START( homecomp )
+ PORT_START("RAM")
+ PORT_CONFNAME( 0x01, 0x00, "RAM Size" )
+ PORT_CONFSETTING( 0x00, "16KB" )
+ PORT_CONFSETTING( 0x01, "32KB" ) // unofficial
+INPUT_PORTS_END
+
+ioport_constructor o2_homecomp_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(homecomp);
+}
+
+
+//-------------------------------------------------
// device_add_mconfig - add device configuration
//-------------------------------------------------
@@ -174,33 +247,7 @@ void o2_homecomp_device::device_add_mconfig(machine_config &config)
m_cass->add_route(ALL_OUTPUTS, "cass_output", 0.05);
}
+} // anonymous namespace
-//-------------------------------------------------
-// mapper specific handlers
-//-------------------------------------------------
-void o2_homecomp_device::write_p1(u8 data)
-{
- // P10: Z80 INT pin
- // P10+P11: Z80 RESET pin
- m_maincpu->set_input_line(INPUT_LINE_IRQ0, (data & 1) ? CLEAR_LINE : ASSERT_LINE);
- m_maincpu->set_input_line(INPUT_LINE_RESET, (data & 3) ? CLEAR_LINE : ASSERT_LINE);
-
- // P11: must be low to access latch 0
- // P14: must be low to access latch 1
- m_control = data;
-}
-
-u8 o2_homecomp_device::io_read(offs_t offset)
-{
- if ((offset & 0xa0) == 0xa0 && ~m_control & 2)
- return m_latch[0]->read();
- else
- return 0xff;
-}
-
-void o2_homecomp_device::io_write(offs_t offset, u8 data)
-{
- if (offset & 0x80 && ~m_control & 0x10)
- m_latch[1]->write(data);
-}
+DEFINE_DEVICE_TYPE_PRIVATE(O2_ROM_HOMECOMP, device_o2_cart_interface, o2_homecomp_device, "o2_homecomp", "Videopac+ C7420 Cartridge")
diff --git a/src/devices/bus/odyssey2/homecomp.h b/src/devices/bus/odyssey2/homecomp.h
index 7971afbff02..0ae5d789898 100644
--- a/src/devices/bus/odyssey2/homecomp.h
+++ b/src/devices/bus/odyssey2/homecomp.h
@@ -13,55 +13,6 @@
#include "slot.h"
-#include "cpu/z80/z80.h"
-#include "imagedev/cassette.h"
-#include "machine/gen_latch.h"
-
-
-// ======================> o2_homecomp_device
-
-class o2_homecomp_device : public device_t,
- public device_o2_cart_interface
-{
-public:
- // construction/destruction
- o2_homecomp_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
-
-protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_add_mconfig(machine_config &config) override;
- virtual ioport_constructor device_input_ports() const override;
-
- virtual void cart_init() override;
-
- virtual u8 read_rom04(offs_t offset) override { return m_rom[offset]; }
- virtual u8 read_rom0c(offs_t offset) override { return m_rom[offset]; }
-
- virtual void write_p1(u8 data) override;
- virtual void io_write(offs_t offset, u8 data) override;
- virtual u8 io_read(offs_t offset) override;
- virtual DECLARE_READ_LINE_MEMBER(t0_read) override { return m_latch[0]->pending_r(); }
-
-private:
- required_device<cpu_device> m_maincpu;
- required_device_array<generic_latch_8_device, 2> m_latch;
- required_device<cassette_image_device> m_cass;
-
- void internal_io_w(offs_t offset, u8 data);
- u8 internal_io_r(offs_t offset);
- u8 internal_rom_r(offs_t offset) { return m_exrom[offset]; }
-
- void homecomp_io(address_map &map);
- void homecomp_mem(address_map &map);
-
- std::unique_ptr<u8[]> m_ram;
- u8 m_control = 0;
- bool m_installed = false;
-};
-
-// device type definition
-DECLARE_DEVICE_TYPE(O2_ROM_HOMECOMP, o2_homecomp_device)
+DECLARE_DEVICE_TYPE(O2_ROM_HOMECOMP, device_o2_cart_interface)
#endif // MAME_BUS_ODYSSEY2_HOMECOMP_H
diff --git a/src/devices/bus/odyssey2/ktaa.cpp b/src/devices/bus/odyssey2/ktaa.cpp
index b9cf38bbf95..f14fdf7c113 100644
--- a/src/devices/bus/odyssey2/ktaa.cpp
+++ b/src/devices/bus/odyssey2/ktaa.cpp
@@ -11,13 +11,33 @@ Bankswitched ROM with page size of 3KB.
#include "emu.h"
#include "ktaa.h"
-DEFINE_DEVICE_TYPE(O2_ROM_KTAA, o2_ktaa_device, "o2_ktaa", "Videopac+ KTAA Cartridge")
-
+namespace {
//-------------------------------------------------
-// o2_ktaa_device - constructor
+// initialization
//-------------------------------------------------
+class o2_ktaa_device : public device_t, public device_o2_cart_interface
+{
+public:
+ o2_ktaa_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual void device_start() override;
+
+ virtual void cart_init() override;
+
+ virtual u8 read_rom04(offs_t offset) override;
+ virtual u8 read_rom0c(offs_t offset) override { return read_rom04(offset + 0x800); }
+
+ virtual void write_p1(u8 data) override { m_bank = data & m_bank_mask; }
+
+private:
+ u32 m_page_size = 0;
+ u8 m_bank_mask = 0;
+ u8 m_bank = 0;
+};
+
o2_ktaa_device::o2_ktaa_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
device_t(mconfig, O2_ROM_KTAA, tag, owner, clock),
device_o2_cart_interface(mconfig, *this)
@@ -61,3 +81,8 @@ u8 o2_ktaa_device::read_rom04(offs_t offset)
offset += m_page_size - 0xc00;
return m_rom[offset + m_bank * m_page_size];
}
+
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(O2_ROM_KTAA, device_o2_cart_interface, o2_ktaa_device, "o2_ktaa", "Videopac+ KTAA Cartridge")
diff --git a/src/devices/bus/odyssey2/ktaa.h b/src/devices/bus/odyssey2/ktaa.h
index ebb2da83a0b..89772bf9cd3 100644
--- a/src/devices/bus/odyssey2/ktaa.h
+++ b/src/devices/bus/odyssey2/ktaa.h
@@ -13,34 +13,6 @@
#include "slot.h"
-
-// ======================> o2_ktaa_device
-
-class o2_ktaa_device : public device_t,
- public device_o2_cart_interface
-{
-public:
- // construction/destruction
- o2_ktaa_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
-
-protected:
- // device-level overrides
- virtual void device_start() override;
-
- virtual void cart_init() override;
-
- virtual u8 read_rom04(offs_t offset) override;
- virtual u8 read_rom0c(offs_t offset) override { return read_rom04(offset + 0x800); }
-
- virtual void write_p1(u8 data) override { m_bank = data & m_bank_mask; }
-
-private:
- u32 m_page_size = 0;
- u8 m_bank_mask = 0;
- u8 m_bank = 0;
-};
-
-// device type definition
-DECLARE_DEVICE_TYPE(O2_ROM_KTAA, o2_ktaa_device)
+DECLARE_DEVICE_TYPE(O2_ROM_KTAA, device_o2_cart_interface)
#endif // MAME_BUS_ODYSSEY2_KTAA_H
diff --git a/src/devices/bus/odyssey2/rally.cpp b/src/devices/bus/odyssey2/rally.cpp
index e2d9adb135d..c02cf078c62 100644
--- a/src/devices/bus/odyssey2/rally.cpp
+++ b/src/devices/bus/odyssey2/rally.cpp
@@ -19,13 +19,33 @@ Used in:
#include "emu.h"
#include "rally.h"
-DEFINE_DEVICE_TYPE(O2_ROM_RALLY, o2_rally_device, "o2_rally", "Videopac+ 60 Cartridge")
-
+namespace {
//-------------------------------------------------
-// o2_rally_device - constructor
+// initialization
//-------------------------------------------------
+class o2_rally_device : public device_t, public device_o2_cart_interface
+{
+public:
+ o2_rally_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual void device_start() override;
+
+ virtual void cart_init() override;
+
+ virtual u8 read_rom04(offs_t offset) override;
+ virtual u8 read_rom0c(offs_t offset) override { return read_rom04(offset + 0x400); }
+
+ virtual void write_p1(u8 data) override { m_control = data; }
+ virtual void io_write(offs_t offset, u8 data) override;
+
+private:
+ u8 m_control = 0;
+ u8 m_bank = 0;
+};
+
o2_rally_device::o2_rally_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
device_t(mconfig, O2_ROM_RALLY, tag, owner, clock),
device_o2_cart_interface(mconfig, *this)
@@ -60,3 +80,8 @@ void o2_rally_device::io_write(offs_t offset, u8 data)
if (offset & 0x80 && ~m_control & 0x10)
m_bank = data;
}
+
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(O2_ROM_RALLY, device_o2_cart_interface, o2_rally_device, "o2_rally", "Videopac+ 60 Cartridge")
diff --git a/src/devices/bus/odyssey2/rally.h b/src/devices/bus/odyssey2/rally.h
index 8d359362dce..9f022d02031 100644
--- a/src/devices/bus/odyssey2/rally.h
+++ b/src/devices/bus/odyssey2/rally.h
@@ -13,34 +13,6 @@
#include "slot.h"
-
-// ======================> o2_rally_device
-
-class o2_rally_device : public device_t,
- public device_o2_cart_interface
-{
-public:
- // construction/destruction
- o2_rally_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
-
-protected:
- // device-level overrides
- virtual void device_start() override;
-
- virtual void cart_init() override;
-
- virtual u8 read_rom04(offs_t offset) override;
- virtual u8 read_rom0c(offs_t offset) override { return read_rom04(offset); }
-
- virtual void write_p1(u8 data) override { m_control = data; }
- virtual void io_write(offs_t offset, u8 data) override;
-
-private:
- u8 m_control = 0;
- u8 m_bank = 0;
-};
-
-// device type definition
-DECLARE_DEVICE_TYPE(O2_ROM_RALLY, o2_rally_device)
+DECLARE_DEVICE_TYPE(O2_ROM_RALLY, device_o2_cart_interface)
#endif // MAME_BUS_ODYSSEY2_RALLY_H
diff --git a/src/devices/bus/odyssey2/rom.cpp b/src/devices/bus/odyssey2/rom.cpp
index b964d99b584..9dcdc480842 100644
--- a/src/devices/bus/odyssey2/rom.cpp
+++ b/src/devices/bus/odyssey2/rom.cpp
@@ -9,13 +9,32 @@ Standard cartridges emulation, optionally bankswitched up to 8KB.
#include "emu.h"
#include "rom.h"
-DEFINE_DEVICE_TYPE(O2_ROM_STD, o2_rom_device, "o2_rom", "Odyssey 2 Standard Cartridge")
-
+namespace {
//-------------------------------------------------
-// o2_rom_device - constructor
+// initialization
//-------------------------------------------------
+class o2_rom_device : public device_t, public device_o2_cart_interface
+{
+public:
+ o2_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual void device_start() override;
+
+ virtual void cart_init() override;
+
+ virtual u8 read_rom04(offs_t offset) override;
+ virtual u8 read_rom0c(offs_t offset) override { return read_rom04(offset + 0x400); }
+
+ virtual void write_p1(u8 data) override { m_bank = data & 3; }
+
+private:
+ u32 m_cart_mask = 0;
+ u8 m_bank = 0;
+};
+
o2_rom_device::o2_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
device_t(mconfig, O2_ROM_STD, tag, owner, clock),
device_o2_cart_interface(mconfig, *this)
@@ -41,3 +60,8 @@ u8 o2_rom_device::read_rom04(offs_t offset)
offset = (offset + m_bank * 0x800) & m_cart_mask;
return (offset < m_rom_size) ? m_rom[offset] : 0xff;
}
+
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(O2_ROM_STD, device_o2_cart_interface, o2_rom_device, "o2_rom", "Odyssey 2 Standard Cartridge")
diff --git a/src/devices/bus/odyssey2/rom.h b/src/devices/bus/odyssey2/rom.h
index 204d96030ce..9305a4c6345 100644
--- a/src/devices/bus/odyssey2/rom.h
+++ b/src/devices/bus/odyssey2/rom.h
@@ -13,33 +13,6 @@
#include "slot.h"
-
-// ======================> o2_rom_device
-
-class o2_rom_device : public device_t,
- public device_o2_cart_interface
-{
-public:
- // construction/destruction
- o2_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
-
-protected:
- // device-level overrides
- virtual void device_start() override;
-
- virtual void cart_init() override;
-
- virtual u8 read_rom04(offs_t offset) override;
- virtual u8 read_rom0c(offs_t offset) override { return read_rom04(offset); }
-
- virtual void write_p1(u8 data) override { m_bank = data & 3; }
-
-private:
- u32 m_cart_mask = 0;
- u8 m_bank = 0;
-};
-
-// device type definition
-DECLARE_DEVICE_TYPE(O2_ROM_STD, o2_rom_device)
+DECLARE_DEVICE_TYPE(O2_ROM_STD, device_o2_cart_interface)
#endif // MAME_BUS_ODYSSEY2_ROM_H
diff --git a/src/devices/bus/odyssey2/slot.cpp b/src/devices/bus/odyssey2/slot.cpp
index 1e85ca3d4fa..dba3fa09ff3 100644
--- a/src/devices/bus/odyssey2/slot.cpp
+++ b/src/devices/bus/odyssey2/slot.cpp
@@ -10,6 +10,9 @@
#include "emu.h"
#include "slot.h"
+#include <tuple>
+
+
//**************************************************************************
// GLOBAL VARIABLES
//**************************************************************************
@@ -130,8 +133,10 @@ static const char *o2_get_slot(int type)
call load
-------------------------------------------------*/
-image_init_result o2_cart_slot_device::call_load()
+std::pair<std::error_condition, std::string> o2_cart_slot_device::call_load()
{
+ std::error_condition err;
+
if (m_cart)
{
if (loaded_through_softlist())
@@ -152,25 +157,34 @@ image_init_result o2_cart_slot_device::call_load()
}
else
{
- u32 size = length();
- fread(m_cart->m_rom, size);
-
- m_cart->m_rom_size = size;
- m_cart->m_exrom_size = 0;
- m_cart->m_voice_size = 0;
- m_b = 0;
-
- m_type = (size == 0x4000) ? O2_RALLY : O2_STD;
+ u32 const size = length();
+ size_t actual;
+ std::tie(err, m_cart->m_rom, actual) = read(image_core_file(), size);
+ if (!err && (actual != size))
+ err = std::errc::io_error;
+
+ if (!err)
+ {
+ m_cart->m_rom_size = size;
+ m_cart->m_exrom_size = 0;
+ m_cart->m_voice_size = 0;
+ m_b = 0;
+
+ m_type = (size == 0x4000) ? O2_RALLY : O2_STD;
+ }
}
if (m_cart->get_rom_size() > 0)
- {
m_cart->cart_init();
- return image_init_result::PASS;
- }
+ else if (!err)
+ err = image_error::UNSPECIFIED;
+ }
+ else
+ {
+ err = image_error::UNSPECIFIED;
}
- return image_init_result::FAIL;
+ return std::make_pair(err, std::string());
}
@@ -241,7 +255,7 @@ u8 o2_cart_slot_device::bus_read()
return (m_cart) ? m_cart->bus_read() : 0xff;
}
-READ_LINE_MEMBER(o2_cart_slot_device::t0_read)
+int o2_cart_slot_device::t0_read()
{
return (m_cart) ? m_cart->t0_read() : 0;
}
diff --git a/src/devices/bus/odyssey2/slot.h b/src/devices/bus/odyssey2/slot.h
index 09fcd34891e..386a6a3aeb5 100644
--- a/src/devices/bus/odyssey2/slot.h
+++ b/src/devices/bus/odyssey2/slot.h
@@ -68,7 +68,7 @@ public:
virtual u8 io_read(offs_t offset) { return 0xff; }
virtual void bus_write(u8 data) { }
virtual u8 bus_read() { return 0xff; }
- virtual DECLARE_READ_LINE_MEMBER(t0_read) { return 0; }
+ virtual int t0_read() { return 0; }
virtual int b_read() { return -1; }
virtual void cart_init() { } // called after loading ROM
@@ -112,15 +112,15 @@ public:
o2_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);
virtual ~o2_cart_slot_device();
- // image-level overrides
- virtual image_init_result call_load() override;
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
virtual void call_unload() override { }
virtual bool is_reset_on_load() const noexcept override { return true; }
virtual const char *image_interface() const noexcept override { return "odyssey_cart"; }
virtual const char *file_extensions() const noexcept override { return "bin,rom"; }
- // slot interface overrides
+ // device_slot_interface implementation
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
int get_type() { return m_type; }
@@ -133,14 +133,14 @@ public:
u8 io_read(offs_t offset);
void bus_write(u8 data);
u8 bus_read();
- DECLARE_READ_LINE_MEMBER(t0_read);
+ int t0_read();
int b_read();
void write_p1(u8 data) { if (m_cart) m_cart->write_p1(data); }
void write_p2(u8 data) { if (m_cart) m_cart->write_p2(data); }
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
int m_type;
diff --git a/src/devices/bus/odyssey2/test.cpp b/src/devices/bus/odyssey2/test.cpp
index 60141698f3c..f5656975818 100644
--- a/src/devices/bus/odyssey2/test.cpp
+++ b/src/devices/bus/odyssey2/test.cpp
@@ -18,13 +18,35 @@ Hold UP to advance to next test.
#include "emu.h"
#include "test.h"
-DEFINE_DEVICE_TYPE(O2_ROM_TEST, o2_test_device, "o2_test", "Videopac Service Test Cartridge")
-
+namespace {
//-------------------------------------------------
-// o2_test_device - constructor
+// initialization
//-------------------------------------------------
+class o2_test_device : public device_t, public device_o2_cart_interface
+{
+public:
+ o2_test_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual void device_start() override;
+
+ virtual void cart_init() override;
+
+ virtual u8 read_rom04(offs_t offset) override { return m_rom[offset]; }
+ virtual u8 read_rom0c(offs_t offset) override { return m_rom[offset + 0x400]; }
+ virtual void bus_write(u8 data) override { m_bus_data = data; }
+
+ virtual void write_p1(u8 data) override;
+
+private:
+ output_finder<> m_digit_out;
+
+ u8 m_control = 0;
+ u8 m_bus_data = 0;
+};
+
o2_test_device::o2_test_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
device_t(mconfig, O2_ROM_TEST, tag, owner, clock),
device_o2_cart_interface(mconfig, *this),
@@ -63,3 +85,8 @@ void o2_test_device::write_p1(u8 data)
m_control = data;
}
+
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(O2_ROM_TEST, device_o2_cart_interface, o2_test_device, "o2_test", "Videopac Service Test Cartridge")
diff --git a/src/devices/bus/odyssey2/test.h b/src/devices/bus/odyssey2/test.h
index 9227a9d6ea1..2bc179e215c 100644
--- a/src/devices/bus/odyssey2/test.h
+++ b/src/devices/bus/odyssey2/test.h
@@ -13,36 +13,6 @@
#include "slot.h"
-
-// ======================> o2_test_device
-
-class o2_test_device : public device_t,
- public device_o2_cart_interface
-{
-public:
- // construction/destruction
- o2_test_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
-
-protected:
- // device-level overrides
- virtual void device_start() override;
-
- virtual void cart_init() override;
-
- virtual u8 read_rom04(offs_t offset) override { return m_rom[offset]; }
- virtual u8 read_rom0c(offs_t offset) override { return m_rom[offset]; }
- virtual void bus_write(u8 data) override { m_bus_data = data; }
-
- virtual void write_p1(u8 data) override;
-
-private:
- output_finder<> m_digit_out;
-
- u8 m_control = 0;
- u8 m_bus_data = 0;
-};
-
-// device type definition
-DECLARE_DEVICE_TYPE(O2_ROM_TEST, o2_test_device)
+DECLARE_DEVICE_TYPE(O2_ROM_TEST, device_o2_cart_interface)
#endif // MAME_BUS_ODYSSEY2_TEST_H
diff --git a/src/devices/bus/odyssey2/voice.cpp b/src/devices/bus/odyssey2/voice.cpp
index 831a02bcc1a..28911004c47 100644
--- a/src/devices/bus/odyssey2/voice.cpp
+++ b/src/devices/bus/odyssey2/voice.cpp
@@ -14,19 +14,56 @@ that (European) cartridges using extra I/O won't work on it.
TODO:
- bees sound at level complete "MORE MORE MORE CHK CHK CHK" should be more rapid
+- turtlesu usually doesn't detect the voice cartridge
******************************************************************************/
#include "emu.h"
#include "voice.h"
+
+#include "sound/sp0256.h"
+
#include "speaker.h"
-DEFINE_DEVICE_TYPE(O2_ROM_VOICE, o2_voice_device, "o2_voice", "Odyssey 2 The Voice Cartridge")
+namespace {
//-------------------------------------------------
-// o2_voice_device - constructor
+// initialization
//-------------------------------------------------
+class o2_voice_device : public device_t, public device_o2_cart_interface
+{
+public:
+ o2_voice_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void cart_init() override;
+
+ virtual u8 read_rom04(offs_t offset) override { return (m_subslot->exists()) ? m_subslot->read_rom04(offset) : 0xff; }
+ virtual u8 read_rom0c(offs_t offset) override { return (m_subslot->exists()) ? m_subslot->read_rom0c(offset) : 0xff; }
+
+ virtual void write_p1(u8 data) override { m_control = data; if (m_subslot->exists()) m_subslot->write_p1(data & 3); }
+ virtual void write_p2(u8 data) override { if (m_subslot->exists()) m_subslot->write_p2(data & ~4); }
+ virtual void bus_write(u8 data) override { if (m_subslot->exists()) m_subslot->bus_write(data); }
+ virtual u8 bus_read() override { return (m_subslot->exists()) ? m_subslot->bus_read() : 0xff; }
+
+ virtual void io_write(offs_t offset, u8 data) override;
+ virtual int t0_read() override;
+
+protected:
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+private:
+ required_device<sp0256_device> m_speech;
+ required_device<o2_cart_slot_device> m_subslot;
+
+ u8 m_control = 0;
+ bool m_reset = false;
+};
+
o2_voice_device::o2_voice_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
device_t(mconfig, O2_ROM_VOICE, tag, owner, clock),
device_o2_cart_interface(mconfig, *this),
@@ -37,6 +74,7 @@ o2_voice_device::o2_voice_device(const machine_config &mconfig, const char *tag,
void o2_voice_device::device_start()
{
save_item(NAME(m_control));
+ save_item(NAME(m_reset));
}
void o2_voice_device::cart_init()
@@ -62,6 +100,34 @@ void o2_voice_device::device_reset()
//-------------------------------------------------
+// mapper specific handlers
+//-------------------------------------------------
+
+int o2_voice_device::t0_read()
+{
+ return m_speech->lrq_r() ? 0 : 1;
+}
+
+void o2_voice_device::io_write(offs_t offset, u8 data)
+{
+ if (offset & 0x80 && ~m_control & 0x10)
+ {
+ // D5: 7474 to SP0256B reset
+ bool reset = !(data & 0x20);
+ if (reset)
+ m_speech->reset();
+ else if (!m_reset)
+ {
+ // A0-A6: SP0256B A1-A7 (A8 to GND)
+ m_speech->ald_w(offset & 0x7f);
+ }
+
+ m_reset = reset;
+ }
+}
+
+
+//-------------------------------------------------
// device_add_mconfig - add device configuration
//-------------------------------------------------
@@ -85,25 +151,7 @@ const tiny_rom_entry *o2_voice_device::device_rom_region() const
return ROM_NAME( o2voice );
}
+} // anonymous namespace
-//-------------------------------------------------
-// mapper specific handlers
-//-------------------------------------------------
-
-READ_LINE_MEMBER(o2_voice_device::t0_read)
-{
- return m_speech->lrq_r() ? 0 : 1;
-}
-void o2_voice_device::io_write(offs_t offset, u8 data)
-{
- if (offset & 0x80 && ~m_control & 0x10)
- {
- // A0-A6: SP0256B A1-A7 (A8 to GND)
- // D5: 7474 to SP0256B reset
- if (data & 0x20)
- m_speech->ald_w(offset & 0x7f);
- else
- m_speech->reset();
- }
-}
+DEFINE_DEVICE_TYPE_PRIVATE(O2_ROM_VOICE, device_o2_cart_interface, o2_voice_device, "o2_voice", "Odyssey 2 The Voice Cartridge")
diff --git a/src/devices/bus/odyssey2/voice.h b/src/devices/bus/odyssey2/voice.h
index a8e3000032f..a773b333846 100644
--- a/src/devices/bus/odyssey2/voice.h
+++ b/src/devices/bus/odyssey2/voice.h
@@ -12,49 +12,7 @@
#pragma once
#include "slot.h"
-#include "sound/sp0256.h"
-
-// ======================> o2_voice_device
-
-class o2_voice_device : public device_t,
- public device_o2_cart_interface
-{
-public:
- // construction/destruction
- o2_voice_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
-
- virtual void cart_init() override;
-
- // reading and writing
- virtual u8 read_rom04(offs_t offset) override { return (m_subslot->exists()) ? m_subslot->read_rom04(offset) : 0xff; }
- virtual u8 read_rom0c(offs_t offset) override { return (m_subslot->exists()) ? m_subslot->read_rom0c(offset) : 0xff; }
-
- virtual void write_p1(u8 data) override { m_control = data; if (m_subslot->exists()) m_subslot->write_p1(data & 3); }
- virtual void write_p2(u8 data) override { if (m_subslot->exists()) m_subslot->write_p2(data & ~4); }
- virtual void bus_write(u8 data) override { if (m_subslot->exists()) m_subslot->bus_write(data); }
- virtual u8 bus_read() override { return (m_subslot->exists()) ? m_subslot->bus_read() : 0xff; }
-
- virtual void io_write(offs_t offset, u8 data) override;
- virtual DECLARE_READ_LINE_MEMBER(t0_read) override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
-
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
-
-private:
- required_device<sp0256_device> m_speech;
- required_device<o2_cart_slot_device> m_subslot;
-
- u8 m_control = 0;
-};
-
-
-// device type definition
-DECLARE_DEVICE_TYPE(O2_ROM_VOICE, o2_voice_device)
+DECLARE_DEVICE_TYPE(O2_ROM_VOICE, device_o2_cart_interface)
#endif // MAME_BUS_ODYSSEY2_VOICE_H
diff --git a/src/devices/bus/oricext/jasmin.cpp b/src/devices/bus/oricext/jasmin.cpp
index a50ab9d742d..25cd54b2f24 100644
--- a/src/devices/bus/oricext/jasmin.cpp
+++ b/src/devices/bus/oricext/jasmin.cpp
@@ -31,10 +31,21 @@ INPUT_PORTS_START( jasmin )
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Boot") PORT_CODE(KEYCODE_F1) PORT_CHAR(UCHAR_MAMEKEY(F1)) PORT_CHANGED_MEMBER(DEVICE_SELF, oric_jasmin_device, boot_pressed, 0)
INPUT_PORTS_END
-void oric_jasmin_device::map(address_map &map)
+void oric_jasmin_device::map_io(address_space_installer &space)
{
- map(0x3f4, 0x3f7).rw("fdc", FUNC(wd1770_device::read), FUNC(wd1770_device::write));
- map(0x3f8, 0x3ff).w(m_fdlatch, FUNC(ls259_device::write_d0));
+ space.install_read_handler(0x3f4, 0x3f7, read8sm_delegate(m_fdc, FUNC(wd1770_device::read)));
+ space.install_write_handler(0x3f4, 0x3f7, write8sm_delegate(m_fdc, FUNC(wd1770_device::write)));
+
+ space.install_write_handler(0x3f8, 0x3ff, write8sm_delegate(m_fdlatch, FUNC(ls259_device::write_d0)));
+}
+
+void oric_jasmin_device::map_rom()
+{
+ (*view)[2].unmap_write(0xf800, 0xffff);
+ (*view)[2].install_rom(0xf800, 0xffff, m_jasmin_rom);
+
+ (*view)[3].unmap_readwrite(0xc000, 0xffff);
+ (*view)[3].install_rom(0xf800, 0xffff, m_jasmin_rom);
}
oric_jasmin_device::oric_jasmin_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
@@ -54,7 +65,6 @@ oric_jasmin_device::~oric_jasmin_device()
void oric_jasmin_device::device_start()
{
- cpu->space(AS_PROGRAM).install_device(0x0000, 0xffff, *this, &oric_jasmin_device::map);
}
const tiny_rom_entry *oric_jasmin_device::device_rom_region() const
@@ -91,37 +101,15 @@ ioport_constructor oric_jasmin_device::device_input_ports() const
void oric_jasmin_device::remap()
{
if(m_fdlatch->q3_r()) {
- if(m_fdlatch->q2_r()) {
- bank_c000_r->set_base(ram+0xc000);
- bank_e000_r->set_base(ram+0xe000);
- bank_f800_r->set_base(m_jasmin_rom.target());
- bank_c000_w->set_base(ram+0xc000);
- bank_e000_w->set_base(ram+0xe000);
- bank_f800_w->set_base(junk_write);
- } else {
- bank_c000_r->set_base(junk_read);
- bank_e000_r->set_base(junk_read);
- bank_f800_r->set_base(m_jasmin_rom.target());
- bank_c000_w->set_base(junk_write);
- bank_e000_w->set_base(junk_write);
- bank_f800_w->set_base(junk_write);
- }
+ if(m_fdlatch->q2_r())
+ view->select(3);
+ else
+ view->select(2);
} else {
- if(m_fdlatch->q2_r()) {
- bank_c000_r->set_base(ram+0xc000);
- bank_e000_r->set_base(ram+0xe000);
- bank_f800_r->set_base(ram+0xf800);
- bank_c000_w->set_base(ram+0xc000);
- bank_e000_w->set_base(ram+0xe000);
- bank_f800_w->set_base(ram+0xf800);
- } else {
- bank_c000_r->set_base(rom+0x0000);
- bank_e000_r->set_base(rom+0x2000);
- bank_f800_r->set_base(rom+0x3800);
- bank_c000_w->set_base(junk_write);
- bank_e000_w->set_base(junk_write);
- bank_f800_w->set_base(junk_write);
- }
+ if(m_fdlatch->q2_r())
+ view->select(1);
+ else
+ view->select(0);
}
}
@@ -129,27 +117,28 @@ INPUT_CHANGED_MEMBER(oric_jasmin_device::boot_pressed)
{
if(newval) {
m_fdlatch->write_bit(3, 1);
- cpu->reset();
+ reset_w(1);
+ reset_w(0);
}
}
-WRITE_LINE_MEMBER(oric_jasmin_device::side_sel_w)
+void oric_jasmin_device::side_sel_w(int state)
{
if(m_cur_floppy)
m_cur_floppy->ss_w(state);
}
-WRITE_LINE_MEMBER(oric_jasmin_device::ram_access_w)
+void oric_jasmin_device::ram_access_w(int state)
{
remap();
}
-WRITE_LINE_MEMBER(oric_jasmin_device::rom_access_w)
+void oric_jasmin_device::rom_access_w(int state)
{
remap();
}
-WRITE_LINE_MEMBER(oric_jasmin_device::select_w)
+void oric_jasmin_device::select_w(int state)
{
m_cur_floppy = nullptr;
for(int i=0; i != 4; i++)
diff --git a/src/devices/bus/oricext/jasmin.h b/src/devices/bus/oricext/jasmin.h
index 17baba8aaad..fa4ffe7bf46 100644
--- a/src/devices/bus/oricext/jasmin.h
+++ b/src/devices/bus/oricext/jasmin.h
@@ -26,15 +26,16 @@ protected:
virtual void device_add_mconfig(machine_config &config) override;
virtual ioport_constructor device_input_ports() const override;
+ virtual void map_io(address_space_installer &space) override;
+ virtual void map_rom() override;
+
private:
void remap();
- DECLARE_WRITE_LINE_MEMBER(side_sel_w);
- DECLARE_WRITE_LINE_MEMBER(ram_access_w);
- DECLARE_WRITE_LINE_MEMBER(rom_access_w);
- DECLARE_WRITE_LINE_MEMBER(select_w);
-
- void map(address_map &map);
+ void side_sel_w(int state);
+ void ram_access_w(int state);
+ void rom_access_w(int state);
+ void select_w(int state);
static void floppy_formats(format_registration &fr);
diff --git a/src/devices/bus/oricext/microdisc.cpp b/src/devices/bus/oricext/microdisc.cpp
index 31ef1a7941d..b85d56182f9 100644
--- a/src/devices/bus/oricext/microdisc.cpp
+++ b/src/devices/bus/oricext/microdisc.cpp
@@ -22,17 +22,28 @@ static void microdisc_floppies(device_slot_interface &device)
device.option_add("3dsdd", FLOPPY_3_DSDD);
}
-void oric_microdisc_device::map(address_map &map)
+void oric_microdisc_device::map_io(address_space_installer &space)
{
- map(0x310, 0x313).rw("fdc", FUNC(fd1793_device::read), FUNC(fd1793_device::write));
- map(0x314, 0x314).rw(FUNC(oric_microdisc_device::port_314_r), FUNC(oric_microdisc_device::port_314_w));
- map(0x318, 0x318).r(FUNC(oric_microdisc_device::port_318_r));
+ space.install_read_handler(0x310, 0x313, read8sm_delegate(fdc, FUNC(fd1793_device::read)));
+ space.install_write_handler(0x310, 0x313, write8sm_delegate(fdc, FUNC(fd1793_device::write)));
+
+ space.install_read_handler(0x314, 0x314, read8smo_delegate(*this, FUNC(oric_microdisc_device::port_314_r)));
+ space.install_write_handler(0x314, 0x314, write8smo_delegate(*this, FUNC(oric_microdisc_device::port_314_w)));
+
+ space.install_read_handler(0x318, 0x318, read8smo_delegate(*this, FUNC(oric_microdisc_device::port_318_r)));
+}
+
+void oric_microdisc_device::map_rom()
+{
+ (*view)[2].unmap_write(0xe000, 0xffff);
+ (*view)[2].install_rom(0xe000, 0xffff, microdisc_rom);
}
oric_microdisc_device::oric_microdisc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, ORIC_MICRODISC, tag, owner, clock),
device_oricext_interface(mconfig, *this),
- fdc(*this, "fdc"), microdisc_rom(nullptr),
+ fdc(*this, "fdc"),
+ microdisc_rom(*this, "microdisc"),
floppies(*this, "fdc:%u", 0U),
port_314(0), intrq_state(false), drq_state(false), hld_state(false)
{
@@ -44,22 +55,15 @@ oric_microdisc_device::~oric_microdisc_device()
void oric_microdisc_device::device_start()
{
- microdisc_rom = device().machine().root_device().memregion(this->subtag("microdisc").c_str())->base();
- cpu->space(AS_PROGRAM).install_device(0x0000, 0xffff, *this, &oric_microdisc_device::map);
-
intrq_state = drq_state = hld_state = false;
}
void oric_microdisc_device::device_reset()
{
port_314 = 0x00;
+ view->select(2);
irq_w(false);
- remap();
fdc->set_floppy(floppies[0]->get_device());
-
- // The bootstrap checksums part of the high ram and if the sum is
- // 0 it goes wrong.
- ram[0xe000] = 0x42;
}
const tiny_rom_entry *oric_microdisc_device::device_rom_region() const
@@ -81,36 +85,16 @@ void oric_microdisc_device::device_add_mconfig(machine_config &config)
FLOPPY_CONNECTOR(config, "fdc:3", microdisc_floppies, nullptr, oric_microdisc_device::floppy_formats);
}
-void oric_microdisc_device::remap()
-{
- if(port_314 & P_ROMDIS) {
- bank_c000_r->set_base(rom+0x0000);
- bank_e000_r->set_base(rom+0x2000);
- bank_f800_r->set_base(rom+0x3800);
- bank_c000_w->set_base(junk_write);
- bank_e000_w->set_base(junk_write);
- bank_f800_w->set_base(junk_write);
- } else {
- bank_c000_r->set_base(ram+0xc000);
- bank_c000_w->set_base(ram+0xc000);
- if(port_314 & P_EPROM) {
- bank_e000_r->set_base(ram+0xe000);
- bank_f800_r->set_base(ram+0xf800);
- bank_e000_w->set_base(ram+0xe000);
- bank_f800_w->set_base(ram+0xf800);
- } else {
- bank_e000_r->set_base(microdisc_rom+0x0000);
- bank_f800_r->set_base(microdisc_rom+0x1800);
- bank_e000_w->set_base(junk_write);
- bank_f800_w->set_base(junk_write);
- }
- }
-}
-
void oric_microdisc_device::port_314_w(uint8_t data)
{
port_314 = data;
- remap();
+ if(port_314 & P_ROMDIS)
+ view->select(0);
+ else if(port_314 & P_EPROM)
+ view->select(1);
+ else
+ view->select(2);
+
floppy_image_device *floppy = floppies[(port_314 >> 5) & 3]->get_device();
fdc->set_floppy(floppy);
fdc->dden_w(port_314 & P_DDEN);
@@ -131,20 +115,19 @@ uint8_t oric_microdisc_device::port_318_r()
return drq_state ? 0x7f : 0xff;
}
-WRITE_LINE_MEMBER(oric_microdisc_device::fdc_irq_w)
+void oric_microdisc_device::fdc_irq_w(int state)
{
intrq_state = state;
irq_w(intrq_state && (port_314 & P_IRQEN));
}
-WRITE_LINE_MEMBER(oric_microdisc_device::fdc_drq_w)
+void oric_microdisc_device::fdc_drq_w(int state)
{
drq_state = state;
}
-WRITE_LINE_MEMBER(oric_microdisc_device::fdc_hld_w)
+void oric_microdisc_device::fdc_hld_w(int state)
{
- logerror("hld %d\n", state);
hld_state = state;
floppy_image_device *floppy = floppies[(port_314 >> 5) & 3]->get_device();
if(floppy)
diff --git a/src/devices/bus/oricext/microdisc.h b/src/devices/bus/oricext/microdisc.h
index 312a9b69954..16696dd8fbf 100644
--- a/src/devices/bus/oricext/microdisc.h
+++ b/src/devices/bus/oricext/microdisc.h
@@ -26,31 +26,30 @@ protected:
P_EPROM = 0x80
};
- required_device<fd1793_device> fdc;
-
- uint8_t *microdisc_rom;
- required_device_array<floppy_connector, 4> floppies;
- uint8_t port_314;
- bool intrq_state, drq_state, hld_state;
-
virtual void device_start() override;
virtual void device_reset() override;
const tiny_rom_entry *device_rom_region() const override;
virtual void device_add_mconfig(machine_config &config) override;
- void remap();
+ virtual void map_io(address_space_installer &space) override;
+ virtual void map_rom() override;
private:
- DECLARE_WRITE_LINE_MEMBER(fdc_irq_w);
- DECLARE_WRITE_LINE_MEMBER(fdc_drq_w);
- DECLARE_WRITE_LINE_MEMBER(fdc_hld_w);
+ required_device<fd1793_device> fdc;
+ required_region_ptr<uint8_t> microdisc_rom;
+ required_device_array<floppy_connector, 4> floppies;
+
+ uint8_t port_314;
+ bool intrq_state, drq_state, hld_state;
+
+ void fdc_irq_w(int state);
+ void fdc_drq_w(int state);
+ void fdc_hld_w(int state);
void port_314_w(uint8_t data);
uint8_t port_314_r();
uint8_t port_318_r();
- void map(address_map &map);
-
static void floppy_formats(format_registration &fr);
};
diff --git a/src/devices/bus/oricext/oricext.cpp b/src/devices/bus/oricext/oricext.cpp
index c678edc0ef6..ee8c285c3ef 100644
--- a/src/devices/bus/oricext/oricext.cpp
+++ b/src/devices/bus/oricext/oricext.cpp
@@ -11,7 +11,7 @@ oricext_connector::oricext_connector(const machine_config &mconfig, const char *
device_t(mconfig, ORICEXT_CONNECTOR, tag, owner, clock),
device_single_card_slot_interface<device_oricext_interface>(mconfig, *this),
irq_handler(*this),
- cpu(*this, finder_base::DUMMY_TAG)
+ reset_handler(*this)
{
}
@@ -21,7 +21,6 @@ oricext_connector::~oricext_connector()
void oricext_connector::device_start()
{
- irq_handler.resolve_safe();
}
void oricext_connector::irq_w(int state)
@@ -29,43 +28,59 @@ void oricext_connector::irq_w(int state)
irq_handler(state);
}
+void oricext_connector::reset_w(int state)
+{
+ reset_handler(state);
+}
+
+void oricext_connector::set_view(memory_view &_view)
+{
+ auto card = get_card_device();
+ if(card)
+ card->set_view(_view);
+}
+
+void oricext_connector::map_io(address_space_installer &space)
+{
+ auto card = get_card_device();
+ if(card)
+ card->map_io(space);
+}
+
+void oricext_connector::map_rom()
+{
+ auto card = get_card_device();
+ if(card)
+ card->map_rom();
+}
+
device_oricext_interface::device_oricext_interface(const machine_config &mconfig, device_t &device) :
device_interface(device, "oricext"),
- cpu(nullptr),
- connector(nullptr),
- bank_c000_r(nullptr),
- bank_e000_r(nullptr),
- bank_f800_r(nullptr),
- bank_c000_w(nullptr),
- bank_e000_w(nullptr),
- bank_f800_w(nullptr),
- rom(nullptr),
- ram(nullptr)
+ view(nullptr),
+ connector(nullptr)
{
}
void device_oricext_interface::interface_pre_start()
{
connector = downcast<oricext_connector *>(device().owner());
- cpu = connector->cpu.target();
- bank_c000_r = device().membank(":bank_c000_r");
- bank_e000_r = device().membank(":bank_e000_r");
- bank_f800_r = device().membank(":bank_f800_r");
- bank_c000_w = device().membank(":bank_c000_w");
- bank_e000_w = device().membank(":bank_e000_w");
- bank_f800_w = device().membank(":bank_f800_w");
- rom = (uint8_t *)cpu->memregion(DEVICE_SELF)->base();
- ram = (uint8_t *)device().memshare(":ram")->ptr();
-
- memset(junk_read, 0xff, sizeof(junk_read));
- memset(junk_write, 0x00, sizeof(junk_write));
}
-WRITE_LINE_MEMBER(device_oricext_interface::irq_w)
+void device_oricext_interface::irq_w(int state)
{
connector->irq_w(state);
}
+void device_oricext_interface::reset_w(int state)
+{
+ connector->reset_w(state);
+}
+
+void device_oricext_interface::set_view(memory_view &_view)
+{
+ view = &_view;
+}
+
void oricext_intf(device_slot_interface &device)
{
device.option_add("jasmin", ORIC_JASMIN);
diff --git a/src/devices/bus/oricext/oricext.h b/src/devices/bus/oricext/oricext.h
index 2d017f1e376..3030888ec9d 100644
--- a/src/devices/bus/oricext/oricext.h
+++ b/src/devices/bus/oricext/oricext.h
@@ -20,46 +20,53 @@ class oricext_connector: public device_t, public device_single_card_slot_interfa
friend class device_oricext_interface;
public:
- template <typename T, typename U>
- oricext_connector(const machine_config &mconfig, const char *tag, device_t *owner, T &&opts, const char *dflt, U &&cputag)
+ template <typename T>
+ oricext_connector(const machine_config &mconfig, const char *tag, device_t *owner, T &&opts, const char *dflt)
: oricext_connector(mconfig, tag, owner, (uint32_t)0)
{
option_reset();
opts(*this);
set_default_option(dflt);
set_fixed(false);
- set_cputag(std::forward<U>(cputag));
}
oricext_connector(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual ~oricext_connector();
- template <typename T> void set_cputag(T &&tag) { cpu.set_tag(std::forward<T>(tag)); }
auto irq_callback() { return irq_handler.bind(); }
+ auto reset_callback() { return reset_handler.bind(); }
+
void irq_w(int state);
+ void reset_w(int state);
+
+ void set_view(memory_view &view);
+ void map_io(address_space_installer &space);
+ void map_rom();
protected:
virtual void device_start() override;
devcb_write_line irq_handler;
- required_device<m6502_device> cpu;
+ devcb_write_line reset_handler;
};
class device_oricext_interface : public device_interface
{
public:
- DECLARE_WRITE_LINE_MEMBER(irq_w);
+ void irq_w(int state);
+ void reset_w(int state);
+
+ void set_view(memory_view &view);
+ virtual void map_io(address_space_installer &space) = 0;
+ virtual void map_rom() = 0;
protected:
device_oricext_interface(const machine_config &mconfig, device_t &device);
virtual void interface_pre_start() override;
- m6502_device *cpu;
+ memory_view *view;
oricext_connector *connector;
- memory_bank *bank_c000_r, *bank_e000_r, *bank_f800_r, *bank_c000_w, *bank_e000_w, *bank_f800_w;
- uint8_t *rom, *ram;
- uint8_t junk_read[8192], junk_write[8192];
};
DECLARE_DEVICE_TYPE(ORICEXT_CONNECTOR, oricext_connector)
diff --git a/src/devices/bus/pasopia/rampac2.cpp b/src/devices/bus/pasopia/rampac2.cpp
index 3c128a10266..21ec9c2baaa 100644
--- a/src/devices/bus/pasopia/rampac2.cpp
+++ b/src/devices/bus/pasopia/rampac2.cpp
@@ -88,8 +88,8 @@ void pasopia_rampac2_device::device_start()
bool pasopia_rampac2_device::nvram_read(util::read_stream &file)
{
- size_t actual;
- return !file.read(&m_ram[0], m_ram_size, actual) && actual == m_ram_size;
+ auto const [err, actual] = read(file, &m_ram[0], m_ram_size);
+ return !err && (actual == m_ram_size);
}
@@ -99,8 +99,8 @@ bool pasopia_rampac2_device::nvram_read(util::read_stream &file)
bool pasopia_rampac2_device::nvram_write(util::write_stream &file)
{
- size_t actual;
- return !file.write(&m_ram[0], m_ram_size, actual) && actual == m_ram_size;
+ auto const [err, actual] = write(file, &m_ram[0], m_ram_size);
+ return !err;
}
diff --git a/src/devices/bus/pc1512/mouse.cpp b/src/devices/bus/pc1512/mouse.cpp
index f1d92ce4df5..988716bbb78 100644
--- a/src/devices/bus/pc1512/mouse.cpp
+++ b/src/devices/bus/pc1512/mouse.cpp
@@ -69,12 +69,6 @@ pc1512_mouse_device::pc1512_mouse_device(const machine_config &mconfig, const ch
void pc1512_mouse_port_device::device_start()
{
m_device = get_card_device();
-
- // resolve callbacks
- m_write_x.resolve_safe();
- m_write_y.resolve_safe();
- m_write_m1.resolve_safe();
- m_write_m2.resolve_safe();
}
void pc1512_mouse_device::device_start()
diff --git a/src/devices/bus/pc8801/README.md b/src/devices/bus/pc8801/README.md
new file mode 100644
index 00000000000..1b0a7547cc7
--- /dev/null
+++ b/src/devices/bus/pc8801/README.md
@@ -0,0 +1,39 @@
+# PC-8801 EXPansion bus
+
+## List of known cards
+- NEC PC-8801-10
+ > MIDI interface
+- NEC PC-8801-11
+ > "Sound Board", single YM2203C OPN, single joy port, mono out
+- NEC PC-8801-12
+ > Modem board, full duplex 300bps
+- NEC PC-8801-13
+ > Parallel I/F board
+- NEC PC-8801-16
+ > extra μPD8086 CPU + 8253, 8255 and 8259 i/f, able to run MS-DOS 1.25, requires extra ROMs for both sides
+- NEC PC-8801-17
+- NEC PC-8801-18
+ > VTR capture card "Video art board" / "Video digitizing unit", 16-bit color
+- NEC PC-8801-21
+ > CMT i/f board
+- NEC PC-8801-22
+ > "Multi board B", upgrades a FH to MH and FA to MA (?)
+- NEC PC-8801-23
+- NEC PC-8801-24
+- NEC PC-8801-25
+ > "Sound Board 2", single YM2608 OPNA, single joy port, stereo out. -24 is the internal FH / MH version, -25 is the internal FE / FE2 with YM2608B. Standard and on main board instead for FA / MA and onward;
+- NEC PC-8801-30
+- NEC PC-8801-31
+ > -31 is CD-ROM SCSI i/f (built-in for MC, optional for MA+), -30 is virtually same to PC Engine CD-ROM² drive
+- NEC PC-8864
+ > Network board mapping at $a0-$a3
+- HAL PCG-8100
+ > PCG and 3x DAC_1BIT at I/O $01, $02. PIT at $0c-$0f
+- HAL GSX-8800
+ > 2x PSG at I/O $a0-$a3, mono out. Has goofy extra connector on top and a couple jumpers, guess it may cascade with another board for 2x extra PSGs at $a4-$a7
+- HIBIKI-8800
+ > YM2151 OPM + YM3802-X MIDI controller, stereo out, has own internal XTAL @ 4MHz. Has an undumped PAL/PROM labeled "HAL-881"
+- HAL HMB-20
+ > earlier version of HIBIKI-8800 board with no MIDI? cfr. GH [#10703](https://github.com/mamedev/mame/issues/10703)
+- JMB-X1
+ > "Sound Board X", 2x OPM + 1x SSG. Used by NRTDRV88J, more info at GH [#8709](https://github.com/mamedev/mame/issues/8709)
diff --git a/src/devices/bus/pc8801/hmb20.cpp b/src/devices/bus/pc8801/hmb20.cpp
new file mode 100644
index 00000000000..82fd4081f48
--- /dev/null
+++ b/src/devices/bus/pc8801/hmb20.cpp
@@ -0,0 +1,42 @@
+// license:BSD-3-Clause
+// copyright-holders:Angelo Salese
+/**************************************************************************************************
+
+ HAL HMB-20
+
+ Used by NRTDRV88 for PC-8801
+
+ TODO:
+ - Not extensively tested beyond on-disk songs, which in turn barely has an
+ OPM-driven "TESTTONE.NRD";
+ - Implement HIBIKI-8800 (same as this plus extra YM3802-X MIDI controller?)
+
+**************************************************************************************************/
+
+#include "emu.h"
+#include "hmb20.h"
+
+
+DEFINE_DEVICE_TYPE(HMB20, hmb20_device, "hmb20", "HAL HMB-20")
+
+hmb20_device::hmb20_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : pc8801_exp_device(mconfig, HMB20, tag, owner, clock)
+ , m_opm(*this, "opm")
+{
+}
+
+void hmb20_device::io_map(address_map &map)
+{
+ map(0x88, 0x89).rw(m_opm, FUNC(ym2151_device::read), FUNC(ym2151_device::write));
+}
+
+void hmb20_device::device_add_mconfig(machine_config &config)
+{
+ constexpr XTAL hmb20_x1_clock = XTAL(4'000'000);
+
+ // TODO: OPM mixing
+ YM2151(config, m_opm, hmb20_x1_clock);
+// m_opm->irq_handler().set(FUNC(hmb20_device::int4_w));
+ m_opm->add_route(ALL_OUTPUTS, "^^lspeaker", 0.50);
+ m_opm->add_route(ALL_OUTPUTS, "^^rspeaker", 0.50);
+}
diff --git a/src/devices/bus/pc8801/hmb20.h b/src/devices/bus/pc8801/hmb20.h
new file mode 100644
index 00000000000..3f2c4b61493
--- /dev/null
+++ b/src/devices/bus/pc8801/hmb20.h
@@ -0,0 +1,28 @@
+// license:BSD-3-Clause
+// copyright-holders:Angelo Salese
+
+#ifndef MAME_BUS_PC8801_HMB20_H
+#define MAME_BUS_PC8801_HMB20_H
+
+#pragma once
+
+#include "pc8801_exp.h"
+#include "sound/ymopm.h"
+
+class hmb20_device : public pc8801_exp_device
+{
+public:
+ hmb20_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void io_map(address_map &map) override;
+
+private:
+ virtual void device_add_mconfig(machine_config &config) override;
+
+ required_device<ym2151_device> m_opm;
+};
+
+DECLARE_DEVICE_TYPE(HMB20, hmb20_device)
+
+
+#endif // MAME_BUS_PC8801_HMB20_H
diff --git a/src/devices/bus/pc8801/jmbx1.cpp b/src/devices/bus/pc8801/jmbx1.cpp
index 33a48019a20..c868a7e2c7b 100644
--- a/src/devices/bus/pc8801/jmbx1.cpp
+++ b/src/devices/bus/pc8801/jmbx1.cpp
@@ -4,7 +4,7 @@
JMB-X1 sound card
- Used for PC-8001mkII/PC-8801 NRTDRV sound program
+ Used for PC-8001mkII/PC-8801 NRTDRV88J sound program
http://upd780c1.g1.xrea.com/pc-8001/j80-25.html
TODO:
diff --git a/src/devices/bus/pc8801/pc8801_23.cpp b/src/devices/bus/pc8801/pc8801_23.cpp
index f0b11773d2c..507f4e49c7b 100644
--- a/src/devices/bus/pc8801/pc8801_23.cpp
+++ b/src/devices/bus/pc8801/pc8801_23.cpp
@@ -81,7 +81,7 @@ void pc8801_23_device::irq_mask_w(u8 data)
int4_w(m_irq_pending);
}
-WRITE_LINE_MEMBER( pc8801_23_device::int4_w )
+void pc8801_23_device::int4_w(int state)
{
bool irq_state = (!m_irq_mask) & state;
pc8801_exp_device::int4_w(irq_state);
diff --git a/src/devices/bus/pc8801/pc8801_23.h b/src/devices/bus/pc8801/pc8801_23.h
index b112274c7d0..ed36a171b10 100644
--- a/src/devices/bus/pc8801/pc8801_23.h
+++ b/src/devices/bus/pc8801/pc8801_23.h
@@ -21,7 +21,7 @@ public:
protected:
virtual void device_start() override;
virtual void device_reset() override;
- virtual DECLARE_WRITE_LINE_MEMBER( int4_w ) override;
+ virtual void int4_w(int state) override;
private:
virtual void device_add_mconfig(machine_config &config) override;
diff --git a/src/devices/bus/pc8801/pc8801_31.cpp b/src/devices/bus/pc8801/pc8801_31.cpp
index f979e59162b..d125b9c9ad6 100644
--- a/src/devices/bus/pc8801/pc8801_31.cpp
+++ b/src/devices/bus/pc8801/pc8801_31.cpp
@@ -74,12 +74,6 @@ void pc8801_31_device::device_add_mconfig(machine_config &config)
// device_start - device-specific startup
//-------------------------------------------------
-void pc8801_31_device::device_resolve_objects()
-{
- m_rom_bank_cb.resolve();
-}
-
-
void pc8801_31_device::device_start()
{
m_sel_off_timer = timer_alloc(FUNC(pc8801_31_device::select_off), this);
diff --git a/src/devices/bus/pc8801/pc8801_31.h b/src/devices/bus/pc8801/pc8801_31.h
index fd580002610..e028d51528b 100644
--- a/src/devices/bus/pc8801/pc8801_31.h
+++ b/src/devices/bus/pc8801/pc8801_31.h
@@ -32,8 +32,7 @@ public:
void amap(address_map &map);
protected:
- // device-level overrides
- virtual void device_resolve_objects() override;
+ // device_t implementation
virtual void device_add_mconfig(machine_config &config) override;
virtual void device_start() override;
virtual void device_reset() override;
diff --git a/src/devices/bus/pc8801/pc8801_exp.cpp b/src/devices/bus/pc8801/pc8801_exp.cpp
index d99a6d252ff..b71c8b140a3 100644
--- a/src/devices/bus/pc8801/pc8801_exp.cpp
+++ b/src/devices/bus/pc8801/pc8801_exp.cpp
@@ -4,41 +4,11 @@
PC-8801 EXPansion bus
- List of known cards:
- \- NEC PC-8801-10
- (MIDI interface);
- \- NEC PC-8801-11
- ("Sound Board", single YM2203C OPN, single joy port, mono out);
- \- NEC PC-8801-12
- (Modem board, full duplex 300bps);
- \- NEC PC-8801-13
- (Parallel I/F board);
- \- NEC PC-8801-17 / -18
- (VTR capture card "Video art board" / "Video digitizing unit", 16-bit color);
- \- NEC PC-8801-21
- (CMT i/f board);
- \- NEC PC-8801-22
- ("Multi board B", upgrades a FH to MH and FA to MA (?));
- \- NEC PC-8801-23 & -24 & -25
- ("Sound Board 2", single YM2608 OPNA, single joy port, stereo out.
- -24 is the internal FH / MH version, -25 is the internal FE / FE2 with YM2608B.
- Standard and on main board instead for FA / MA and onward);
- \- NEC PC-8801-30 & -31
- (-31 is CD-ROM SCSI i/f, -30 is virtually same to PC Engine CD-ROM² drive)
- \- NEC PC-8864
- (Network board mapping at $a0-$a3)
- \- HAL PCG-8100
- (PCG and 3x DAC_1BIT at I/O $01, $02. PIT at $0c-$0f)
- \- HAL GSX-8800
- (2x PSG at I/O $a0-$a3, mono out. Has goofy extra connector on top and a couple jumpers,
- guess it may cascade with another board for 2x extra PSGs at $a4-$a7);
- \- HIBIKI-8800
- (YM2151 OPM + YM3802-X MIDI controller, stereo out, has own internal XTAL @ 4MHz.
- Has an undumped PAL/PROM labeled "HAL-881");
- \- HAL HMB-20
- (same as HIBIKI-8800 board?)
- \- JMB-X1
- ("Sound Board X", 2x OPM + 1x SSG. Used by NRTDRV, more info at GH #8709);
+ TODO:
+ - Extend for PC-88VA EXPansion bus
+ (can potentially access 16-bit iospace rather than 8 at very least);
+ - Transparent support for on-board ROMs;
+ - Implement device_mixer_interface for sound cards using it (GH #10746);
**************************************************************************************************/
@@ -65,13 +35,6 @@ void pc8801_exp_slot_device::device_start()
{
}
-void pc8801_exp_slot_device::device_resolve_objects()
-{
- m_int3_cb.resolve_safe();
- m_int4_cb.resolve_safe();
- m_int5_cb.resolve_safe();
-}
-
device_pc8801_exp_interface::device_pc8801_exp_interface(const machine_config &mconfig, device_t &device)
: device_interface(device, "pc8801exp")
{
@@ -95,9 +58,9 @@ void device_pc8801_exp_interface::interface_post_start()
// generic passthroughs to INT* lines
// NB: clients are responsible to handle irq masking just like base HW if available
-WRITE_LINE_MEMBER( device_pc8801_exp_interface::int3_w ) { m_slot->m_int3_cb(state); }
-WRITE_LINE_MEMBER( device_pc8801_exp_interface::int4_w ) { m_slot->m_int4_cb(state); }
-WRITE_LINE_MEMBER( device_pc8801_exp_interface::int5_w ) { m_slot->m_int5_cb(state); }
+void device_pc8801_exp_interface::int3_w(int state) { m_slot->m_int3_cb(state); }
+void device_pc8801_exp_interface::int4_w(int state) { m_slot->m_int4_cb(state); }
+void device_pc8801_exp_interface::int5_w(int state) { m_slot->m_int5_cb(state); }
pc8801_exp_device::pc8801_exp_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, type, tag, owner, clock)
@@ -116,11 +79,14 @@ void pc8801_exp_device::device_start()
#include "pcg8100.h"
#include "pc8801_23.h"
#include "jmbx1.h"
+#include "hmb20.h"
void pc8801_exp_devices(device_slot_interface &device)
{
device.option_add("sbii", PC8801_23);
device.option_add("pcg8100", PCG8100);
+
device.option_add("jmbx1", JMBX1);
+ device.option_add("hmb20", HMB20);
}
diff --git a/src/devices/bus/pc8801/pc8801_exp.h b/src/devices/bus/pc8801/pc8801_exp.h
index f3f540a1c9b..411d15e5fe8 100644
--- a/src/devices/bus/pc8801/pc8801_exp.h
+++ b/src/devices/bus/pc8801/pc8801_exp.h
@@ -38,9 +38,8 @@ public:
auto int5_callback() { return m_int5_cb.bind(); }
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
- virtual void device_resolve_objects() override;
private:
required_address_space m_iospace;
@@ -68,9 +67,9 @@ protected:
pc8801_exp_slot_device *m_slot;
- DECLARE_WRITE_LINE_MEMBER( int3_w );
- virtual DECLARE_WRITE_LINE_MEMBER( int4_w );
- DECLARE_WRITE_LINE_MEMBER( int5_w );
+ void int3_w(int state);
+ virtual void int4_w(int state);
+ void int5_w(int state);
};
class pc8801_exp_device : public device_t, public device_pc8801_exp_interface
diff --git a/src/devices/bus/pc_joy/pc_joy.cpp b/src/devices/bus/pc_joy/pc_joy.cpp
index 2171a9ddbf7..98bd20deaef 100644
--- a/src/devices/bus/pc_joy/pc_joy.cpp
+++ b/src/devices/bus/pc_joy/pc_joy.cpp
@@ -10,6 +10,7 @@
#include "emu.h"
#include "pc_joy.h"
+#include "pc_joy_magnum6.h"
#include "pc_joy_sw.h"
DEFINE_DEVICE_TYPE(PC_JOY, pc_joy_device, "pc_joy", "PC joystick port")
@@ -84,8 +85,8 @@ ioport_constructor pc_basic_joy_device::device_input_ports() const
DEFINE_DEVICE_TYPE(PC_BASIC_JOY, pc_basic_joy_device, "pc_basic_joy", "PC basic joystick")
-pc_basic_joy_device::pc_basic_joy_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, PC_BASIC_JOY, tag, owner, clock),
+pc_basic_joy_device::pc_basic_joy_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, type, tag, owner, clock),
device_pc_joy_interface(mconfig, *this),
m_btn(*this, "btn"),
m_x1(*this, "x1"),
@@ -95,8 +96,14 @@ pc_basic_joy_device::pc_basic_joy_device(const machine_config &mconfig, const ch
{
}
+pc_basic_joy_device::pc_basic_joy_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ pc_basic_joy_device(mconfig, PC_BASIC_JOY, tag, owner, clock)
+{
+}
+
void pc_joysticks(device_slot_interface &device)
{
- device.option_add("basic_joy", PC_BASIC_JOY);
- device.option_add("mssw_pad", PC_MSSW_PAD);
+ device.option_add("basic_joy", PC_BASIC_JOY);
+ device.option_add("magnum6_pad", PC_MAGNUM6_PAD);
+ device.option_add("mssw_pad", PC_MSSW_PAD);
}
diff --git a/src/devices/bus/pc_joy/pc_joy.h b/src/devices/bus/pc_joy/pc_joy.h
index e09520f6436..7ad13fa97f6 100644
--- a/src/devices/bus/pc_joy/pc_joy.h
+++ b/src/devices/bus/pc_joy/pc_joy.h
@@ -65,10 +65,13 @@ public:
virtual uint8_t btn() override { return m_btn->read(); }
protected:
+ pc_basic_joy_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock = 0);
+
virtual void device_start() override { }
-private:
required_ioport m_btn;
+
+private:
required_ioport m_x1;
required_ioport m_y1;
required_ioport m_x2;
diff --git a/src/devices/bus/pc_joy/pc_joy_magnum6.cpp b/src/devices/bus/pc_joy/pc_joy_magnum6.cpp
new file mode 100644
index 00000000000..578f97701e0
--- /dev/null
+++ b/src/devices/bus/pc_joy/pc_joy_magnum6.cpp
@@ -0,0 +1,41 @@
+// license:BSD-3-Clause
+// copyright-holders:Angelo Salese
+
+#include "emu.h"
+#include "pc_joy_magnum6.h"
+
+DEFINE_DEVICE_TYPE(PC_MAGNUM6_PAD, pc_joy_magnum6_device, "magnum6_pad", "Interact Magnum 6 Game Controller")
+
+
+pc_joy_magnum6_device::pc_joy_magnum6_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock)
+ : pc_basic_joy_device(mconfig, PC_MAGNUM6_PAD, tag, owner, clock)
+{
+}
+
+static INPUT_PORTS_START( magnum6 )
+ // TODO: input modes (4-button with throttle and 4-way view)
+ PORT_START("btn")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("Joystick 1 Button A")
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("Joystick 1 Button B")
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("Joystick 1 Button C")
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_NAME("Joystick 1 Button D")
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_NAME("Joystick 1 Button R")
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_NAME("Joystick 1 Button L")
+
+ PORT_START("x1")
+ PORT_BIT(0xff, 0x80, IPT_AD_STICK_X ) PORT_SENSITIVITY(100) PORT_KEYDELTA(10) PORT_MINMAX(1,0xff) PORT_CODE_DEC(KEYCODE_LEFT) PORT_CODE_INC(KEYCODE_RIGHT) PORT_CODE_DEC(JOYCODE_X_LEFT_SWITCH) PORT_CODE_INC(JOYCODE_X_RIGHT_SWITCH)
+
+ PORT_START("y1")
+ PORT_BIT(0xff, 0x80, IPT_AD_STICK_Y ) PORT_SENSITIVITY(100) PORT_KEYDELTA(10) PORT_MINMAX(1,0xff) PORT_CODE_DEC(KEYCODE_UP) PORT_CODE_INC(KEYCODE_DOWN) PORT_CODE_DEC(JOYCODE_Y_UP_SWITCH) PORT_CODE_INC(JOYCODE_Y_DOWN_SWITCH)
+
+ PORT_START("x2")
+ PORT_BIT(0xff, IP_ACTIVE_LOW, IPT_UNUSED )
+
+ PORT_START("y2")
+ PORT_BIT(0xff, IP_ACTIVE_LOW, IPT_UNUSED )
+INPUT_PORTS_END
+
+ioport_constructor pc_joy_magnum6_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( magnum6 );
+}
diff --git a/src/devices/bus/pc_joy/pc_joy_magnum6.h b/src/devices/bus/pc_joy/pc_joy_magnum6.h
new file mode 100644
index 00000000000..c08fe34cdfa
--- /dev/null
+++ b/src/devices/bus/pc_joy/pc_joy_magnum6.h
@@ -0,0 +1,24 @@
+// license:BSD-3-Clause
+// copyright-holders:Angelo Salese
+
+#ifndef MAME_BUS_PC_JOY_MAGNUM6_H
+#define MAME_BUS_PC_JOY_MAGNUM6_H
+
+#include "pc_joy.h"
+
+class pc_joy_magnum6_device : public pc_basic_joy_device
+{
+public:
+ pc_joy_magnum6_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
+
+ static constexpr feature_type imperfect_features() { return feature::CONTROLS; }
+
+ virtual uint8_t x2(int delta) override { return BIT(m_btn->read(), 4); }
+ virtual uint8_t y2(int delta) override { return BIT(m_btn->read(), 5); }
+
+ virtual ioport_constructor device_input_ports() const override;
+};
+
+DECLARE_DEVICE_TYPE(PC_MAGNUM6_PAD, pc_joy_magnum6_device)
+
+#endif // MAME_BUS_PC_JOY_MAGNUM6_H
diff --git a/src/devices/bus/pc_kbd/cherry_mx1500.cpp b/src/devices/bus/pc_kbd/cherry_mx1500.cpp
index 4fc451d8354..c0f796d40e6 100644
--- a/src/devices/bus/pc_kbd/cherry_mx1500.cpp
+++ b/src/devices/bus/pc_kbd/cherry_mx1500.cpp
@@ -63,7 +63,7 @@ static INPUT_PORTS_START(g80_1500)
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("O") PORT_CHAR('o') PORT_CHAR('O') PORT_CODE(KEYCODE_O)
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('9') PORT_CHAR('(') PORT_CODE(KEYCODE_9) PORT_CONDITION("CONFIG", 3, EQUALS, 0)
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('9') PORT_CHAR(')') PORT_CHAR(']') PORT_CODE(KEYCODE_9) PORT_CONDITION("CONFIG", 3, EQUALS, 1)
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(0x00e7) PORT_CHAR('9') PORT_CHAR('^') PORT_CODE(KEYCODE_9) PORT_CONDITION("CONFIG", 3, EQUALS, 2)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(U'ç') PORT_CHAR('9') PORT_CHAR('^') PORT_CODE(KEYCODE_9) PORT_CONDITION("CONFIG", 3, EQUALS, 2)
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(ENTER_PAD)) PORT_CODE(KEYCODE_ENTER_PAD)
PORT_START("ROW1")
@@ -71,7 +71,7 @@ static INPUT_PORTS_START(g80_1500)
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(MINUS_PAD)) PORT_CODE(KEYCODE_MINUS_PAD)
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(3_PAD)) PORT_CODE(KEYCODE_3_PAD)
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("M") PORT_CHAR('m') PORT_CHAR('M') PORT_CODE(KEYCODE_M) PORT_CONDITION("CONFIG", 3, EQUALS, 0)
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("M \xCE\xBC") PORT_CHAR('m') PORT_CHAR('M') PORT_CHAR(0x03bc) PORT_CODE(KEYCODE_M) PORT_CONDITION("CONFIG", 3, EQUALS, 1)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(u8"M μ") PORT_CHAR('m') PORT_CHAR('M') PORT_CHAR(U'μ') PORT_CODE(KEYCODE_M) PORT_CONDITION("CONFIG", 3, EQUALS, 1)
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(',') PORT_CHAR('?') PORT_CODE(KEYCODE_M) PORT_CONDITION("CONFIG", 3, EQUALS, 2)
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("K") PORT_CHAR('k') PORT_CHAR('K') PORT_CODE(KEYCODE_K)
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("I") PORT_CHAR('i') PORT_CHAR('I') PORT_CODE(KEYCODE_I)
@@ -87,12 +87,12 @@ static INPUT_PORTS_START(g80_1500)
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(RSHIFT)) PORT_CODE(KEYCODE_RSHIFT)
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_UNUSED) PORT_CONDITION("CONFIG", 3, EQUALS, 0) // INT 2 key
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('#') PORT_CHAR('\'') PORT_CODE(KEYCODE_BACKSLASH) PORT_CONDITION("CONFIG", 3, EQUALS, 1)
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('*') PORT_CHAR(0x03bc) PORT_CODE(KEYCODE_BACKSLASH) PORT_CONDITION("CONFIG", 3, EQUALS, 2)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('*') PORT_CHAR(U'μ') PORT_CODE(KEYCODE_BACKSLASH) PORT_CONDITION("CONFIG", 3, EQUALS, 2)
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(']') PORT_CHAR('}') PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CONDITION("CONFIG", 3, EQUALS, 0)
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('+') PORT_CHAR('*') PORT_CHAR('~') PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CONDITION("CONFIG", 3, EQUALS, 1)
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('$') PORT_CHAR(0x00a3) PORT_CHAR(0x00a4) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CONDITION("CONFIG", 3, EQUALS, 2)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('$') PORT_CHAR(U'£') PORT_CHAR(U'¤') PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CONDITION("CONFIG", 3, EQUALS, 2)
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('=') PORT_CHAR('+') PORT_CODE(KEYCODE_EQUALS) PORT_CONDITION("CONFIG", 3, EQUALS, 0)
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("\xC2\xB4 `") PORT_CODE(KEYCODE_EQUALS) PORT_CONDITION("CONFIG", 3, EQUALS, 1)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(U'´') PORT_CHAR('`') PORT_CODE(KEYCODE_EQUALS) PORT_CONDITION("CONFIG", 3, EQUALS, 1)
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('=') PORT_CHAR('+') PORT_CHAR('}') PORT_CODE(KEYCODE_EQUALS) PORT_CONDITION("CONFIG", 3, EQUALS, 2)
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(DOWN)) PORT_CODE(KEYCODE_DOWN)
@@ -102,16 +102,16 @@ static INPUT_PORTS_START(g80_1500)
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(END)) PORT_CODE(KEYCODE_END)
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('/') PORT_CHAR('?') PORT_CODE(KEYCODE_SLASH) PORT_CONDITION("CONFIG", 3, EQUALS, 0)
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('-') PORT_CHAR('_') PORT_CODE(KEYCODE_SLASH) PORT_CONDITION("CONFIG", 3, EQUALS, 1)
- PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('!') PORT_CHAR(0x00a7) PORT_CODE(KEYCODE_SLASH) PORT_CONDITION("CONFIG", 3, EQUALS, 2)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('!') PORT_CHAR(U'§') PORT_CODE(KEYCODE_SLASH) PORT_CONDITION("CONFIG", 3, EQUALS, 2)
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('\'') PORT_CHAR('"') PORT_CODE(KEYCODE_QUOTE) PORT_CONDITION("CONFIG", 3, EQUALS, 0)
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("\xC3\x84") PORT_CHAR(0x00e4) PORT_CHAR(0x00c4) PORT_CODE(KEYCODE_QUOTE) PORT_CONDITION("CONFIG", 3, EQUALS, 1)
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(0x00f9) PORT_CHAR('%') PORT_CODE(KEYCODE_QUOTE) PORT_CONDITION("CONFIG", 3, EQUALS, 2)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(U'Ä',U'ä') PORT_CODE(KEYCODE_QUOTE) PORT_CONDITION("CONFIG", 3, EQUALS, 1)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(U'ù') PORT_CHAR('%') PORT_CODE(KEYCODE_QUOTE) PORT_CONDITION("CONFIG", 3, EQUALS, 2)
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('[') PORT_CHAR('{') PORT_CODE(KEYCODE_OPENBRACE) PORT_CONDITION("CONFIG", 3, EQUALS, 0)
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("\xC3\x9C") PORT_CHAR(0x00fc) PORT_CHAR(0x00dc) PORT_CODE(KEYCODE_OPENBRACE) PORT_CONDITION("CONFIG", 3, EQUALS, 1)
- PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("^ \xC2\xA8") PORT_CODE(KEYCODE_OPENBRACE) PORT_CONDITION("CONFIG", 3, EQUALS, 2)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(U'Ü',U'ü') PORT_CODE(KEYCODE_OPENBRACE) PORT_CONDITION("CONFIG", 3, EQUALS, 1)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(u8"^ ¨") PORT_CODE(KEYCODE_OPENBRACE) PORT_CONDITION("CONFIG", 3, EQUALS, 2)
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('-') PORT_CHAR('_') PORT_CODE(KEYCODE_MINUS) PORT_CONDITION("CONFIG", 3, EQUALS, 0)
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(0x00df) PORT_CHAR('?') PORT_CHAR('\\') PORT_CODE(KEYCODE_MINUS) PORT_CONDITION("CONFIG", 3, EQUALS, 1)
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(')') PORT_CHAR(0x00b0) PORT_CHAR(']') PORT_CODE(KEYCODE_MINUS) PORT_CONDITION("CONFIG", 3, EQUALS, 2)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(U'ß') PORT_CHAR('?') PORT_CHAR('\\') PORT_CODE(KEYCODE_MINUS) PORT_CONDITION("CONFIG", 3, EQUALS, 1)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(')') PORT_CHAR(U'°') PORT_CHAR(']') PORT_CODE(KEYCODE_MINUS) PORT_CONDITION("CONFIG", 3, EQUALS, 2)
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(LEFT)) PORT_CODE(KEYCODE_LEFT)
PORT_START("ROW4")
@@ -122,12 +122,12 @@ static INPUT_PORTS_START(g80_1500)
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('.') PORT_CHAR(':') PORT_CODE(KEYCODE_STOP) PORT_CONDITION("CONFIG", 3, EQUALS, 1)
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(':') PORT_CHAR('/') PORT_CODE(KEYCODE_STOP) PORT_CONDITION("CONFIG", 3, EQUALS, 2)
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(';') PORT_CHAR(':') PORT_CODE(KEYCODE_COLON) PORT_CONDITION("CONFIG", 3, EQUALS, 0)
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("\xC3\x96") PORT_CHAR(0x00f6) PORT_CHAR(0x00d6) PORT_CODE(KEYCODE_COLON) PORT_CONDITION("CONFIG", 3, EQUALS, 1)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(u8"Ö") PORT_CHAR(U'ö') PORT_CHAR(U'Ö') PORT_CODE(KEYCODE_COLON) PORT_CONDITION("CONFIG", 3, EQUALS, 1)
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("M") PORT_CHAR('m') PORT_CHAR('M') PORT_CODE(KEYCODE_COLON) PORT_CONDITION("CONFIG", 3, EQUALS, 2)
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("P") PORT_CHAR('p') PORT_CHAR('P') PORT_CODE(KEYCODE_P)
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('0') PORT_CHAR(')') PORT_CODE(KEYCODE_0) PORT_CONDITION("CONFIG", 3, EQUALS, 0)
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('0') PORT_CHAR('=') PORT_CHAR('}') PORT_CODE(KEYCODE_0) PORT_CONDITION("CONFIG", 3, EQUALS, 1)
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(0x00e0) PORT_CHAR('0') PORT_CHAR('@') PORT_CODE(KEYCODE_0) PORT_CONDITION("CONFIG", 3, EQUALS, 2)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(U'à') PORT_CHAR('0') PORT_CHAR('@') PORT_CODE(KEYCODE_0) PORT_CONDITION("CONFIG", 3, EQUALS, 2)
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(RCONTROL)) PORT_CODE(KEYCODE_RCONTROL)
PORT_START("ROW5")
@@ -139,7 +139,7 @@ static INPUT_PORTS_START(g80_1500)
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("U") PORT_CHAR('u') PORT_CHAR('U') PORT_CODE(KEYCODE_U)
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('7') PORT_CHAR('&') PORT_CODE(KEYCODE_7) PORT_CONDITION("CONFIG", 3, EQUALS, 0)
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('7') PORT_CHAR('/') PORT_CHAR('{') PORT_CODE(KEYCODE_7) PORT_CONDITION("CONFIG", 3, EQUALS, 1)
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(0x00e8) PORT_CHAR('7') PORT_CHAR('`') PORT_CODE(KEYCODE_7) PORT_CONDITION("CONFIG", 3, EQUALS, 2)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(U'è') PORT_CHAR('7') PORT_CHAR('`') PORT_CODE(KEYCODE_7) PORT_CONDITION("CONFIG", 3, EQUALS, 2)
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Esc") PORT_CHAR(0x1b) PORT_CODE(KEYCODE_ESC)
PORT_START("ROW6")
@@ -161,7 +161,7 @@ static INPUT_PORTS_START(g80_1500)
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("D") PORT_CHAR('d') PORT_CHAR('D') PORT_CODE(KEYCODE_D)
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("E") PORT_CHAR('e') PORT_CHAR('E') PORT_CODE(KEYCODE_E)
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('3') PORT_CHAR('#') PORT_CODE(KEYCODE_3) PORT_CONDITION("CONFIG", 3, EQUALS, 0)
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('3') PORT_CHAR(0x00a7) PORT_CHAR(0x00b3) PORT_CODE(KEYCODE_3) PORT_CONDITION("CONFIG", 3, EQUALS, 1)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('3') PORT_CHAR(U'§') PORT_CHAR(U'³') PORT_CODE(KEYCODE_3) PORT_CONDITION("CONFIG", 3, EQUALS, 1)
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('"') PORT_CHAR('3') PORT_CHAR('#') PORT_CODE(KEYCODE_3) PORT_CONDITION("CONFIG", 3, EQUALS, 2)
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(0_PAD)) PORT_CODE(KEYCODE_0_PAD)
@@ -176,8 +176,8 @@ static INPUT_PORTS_START(g80_1500)
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("W") PORT_CHAR('w') PORT_CHAR('W') PORT_CODE(KEYCODE_W) PORT_CONDITION("CONFIG", 3, NOTEQUALS, 2)
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Z") PORT_CHAR('z') PORT_CHAR('Z') PORT_CODE(KEYCODE_W) PORT_CONDITION("CONFIG", 3, EQUALS, 2)
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('2') PORT_CHAR('@') PORT_CODE(KEYCODE_2) PORT_CONDITION("CONFIG", 3, EQUALS, 0)
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('2') PORT_CHAR('"') PORT_CHAR(0x00b2) PORT_CODE(KEYCODE_2) PORT_CONDITION("CONFIG", 3, EQUALS, 1)
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(0x00e9) PORT_CHAR('2') PORT_CHAR('~') PORT_CODE(KEYCODE_2) PORT_CONDITION("CONFIG", 3, EQUALS, 2)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('2') PORT_CHAR('"') PORT_CHAR(U'²') PORT_CODE(KEYCODE_2) PORT_CONDITION("CONFIG", 3, EQUALS, 1)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(U'é') PORT_CHAR('2') PORT_CHAR('~') PORT_CODE(KEYCODE_2) PORT_CONDITION("CONFIG", 3, EQUALS, 2)
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(RIGHT)) PORT_CODE(KEYCODE_RIGHT)
PORT_START("ROW9")
@@ -204,8 +204,8 @@ static INPUT_PORTS_START(g80_1500)
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(CAPSLOCK)) PORT_CODE(KEYCODE_CAPSLOCK)
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(0x09) PORT_CODE(KEYCODE_TAB)
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('`') PORT_CHAR('~') PORT_CODE(KEYCODE_TILDE) PORT_CONDITION("CONFIG", 3, EQUALS, 0)
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('^') PORT_CHAR(0x00b0) PORT_CODE(KEYCODE_TILDE) PORT_CONDITION("CONFIG", 3, EQUALS, 1)
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(0x00b2) PORT_CODE(KEYCODE_TILDE) PORT_CONDITION("CONFIG", 3, EQUALS, 2)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('^') PORT_CHAR(U'°') PORT_CODE(KEYCODE_TILDE) PORT_CONDITION("CONFIG", 3, EQUALS, 1)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(U'²') PORT_CODE(KEYCODE_TILDE) PORT_CONDITION("CONFIG", 3, EQUALS, 2)
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(' ') PORT_CODE(KEYCODE_SPACE)
PORT_START("ROW11")
@@ -241,7 +241,7 @@ ioport_constructor cherry_g80_1500_device::device_input_ports() const
}
-WRITE_LINE_MEMBER(cherry_g80_1500_device::data_write)
+void cherry_g80_1500_device::data_write(int state)
{
m_mcu->set_input_line(MCS51_INT1_LINE, state ? CLEAR_LINE : ASSERT_LINE);
}
diff --git a/src/devices/bus/pc_kbd/cherry_mx1500.h b/src/devices/bus/pc_kbd/cherry_mx1500.h
index 902ee7a40f8..5bdabe34642 100644
--- a/src/devices/bus/pc_kbd/cherry_mx1500.h
+++ b/src/devices/bus/pc_kbd/cherry_mx1500.h
@@ -14,7 +14,7 @@ public:
cherry_g80_1500_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
protected:
- virtual DECLARE_WRITE_LINE_MEMBER(data_write) override;
+ virtual void data_write(int state) override;
virtual ioport_constructor device_input_ports() const override;
virtual void device_start() override;
diff --git a/src/devices/bus/pc_kbd/ec1841.cpp b/src/devices/bus/pc_kbd/ec1841.cpp
index a7cc897cb8a..9f189e7456d 100644
--- a/src/devices/bus/pc_kbd/ec1841.cpp
+++ b/src/devices/bus/pc_kbd/ec1841.cpp
@@ -35,9 +35,8 @@
#include "ec1841.h"
-//#define LOG_GENERAL (1U << 0) //defined in logmacro.h already
-#define LOG_KEYBOARD (1U << 1)
-#define LOG_DEBUG (1U << 2)
+#define LOG_KEYBOARD (1U << 1)
+#define LOG_DEBUG (1U << 2)
//#define VERBOSE (LOG_DEBUG)
//#define LOG_OUTPUT_FUNC printf
@@ -127,7 +126,7 @@ INPUT_PORTS_START( ec_1841_keyboard )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D')
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C')
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Rus/Lat R") PORT_CODE(KEYCODE_RCONTROL) PORT_CHAR(UCHAR_MAMEKEY(RCONTROL)) // scancode 0x5a
- PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Keypad 8 " UTF8_UP) PORT_CODE(KEYCODE_8_PAD) PORT_CHAR(UCHAR_MAMEKEY(8_PAD))
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"Keypad 8 \u2191") PORT_CODE(KEYCODE_8_PAD) PORT_CHAR(UCHAR_MAMEKEY(8_PAD)) // U+2191 = ↑
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED )
@@ -147,7 +146,7 @@ INPUT_PORTS_START( ec_1841_keyboard )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G')
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B')
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F1) PORT_CHAR(UCHAR_MAMEKEY(F1))
- PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Keypad 4 " UTF8_LEFT) PORT_CODE(KEYCODE_4_PAD) PORT_CHAR(UCHAR_MAMEKEY(4_PAD))
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"Keypad 4 \u2190") PORT_CODE(KEYCODE_4_PAD) PORT_CHAR(UCHAR_MAMEKEY(4_PAD)) // U+2190 = ←
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED )
@@ -167,7 +166,7 @@ INPUT_PORTS_START( ec_1841_keyboard )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J')
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M')
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F3) PORT_CHAR(UCHAR_MAMEKEY(F3))
- PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Keypad 6 " UTF8_RIGHT) PORT_CODE(KEYCODE_6_PAD) PORT_CHAR(UCHAR_MAMEKEY(6_PAD))
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"Keypad 6 \u2192") PORT_CODE(KEYCODE_6_PAD) PORT_CHAR(UCHAR_MAMEKEY(6_PAD)) // U+2192 = →
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED )
@@ -185,9 +184,9 @@ INPUT_PORTS_START( ec_1841_keyboard )
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('&')
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I')
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L')
- PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("~ \xd0\xae") PORT_CODE(KEYCODE_BACKSLASH2) PORT_CHAR('~') // scancode 0x2a, Cyrillic Yu
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"~ Ю") PORT_CODE(KEYCODE_BACKSLASH2) PORT_CHAR('~') // scancode 0x2a, Cyrillic Yu
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F5) PORT_CHAR(UCHAR_MAMEKEY(F5))
- PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Keypad 2 " UTF8_DOWN) PORT_CODE(KEYCODE_2_PAD) PORT_CHAR(UCHAR_MAMEKEY(2_PAD))
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"Keypad 2 \u2193") PORT_CODE(KEYCODE_2_PAD) PORT_CHAR(UCHAR_MAMEKEY(2_PAD)) // U+2193 = ↓
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED )
@@ -195,7 +194,7 @@ INPUT_PORTS_START( ec_1841_keyboard )
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('*')
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O')
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('[') PORT_CHAR('[')
- PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("\xd0\x81") PORT_CODE(KEYCODE_ENTER_PAD) PORT_CHAR(UCHAR_MAMEKEY(ENTER_PAD)) // scancode 0x5c, Cyrillic Io
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"Ё") PORT_CODE(KEYCODE_ENTER_PAD) PORT_CHAR(UCHAR_MAMEKEY(ENTER_PAD)) // scancode 0x5c, Cyrillic Io
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F6) PORT_CHAR(UCHAR_MAMEKEY(F6))
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Keypad 3 PgDn") PORT_CODE(KEYCODE_3_PAD) PORT_CHAR(UCHAR_MAMEKEY(3_PAD))
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED )
@@ -213,7 +212,7 @@ INPUT_PORTS_START( ec_1841_keyboard )
PORT_START("MD11")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR(')')
- PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("{ \xd0\xa5") PORT_CODE(KEYCODE_SLASH_PAD) PORT_CHAR('{') // scancode 0x36, Cyrillic Ha
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"{ Х") PORT_CODE(KEYCODE_SLASH_PAD) PORT_CHAR('{') // scancode 0x36, Cyrillic Ha
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR('\'')
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>')
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F8) PORT_CHAR(UCHAR_MAMEKEY(F8))
@@ -223,7 +222,7 @@ INPUT_PORTS_START( ec_1841_keyboard )
PORT_START("MD12")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHAR('_')
- PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("} \xd0\xaa") PORT_CODE(KEYCODE_ASTERISK) PORT_CHAR('}') // scancode 0x3a, Cyrillic Hard sign
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"} Ъ") PORT_CODE(KEYCODE_ASTERISK) PORT_CHAR('}') // scancode 0x3a, Cyrillic Hard sign
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(':') PORT_CHAR('"')
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_RSHIFT) PORT_CHAR(UCHAR_SHIFT_1) PORT_CHAR(UCHAR_MAMEKEY(RSHIFT)) // scancode 0x55
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F9) PORT_CHAR(UCHAR_MAMEKEY(F9))
@@ -243,7 +242,7 @@ INPUT_PORTS_START( ec_1841_keyboard )
PORT_START("MD14")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('\\') PORT_CHAR('|')
- PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("* PrtSc") PORT_CODE(KEYCODE_PRTSCR) PORT_CHAR(UCHAR_MAMEKEY(PRTSCR))
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("* PrtSc") PORT_CODE(KEYCODE_PRTSCR) PORT_CHAR(UCHAR_MAMEKEY(PRTSCR))
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_LALT) PORT_CHAR(UCHAR_MAMEKEY(LALT))
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Lat") PORT_CODE(KEYCODE_F11) PORT_CHAR(UCHAR_MAMEKEY(F11)) // scancode 0x57
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_NUMLOCK) PORT_CHAR(UCHAR_MAMEKEY(NUMLOCK))
@@ -324,7 +323,7 @@ void ec_1841_keyboard_device::device_reset()
// clock_write -
//-------------------------------------------------
-WRITE_LINE_MEMBER( ec_1841_keyboard_device::clock_write )
+void ec_1841_keyboard_device::clock_write(int state)
{
LOG("clock write %d\n", state);
}
@@ -334,7 +333,7 @@ WRITE_LINE_MEMBER( ec_1841_keyboard_device::clock_write )
// data_write -
//-------------------------------------------------
-WRITE_LINE_MEMBER( ec_1841_keyboard_device::data_write )
+void ec_1841_keyboard_device::data_write(int state)
{
LOG("data write %d\n", state);
}
@@ -439,7 +438,7 @@ void ec_1841_keyboard_device::p2_w(uint8_t data)
// t1_r -
//-------------------------------------------------
-READ_LINE_MEMBER( ec_1841_keyboard_device::t1_r )
+int ec_1841_keyboard_device::t1_r()
{
if (BIT(m_p2,0)) {
m_q = 1;
diff --git a/src/devices/bus/pc_kbd/ec1841.h b/src/devices/bus/pc_kbd/ec1841.h
index 08309b35d9e..cade4b56eee 100644
--- a/src/devices/bus/pc_kbd/ec1841.h
+++ b/src/devices/bus/pc_kbd/ec1841.h
@@ -39,15 +39,15 @@ protected:
virtual ioport_constructor device_input_ports() const override;
// device_pc_kbd_interface overrides
- virtual DECLARE_WRITE_LINE_MEMBER( clock_write ) override;
- virtual DECLARE_WRITE_LINE_MEMBER( data_write ) override;
+ virtual void clock_write(int state) override;
+ virtual void data_write(int state) override;
private:
void bus_w(uint8_t data);
uint8_t p1_r();
void p1_w(uint8_t data);
void p2_w(uint8_t data);
- DECLARE_READ_LINE_MEMBER( t1_r );
+ int t1_r();
required_device<i8048_device> m_maincpu;
required_ioport_array<16> m_kbd;
diff --git a/src/devices/bus/pc_kbd/hle_mouse.cpp b/src/devices/bus/pc_kbd/hle_mouse.cpp
index 15ac7854d09..507a3be8d94 100644
--- a/src/devices/bus/pc_kbd/hle_mouse.cpp
+++ b/src/devices/bus/pc_kbd/hle_mouse.cpp
@@ -37,7 +37,6 @@
#include "emu.h"
#include "hle_mouse.h"
-#define LOG_GENERAL (1U << 0)
#define LOG_RXTX (1U << 1)
#define LOG_COMMAND (1U << 2)
#define LOG_REPORT (1U << 3)
diff --git a/src/devices/bus/pc_kbd/iskr1030.cpp b/src/devices/bus/pc_kbd/iskr1030.cpp
index 5a39c103b50..78b2bfcd09c 100644
--- a/src/devices/bus/pc_kbd/iskr1030.cpp
+++ b/src/devices/bus/pc_kbd/iskr1030.cpp
@@ -10,9 +10,8 @@
#include "iskr1030.h"
-//#define LOG_GENERAL (1U << 0) //defined in logmacro.h already
-#define LOG_KEYBOARD (1U << 1)
-#define LOG_DEBUG (1U << 2)
+#define LOG_KEYBOARD (1U << 1)
+#define LOG_DEBUG (1U << 2)
//#define VERBOSE (LOG_DEBUG)
//#define LOG_OUTPUT_FUNC printf
@@ -317,7 +316,7 @@ void iskr_1030_keyboard_device::device_reset()
// clock_write -
//-------------------------------------------------
-WRITE_LINE_MEMBER( iskr_1030_keyboard_device::clock_write )
+void iskr_1030_keyboard_device::clock_write(int state)
{
LOG("clock write %d\n", state);
m_maincpu->set_input_line(MCS48_INPUT_IRQ, state ? CLEAR_LINE : ASSERT_LINE);
@@ -328,7 +327,7 @@ WRITE_LINE_MEMBER( iskr_1030_keyboard_device::clock_write )
// data_write -
//-------------------------------------------------
-WRITE_LINE_MEMBER( iskr_1030_keyboard_device::data_write )
+void iskr_1030_keyboard_device::data_write(int state)
{
LOG("data write %d\n", state);
}
@@ -338,7 +337,7 @@ WRITE_LINE_MEMBER( iskr_1030_keyboard_device::data_write )
// t1_r -
//-------------------------------------------------
-READ_LINE_MEMBER( iskr_1030_keyboard_device::t1_r )
+int iskr_1030_keyboard_device::t1_r()
{
uint8_t data = data_signal();
uint8_t bias = m_p1 & 15;
diff --git a/src/devices/bus/pc_kbd/iskr1030.h b/src/devices/bus/pc_kbd/iskr1030.h
index 5c849a2b6b0..8d4224eb5f2 100644
--- a/src/devices/bus/pc_kbd/iskr1030.h
+++ b/src/devices/bus/pc_kbd/iskr1030.h
@@ -40,14 +40,14 @@ protected:
virtual ioport_constructor device_input_ports() const override;
// device_pc_kbd_interface overrides
- virtual DECLARE_WRITE_LINE_MEMBER( clock_write ) override;
- virtual DECLARE_WRITE_LINE_MEMBER( data_write ) override;
+ virtual void clock_write(int state) override;
+ virtual void data_write(int state) override;
private:
uint8_t p1_r();
void p1_w(uint8_t data);
void p2_w(uint8_t data);
- DECLARE_READ_LINE_MEMBER( t1_r );
+ int t1_r();
uint8_t ram_r(offs_t offset);
void ram_w(offs_t offset, uint8_t data);
diff --git a/src/devices/bus/pc_kbd/keytro.cpp b/src/devices/bus/pc_kbd/keytro.cpp
index d178bfceb6f..53a140894e7 100644
--- a/src/devices/bus/pc_kbd/keytro.cpp
+++ b/src/devices/bus/pc_kbd/keytro.cpp
@@ -456,13 +456,13 @@ const tiny_rom_entry *pc_kbd_keytronic_pc3270_device::device_rom_region() const
}
-WRITE_LINE_MEMBER( pc_kbd_keytronic_pc3270_device::clock_write )
+void pc_kbd_keytronic_pc3270_device::clock_write(int state)
{
m_cpu->set_input_line(MCS51_INT0_LINE, state ? CLEAR_LINE : ASSERT_LINE);
}
-WRITE_LINE_MEMBER( pc_kbd_keytronic_pc3270_device::data_write )
+void pc_kbd_keytronic_pc3270_device::data_write(int state)
{
m_cpu->set_input_line(MCS51_T0_LINE, state);
}
diff --git a/src/devices/bus/pc_kbd/keytro.h b/src/devices/bus/pc_kbd/keytro.h
index 8fb6f021967..3ba6b6a583e 100644
--- a/src/devices/bus/pc_kbd/keytro.h
+++ b/src/devices/bus/pc_kbd/keytro.h
@@ -44,8 +44,8 @@ protected:
virtual ioport_constructor device_input_ports() const override;
virtual const tiny_rom_entry *device_rom_region() const override;
- virtual DECLARE_WRITE_LINE_MEMBER(clock_write) override;
- virtual DECLARE_WRITE_LINE_MEMBER(data_write) override;
+ virtual void clock_write(int state) override;
+ virtual void data_write(int state) override;
uint8_t internal_data_read(offs_t offset);
void internal_data_write(offs_t offset, uint8_t data);
diff --git a/src/devices/bus/pc_kbd/msnat.cpp b/src/devices/bus/pc_kbd/msnat.cpp
index 058a1ef39ff..bc6310c9465 100644
--- a/src/devices/bus/pc_kbd/msnat.cpp
+++ b/src/devices/bus/pc_kbd/msnat.cpp
@@ -272,12 +272,12 @@ const tiny_rom_entry *pc_kbd_microsoft_natural_device::device_rom_region() const
}
-WRITE_LINE_MEMBER( pc_kbd_microsoft_natural_device::clock_write )
+void pc_kbd_microsoft_natural_device::clock_write(int state)
{
}
-WRITE_LINE_MEMBER( pc_kbd_microsoft_natural_device::data_write )
+void pc_kbd_microsoft_natural_device::data_write(int state)
{
}
diff --git a/src/devices/bus/pc_kbd/msnat.h b/src/devices/bus/pc_kbd/msnat.h
index 6ec5327675e..01a1d325a67 100644
--- a/src/devices/bus/pc_kbd/msnat.h
+++ b/src/devices/bus/pc_kbd/msnat.h
@@ -35,8 +35,8 @@ protected:
virtual ioport_constructor device_input_ports() const override;
virtual const tiny_rom_entry *device_rom_region() const override;
- virtual DECLARE_WRITE_LINE_MEMBER(clock_write) override;
- virtual DECLARE_WRITE_LINE_MEMBER(data_write) override;
+ virtual void clock_write(int state) override;
+ virtual void data_write(int state) override;
private:
required_device<i8051_device> m_cpu;
diff --git a/src/devices/bus/pc_kbd/pc83.cpp b/src/devices/bus/pc_kbd/pc83.cpp
index 5e214660257..53c85c4d254 100644
--- a/src/devices/bus/pc_kbd/pc83.cpp
+++ b/src/devices/bus/pc_kbd/pc83.cpp
@@ -346,7 +346,7 @@ void ibm_pc_83_keyboard_device::p2_w(uint8_t data)
// t0_r -
//-------------------------------------------------
-READ_LINE_MEMBER( ibm_pc_83_keyboard_device::t0_r )
+int ibm_pc_83_keyboard_device::t0_r()
{
uint8_t data = 0xff;
diff --git a/src/devices/bus/pc_kbd/pc83.h b/src/devices/bus/pc_kbd/pc83.h
index 44b58dfbc7f..ea1c762e6dd 100644
--- a/src/devices/bus/pc_kbd/pc83.h
+++ b/src/devices/bus/pc_kbd/pc83.h
@@ -41,14 +41,14 @@ protected:
virtual ioport_constructor device_input_ports() const override;
// device_pc_kbd_interface overrides
- virtual DECLARE_WRITE_LINE_MEMBER( clock_write ) override { }
- virtual DECLARE_WRITE_LINE_MEMBER( data_write ) override { }
+ virtual void clock_write(int state) override { }
+ virtual void data_write(int state) override { }
private:
void bus_w(uint8_t data);
uint8_t p1_r();
void p2_w(uint8_t data);
- DECLARE_READ_LINE_MEMBER( t0_r );
+ int t0_r();
required_device<i8048_device> m_maincpu;
required_ioport_array<24> m_dr;
diff --git a/src/devices/bus/pc_kbd/pc_kbdc.cpp b/src/devices/bus/pc_kbd/pc_kbdc.cpp
index 4461648de7f..4eee89f4188 100644
--- a/src/devices/bus/pc_kbd/pc_kbdc.cpp
+++ b/src/devices/bus/pc_kbd/pc_kbdc.cpp
@@ -61,9 +61,6 @@ void pc_kbdc_device::device_resolve_objects()
device_pc_kbd_interface *const pc_kbd = get_card_device();
if (pc_kbd)
pc_kbd->set_pc_kbdc(this);
-
- m_out_clock_cb.resolve_safe();
- m_out_data_cb.resolve_safe();
}
void pc_kbdc_device::device_start()
@@ -126,28 +123,28 @@ void pc_kbdc_device::update_data_state(bool fromkb)
}
-WRITE_LINE_MEMBER(pc_kbdc_device::clock_write_from_mb)
+void pc_kbdc_device::clock_write_from_mb(int state)
{
m_mb_clock_state = state;
update_clock_state(false);
}
-WRITE_LINE_MEMBER(pc_kbdc_device::data_write_from_mb)
+void pc_kbdc_device::data_write_from_mb(int state)
{
m_mb_data_state = state;
update_data_state(false);
}
-WRITE_LINE_MEMBER(pc_kbdc_device::clock_write_from_kb)
+void pc_kbdc_device::clock_write_from_kb(int state)
{
m_kb_clock_state = state;
update_clock_state(true);
}
-WRITE_LINE_MEMBER(pc_kbdc_device::data_write_from_kb)
+void pc_kbdc_device::data_write_from_kb(int state)
{
m_kb_data_state = state;
update_data_state(true);
@@ -179,12 +176,12 @@ device_pc_kbd_interface::~device_pc_kbd_interface()
}
-WRITE_LINE_MEMBER(device_pc_kbd_interface::clock_write)
+void device_pc_kbd_interface::clock_write(int state)
{
}
-WRITE_LINE_MEMBER(device_pc_kbd_interface::data_write)
+void device_pc_kbd_interface::data_write(int state)
{
}
diff --git a/src/devices/bus/pc_kbd/pc_kbdc.h b/src/devices/bus/pc_kbd/pc_kbdc.h
index 4cbff6fc890..dbbf8024872 100644
--- a/src/devices/bus/pc_kbd/pc_kbdc.h
+++ b/src/devices/bus/pc_kbd/pc_kbdc.h
@@ -46,10 +46,10 @@ public:
int clock_signal() { return m_clock_state; }
int data_signal() { return m_data_state; }
- DECLARE_WRITE_LINE_MEMBER( clock_write_from_mb );
- DECLARE_WRITE_LINE_MEMBER( data_write_from_mb );
- DECLARE_WRITE_LINE_MEMBER( clock_write_from_kb );
- DECLARE_WRITE_LINE_MEMBER( data_write_from_kb );
+ void clock_write_from_mb(int state);
+ void data_write_from_mb(int state);
+ void clock_write_from_kb(int state);
+ void data_write_from_kb(int state);
protected:
// device-level overrides
@@ -91,8 +91,8 @@ public:
//
// Override the clock_write and data_write methods in a keyboard implementation
//
- virtual DECLARE_WRITE_LINE_MEMBER( clock_write );
- virtual DECLARE_WRITE_LINE_MEMBER( data_write );
+ virtual void clock_write(int state);
+ virtual void data_write(int state);
// inline configuration
void set_pc_kbdc(device_t *kbdc_device) { m_pc_kbdc = dynamic_cast<pc_kbdc_device *>(kbdc_device); }
diff --git a/src/devices/bus/pc_kbd/pcat101.cpp b/src/devices/bus/pc_kbd/pcat101.cpp
index 955e9d17f48..20f9f1b057a 100644
--- a/src/devices/bus/pc_kbd/pcat101.cpp
+++ b/src/devices/bus/pc_kbd/pcat101.cpp
@@ -18,7 +18,6 @@
#include "emu.h"
#include "pcat101.h"
-#define LOG_GENERAL (1U << 0)
#define LOG_RXTX (1U << 1)
//#define VERBOSE (LOG_GENERAL|LOG_RXTX)
diff --git a/src/devices/bus/pc_kbd/pcat84.cpp b/src/devices/bus/pc_kbd/pcat84.cpp
index a3796a7408a..0d0d10fe664 100644
--- a/src/devices/bus/pc_kbd/pcat84.cpp
+++ b/src/devices/bus/pc_kbd/pcat84.cpp
@@ -255,7 +255,7 @@ INPUT_PORTS_START( ibm_pc_at_84_keyboard )
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Keypad 1 End") PORT_CODE(KEYCODE_1_PAD) PORT_CHAR(UCHAR_MAMEKEY(1_PAD))
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED )
- PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Keypad 4 " UTF8_LEFT) PORT_CODE(KEYCODE_4_PAD) PORT_CHAR(UCHAR_MAMEKEY(4_PAD))
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"Keypad 4 \u2190") PORT_CODE(KEYCODE_4_PAD) PORT_CHAR(UCHAR_MAMEKEY(4_PAD)) // U+2190 = ←
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Keypad 7 Home") PORT_CODE(KEYCODE_7_PAD) PORT_CHAR(UCHAR_MAMEKEY(7_PAD))
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED )
@@ -264,10 +264,10 @@ INPUT_PORTS_START( ibm_pc_at_84_keyboard )
PORT_START("DR14")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Keypad 0 Ins") PORT_CODE(KEYCODE_0_PAD) PORT_CHAR(UCHAR_MAMEKEY(0_PAD))
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Keypad . Del") PORT_CODE(KEYCODE_DEL_PAD) PORT_CHAR(UCHAR_MAMEKEY(DEL_PAD))
- PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Keypad 2 " UTF8_DOWN) PORT_CODE(KEYCODE_2_PAD) PORT_CHAR(UCHAR_MAMEKEY(2_PAD))
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"Keypad 2 \u2193") PORT_CODE(KEYCODE_2_PAD) PORT_CHAR(UCHAR_MAMEKEY(2_PAD)) // U+2193 = ↓
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_5_PAD) PORT_CHAR(UCHAR_MAMEKEY(5_PAD))
- PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Keypad 6 " UTF8_RIGHT) PORT_CODE(KEYCODE_6_PAD) PORT_CHAR(UCHAR_MAMEKEY(6_PAD))
- PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Keypad 8 " UTF8_UP) PORT_CODE(KEYCODE_8_PAD) PORT_CHAR(UCHAR_MAMEKEY(8_PAD))
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"Keypad 6 \u2192") PORT_CODE(KEYCODE_6_PAD) PORT_CHAR(UCHAR_MAMEKEY(6_PAD)) // U+2192 = →
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"Keypad 8 \u2191") PORT_CODE(KEYCODE_8_PAD) PORT_CHAR(UCHAR_MAMEKEY(8_PAD)) // U+2191 = ↑
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_ESC) PORT_CHAR(UCHAR_MAMEKEY(ESC))
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_NUMLOCK) PORT_CHAR(UCHAR_MAMEKEY(NUMLOCK))
@@ -543,7 +543,7 @@ void ibm_pc_at_84_keyboard_device::p2_w(uint8_t data)
// t0_r -
//-------------------------------------------------
-READ_LINE_MEMBER( ibm_pc_at_84_keyboard_device::t0_r )
+int ibm_pc_at_84_keyboard_device::t0_r()
{
return !data_signal();
}
@@ -553,7 +553,7 @@ READ_LINE_MEMBER( ibm_pc_at_84_keyboard_device::t0_r )
// t1_r -
//-------------------------------------------------
-READ_LINE_MEMBER( ibm_pc_at_84_keyboard_device::t1_r )
+int ibm_pc_at_84_keyboard_device::t1_r()
{
return key_depressed();
}
diff --git a/src/devices/bus/pc_kbd/pcat84.h b/src/devices/bus/pc_kbd/pcat84.h
index 3953786f900..b9f6374eaca 100644
--- a/src/devices/bus/pc_kbd/pcat84.h
+++ b/src/devices/bus/pc_kbd/pcat84.h
@@ -43,8 +43,8 @@ protected:
virtual ioport_constructor device_input_ports() const override;
// device_pc_kbd_interface overrides
- virtual DECLARE_WRITE_LINE_MEMBER( clock_write ) override { m_maincpu->set_input_line(MCS48_INPUT_IRQ, state); }
- virtual DECLARE_WRITE_LINE_MEMBER( data_write ) override { }
+ virtual void clock_write(int state) override { m_maincpu->set_input_line(MCS48_INPUT_IRQ, state); }
+ virtual void data_write(int state) override { }
private:
void bus_w(uint8_t data);
@@ -52,8 +52,8 @@ private:
void p1_w(uint8_t data);
uint8_t p2_r();
void p2_w(uint8_t data);
- DECLARE_READ_LINE_MEMBER( t0_r );
- DECLARE_READ_LINE_MEMBER( t1_r );
+ int t0_r();
+ int t1_r();
enum
{
diff --git a/src/devices/bus/pc_kbd/pcxt83.cpp b/src/devices/bus/pc_kbd/pcxt83.cpp
index 728d858845f..9d5379ba80e 100644
--- a/src/devices/bus/pc_kbd/pcxt83.cpp
+++ b/src/devices/bus/pc_kbd/pcxt83.cpp
@@ -93,7 +93,7 @@ INPUT_PORTS_START( ibm_pc_xt_83_keyboard )
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_PLUS_PAD) PORT_CHAR(UCHAR_MAMEKEY(PLUS_PAD))
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Keypad 3 PgDn") PORT_CODE(KEYCODE_3_PAD) PORT_CHAR(UCHAR_MAMEKEY(3_PAD))
- PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Keypad 6 " UTF8_RIGHT) PORT_CODE(KEYCODE_6_PAD) PORT_CHAR(UCHAR_MAMEKEY(6_PAD))
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"Keypad 6 \u2192") PORT_CODE(KEYCODE_6_PAD) PORT_CHAR(UCHAR_MAMEKEY(6_PAD)) // U+2192 = →
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_MINUS_PAD) PORT_CHAR(UCHAR_MAMEKEY(MINUS_PAD))
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Keypad 9 PgUp") PORT_CODE(KEYCODE_9_PAD) PORT_CHAR(UCHAR_MAMEKEY(9_PAD))
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED )
@@ -101,12 +101,12 @@ INPUT_PORTS_START( ibm_pc_xt_83_keyboard )
PORT_START("MD01")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Keypad . Del") PORT_CODE(KEYCODE_DEL_PAD) PORT_CHAR(UCHAR_MAMEKEY(DEL_PAD))
- PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Keypad 2 " UTF8_DOWN) PORT_CODE(KEYCODE_2_PAD) PORT_CHAR(UCHAR_MAMEKEY(2_PAD))
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"Keypad 2 \u2193") PORT_CODE(KEYCODE_2_PAD) PORT_CHAR(UCHAR_MAMEKEY(2_PAD)) // U+2193 = ↓
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Keypad 1 End") PORT_CODE(KEYCODE_1_PAD) PORT_CHAR(UCHAR_MAMEKEY(1_PAD))
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_5_PAD) PORT_CHAR(UCHAR_MAMEKEY(5_PAD))
- PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Keypad 4 " UTF8_LEFT) PORT_CODE(KEYCODE_4_PAD) PORT_CHAR(UCHAR_MAMEKEY(4_PAD))
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"Keypad 4 \u2190") PORT_CODE(KEYCODE_4_PAD) PORT_CHAR(UCHAR_MAMEKEY(4_PAD)) // U+2190 = ←
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Keypad 7 Home") PORT_CODE(KEYCODE_7_PAD) PORT_CHAR(UCHAR_MAMEKEY(7_PAD))
- PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("Keypad 8 " UTF8_UP) PORT_CODE(KEYCODE_8_PAD) PORT_CHAR(UCHAR_MAMEKEY(8_PAD))
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"Keypad 8 \u2191") PORT_CODE(KEYCODE_8_PAD) PORT_CHAR(UCHAR_MAMEKEY(8_PAD)) // U+2191 = ↑
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_NUMLOCK) PORT_CHAR(UCHAR_MAMEKEY(NUMLOCK))
PORT_START("MD02")
@@ -274,7 +274,7 @@ void ibm_pc_xt_83_keyboard_device::device_reset()
// clock_write -
//-------------------------------------------------
-WRITE_LINE_MEMBER( ibm_pc_xt_83_keyboard_device::clock_write )
+void ibm_pc_xt_83_keyboard_device::clock_write(int state)
{
}
@@ -283,7 +283,7 @@ WRITE_LINE_MEMBER( ibm_pc_xt_83_keyboard_device::clock_write )
// data_write -
//-------------------------------------------------
-WRITE_LINE_MEMBER( ibm_pc_xt_83_keyboard_device::data_write )
+void ibm_pc_xt_83_keyboard_device::data_write(int state)
{
m_maincpu->set_input_line(MCS48_INPUT_IRQ, state ? CLEAR_LINE : ASSERT_LINE);
}
@@ -407,7 +407,7 @@ void ibm_pc_xt_83_keyboard_device::p2_w(uint8_t data)
// t0_r -
//-------------------------------------------------
-READ_LINE_MEMBER( ibm_pc_xt_83_keyboard_device::t0_r )
+int ibm_pc_xt_83_keyboard_device::t0_r()
{
return clock_signal();
}
@@ -417,7 +417,7 @@ READ_LINE_MEMBER( ibm_pc_xt_83_keyboard_device::t0_r )
// t1_r -
//-------------------------------------------------
-READ_LINE_MEMBER( ibm_pc_xt_83_keyboard_device::t1_r )
+int ibm_pc_xt_83_keyboard_device::t1_r()
{
return BIT(m_p2, 3) && m_q;
}
diff --git a/src/devices/bus/pc_kbd/pcxt83.h b/src/devices/bus/pc_kbd/pcxt83.h
index 6044141610e..d12ceade4fc 100644
--- a/src/devices/bus/pc_kbd/pcxt83.h
+++ b/src/devices/bus/pc_kbd/pcxt83.h
@@ -40,16 +40,16 @@ protected:
virtual ioport_constructor device_input_ports() const override;
// device_pc_kbd_interface overrides
- virtual DECLARE_WRITE_LINE_MEMBER( clock_write ) override;
- virtual DECLARE_WRITE_LINE_MEMBER( data_write ) override;
+ virtual void clock_write(int state) override;
+ virtual void data_write(int state) override;
private:
uint8_t bus_r();
void bus_w(uint8_t data);
void p1_w(uint8_t data);
void p2_w(uint8_t data);
- DECLARE_READ_LINE_MEMBER( t0_r );
- DECLARE_READ_LINE_MEMBER( t1_r );
+ int t0_r();
+ int t1_r();
required_device<i8048_device> m_maincpu;
required_ioport_array<12> m_md;
diff --git a/src/devices/bus/pce/pce_acard.cpp b/src/devices/bus/pce/pce_acard.cpp
new file mode 100644
index 00000000000..833f78e9536
--- /dev/null
+++ b/src/devices/bus/pce/pce_acard.cpp
@@ -0,0 +1,232 @@
+// license:BSD-3-Clause
+// copyright-holders:Fabio Priuli, Angelo Salese
+/***********************************************************************************************************
+
+
+ PC-Engine Arcade Card emulation
+
+ TODO:
+ - Proper Arcade Card Duo support
+
+ ***********************************************************************************************************/
+
+
+#include "emu.h"
+#include "pce_acard.h"
+
+
+
+//-------------------------------------------------
+// pce_acard_device - constructor
+//-------------------------------------------------
+
+DEFINE_DEVICE_TYPE(PCE_ROM_ACARD_DUO, pce_acard_duo_device, "pce_acard_duo", "Arcade Card Duo")
+DEFINE_DEVICE_TYPE(PCE_ROM_ACARD_PRO, pce_acard_pro_device, "pce_acard_pro", "Arcade Card Pro")
+
+
+pce_acard_duo_device::pce_acard_duo_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, type, tag, owner, clock)
+ , device_pce_cart_interface( mconfig, *this )
+ , m_ram(*this, "ram", 0x200000, ENDIANNESS_LITTLE)
+ , m_shift(0)
+ , m_shift_reg(0)
+ , m_rotate_reg(0)
+{
+}
+
+pce_acard_duo_device::pce_acard_duo_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : pce_acard_duo_device(mconfig, PCE_ROM_ACARD_DUO, tag, owner, clock)
+{
+}
+
+pce_acard_pro_device::pce_acard_pro_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : pce_acard_duo_device(mconfig, PCE_ROM_ACARD_PRO, tag, owner, clock)
+ , m_scdsys()
+{
+}
+
+
+//-------------------------------------------------
+// mapper specific start/reset
+//-------------------------------------------------
+
+
+void pce_acard_duo_device::device_start()
+{
+ save_item(STRUCT_MEMBER(m_port, m_ctrl));
+ save_item(STRUCT_MEMBER(m_port, m_base_addr));
+ save_item(STRUCT_MEMBER(m_port, m_addr_offset));
+ save_item(STRUCT_MEMBER(m_port, m_addr_inc));
+ save_item(NAME(m_shift));
+ save_item(NAME(m_shift_reg));
+ save_item(NAME(m_rotate_reg));
+}
+
+void pce_acard_pro_device::device_start()
+{
+ pce_acard_duo_device::device_start();
+
+ m_scdsys.init(*this);
+ m_scdsys.set_region(false);
+}
+
+void pce_acard_duo_device::device_reset()
+{
+ for (auto &port : m_port)
+ {
+ port.m_ctrl = 0;
+ port.m_base_addr = 0;
+ port.m_addr_offset = 0;
+ port.m_addr_inc = 0;
+ }
+ m_shift = 0;
+ m_shift_reg = 0;
+ m_rotate_reg = 0;
+}
+
+/*-------------------------------------------------
+ mapper specific handlers
+ -------------------------------------------------*/
+
+void pce_acard_duo_device::install_memory_handlers(address_space &space)
+{
+ space.install_readwrite_handler(0x080000, 0x087fff, emu::rw_delegate(*this, FUNC(pce_acard_duo_device::ram_r)), emu::rw_delegate(*this, FUNC(pce_acard_duo_device::ram_w)));
+ // TODO: mirrored?
+ space.install_readwrite_handler(0x1ffa00, 0x1ffaff, 0, 0x100, 0, emu::rw_delegate(*this, FUNC(pce_acard_duo_device::peripheral_r)), emu::rw_delegate(*this, FUNC(pce_acard_duo_device::peripheral_w)));
+}
+
+void pce_acard_pro_device::install_memory_handlers(address_space &space)
+{
+ space.install_rom(0x000000, 0x03ffff, 0x040000, m_rom); // TODO: underdumped or mirrored?
+ space.install_ram(0x0d0000, 0x0fffff, m_scdsys.ram());
+ space.install_read_handler(0x1ff8c0, 0x1ff8c7, 0, 0x130, 0, emu::rw_delegate(*this, FUNC(pce_acard_pro_device::register_r)));
+ pce_acard_duo_device::install_memory_handlers(space);
+}
+
+uint8_t pce_acard_duo_device::ram_r(offs_t offset)
+{
+ return peripheral_r((offset & 0x6000) >> 9);
+}
+
+void pce_acard_duo_device::ram_w(offs_t offset, uint8_t data)
+{
+ peripheral_w((offset & 0x6000) >> 9, data);
+}
+
+uint8_t pce_acard_duo_device::peripheral_r(offs_t offset)
+{
+ if ((offset & 0xe0) == 0xe0)
+ {
+ switch (offset & 0x1f)
+ {
+ case 0x00: return (m_shift >> 0) & 0xff;
+ case 0x01: return (m_shift >> 8) & 0xff;
+ case 0x02: return (m_shift >> 16) & 0xff;
+ case 0x03: return (m_shift >> 24) & 0xff;
+ case 0x04: return m_shift_reg;
+ case 0x05: return m_rotate_reg;
+ case 0x1c: return 0x00;
+ case 0x1d: return 0x00;
+ case 0x1e: return 0x10; // Version number (MSB?)
+ case 0x1f: return 0x51; // Arcade Card ID
+ }
+
+ return 0xff;
+ }
+
+ dram_port &port = m_port[(offset & 0x30) >> 4];
+
+ switch (offset & 0x8f)
+ {
+ case 0x00:
+ case 0x01:
+ {
+ uint8_t const res = m_ram[port.ram_addr()];
+
+ if (!machine().side_effects_disabled())
+ port.addr_increment();
+
+ return res;
+ }
+ case 0x02: return (port.m_base_addr >> 0) & 0xff;
+ case 0x03: return (port.m_base_addr >> 8) & 0xff;
+ case 0x04: return (port.m_base_addr >> 16) & 0xff;
+ case 0x05: return (port.m_addr_offset >> 0) & 0xff;
+ case 0x06: return (port.m_addr_offset >> 8) & 0xff;
+ case 0x07: return (port.m_addr_inc >> 0) & 0xff;
+ case 0x08: return (port.m_addr_inc >> 8) & 0xff;
+ case 0x09: return port.m_ctrl;
+ default: return 0xff;
+ }
+}
+
+void pce_acard_duo_device::peripheral_w(offs_t offset, uint8_t data)
+{
+ if ((offset & 0xe0) == 0xe0)
+ {
+ switch (offset & 0x0f)
+ {
+ case 0: m_shift = (data & 0xff) | (m_shift & 0xffffff00); break;
+ case 1: m_shift = (data << 8) | (m_shift & 0xffff00ff); break;
+ case 2: m_shift = (data << 16) | (m_shift & 0xff00ffff); break;
+ case 3: m_shift = (data << 24) | (m_shift & 0x00ffffff); break;
+ case 4:
+ m_shift_reg = data & 0x0f;
+
+ if (m_shift_reg != 0)
+ {
+ m_shift = (m_shift_reg < 8)
+ ? (m_shift << m_shift_reg)
+ : (m_shift >> (16 - m_shift_reg));
+ }
+ break;
+ case 5:
+ m_rotate_reg = data & 0x0f;
+
+ if (m_rotate_reg != 0)
+ {
+ m_shift = (m_rotate_reg < 8)
+ ? ((m_shift << m_rotate_reg) | (m_shift >> (32 - m_rotate_reg)))
+ : ((m_shift >> (16 - m_rotate_reg)) | (m_shift << (32 - (16 - m_rotate_reg))));
+ }
+ break;
+ }
+ }
+ else
+ {
+ dram_port &port = m_port[(offset & 0x30) >> 4];
+
+ switch (offset & 0x8f)
+ {
+ case 0x00:
+ case 0x01:
+ m_ram[port.ram_addr()] = data;
+
+ port.addr_increment();
+ break;
+
+ case 0x02: port.m_base_addr = (data & 0xff) | (port.m_base_addr & 0xffff00); break;
+ case 0x03: port.m_base_addr = (data << 8) | (port.m_base_addr & 0xff00ff); break;
+ case 0x04: port.m_base_addr = (data << 16) | (port.m_base_addr & 0x00ffff); break;
+ case 0x05:
+ port.m_addr_offset = (data & 0xff) | (port.m_addr_offset & 0xff00);
+
+ if ((port.m_ctrl & 0x60) == 0x20)
+ port.adjust_addr();
+ break;
+ case 0x06:
+ port.m_addr_offset = (data << 8) | (port.m_addr_offset & 0x00ff);
+
+ if ((port.m_ctrl & 0x60) == 0x40)
+ port.adjust_addr();
+ break;
+ case 0x07: port.m_addr_inc = (data & 0xff) | (port.m_addr_inc & 0xff00); break;
+ case 0x08: port.m_addr_inc = (data << 8) | (port.m_addr_inc & 0x00ff); break;
+ case 0x09: port.m_ctrl = data & 0x7f; break;
+ case 0x0a:
+ if ((port.m_ctrl & 0x60) == 0x60)
+ port.adjust_addr();
+ break;
+ }
+ }
+}
diff --git a/src/devices/bus/pce/pce_acard.h b/src/devices/bus/pce/pce_acard.h
new file mode 100644
index 00000000000..2c3622ac2b2
--- /dev/null
+++ b/src/devices/bus/pce/pce_acard.h
@@ -0,0 +1,114 @@
+// license:BSD-3-Clause
+// copyright-holders:Fabio Priuli, Angelo Salese
+#ifndef MAME_BUS_PCE_PCE_ACARD_H
+#define MAME_BUS_PCE_PCE_ACARD_H
+
+#pragma once
+
+#include "pce_scdsys.h"
+#include "pce_slot.h"
+
+
+// ======================> pce_acard_duo_device
+
+class pce_acard_duo_device : public device_t,
+ public device_pce_cart_interface
+{
+public:
+ // construction/destruction
+ pce_acard_duo_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ // reading and writing
+ virtual void install_memory_handlers(address_space &space) override;
+
+protected:
+ // construction/destruction
+ pce_acard_duo_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+private:
+ uint8_t ram_r(offs_t offset);
+ void ram_w(offs_t offset, uint8_t data);
+ uint8_t peripheral_r(offs_t offset);
+ void peripheral_w(offs_t offset, uint8_t data);
+
+ /* Arcade Card specific */
+ memory_share_creator<uint8_t> m_ram;
+
+ struct dram_port
+ {
+ uint32_t ram_addr()
+ {
+ if (BIT(m_ctrl, 1))
+ return (m_base_addr + m_addr_offset + (BIT(m_ctrl, 3) ? 0xff0000 : 0)) & 0x1fffff;
+ else
+ return m_base_addr & 0x1fffff;
+ }
+
+ void addr_increment()
+ {
+ if (BIT(m_ctrl, 0))
+ {
+ if (BIT(m_ctrl, 4))
+ {
+ m_base_addr += m_addr_inc;
+ m_base_addr &= 0xffffff;
+ }
+ else
+ {
+ m_addr_offset += m_addr_inc;
+ }
+ }
+ }
+
+ void adjust_addr()
+ {
+ m_base_addr += m_addr_offset + (BIT(m_ctrl, 3) ? 0xff0000 : 0);
+ m_base_addr &= 0xffffff;
+ }
+
+ uint8_t m_ctrl;
+ uint32_t m_base_addr;
+ uint16_t m_addr_offset;
+ uint16_t m_addr_inc;
+ };
+
+ dram_port m_port[4];
+ uint32_t m_shift;
+ uint8_t m_shift_reg;
+ uint8_t m_rotate_reg;
+};
+
+
+// ======================> pce_acard_duo_device
+
+class pce_acard_pro_device : public pce_acard_duo_device
+
+{
+public:
+ // construction/destruction
+ pce_acard_pro_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ // reading and writing
+ virtual void install_memory_handlers(address_space &space) override;
+
+protected:
+ virtual void device_start() override;
+
+private:
+ pce_scdsys_shared m_scdsys;
+
+ // reading
+ uint8_t register_r(offs_t offset) { return m_scdsys.register_r(offset); }
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(PCE_ROM_ACARD_DUO, pce_acard_duo_device)
+DECLARE_DEVICE_TYPE(PCE_ROM_ACARD_PRO, pce_acard_pro_device)
+
+
+#endif // MAME_BUS_PCE_PCE_ACARD_H
diff --git a/src/devices/bus/pce/pce_rom.cpp b/src/devices/bus/pce/pce_rom.cpp
index fea0d9f7dcc..374fedf595b 100644
--- a/src/devices/bus/pce/pce_rom.cpp
+++ b/src/devices/bus/pce/pce_rom.cpp
@@ -3,7 +3,7 @@
/***********************************************************************************************************
- PC-Engine & Turbografx-16 cart emulation
+ PC-Engine & Turbografx-16 HuCard emulation
***********************************************************************************************************/
@@ -18,16 +18,15 @@
// pce_rom_device - constructor
//-------------------------------------------------
-DEFINE_DEVICE_TYPE(PCE_ROM_STD, pce_rom_device, "pce_rom", "PCE/TG16 Carts")
-DEFINE_DEVICE_TYPE(PCE_ROM_CDSYS3, pce_cdsys3_device, "pce_cdsys3", "PCE/TG16 CD-System Cart v3.00")
-DEFINE_DEVICE_TYPE(PCE_ROM_POPULOUS, pce_populous_device, "pce_populous", "PCE Populous Cart")
-DEFINE_DEVICE_TYPE(PCE_ROM_SF2, pce_sf2_device, "pce_sf2", "PCE Street Fighter 2 CE Cart")
-DEFINE_DEVICE_TYPE(PCE_ROM_TENNOKOE, pce_tennokoe_device, "pce_tennokoe", "PCE Tennokoe Bank Cart")
+DEFINE_DEVICE_TYPE(PCE_ROM_STD, pce_rom_device, "pce_rom", "PCE/TG16 HuCards")
+DEFINE_DEVICE_TYPE(PCE_ROM_POPULOUS, pce_populous_device, "pce_populous", "PCE Populous HuCard")
+DEFINE_DEVICE_TYPE(PCE_ROM_SF2, pce_sf2_device, "pce_sf2", "PCE Street Fighter 2 CE HuCard")
+DEFINE_DEVICE_TYPE(PCE_ROM_TENNOKOE, pce_tennokoe_device, "pce_tennokoe", "PCE Tennokoe Bank HuCard")
pce_rom_device::pce_rom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, type, tag, owner, clock)
- , device_pce_cart_interface( mconfig, *this )
+ , device_pce_cart_interface(mconfig, *this)
{
}
@@ -36,24 +35,20 @@ pce_rom_device::pce_rom_device(const machine_config &mconfig, const char *tag, d
{
}
-pce_cdsys3_device::pce_cdsys3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : pce_rom_device(mconfig, PCE_ROM_CDSYS3, tag, owner, clock)
-{
-}
-
pce_populous_device::pce_populous_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: pce_rom_device(mconfig, PCE_ROM_POPULOUS, tag, owner, clock)
{
}
pce_sf2_device::pce_sf2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : pce_rom_device(mconfig, PCE_ROM_SF2, tag, owner, clock), m_bank_base(0)
+ : pce_rom_device(mconfig, PCE_ROM_SF2, tag, owner, clock)
+ , m_rom_bank(*this, "rom_bank")
{
}
pce_tennokoe_device::pce_tennokoe_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : pce_rom_device(mconfig, PCE_ROM_TENNOKOE, tag, owner, clock),
- device_nvram_interface(mconfig, *this)
+ : pce_rom_device(mconfig, PCE_ROM_TENNOKOE, tag, owner, clock)
+ , device_nvram_interface(mconfig, *this)
{
}
@@ -63,14 +58,9 @@ pce_tennokoe_device::pce_tennokoe_device(const machine_config &mconfig, const ch
//-------------------------------------------------
-void pce_sf2_device::device_start()
-{
- save_item(NAME(m_bank_base));
-}
-
void pce_sf2_device::device_reset()
{
- m_bank_base = 0;
+ m_rom_bank->set_entry(0);
}
void pce_tennokoe_device::device_start()
@@ -114,112 +104,79 @@ void pce_tennokoe_device::nvram_default()
bool pce_tennokoe_device::nvram_read(util::read_stream &file)
{
- size_t actual_size;
- return !file.read(m_bram, m_bram_size, actual_size) && actual_size == m_bram_size;
+ auto const [err, actual] = read(file, m_bram, m_bram_size);
+ return !err && (actual == m_bram_size);
}
bool pce_tennokoe_device::nvram_write(util::write_stream &file)
{
- size_t actual_size;
- return !file.write(m_bram, m_bram_size, actual_size) && actual_size == m_bram_size;
+ auto const [err, actual] = write(file, m_bram, m_bram_size);
+ return !err;
}
/*-------------------------------------------------
mapper specific handlers
-------------------------------------------------*/
-uint8_t pce_rom_device::read_cart(offs_t offset)
+uint8_t pce_rom_device::rom_r(offs_t offset)
{
int bank = offset / 0x20000;
return m_rom[rom_bank_map[bank] * 0x20000 + (offset & 0x1ffff)];
}
-
-uint8_t pce_cdsys3_device::read_cart(offs_t offset)
+void pce_rom_device::install_memory_handlers(address_space &space)
{
- int bank = offset / 0x20000;
- if (!m_ram.empty() && offset >= 0xd0000)
- return m_ram[offset - 0xd0000];
+ space.install_read_handler(0x00000, 0xfffff, emu::rw_delegate(*this, FUNC(pce_rom_device::rom_r)));
+}
- return m_rom[rom_bank_map[bank] * 0x20000 + (offset & 0x1ffff)];
+
+void pce_populous_device::install_memory_handlers(address_space &space)
+{
+ pce_rom_device::install_memory_handlers(space);
+ space.install_ram(0x80000, 0x87fff, &m_ram[0]);
}
-void pce_cdsys3_device::write_cart(offs_t offset, uint8_t data)
+
+void pce_sf2_device::bank_w(offs_t offset, uint8_t data)
{
- if (!m_ram.empty() && offset >= 0xd0000)
- m_ram[offset - 0xd0000] = data;
+ m_rom_bank->set_entry(offset & 3);
}
-uint8_t pce_populous_device::read_cart(offs_t offset)
+void pce_sf2_device::install_memory_handlers(address_space &space)
{
- int bank = offset / 0x20000;
- if (!m_ram.empty() && offset >= 0x80000 && offset < 0x88000)
- return m_ram[offset & 0x7fff];
+ m_rom_bank->configure_entries(0, 4, m_rom + 0x80000, 0x80000);
+ space.install_rom(0x000000, 0x07ffff, m_rom);
+ space.install_read_bank(0x080000, 0x0fffff, m_rom_bank);
+ space.install_write_handler(0x001ff0, 0x001ff3, emu::rw_delegate(*this, FUNC(pce_sf2_device::bank_w)));
+}
- return m_rom[rom_bank_map[bank] * 0x20000 + (offset & 0x1ffff)];
+
+uint8_t pce_tennokoe_device::bram_r(offs_t offset)
+{
+ if (m_bram_locked)
+ return 0xff;
+ else
+ return m_bram[offset & (m_bram_size-1)];
}
-void pce_populous_device::write_cart(offs_t offset, uint8_t data)
+void pce_tennokoe_device::bram_w(offs_t offset, uint8_t data)
{
- if (!m_ram.empty() && offset >= 0x80000 && offset < 0x88000)
- m_ram[offset & 0x7fff] = data;
+ if (!m_bram_locked)
+ m_bram[offset & (m_bram_size-1)] = data;
}
+void pce_tennokoe_device::bram_lock_w(offs_t offset, uint8_t data)
+{
+ // TODO: lock/unlock mechanism is a complete guess, needs real HW study
+ m_bram_locked = (data == 0);
+}
-uint8_t pce_sf2_device::read_cart(offs_t offset)
+void pce_tennokoe_device::install_memory_handlers(address_space &space)
{
- if (offset < 0x80000)
- return m_rom[offset];
- else
- return m_rom[0x80000 + m_bank_base * 0x80000 + (offset & 0x7ffff)];
-}
-
-void pce_sf2_device::write_cart(offs_t offset, uint8_t data)
-{
- if (offset >= 0x1ff0 && offset < 0x1ff4)
- m_bank_base = offset & 3;
-}
-
-uint8_t pce_tennokoe_device::read_cart(offs_t offset)
-{
- switch((offset & 0xf0000) >> 16)
- {
- case 0:
- case 1:
- case 2:
- case 3:
- case 4:
- case 5:
- case 6:
- case 7:
- return m_rom[offset];
- case 8:
- if (m_bram_locked)
- return 0xff;
- else
- return m_bram[offset & (m_bram_size-1)];
- }
-
- logerror("tennokoe: ROM reading at %06x\n",offset);
- return 0xff;
-}
-
-void pce_tennokoe_device::write_cart(offs_t offset, uint8_t data)
-{
- switch((offset & 0xf0000) >> 16)
- {
- case 8:
- if(!m_bram_locked)
- m_bram[offset & (m_bram_size-1)] = data;
- break;
- case 0xf:
- // TODO: lock/unlock mechanism is a complete guess, needs real HW study
- // (writes to ports $c0000, $d0000, $f0000)
- m_bram_locked = (data == 0);
- [[fallthrough]];
- default:
- logerror("tennokoe: ROM writing at %06x %02x\n",offset,data);
- break;
- }
+ space.install_rom(0x000000, 0x07ffff, m_rom);
+ space.install_readwrite_handler(0x080000, 0x081fff, 0, 0x00e000, 0, emu::rw_delegate(*this, FUNC(pce_tennokoe_device::bram_r)), emu::rw_delegate(*this, FUNC(pce_tennokoe_device::bram_w)));
+ // (writes to ports $c0000, $d0000, $f0000)
+ space.install_write_handler(0x0f0000, 0x0f0000, 0, 0x00ffff, 0, emu::rw_delegate(*this, FUNC(pce_tennokoe_device::bram_lock_w)));
}
+
diff --git a/src/devices/bus/pce/pce_rom.h b/src/devices/bus/pce/pce_rom.h
index 43499851eb7..714e891706f 100644
--- a/src/devices/bus/pce/pce_rom.h
+++ b/src/devices/bus/pce/pce_rom.h
@@ -19,7 +19,7 @@ public:
pce_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual uint8_t read_cart(offs_t offset) override;
+ virtual void install_memory_handlers(address_space &space) override;
protected:
pce_rom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
@@ -27,24 +27,10 @@ protected:
// device-level overrides
virtual void device_start() override { }
virtual void device_reset() override { }
-};
-
-// ======================> pce_cdsys3_device
-class pce_cdsys3_device : public pce_rom_device
-{
-public:
- // construction/destruction
- pce_cdsys3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- // reading and writing
- virtual uint8_t read_cart(offs_t offset) override;
- virtual void write_cart(offs_t offset, uint8_t data) override;
+ uint8_t rom_r(offs_t offset);
};
-
-// ======================> pce_populous_device
-
class pce_populous_device : public pce_rom_device
{
public:
@@ -52,11 +38,9 @@ public:
pce_populous_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual uint8_t read_cart(offs_t offset) override;
- virtual void write_cart(offs_t offset, uint8_t data) override;
+ virtual void install_memory_handlers(address_space &space) override;
};
-
// ======================> pce_sf2_device
class pce_sf2_device : public pce_rom_device
@@ -66,16 +50,16 @@ public:
pce_sf2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual uint8_t read_cart(offs_t offset) override;
- virtual void write_cart(offs_t offset, uint8_t data) override;
+ virtual void install_memory_handlers(address_space &space) override;
protected:
// device-level overrides
- virtual void device_start() override;
virtual void device_reset() override;
private:
- uint8_t m_bank_base;
+ void bank_w(offs_t offset, uint8_t data);
+
+ memory_bank_creator m_rom_bank;
};
// ======================> pce_tennokoe_device
@@ -88,8 +72,7 @@ public:
pce_tennokoe_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// reading and writing
- virtual uint8_t read_cart(offs_t offset) override;
- virtual void write_cart(offs_t offset, uint8_t data) override;
+ virtual void install_memory_handlers(address_space &space) override;
protected:
// device-level overrides
@@ -100,6 +83,10 @@ protected:
virtual bool nvram_write(util::write_stream &file) override;
private:
+ uint8_t bram_r(offs_t offset);
+ void bram_w(offs_t offset, uint8_t data);
+ void bram_lock_w(offs_t offset, uint8_t data);
+
const uint32_t m_bram_size = 0x800*4;
uint8_t m_bram[0x800*4];
@@ -108,11 +95,10 @@ private:
// device type definition
-DECLARE_DEVICE_TYPE(PCE_ROM_STD, pce_rom_device)
-DECLARE_DEVICE_TYPE(PCE_ROM_CDSYS3, pce_cdsys3_device)
-DECLARE_DEVICE_TYPE(PCE_ROM_POPULOUS, pce_populous_device)
-DECLARE_DEVICE_TYPE(PCE_ROM_SF2, pce_sf2_device)
-DECLARE_DEVICE_TYPE(PCE_ROM_TENNOKOE, pce_tennokoe_device)
+DECLARE_DEVICE_TYPE(PCE_ROM_STD, pce_rom_device)
+DECLARE_DEVICE_TYPE(PCE_ROM_POPULOUS, pce_populous_device)
+DECLARE_DEVICE_TYPE(PCE_ROM_SF2, pce_sf2_device)
+DECLARE_DEVICE_TYPE(PCE_ROM_TENNOKOE, pce_tennokoe_device)
#endif // MAME_BUS_PCE_PCE_ROM_H
diff --git a/src/devices/bus/pce/pce_scdsys.cpp b/src/devices/bus/pce/pce_scdsys.cpp
new file mode 100644
index 00000000000..78b413f9d31
--- /dev/null
+++ b/src/devices/bus/pce/pce_scdsys.cpp
@@ -0,0 +1,98 @@
+// license:BSD-3-Clause
+// copyright-holders:Fabio Priuli, Wilbert Pol
+/***********************************************************************************************************
+
+
+ PC-Engine & Turbografx-16 Super System Card emulation
+
+
+ ***********************************************************************************************************/
+
+
+#include "emu.h"
+#include "pce_scdsys.h"
+
+
+
+//-------------------------------------------------
+// pce_cdsys3_device - constructor
+//-------------------------------------------------
+
+DEFINE_DEVICE_TYPE(PCE_ROM_CDSYS3J, pce_cdsys3j_device, "pce_cdsys3j", "PCE Super System Card")
+DEFINE_DEVICE_TYPE(PCE_ROM_CDSYS3U, pce_cdsys3u_device, "pce_cdsys3u", "TG16 Super System Card")
+
+
+pce_cdsys3_device::pce_cdsys3_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, type, tag, owner, clock)
+ , device_pce_cart_interface(mconfig, *this)
+ , m_scdsys()
+{
+}
+
+pce_cdsys3j_device::pce_cdsys3j_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : pce_cdsys3_device(mconfig, PCE_ROM_CDSYS3J, tag, owner, clock)
+{
+}
+
+pce_cdsys3u_device::pce_cdsys3u_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : pce_cdsys3_device(mconfig, PCE_ROM_CDSYS3U, tag, owner, clock)
+{
+}
+
+pce_scdsys_shared::pce_scdsys_shared()
+ : m_ram(nullptr)
+ , m_region(false)
+{
+}
+
+
+//-------------------------------------------------
+// mapper specific start/reset
+//-------------------------------------------------
+
+void pce_cdsys3_device::device_start()
+{
+ m_scdsys.init(*this);
+ m_scdsys.set_region(false);
+}
+
+void pce_cdsys3u_device::device_start()
+{
+ pce_cdsys3_device::device_start();
+ m_scdsys.set_region(true);
+}
+
+void pce_scdsys_shared::init(device_t &device)
+{
+ m_ram = make_unique_clear<uint8_t[]>(0x30000);
+
+ device.save_pointer(NAME(m_ram), 0x30000);
+}
+
+/*-------------------------------------------------
+ mapper specific handlers
+ -------------------------------------------------*/
+
+uint8_t pce_scdsys_shared::register_r(offs_t offset)
+{
+ switch (offset & 0x0f)
+ {
+ // TODO: 0x1 through 0x3 is Super CD-ROM²/PCE Duo stuff?
+ case 0x1: return 0xaa;
+ case 0x2: return 0x55;
+ case 0x3: return 0x00;
+ case 0x5: return (m_region) ? 0x55 : 0xaa;
+ case 0x6: return (m_region) ? 0xaa : 0x55;
+ case 0x7: return 0x03;
+ }
+ return 0x00;
+}
+
+
+void pce_cdsys3_device::install_memory_handlers(address_space &space)
+{
+ // TODO: ROM address mirrored?
+ space.install_rom(0x000000, 0x03ffff, 0x040000, m_rom);
+ space.install_ram(0x0d0000, 0x0fffff, m_scdsys.ram());
+ space.install_read_handler(0x1ff8c0, 0x1ff8c7, 0, 0x330, 0, emu::rw_delegate(*this, FUNC(pce_cdsys3_device::register_r)));
+}
diff --git a/src/devices/bus/pce/pce_scdsys.h b/src/devices/bus/pce/pce_scdsys.h
new file mode 100644
index 00000000000..1a4220bdc57
--- /dev/null
+++ b/src/devices/bus/pce/pce_scdsys.h
@@ -0,0 +1,83 @@
+// license:BSD-3-Clause
+// copyright-holders:Fabio Priuli, Wilbert Pol
+#ifndef MAME_BUS_PCE_PCE_SCDSYS_H
+#define MAME_BUS_PCE_PCE_SCDSYS_H
+
+#pragma once
+
+#include "pce_slot.h"
+
+
+// ======================> pce_scdsys_shared
+
+class pce_scdsys_shared
+{
+public:
+ // construction/destruction
+ pce_scdsys_shared();
+
+ // configuration
+ void set_region(bool region) { m_region = region; }
+
+ // reading and writing
+ uint8_t register_r(offs_t offset);
+
+ uint8_t *ram() { return m_ram.get(); }
+
+ void init(device_t &device);
+
+private:
+ std::unique_ptr<uint8_t[]> m_ram; // internal RAM
+ bool m_region; // Cartridge region
+};
+
+// ======================> pce_cdsys3_device
+
+class pce_cdsys3_device : public device_t,
+ public device_pce_cart_interface
+{
+public:
+ // reading and writing
+ virtual void install_memory_handlers(address_space &space) override;
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+
+ // construction/destruction
+ pce_cdsys3_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ // helper classes
+ pce_scdsys_shared m_scdsys;
+
+ // reading
+ uint8_t register_r(offs_t offset) { return m_scdsys.register_r(offset); }
+};
+
+// ======================> pce_cdsys3j_device
+
+class pce_cdsys3j_device : public pce_cdsys3_device
+{
+public:
+ // construction/destruction
+ pce_cdsys3j_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+};
+
+// ======================> pce_cdsys3u_device
+
+class pce_cdsys3u_device : public pce_cdsys3_device
+{
+public:
+ // construction/destruction
+ pce_cdsys3u_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual void device_start() override;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(PCE_ROM_CDSYS3J, pce_cdsys3j_device)
+DECLARE_DEVICE_TYPE(PCE_ROM_CDSYS3U, pce_cdsys3u_device)
+
+
+#endif // MAME_BUS_PCE_PCE_SCDSYS_H
diff --git a/src/devices/bus/pce/pce_slot.cpp b/src/devices/bus/pce/pce_slot.cpp
index 5e30efbe283..2a6d3dd3290 100644
--- a/src/devices/bus/pce/pce_slot.cpp
+++ b/src/devices/bus/pce/pce_slot.cpp
@@ -48,11 +48,11 @@ device_pce_cart_interface::~device_pce_cart_interface()
// rom_alloc - alloc the space for the cart
//-------------------------------------------------
-void device_pce_cart_interface::rom_alloc(uint32_t size, const char *tag)
+void device_pce_cart_interface::rom_alloc(uint32_t size)
{
if (m_rom == nullptr)
{
- m_rom = device().machine().memory().region_alloc(std::string(tag).append(PCESLOT_ROM_REGION_TAG).c_str(), size, 1, ENDIANNESS_LITTLE)->base();
+ m_rom = device().machine().memory().region_alloc(device().subtag("^cart:rom"), size, 1, ENDIANNESS_LITTLE)->base();
m_rom_size = size;
}
}
@@ -139,7 +139,9 @@ pce_cart_slot_device::pce_cart_slot_device(const machine_config &mconfig, const
device_cartrom_image_interface(mconfig, *this),
device_single_card_slot_interface<device_pce_cart_interface>(mconfig, *this),
m_interface("pce_cart"),
- m_type(PCE_STD), m_cart(nullptr)
+ m_type(PCE_STD),
+ m_cart(nullptr),
+ m_address_space(*this, finder_base::DUMMY_TAG, -1, 8)
{
}
@@ -181,6 +183,8 @@ static const pce_slot slot_list[] =
{ PCE_POPULOUS, "populous" },
{ PCE_SF2, "sf2" },
{ PCE_TENNOKOE, "tennokoe" },
+ { PCE_ACARD_DUO, "acard_duo" },
+ { PCE_ACARD_PRO, "acard_pro" },
};
static int pce_get_pcb_id(const char *slot)
@@ -210,43 +214,40 @@ static const char *pce_get_slot(int type)
call load
-------------------------------------------------*/
-image_init_result pce_cart_slot_device::call_load()
+std::pair<std::error_condition, std::string> pce_cart_slot_device::call_load()
{
if (m_cart)
{
- uint32_t offset;
uint32_t len = !loaded_through_softlist() ? length() : get_software_region_length("rom");
- uint8_t *ROM;
// From fullpath, check for presence of a header and skip it
if (!loaded_through_softlist() && (len % 0x4000) == 512)
{
- logerror("Rom-header found, skipping\n");
- offset = 512;
+ logerror("ROM header found, skipping\n");
+ uint32_t const offset = 512;
len -= offset;
fseek(offset, SEEK_SET);
}
- m_cart->rom_alloc(len, tag());
- ROM = m_cart->get_rom_base();
+ m_cart->rom_alloc(len);
+ uint8_t *const ROM = m_cart->get_rom_base();
if (!loaded_through_softlist())
fread(ROM, len);
else
memcpy(ROM, get_software_region("rom"), len);
- // check for encryption (US carts)
+ // check for bit-reversal (US carts)
if (ROM[0x1fff] < 0xe0)
{
- uint8_t decrypted[256];
-
- /* Initialize decryption table */
+ // Initialize unscrambling table
+ uint8_t unscrambled[256];
for (int i = 0; i < 256; i++)
- decrypted[i] = ((i & 0x01) << 7) | ((i & 0x02) << 5) | ((i & 0x04) << 3) | ((i & 0x08) << 1) | ((i & 0x10) >> 1) | ((i & 0x20 ) >> 3) | ((i & 0x40) >> 5) | ((i & 0x80) >> 7);
+ unscrambled[i] = bitswap<8>(i, 0, 1, 2, 3, 4, 5, 6, 7);
- /* Decrypt ROM image */
+ // Unscramble ROM image
for (int i = 0; i < len; i++)
- ROM[i] = decrypted[ROM[i]];
+ ROM[i] = unscrambled[ROM[i]];
}
m_cart->rom_map_setup(len);
@@ -263,13 +264,11 @@ image_init_result pce_cart_slot_device::call_load()
if (m_type == PCE_POPULOUS)
m_cart->ram_alloc(0x8000);
- if (m_type == PCE_CDSYS3J || m_type == PCE_CDSYS3U)
- m_cart->ram_alloc(0x30000);
- return image_init_result::PASS;
+ m_cart->install_memory_handlers(*m_address_space);
}
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
@@ -325,8 +324,7 @@ std::string pce_cart_slot_device::get_default_card_software(get_default_card_sof
hook.image_file()->length(len); // FIXME: check error return, guard against excessively large files
std::vector<uint8_t> rom(len);
- size_t actual;
- hook.image_file()->read(&rom[0], len, actual); // FIXME: check error return or read returning short
+ read(*hook.image_file(), &rom[0], len); // FIXME: check error return or read returning short
int const type = get_cart_type(&rom[0], len);
char const *const slot_string = pce_get_slot(type);
@@ -338,25 +336,3 @@ std::string pce_cart_slot_device::get_default_card_software(get_default_card_sof
return software_get_default_slot("rom");
}
-
-/*-------------------------------------------------
- read
- -------------------------------------------------*/
-
-uint8_t pce_cart_slot_device::read_cart(offs_t offset)
-{
- if (m_cart)
- return m_cart->read_cart(offset);
- else
- return 0xff;
-}
-
-/*-------------------------------------------------
- write
- -------------------------------------------------*/
-
-void pce_cart_slot_device::write_cart(offs_t offset, uint8_t data)
-{
- if (m_cart)
- m_cart->write_cart(offset, data);
-}
diff --git a/src/devices/bus/pce/pce_slot.h b/src/devices/bus/pce/pce_slot.h
index 0d2a032cb38..337214d0b81 100644
--- a/src/devices/bus/pce/pce_slot.h
+++ b/src/devices/bus/pce/pce_slot.h
@@ -21,7 +21,9 @@ enum
PCE_CDSYS3U,
PCE_POPULOUS,
PCE_SF2,
- PCE_TENNOKOE
+ PCE_TENNOKOE,
+ PCE_ACARD_DUO,
+ PCE_ACARD_PRO
};
@@ -33,11 +35,9 @@ public:
// construction/destruction
virtual ~device_pce_cart_interface();
- // reading and writing
- virtual uint8_t read_cart(offs_t offset) { return 0xff; }
- virtual void write_cart(offs_t offset, uint8_t data) {}
+ virtual void install_memory_handlers(address_space &space) { }
- void rom_alloc(uint32_t size, const char *tag);
+ void rom_alloc(uint32_t size);
void ram_alloc(uint32_t size);
uint8_t* get_rom_base() { return m_rom; }
uint8_t* get_ram_base() { return &m_ram[0]; }
@@ -80,15 +80,18 @@ public:
pce_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual ~pce_cart_slot_device();
- // image-level overrides
- virtual image_init_result call_load() override;
+ // configuration
+ template <typename T> void set_address_space(T &&tag, int no) { m_address_space.set_tag(std::forward<T>(tag), no); }
+
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
virtual void call_unload() override;
virtual bool is_reset_on_load() const noexcept override { return true; }
virtual const char *image_interface() const noexcept override { return m_interface; }
virtual const char *file_extensions() const noexcept override { return "pce,bin"; }
- // slot interface overrides
+ // device_slot_interface implementation
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
int get_type() { return m_type; }
@@ -96,17 +99,14 @@ public:
void set_intf(const char * interface) { m_interface = interface; }
- // reading and writing
- uint8_t read_cart(offs_t offset);
- void write_cart(offs_t offset, uint8_t data);
-
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
const char *m_interface;
int m_type;
device_pce_cart_interface *m_cart;
+ required_address_space m_address_space;
};
@@ -114,11 +114,4 @@ protected:
// device type definition
DECLARE_DEVICE_TYPE(PCE_CART_SLOT, pce_cart_slot_device)
-
-/***************************************************************************
- DEVICE CONFIGURATION MACROS
- ***************************************************************************/
-
-#define PCESLOT_ROM_REGION_TAG ":cart:rom"
-
#endif // MAME_BUS_PCE_PCE_SLOT_H
diff --git a/src/devices/bus/pce_ctrl/joypad2.cpp b/src/devices/bus/pce_ctrl/joypad2.cpp
index 2da64ed49ce..ff09eb8dbe9 100644
--- a/src/devices/bus/pce_ctrl/joypad2.cpp
+++ b/src/devices/bus/pce_ctrl/joypad2.cpp
@@ -33,22 +33,17 @@
#include "emu.h"
#include "joypad2.h"
+#include "machine/74157.h"
-//**************************************************************************
-// DEVICE DEFINITIONS
-//**************************************************************************
-
-DEFINE_DEVICE_TYPE(PCE_JOYPAD2, pce_joypad2_device, "pce_joypad2", "NEC PC Engine Pad")
-DEFINE_DEVICE_TYPE(PCE_JOYPAD2_TURBO, pce_joypad2_turbo_device, "pce_joypad2_turbo", "NEC PC Engine/TurboGrafx-16 2 Button Joypad")
-
+namespace {
-static INPUT_PORTS_START( pce_joypad2 )
+INPUT_PORTS_START( pce_joypad2 )
// II is left of I on the original pad so we map them in reverse order
PORT_START("BUTTONS")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("%p Button I")
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("%p Button II")
- PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_SELECT ) PORT_NAME("%p Select")
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_SELECT )
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_START ) PORT_NAME("%p Run")
PORT_START("DIRECTION")
@@ -59,7 +54,7 @@ static INPUT_PORTS_START( pce_joypad2 )
INPUT_PORTS_END
-static INPUT_PORTS_START( pce_joypad2_turbo )
+INPUT_PORTS_START( pce_joypad2_turbo )
PORT_INCLUDE( pce_joypad2 )
PORT_START("TURBO")
@@ -74,6 +69,74 @@ static INPUT_PORTS_START( pce_joypad2_turbo )
INPUT_PORTS_END
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> pce_joypad2_device
+
+class pce_joypad2_device : public device_t, public device_pce_control_port_interface
+{
+public:
+ // construction/destruction
+ pce_joypad2_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // construction/destruction
+ pce_joypad2_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
+ // optional information overrides
+ virtual ioport_constructor device_input_ports() const override;
+
+ // device-level overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_start() override;
+
+ // device_pce_control_port_interface overrides
+ virtual u8 peripheral_r() override;
+ virtual void sel_w(int state) override;
+ virtual void clr_w(int state) override;
+
+ // devices
+ required_device<ls157_device> m_muxer;
+};
+
+
+// ======================> pce_joypad2_turbo_device
+
+class pce_joypad2_turbo_device : public pce_joypad2_device
+{
+public:
+ // construction/destruction
+ pce_joypad2_turbo_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // optional information overrides
+ virtual ioport_constructor device_input_ports() const override;
+
+ // device-level overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ // device_pce_control_port_interface overrides
+ virtual void clr_w(int state) override;
+
+private:
+ u8 buttons_r();
+
+ // IO ports
+ required_ioport m_buttons_io;
+ required_ioport m_turbo_io;
+
+ // internal states
+ u8 m_counter; // Turbo rate counter, connected on 74xx163 QB and QC.
+ bool m_prev_clr; // previous CLR pin state
+};
+
+
+
//-------------------------------------------------
// input_ports - device-specific input ports
//-------------------------------------------------
@@ -242,3 +305,14 @@ u8 pce_joypad2_turbo_device::buttons_r()
}
return ret;
}
+
+} // anonymous namespace
+
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(PCE_JOYPAD2, device_pce_control_port_interface, pce_joypad2_device, "pce_joypad2", "NEC PC Engine Pad")
+DEFINE_DEVICE_TYPE_PRIVATE(PCE_JOYPAD2_TURBO, device_pce_control_port_interface, pce_joypad2_turbo_device, "pce_joypad2_turbo", "NEC PC Engine/TurboGrafx-16 2 Button Joypad")
diff --git a/src/devices/bus/pce_ctrl/joypad2.h b/src/devices/bus/pce_ctrl/joypad2.h
index 13fc0cbe7de..008a9100825 100644
--- a/src/devices/bus/pce_ctrl/joypad2.h
+++ b/src/devices/bus/pce_ctrl/joypad2.h
@@ -5,87 +5,15 @@
NEC PC Engine/TurboGrafx-16 2 Button Joypad emulation
**********************************************************************/
-
#ifndef MAME_BUS_PCE_CTRL_JOYPAD2_H
#define MAME_BUS_PCE_CTRL_JOYPAD2_H
#pragma once
-
-#include "machine/74157.h"
#include "pcectrl.h"
-
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-// ======================> pce_joypad2_device
-
-class pce_joypad2_device : public device_t,
- public device_pce_control_port_interface
-{
-public:
- // construction/destruction
- pce_joypad2_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
-
-protected:
- // construction/destruction
- pce_joypad2_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
-
- // optional information overrides
- virtual ioport_constructor device_input_ports() const override;
-
- // device-level overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual void device_start() override;
-
- // device_pce_control_port_interface overrides
- virtual u8 peripheral_r() override;
- virtual void sel_w(int state) override;
- virtual void clr_w(int state) override;
-
- // devices
- required_device<ls157_device> m_muxer;
-};
-
-// ======================> pce_joypad2_turbo_device
-
-class pce_joypad2_turbo_device : public pce_joypad2_device
-{
-public:
- // construction/destruction
- pce_joypad2_turbo_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
-
-protected:
- // optional information overrides
- virtual ioport_constructor device_input_ports() const override;
-
- // device-level overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual void device_start() override;
- virtual void device_reset() override;
-
- // device_pce_control_port_interface overrides
- virtual void clr_w(int state) override;
-
-private:
- u8 buttons_r();
-
- // IO ports
- required_ioport m_buttons_io;
- required_ioport m_turbo_io;
-
- // internal states
- u8 m_counter; // Turbo rate counter, connected on 74xx163 QB and QC.
- bool m_prev_clr; // previous CLR pin state
-};
-
-
-// device type definition
-DECLARE_DEVICE_TYPE(PCE_JOYPAD2, pce_joypad2_device)
-DECLARE_DEVICE_TYPE(PCE_JOYPAD2_TURBO, pce_joypad2_turbo_device)
-
+DECLARE_DEVICE_TYPE(PCE_JOYPAD2, device_pce_control_port_interface)
+DECLARE_DEVICE_TYPE(PCE_JOYPAD2_TURBO, device_pce_control_port_interface)
#endif // MAME_BUS_PCE_CTRL_JOYPAD2_H
diff --git a/src/devices/bus/pce_ctrl/joypad6.cpp b/src/devices/bus/pce_ctrl/joypad6.cpp
index b11d400d5d1..ef5deb6d272 100644
--- a/src/devices/bus/pce_ctrl/joypad6.cpp
+++ b/src/devices/bus/pce_ctrl/joypad6.cpp
@@ -26,17 +26,94 @@
#include "emu.h"
#include "joypad6.h"
+#include "machine/74157.h"
+namespace {
+
//**************************************************************************
-// DEVICE DEFINITIONS
+// TYPE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(PCE_AVENUE_PAD_6, pce_avenue_pad_6_device, "pce_avenue_pad_6", "NEC Avenue Pad 6")
-DEFINE_DEVICE_TYPE(PCE_ARCADE_PAD_6, pce_arcade_pad_6_device, "pce_arcade_pad_6", "NEC Arcade Pad 6")
+// ======================> pce_joypad6_base_device
+
+class pce_joypad6_base_device : public device_t,
+ public device_pce_control_port_interface
+{
+public:
+ DECLARE_INPUT_CHANGED_MEMBER(joypad_mode_changed);
+
+protected:
+ // construction/destruction
+ pce_joypad6_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
+ // device-level overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ // device_pce_control_port_interface overrides
+ virtual u8 peripheral_r() override;
+ virtual void sel_w(int state) override;
+ virtual void clr_w(int state) override;
+
+ // button handlers
+ void buttonset_update();
+
+ // devices
+ required_device_array<ls157_device, 3> m_muxer;
+
+ // IO ports
+ required_ioport m_joypad_mode;
+
+ // internal states
+ u8 m_counter; // buttonset select, autofire counter (74xx163 QA-QB pin)
+ bool m_prev_clr; // previous CLR pin state
+};
+
+
+// ======================> pce_avenue_pad_6_device
+
+class pce_avenue_pad_6_device : public pce_joypad6_base_device
+{
+public:
+ // construction/destruction
+ pce_avenue_pad_6_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // construction/destruction
+ pce_avenue_pad_6_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
+ // optional information overrides
+ virtual ioport_constructor device_input_ports() const override;
+ // device-level overrides
+ virtual void device_add_mconfig(machine_config &config) override;
-static INPUT_PORTS_START( pce_joypad6 )
+ template<unsigned Buttonset> u8 buttons_r();
+
+ // IO ports
+ required_ioport_array<2> m_buttons_io;
+ required_ioport m_turbo_io;
+};
+
+
+// ======================> pce_arcade_pad_6_device
+
+class pce_arcade_pad_6_device : public pce_avenue_pad_6_device
+{
+public:
+ // construction/destruction
+ pce_arcade_pad_6_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // optional information overrides
+ virtual ioport_constructor device_input_ports() const override;
+};
+
+
+
+INPUT_PORTS_START( pce_joypad6 )
// Action button order on original pad is bottom row: III, II, I, and top row: IV, V, VI
PORT_START("BUTTONS_0")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("%p Button I")
@@ -298,3 +375,14 @@ u8 pce_avenue_pad_6_device::buttons_r()
}
return ret;
}
+
+} // anonymous namespace
+
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(PCE_AVENUE_PAD_6, device_pce_control_port_interface, pce_avenue_pad_6_device, "pce_avenue_pad_6", "NEC Avenue Pad 6")
+DEFINE_DEVICE_TYPE_PRIVATE(PCE_ARCADE_PAD_6, device_pce_control_port_interface, pce_arcade_pad_6_device, "pce_arcade_pad_6", "NEC Arcade Pad 6")
diff --git a/src/devices/bus/pce_ctrl/joypad6.h b/src/devices/bus/pce_ctrl/joypad6.h
index fedac375a22..88d83b4e3c2 100644
--- a/src/devices/bus/pce_ctrl/joypad6.h
+++ b/src/devices/bus/pce_ctrl/joypad6.h
@@ -5,102 +5,15 @@
NEC PC Engine/TurboGrafx-16 6 Button Joypad emulation
**********************************************************************/
-
#ifndef MAME_BUS_PCE_CTRL_JOYPAD6_H
#define MAME_BUS_PCE_CTRL_JOYPAD6_H
#pragma once
-
-#include "machine/74157.h"
#include "pcectrl.h"
-
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-// ======================> pce_joypad6_base_device
-
-class pce_joypad6_base_device : public device_t,
- public device_pce_control_port_interface
-{
-public:
- DECLARE_INPUT_CHANGED_MEMBER(joypad_mode_changed);
-
-protected:
- // construction/destruction
- pce_joypad6_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
-
- // device-level overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual void device_start() override;
- virtual void device_reset() override;
-
- // device_pce_control_port_interface overrides
- virtual u8 peripheral_r() override;
- virtual void sel_w(int state) override;
- virtual void clr_w(int state) override;
-
- // button handlers
- void buttonset_update();
-
- // devices
- required_device_array<ls157_device, 3> m_muxer;
-
- // IO ports
- required_ioport m_joypad_mode;
-
- // internal states
- u8 m_counter; // buttonset select, autofire counter (74xx163 QA-QB pin)
- bool m_prev_clr; // previous CLR pin state
-};
-
-
-// ======================> pce_avenue_pad_6_device
-
-class pce_avenue_pad_6_device : public pce_joypad6_base_device
-{
-public:
- // construction/destruction
- pce_avenue_pad_6_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
-
-protected:
- // construction/destruction
- pce_avenue_pad_6_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
-
- // optional information overrides
- virtual ioport_constructor device_input_ports() const override;
-
- // device-level overrides
- virtual void device_add_mconfig(machine_config &config) override;
-
- template<unsigned Buttonset> u8 buttons_r();
-
- // IO ports
- required_ioport_array<2> m_buttons_io;
- required_ioport m_turbo_io;
-};
-
-
-// ======================> pce_arcade_pad_6_device
-
-class pce_arcade_pad_6_device : public pce_avenue_pad_6_device
-{
-public:
- // construction/destruction
- pce_arcade_pad_6_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
-
-protected:
- // optional information overrides
- virtual ioport_constructor device_input_ports() const override;
-};
-
-
-// device type definition
-DECLARE_DEVICE_TYPE(PCE_AVENUE_PAD_6, pce_avenue_pad_6_device)
-DECLARE_DEVICE_TYPE(PCE_ARCADE_PAD_6, pce_arcade_pad_6_device)
-
+DECLARE_DEVICE_TYPE(PCE_AVENUE_PAD_6, device_pce_control_port_interface)
+DECLARE_DEVICE_TYPE(PCE_ARCADE_PAD_6, device_pce_control_port_interface)
#endif // MAME_BUS_PCE_CTRL_JOYPAD6_H
diff --git a/src/devices/bus/pce_ctrl/mouse.cpp b/src/devices/bus/pce_ctrl/mouse.cpp
new file mode 100644
index 00000000000..9d608008104
--- /dev/null
+++ b/src/devices/bus/pce_ctrl/mouse.cpp
@@ -0,0 +1,137 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/***********************************************************************
+
+ NEC PC Engine/TurboGrafx-16 Mouse emulation
+
+***********************************************************************/
+
+#include "emu.h"
+#include "mouse.h"
+
+#include <algorithm>
+#include <iterator>
+
+//#define VERBOSE 1
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+
+namespace {
+
+INPUT_PORTS_START( pce_mouse )
+ PORT_START("BUTTONS")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("%p Button I (right)")
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("%p Button II (left)")
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_SELECT )
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_START ) PORT_NAME("%p Run")
+
+ PORT_START("X")
+ PORT_BIT( 0xff, 0x00, IPT_MOUSE_X ) PORT_SENSITIVITY(20) PORT_KEYDELTA(1) PORT_REVERSE
+
+ PORT_START("Y")
+ PORT_BIT( 0xff, 0x00, IPT_MOUSE_Y ) PORT_SENSITIVITY(20) PORT_KEYDELTA(1) PORT_REVERSE
+INPUT_PORTS_END
+
+
+class pce_mouse_device : public device_t, public device_pce_control_port_interface
+{
+public:
+ pce_mouse_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+ virtual u8 peripheral_r() override;
+ virtual void sel_w(int state) override { m_sel_in = state ? 1 : 0; }
+ virtual void clr_w(int state) override;
+
+protected:
+ virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(pce_mouse); }
+ virtual void device_start() override;
+
+private:
+ required_ioport m_buttons;
+ required_ioport_array<2> m_axes;
+
+ attotime m_squeak;
+ u16 m_data;
+ u8 m_base[2];
+ u8 m_sel_in;
+ u8 m_clr_in;
+};
+
+
+pce_mouse_device::pce_mouse_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) :
+ device_t(mconfig, PCE_MOUSE, tag, owner, clock),
+ device_pce_control_port_interface(mconfig, *this),
+ m_buttons(*this, "BUTTONS"),
+ m_axes(*this, "%c", 'X'),
+ m_squeak(),
+ m_data(0),
+ m_sel_in(1),
+ m_clr_in(1)
+{
+}
+
+
+u8 pce_mouse_device::peripheral_r()
+{
+ if (m_clr_in)
+ return 0x0f;
+ else if (!m_sel_in)
+ return m_buttons->read();
+ else
+ return BIT(m_data, 12, 4);
+}
+
+
+void pce_mouse_device::clr_w(int state)
+{
+ u8 const clr = state ? 1 : 0;
+ if (clr != m_clr_in)
+ {
+ m_clr_in = clr;
+ if (clr)
+ {
+ attotime const now = machine().time();
+ if ((now - m_squeak) > attotime::from_usec(550))
+ {
+ LOG("%s: CLR rising, latch count\n", machine().describe_context());
+ m_squeak = now;
+ for (unsigned i = 0; m_axes.size() > i; ++i)
+ {
+ uint8_t const count = m_axes[i]->read();
+ m_data <<= 8;
+ m_data |= (count - m_base[i]) & 0x00ff;
+ m_base[i] = count;
+ }
+ }
+ else
+ {
+ LOG("%s: CLR rising, shift count\n", machine().describe_context());
+ m_data <<= 4;
+ }
+ }
+ else
+ {
+ LOG("%s: CLR falling\n", machine().describe_context());
+ }
+ }
+}
+
+
+void pce_mouse_device::device_start()
+{
+ m_squeak = machine().time();
+ m_data = 0;
+ std::fill(std::begin(m_base), std::end(m_base), 0);
+
+ save_item(NAME(m_squeak));
+ save_item(NAME(m_data));
+ save_item(NAME(m_base));
+ save_item(NAME(m_sel_in));
+ save_item(NAME(m_clr_in));
+}
+
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(PCE_MOUSE, device_pce_control_port_interface, pce_mouse_device, "pce_mouse", "NEC PC Engine Mouse")
diff --git a/src/devices/bus/pce_ctrl/mouse.h b/src/devices/bus/pce_ctrl/mouse.h
new file mode 100644
index 00000000000..3855c7cd5e3
--- /dev/null
+++ b/src/devices/bus/pce_ctrl/mouse.h
@@ -0,0 +1,18 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/***********************************************************************
+
+ NEC PC Engine/TurboGrafx-16 Mouse emulation
+
+***********************************************************************/
+#ifndef MAME_BUS_PCE_CTRL_MOUSE_H
+#define MAME_BUS_PCE_CTRL_MOUSE_H
+
+#pragma once
+
+#include "pcectrl.h"
+
+
+DECLARE_DEVICE_TYPE(PCE_MOUSE, device_pce_control_port_interface)
+
+#endif // MAME_BUS_PCE_CTRL_MOUSE_H
diff --git a/src/devices/bus/pce_ctrl/pcectrl.cpp b/src/devices/bus/pce_ctrl/pcectrl.cpp
index 71e2d9db525..6d0f9ffa7de 100644
--- a/src/devices/bus/pce_ctrl/pcectrl.cpp
+++ b/src/devices/bus/pce_ctrl/pcectrl.cpp
@@ -51,14 +51,17 @@
**********************************************************************/
#include "emu.h"
-#include "screen.h"
#include "pcectrl.h"
+#include "screen.h"
+
// slot devices
#include "joypad2.h"
#include "joypad6.h"
+#include "mouse.h"
#include "multitap.h"
#include "pachinko.h"
+#include "xhe3.h"
@@ -170,14 +173,28 @@ void pce_control_port_devices(device_slot_interface &device)
// 2 Button Joypad/Joysticks
device.option_add("joypad2", PCE_JOYPAD2); // bundled pad for White PC Engine
device.option_add("joypad2_turbo", PCE_JOYPAD2_TURBO); // Turbo pad and compatibles
+
// 6 Button Joypad/Joysticks
device.option_add("avenue_pad_6", PCE_AVENUE_PAD_6);
device.option_add("arcade_pad_6", PCE_ARCADE_PAD_6);
+ device.option_add("mouse", PCE_MOUSE);
+
device.option_add("multitap", PCE_MULTITAP);
device.option_add("pachinko", PCE_PACHINKO);
+
+ device.option_add("pcjoy", PCE_XHE3); // PC joystick adapter (most useful with analog pad)
+
// 3 Button Joypad/Joysticks (ex: Avenue Pad 3)
// PC Engine Mouse (PI-PD10)
- // Memory Base 128 (PI-AD19)
+
+ // Memory BRAM storages, connects to joyport and exposes another DIN-8 port
+ // cfr. https://github.com/BlockoS/mb128
+ // NEC Memory Base 128 (PI-AD19, メモリベース128)
+ // Koei Save-Kun (セーブくん), clone of above?
+
+ // Serial Monitor for PCEMon
+ // https://www.chrismcovell.com/PCEmon/index.html
+
// etc...
}
diff --git a/src/devices/bus/pce_ctrl/xhe3.cpp b/src/devices/bus/pce_ctrl/xhe3.cpp
new file mode 100644
index 00000000000..db73882e0fc
--- /dev/null
+++ b/src/devices/bus/pce_ctrl/xhe3.cpp
@@ -0,0 +1,92 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/***********************************************************************
+
+ Micom Soft XHE-3 PC Joystick Adapter for PC Engine emuation
+
+***********************************************************************/
+
+#include "emu.h"
+#include "xhe3.h"
+
+#include "bus/msx/ctrl/ctrl.h"
+
+
+namespace {
+
+INPUT_PORTS_START( pce_xhe3 )
+ PORT_START("BUTTONS") // using IPT_START/IPT_SELECT would steal a player index
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("Select")
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("Run")
+INPUT_PORTS_END
+
+
+
+class pce_xhe3_device : public device_t, public device_pce_control_port_interface
+{
+public:
+ pce_xhe3_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+ virtual u8 peripheral_r() override;
+ virtual void sel_w(int state) override;
+ virtual void clr_w(int state) override;
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(pce_xhe3); }
+ virtual void device_start() override;
+
+private:
+ required_device<msx_general_purpose_port_device> m_port;
+ required_ioport m_buttons;
+
+ u8 m_sel_in;
+};
+
+
+pce_xhe3_device::pce_xhe3_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) :
+ device_t(mconfig, PCE_XHE3, tag, owner, clock),
+ device_pce_control_port_interface(mconfig, *this),
+ m_port(*this, "joy"),
+ m_buttons(*this, "BUTTONS"),
+ m_sel_in(1)
+{
+}
+
+
+u8 pce_xhe3_device::peripheral_r()
+{
+ if (m_sel_in)
+ return bitswap<4>(m_port->read(), 2, 1, 3, 0);
+ else
+ return bitswap<2>(m_port->read(), 5, 4) | (m_buttons->read() << 2);
+}
+
+
+void pce_xhe3_device::sel_w(int state)
+{
+ m_sel_in = state ? 1 : 0;
+}
+
+
+void pce_xhe3_device::clr_w(int state)
+{
+ m_port->pin_8_w(state);
+}
+
+
+void pce_xhe3_device::device_add_mconfig(machine_config &config)
+{
+ MSX_GENERAL_PURPOSE_PORT(config, m_port, msx_general_purpose_port_devices, "xe1ap");
+}
+
+
+void pce_xhe3_device::device_start()
+{
+ save_item(NAME(m_sel_in));
+}
+
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(PCE_XHE3, device_pce_control_port_interface, pce_xhe3_device, "pce_xhe3", "Micom Soft XHE-3 PC Joystick Adapter for PC Engine")
diff --git a/src/devices/bus/pce_ctrl/xhe3.h b/src/devices/bus/pce_ctrl/xhe3.h
new file mode 100644
index 00000000000..86323dd08a9
--- /dev/null
+++ b/src/devices/bus/pce_ctrl/xhe3.h
@@ -0,0 +1,18 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/***********************************************************************
+
+ Micom Soft XHE-3 PC Joystick Adapter for PC Engine emuation
+
+***********************************************************************/
+#ifndef MAME_BUS_PCE_CTRL_XHE3_H
+#define MAME_BUS_PCE_CTRL_XHE3_H
+
+#pragma once
+
+#include "pcectrl.h"
+
+
+DECLARE_DEVICE_TYPE(PCE_XHE3, device_pce_control_port_interface)
+
+#endif // MAME_BUS_PCE_CTRL_XHE3_H
diff --git a/src/devices/bus/pci/aha2940au.cpp b/src/devices/bus/pci/aha2940au.cpp
new file mode 100644
index 00000000000..5fd4f4668c8
--- /dev/null
+++ b/src/devices/bus/pci/aha2940au.cpp
@@ -0,0 +1,96 @@
+// license:BSD-3-Clause
+// copyright-holders:
+/**************************************************************************************************
+
+Adaptec AHA-2940AU PCI
+
+Based off AIC-7860/7861
+
+TODO:
+- Plays with southbridge SMI & APMCAPMS regs soon after entering in its own BIOS (PC=ccfe1),
+ going off the track blanking the almost entirety of I/O space range.
+
+**************************************************************************************************/
+
+#include "emu.h"
+#include "aha2940au.h"
+
+#define LOG_WARN (1U << 1)
+
+#define VERBOSE (LOG_GENERAL | LOG_WARN)
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+#define LOGWARN(...) LOGMASKED(LOG_WARN, __VA_ARGS__)
+
+
+DEFINE_DEVICE_TYPE(AHA2940AU, aha2940au_scsi_device, "aha2940au", "Adaptec AHA-2940AU SCSI controller")
+
+
+
+aha2940au_scsi_device::aha2940au_scsi_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : pci_card_device(mconfig, type, tag, owner, clock)
+ , m_scsi_rom(*this, "scsi_rom")
+{
+ // TODO: unknown revision & class code
+ set_ids(0x90046178, 0x00, 0x010700, 0x90046178);
+}
+
+aha2940au_scsi_device::aha2940au_scsi_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : aha2940au_scsi_device(mconfig, AHA2940AU, tag, owner, clock)
+{
+}
+
+// NOTE: BIOS is FAT compressed, decompress as 8bios.bin under the hood.
+ROM_START( aha2940au )
+ ROM_REGION32_LE( 0x8000, "scsi_rom", ROMREGION_ERASEFF )
+ ROM_SYSTEM_BIOS( 0, "v1.30", "AHA-2940AU (v1.30)" )
+ // "589247-00_c_bios_2400_(C)1996_v1.30.u3"
+ ROMX_LOAD( "589247-00.u3", 0x0000, 0x8000, CRC(de00492b) SHA1(a6015bcd51e51015a5710d7ac1929e28bf033db4), ROM_BIOS(0) )
+
+ // default eeprom contents, to be verified
+ ROM_REGION( 0x80, "eeprom", ROMREGION_ERASEFF )
+ ROM_LOAD( "93c46.u1", 0x00, 0x80, CRC(c82242ce) SHA1(93311b8c02e87492a40c1df6ea4eb60628bb2825) )
+ROM_END
+
+const tiny_rom_entry *aha2940au_scsi_device::device_rom_region() const
+{
+ return ROM_NAME(aha2940au);
+}
+
+void aha2940au_scsi_device::device_add_mconfig(machine_config &config)
+{
+ // AIC-7860Q
+ // 93C46 EEPROM
+}
+
+void aha2940au_scsi_device::device_start()
+{
+ pci_card_device::device_start();
+
+ // TODO: unknown BAR setup
+// add_map( size, M_MEM, FUNC(aha2940au_scsi_device::map));
+
+ add_rom((u8 *)m_scsi_rom->base(), 0x8000);
+ expansion_rom_base = 0xc8000;
+
+ // TODO: unknown irq pin
+// intr_pin = 1;
+}
+
+void aha2940au_scsi_device::device_reset()
+{
+ pci_card_device::device_reset();
+
+ // TODO: unknown startup state
+ command = 0x0000;
+ status = 0x0200;
+
+ remap_cb();
+}
+
+void aha2940au_scsi_device::config_map(address_map &map)
+{
+ pci_card_device::config_map(map);
+ // ...
+}
diff --git a/src/devices/bus/pci/aha2940au.h b/src/devices/bus/pci/aha2940au.h
new file mode 100644
index 00000000000..8e119f4312c
--- /dev/null
+++ b/src/devices/bus/pci/aha2940au.h
@@ -0,0 +1,40 @@
+// license:BSD-3-Clause
+// copyright-holders:
+
+#ifndef MAME_BUS_PCI_AHA2940AU_H
+#define MAME_BUS_PCI_AHA2940AU_H
+
+#pragma once
+
+#include "pci_slot.h"
+
+class aha2940au_scsi_device : public pci_card_device
+{
+public:
+ aha2940au_scsi_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ static constexpr feature_type unemulated_features() { return feature::MEDIA; }
+
+protected:
+ aha2940au_scsi_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+// virtual void map_extra(uint64_t memory_window_start, uint64_t memory_window_end, uint64_t memory_offset, address_space *memory_space,
+// uint64_t io_window_start, uint64_t io_window_end, uint64_t io_offset, address_space *io_space) override;
+
+ virtual void config_map(address_map &map) override;
+
+ required_memory_region m_scsi_rom;
+
+private:
+ // ...
+};
+
+DECLARE_DEVICE_TYPE(AHA2940AU, aha2940au_scsi_device)
+
+#endif // MAME_BUS_PCI_AHA2940AU_H
diff --git a/src/devices/bus/pci/audiowerk2.cpp b/src/devices/bus/pci/audiowerk2.cpp
new file mode 100644
index 00000000000..d6fbfda7445
--- /dev/null
+++ b/src/devices/bus/pci/audiowerk2.cpp
@@ -0,0 +1,93 @@
+// license:BSD-3-Clause
+// copyright-holders:
+/**************************************************************************************************
+
+Emagic Audiowerk2 / Audiowerk8 Digital Audio Recording PCI
+
+Audiowerk2 HW:
+- SAA7146A (Multimedia PCI Bridge Scaler)
+- SAA7367 (Digital audio ADC bitstream conversion)
+- 2x TDA1315H (?)
+- 28-ish MHz (?)
+
+Back cover box claims:
+- 2x analog inputs (-10dBV, unbalanced RCA);
+- 2x analog outputs (-10dBV, unbalanced RCA);
+- 2x Stereo digital I/O (S/PDIF, RCA);
+- Bitstream A/D and D/A converters (128 oversampling);
+- Sample Rate 44.1 kHz;
+- THD: 0.006% @ 1 kHz, 0 dB signal level;
+- dynamic range: 92 dB, input-to-output, A-weighted;
+- Frequency response: 20 Hz to 20 kHz, -/+ 0.5 dB, input-to-output;
+- PCI busmaster;
+
+SAA7146A is also the basis of several other DVB-based capture cards
+cfr. https://admin.pci-ids.ucw.cz/read/PC/1131/7146
+
+**************************************************************************************************/
+
+#include "emu.h"
+#include "audiowerk2.h"
+
+#define LOG_WARN (1U << 1)
+
+#define VERBOSE (LOG_GENERAL | LOG_WARN)
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+#define LOGWARN(...) LOGMASKED(LOG_WARN, __VA_ARGS__)
+
+
+DEFINE_DEVICE_TYPE(AUDIOWERK2, audiowerk2_device, "audiowerk2", "Emagic Audiowerk2 Digital Audio Recording")
+
+
+
+audiowerk2_device::audiowerk2_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : pci_card_device(mconfig, type, tag, owner, clock)
+{
+ // TODO: subvendor ID, comes from i2c bus
+ set_ids(0x11317146, 0x01, 0x048000, 0x00000000);
+}
+
+audiowerk2_device::audiowerk2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : audiowerk2_device(mconfig, AUDIOWERK2, tag, owner, clock)
+{
+}
+
+void audiowerk2_device::device_add_mconfig(machine_config &config)
+{
+
+}
+
+void audiowerk2_device::device_start()
+{
+ pci_card_device::device_start();
+
+ add_map( 0x1000000, M_MEM, FUNC(audiowerk2_device::map));
+
+ // INTA#
+ intr_pin = 1;
+ // TODO: PCI regs 0x3e/0x3f max_lat = 0x26, min_gnt = 0x0f
+}
+
+void audiowerk2_device::device_reset()
+{
+ pci_card_device::device_reset();
+
+ // TODO: default
+ command = 0x0000;
+ // fast back-to-back, medium DEVSEL#
+ status = 0x0280;
+
+ remap_cb();
+}
+
+void audiowerk2_device::config_map(address_map &map)
+{
+ pci_card_device::config_map(map);
+}
+
+void audiowerk2_device::map(address_map &map)
+{
+ // ...
+}
diff --git a/src/devices/bus/pci/audiowerk2.h b/src/devices/bus/pci/audiowerk2.h
new file mode 100644
index 00000000000..f7b5bdd976b
--- /dev/null
+++ b/src/devices/bus/pci/audiowerk2.h
@@ -0,0 +1,38 @@
+// license:BSD-3-Clause
+// copyright-holders:
+
+#ifndef MAME_BUS_PCI_AUDIOWERK2_H
+#define MAME_BUS_PCI_AUDIOWERK2_H
+
+#pragma once
+
+#include "pci_slot.h"
+
+class audiowerk2_device : public pci_card_device
+{
+public:
+ audiowerk2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ static constexpr feature_type unemulated_features() { return feature::SOUND | feature::CAPTURE; }
+
+protected:
+ audiowerk2_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+
+// virtual const tiny_rom_entry *device_rom_region() const override;
+
+// virtual void map_extra(uint64_t memory_window_start, uint64_t memory_window_end, uint64_t memory_offset, address_space *memory_space,
+// uint64_t io_window_start, uint64_t io_window_end, uint64_t io_offset, address_space *io_space) override;
+
+ virtual void config_map(address_map &map) override;
+
+private:
+ void map(address_map &map);
+};
+
+DECLARE_DEVICE_TYPE(AUDIOWERK2, audiowerk2_device)
+
+#endif // MAME_BUS_PCI_AUDIOWERK2_H
diff --git a/src/devices/bus/pci/clgd5446.cpp b/src/devices/bus/pci/clgd5446.cpp
new file mode 100644
index 00000000000..39d26fd94c1
--- /dev/null
+++ b/src/devices/bus/pci/clgd5446.cpp
@@ -0,0 +1,146 @@
+// license:BSD-3-Clause
+// copyright-holders:Angelo Salese
+/**************************************************************************************************
+
+Cirrus Logic CL-GD5446
+
+Assume Rev. B
+
+**************************************************************************************************/
+
+#include "emu.h"
+#include "clgd5446.h"
+
+#include "screen.h"
+
+#define LOG_WARN (1U << 1)
+#define LOG_TODO (1U << 2) // log unimplemented registers
+
+#define VERBOSE (LOG_GENERAL | LOG_WARN | LOG_TODO)
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+#define LOGWARN(...) LOGMASKED(LOG_WARN, __VA_ARGS__)
+#define LOGTODO(...) LOGMASKED(LOG_TODO, __VA_ARGS__)
+
+DEFINE_DEVICE_TYPE(GD5446_PCI, cirrus_gd5446_pci_device, "clgd5446_pci", "Cirrus Logic GD5446 card")
+
+cirrus_gd5446_pci_device::cirrus_gd5446_pci_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : pci_card_device(mconfig, GD5446_PCI, tag, owner, clock)
+ , m_vga(*this, "svga")
+ , m_vga_rom(*this, "vga_rom")
+{
+ // subvendor ID: Returns values from ROM 0x7ffc-0x7ffe
+ set_ids(0x101300b8, 0x00, 0x030000, 0x10130000);
+}
+
+ROM_START( gd5446 )
+ // Cirrus Logic/Quadtel CL-GD5446 PCI VGA BIOS v1.31, AT27C256R
+ // from photoply
+ ROM_REGION32_LE( 0x8000, "vga_rom", ROMREGION_ERASEFF )
+ ROM_SYSTEM_BIOS( 0, "quadtel", "Quadtel CL-GD5446 1.31" )
+ ROMX_LOAD( "cl-gd5446_pci_vga_bios_version_1.31.u2", 0x0000, 0x8000, CRC(61f8cac7) SHA1(6e54aadfe10dfa5c7e417a054e9a64499a99083c), ROM_BIOS(0) )
+ // Chip:CL-GD5446-HC-A - ROM: CL-GD5436/46 PCI VGA BIOS Version 1.25 - RAM: 1MB, 2MB, 4MB -
+ // OSC: 14.31818MHz - Connector: DB15 - VESA feature connector
+ ROM_SYSTEM_BIOS( 1, "quadtelo", "Quadtel CL-GD5446 1.25" )
+ ROMX_LOAD("cl-gd5446_pci_vga_bios_version_1.25.u2", 0x0000, 0x8000, CRC(7a859659) SHA1(ff667218261969c48082ec12aa91088a01b0cb2a), ROM_BIOS(1) )
+// ROMX_LOAD("5446bv.vbi", 0x00000, 0x10000, CRC(7a859659) SHA1(ff667218261969c48082ec12aa91088a01b0cb2a) )
+ROM_END
+
+const tiny_rom_entry *cirrus_gd5446_pci_device::device_rom_region() const
+{
+ return ROM_NAME(gd5446);
+}
+
+void cirrus_gd5446_pci_device::device_add_mconfig(machine_config &config)
+{
+ screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
+ screen.set_raw(XTAL(25'174'800), 900, 0, 640, 526, 0, 480);
+ screen.set_screen_update(m_vga, FUNC(cirrus_gd5446_vga_device::screen_update));
+
+ CIRRUS_GD5446_VGA(config, m_vga, 0);
+ m_vga->set_screen("screen");
+ // 1MB or 2MB, max 4MB
+ m_vga->set_vram_size(4*1024*1024);
+}
+
+void cirrus_gd5446_pci_device::device_start()
+{
+ pci_device::device_start();
+
+ add_map( 32*1024*1024, M_MEM, FUNC(cirrus_gd5446_pci_device::vram_aperture_map));
+ // TODO: special in Rev A, can be either M_MEM or M_IO thru CF8 / CF4 / CF3
+ //add_map( 4096, M_MEM, FUNC(cirrus_gd5446_pci_device::mmio_map));
+ add_map( 512, M_MEM, FUNC(cirrus_gd5446_pci_device::mmio_map));
+ // TODO: Rev B do the same, except it just maps GPIO here thru CF8 / CF4
+ add_map( 512, M_MEM, FUNC(cirrus_gd5446_pci_device::gpio_map));
+
+ add_rom((u8 *)m_vga_rom->base(), 0x8000);
+ expansion_rom_base = 0xc0000;
+
+ // INTA#
+ intr_pin = 1;
+}
+
+void cirrus_gd5446_pci_device::device_reset()
+{
+ pci_device::device_reset();
+
+ command = 0x0000;
+ command_mask = 0x0023;
+ // medium DEVSEL#
+ status = 0x0200;
+
+ remap_cb();
+}
+
+void cirrus_gd5446_pci_device::config_map(address_map &map)
+{
+ pci_device::config_map(map);
+}
+
+void cirrus_gd5446_pci_device::vram_aperture_map(address_map &map)
+{
+ map(0x000000, 0x3fffff).rw(m_vga, FUNC(cirrus_gd5446_vga_device::mem_linear_r), FUNC(cirrus_gd5446_vga_device::mem_linear_w));
+}
+
+void cirrus_gd5446_pci_device::mmio_map(address_map &map)
+{
+
+}
+
+void cirrus_gd5446_pci_device::gpio_map(address_map &map)
+{
+
+}
+
+// TODO: this should really be a subclass of VGA
+void cirrus_gd5446_pci_device::legacy_memory_map(address_map &map)
+{
+ map(0xa0000, 0xbffff).rw(FUNC(cirrus_gd5446_pci_device::vram_r), FUNC(cirrus_gd5446_pci_device::vram_w));
+}
+
+void cirrus_gd5446_pci_device::legacy_io_map(address_map &map)
+{
+ map(0, 0x02f).m(m_vga, FUNC(cirrus_gd5446_vga_device::io_map));
+}
+
+uint8_t cirrus_gd5446_pci_device::vram_r(offs_t offset)
+{
+ return downcast<cirrus_gd5446_vga_device *>(m_vga.target())->mem_r(offset);
+}
+
+void cirrus_gd5446_pci_device::vram_w(offs_t offset, uint8_t data)
+{
+ downcast<cirrus_gd5446_vga_device *>(m_vga.target())->mem_w(offset, data);
+}
+
+void cirrus_gd5446_pci_device::map_extra(uint64_t memory_window_start, uint64_t memory_window_end, uint64_t memory_offset, address_space *memory_space,
+ uint64_t io_window_start, uint64_t io_window_end, uint64_t io_offset, address_space *io_space)
+{
+ {
+ memory_space->install_readwrite_handler(0xa0000, 0xbffff, read8sm_delegate(*this, FUNC(cirrus_gd5446_pci_device::vram_r)), write8sm_delegate(*this, FUNC(cirrus_gd5446_pci_device::vram_w)));
+
+ io_space->install_device(0x03b0, 0x03df, *this, &cirrus_gd5446_pci_device::legacy_io_map);
+ }
+}
diff --git a/src/devices/bus/pci/clgd5446.h b/src/devices/bus/pci/clgd5446.h
new file mode 100644
index 00000000000..b25937d1cce
--- /dev/null
+++ b/src/devices/bus/pci/clgd5446.h
@@ -0,0 +1,47 @@
+// license:BSD-3-Clause
+// copyright-holders:Angelo Salese
+#ifndef MAME_BUS_PCI_CLGD5446_H
+#define MAME_BUS_PCI_CLGD5446_H
+
+#pragma once
+
+#include "pci_slot.h"
+#include "video/pc_vga_cirrus.h"
+
+class cirrus_gd5446_pci_device : public pci_card_device
+{
+public:
+ cirrus_gd5446_pci_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ void legacy_memory_map(address_map &map);
+ void legacy_io_map(address_map &map);
+
+protected:
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+ virtual void map_extra(uint64_t memory_window_start, uint64_t memory_window_end, uint64_t memory_offset, address_space *memory_space,
+ uint64_t io_window_start, uint64_t io_window_end, uint64_t io_offset, address_space *io_space) override;
+
+ virtual void config_map(address_map &map) override;
+
+ virtual void mmio_map(address_map &map);
+ virtual void vram_aperture_map(address_map &map);
+ virtual void gpio_map(address_map &map);
+private:
+ required_device<cirrus_gd5446_vga_device> m_vga;
+ required_memory_region m_vga_rom;
+
+ u8 vram_r(offs_t offset);
+ void vram_w(offs_t offset, uint8_t data);
+
+// u32 unmap_log_r(offs_t offset, u32 mem_mask = ~0);
+// void unmap_log_w(offs_t offset, u32 data, u32 mem_mask = ~0);
+};
+
+DECLARE_DEVICE_TYPE(GD5446_PCI, cirrus_gd5446_pci_device)
+
+#endif // MAME_BUS_PCI_CLGD546X_LAGUNA_H
diff --git a/src/devices/bus/pci/clgd546x_laguna.cpp b/src/devices/bus/pci/clgd546x_laguna.cpp
new file mode 100644
index 00000000000..ff9e3b309db
--- /dev/null
+++ b/src/devices/bus/pci/clgd546x_laguna.cpp
@@ -0,0 +1,205 @@
+// license:BSD-3-Clause
+// copyright-holders:Angelo Salese
+
+#include "emu.h"
+#include "clgd546x_laguna.h"
+
+#include "screen.h"
+
+#define LOG_WARN (1U << 1)
+#define LOG_TODO (1U << 2) // log unimplemented registers
+
+#define VERBOSE (LOG_GENERAL | LOG_WARN | LOG_TODO)
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+#define LOGWARN(...) LOGMASKED(LOG_WARN, __VA_ARGS__)
+#define LOGTODO(...) LOGMASKED(LOG_TODO, __VA_ARGS__)
+
+DEFINE_DEVICE_TYPE(GD5465_LAGUNA3D, cirrus_gd5465_laguna3d_device, "clgd5465_laguna", "Cirrus Logic GD-5465 \"Laguna 3D\"")
+
+cirrus_gd5465_laguna3d_device::cirrus_gd5465_laguna3d_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : pci_card_device(mconfig, GD5465_LAGUNA3D, tag, owner, clock)
+ , m_vga(*this, "vga")
+ , m_vga_rom(*this, "vga_rom")
+{
+ // device ID 0x1013 Cirrus Logic
+ // 0x00dx for Laguna revs
+ // subvendor ID: Returns values from ROM 0x7ff8-0x7ffb
+ set_ids_agp(0x101300d6, 0x00, 0x10130000);
+ // TODO: class can be 0x80 (other display controller) with P18 pin.
+}
+
+/*
+ Cirrus Logic CL-GD5464 Laguna3D
+// DSystems Wizar3D PCI graphics card - Chip: CL-GD5464-HC-A - ROM: DSystems Wizar3D 144a.10H - RAM: 2MB, 4MB, 8MB - Connector: DB15 - VESA feature connector
+ROM_START( clgd5464 )
+ ROM_REGION32_LE( 0x08000, "vga_rom", ROMREGION_ERASEFF )
+ ROM_LOAD("dsystems_wizard3d.vbi", 0x00000, 0x08000, CRC(df9f1570), SHA1(4e611f4039b851fd4237d450e38c9d764920a747) )
+ROM_END
+
+*/
+
+ROM_START( gd5465 )
+ // Chaintech GA-5465AS AGP graphics card - Chip: CL-GD5465 - ROM: CL-GD546x Laguna PCI VGA BIOS Version 1.62c - RAM: 4MB, 8MB - OSC: 14.3C7Y - Connector: DB15 - VESA feature connector
+ ROM_REGION32_LE( 0x8000, "vga_rom", ROMREGION_ERASEFF )
+ ROM_SYSTEM_BIOS( 0, "chaintech", "Chaintech GA-5465AS 1.62c" )
+ ROMX_LOAD( "chaintech.vbi", 0x0000, 0x8000, CRC(8afa1afb) SHA1(251a953d442dc34738f80371cfbd0fd9f1097635), ROM_BIOS(0) )
+ROM_END
+
+const tiny_rom_entry *cirrus_gd5465_laguna3d_device::device_rom_region() const
+{
+ return ROM_NAME(gd5465);
+}
+
+void cirrus_gd5465_laguna3d_device::device_add_mconfig(machine_config &config)
+{
+ screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
+ screen.set_raw(XTAL(25'174'800), 900, 0, 640, 526, 0, 480);
+ screen.set_screen_update(m_vga, FUNC(cirrus_gd5446_vga_device::screen_update));
+
+ // TODO: bump to GD5465
+ CIRRUS_GD5446_VGA(config, m_vga, 0);
+ m_vga->set_screen("screen");
+ // FIXME: shared RAM
+ // in 4 and 8 MB versions
+ m_vga->set_vram_size(8*1024*1024);
+}
+
+void cirrus_gd5465_laguna3d_device::device_start()
+{
+ pci_device::device_start();
+
+ add_map( 32*1024, M_MEM, FUNC(cirrus_gd5465_laguna3d_device::mmio_map));
+ add_map( 32*1024*1024, M_MEM, FUNC(cirrus_gd5465_laguna3d_device::vram_aperture_map));
+
+ add_rom((u8 *)m_vga_rom->base(), 0x8000);
+ expansion_rom_base = 0xc0000;
+
+ // INTA#
+ intr_pin = 1;
+ save_item(NAME(m_vga_legacy_enable));
+
+ // TODO: fast back-to-back
+}
+
+void cirrus_gd5465_laguna3d_device::device_reset()
+{
+ pci_device::device_reset();
+
+ // TODO: to be checked
+ command = 0x0000;
+ status = 0x0000;
+
+ m_vga_legacy_enable = true;
+ remap_cb();
+}
+
+void cirrus_gd5465_laguna3d_device::config_map(address_map &map)
+{
+ pci_device::config_map(map);
+ // TODO: AGP CAPPTR
+// map(0xf8, 0xf8) PCI VGA Shadow Register
+// map(0xfc, 0xfc) PCI Vendor Specific Control Register
+}
+
+void cirrus_gd5465_laguna3d_device::mmio_map(address_map &map)
+{
+
+}
+
+void cirrus_gd5465_laguna3d_device::vram_aperture_map(address_map &map)
+{
+
+}
+
+// TODO: this should really be a subclass of VGA
+void cirrus_gd5465_laguna3d_device::legacy_memory_map(address_map &map)
+{
+ map(0xa0000, 0xbffff).rw(FUNC(cirrus_gd5465_laguna3d_device::vram_r), FUNC(cirrus_gd5465_laguna3d_device::vram_w));
+}
+
+void cirrus_gd5465_laguna3d_device::legacy_io_map(address_map &map)
+{
+ map(0, 0x02f).m(m_vga, FUNC(cirrus_gd5446_vga_device::io_map));
+}
+
+uint8_t cirrus_gd5465_laguna3d_device::vram_r(offs_t offset)
+{
+ return downcast<cirrus_gd5446_vga_device *>(m_vga.target())->mem_r(offset);
+}
+
+void cirrus_gd5465_laguna3d_device::vram_w(offs_t offset, uint8_t data)
+{
+ downcast<cirrus_gd5446_vga_device *>(m_vga.target())->mem_w(offset, data);
+}
+
+void cirrus_gd5465_laguna3d_device::map_extra(uint64_t memory_window_start, uint64_t memory_window_end, uint64_t memory_offset, address_space *memory_space,
+ uint64_t io_window_start, uint64_t io_window_end, uint64_t io_offset, address_space *io_space)
+{
+ if (m_vga_legacy_enable)
+ {
+ memory_space->install_readwrite_handler(0xa0000, 0xbffff, read8sm_delegate(*this, FUNC(cirrus_gd5465_laguna3d_device::vram_r)), write8sm_delegate(*this, FUNC(cirrus_gd5465_laguna3d_device::vram_w)));
+
+ io_space->install_device(0x03b0, 0x03df, *this, &cirrus_gd5465_laguna3d_device::legacy_io_map);
+ }
+}
+
+/*
+ Cirrus Logic CL-GD54M30 - PCI
+ROM_START( clgd54m30 )
+ ROM_REGION(0x10000, "clgd54m30", 0)
+ // Chip: CL-GD54M30-I-QC-A, ROM: 32KB, RAM: 1MB, 2MB, Connector: DB15, VESA veature connector
+ ROM_SYSTEM_BIOS(0, "version_1.00d", "VGA BIOS Version 1.00d")
+ ROMX_LOAD("korea.bin", 0x00000, 0x10000, CRC(0870507b) SHA1(b3873cb8834767250fcb7043918a35b1b895b0b1), ROM_BIOS(0) )
+ ROM_SYSTEM_BIOS(1, "stlab_ver_1.00d", "STlab Version 1.00d")
+ ROMX_LOAD("gd54m30stlab.bin", 0x08000, 0x8000, CRC(72116f4e) SHA1(4618640aa0f07586ebab02260fc58aa3035114fb), ROM_BIOS(1) )
+ ROM_SYSTEM_BIOS(2, "clgd54m30_ver1.00d", "CL-GD54M30 Ver.1.00d")
+ ROMX("gd54m30.bin", 0x08000, 0x000, CRC(45a1d9d0) SHA1(0e8a88ff354699bfb75a1de807f2187ff9910c67), ROM_BIOS(2) )
+ROM_END
+
+*/
+
+/*
+ Cirrus Logic CL-GD543x - PCI cards
+
+// PCI card CL543XPCI Ver 4.0 - ROM: CL-GD543x PCI VGA BIOS Version 1.10B - RAM: 1MB, 2MB or 4MB - Chip: CL-GD5430-0C-C - OSC: 14.318 MHz - Connector: DB15
+// VESA feature connector - Jumpers: IRQ9 enable/disable, Green control
+ROM_START( clgd543x_pci )
+ ROM_REGION(0x08000, "clgd543x_pci", 0)
+ ROM_SYSTEM_BIOS(0, "pci_version_1.10b", "PCI VGA BIOS Version 1.10B")
+ ROMX_LOAD("cl543x_pci_rev4.bin", 0x00000, 0x8000, CRC(553171a3) SHA1(b72edc318710c46c9cb280e9b1b3c9f8a34844f2), ROM_BIOS(0) )
+ ROM_IGNORE( 0x8000 )
+ ROM_SYSTEM_BIOS(1, "pci_version_1.00e", "PCI VGA BIOS Version 1.00e")
+ ROMX_LOAD("cirrus5434.bin", 0x00000, 0x8000, CRC(bc271648) SHA1(08afd4468c4c1a1630a200de1007b1671f109b3c), ROM_BIOS(1) )
+ ROM_SYSTEM_BIOS(2, "pci_version_1.22", "PCI VGA BIOS Version 1.22")
+ ROMX_LOAD("gd5434pci.bin", 0x00000, 0x8000, CRC(fa76dabf) SHA1(0310ef02df941e7d35e1d832400e2e4dd07d6309), ROM_BIOS(2) )
+ ROM_SYSTEM_BIOS(3, "pci_ver_1.10b_jap", "PCI VGA BIOS Version 1.10B Japan chip")
+ ROMX_LOAD("japan.bin", 0x00000, 0x8000, CRC(46fe9efa) SHA1(58712b00faf102509c4129c0babeb98df2b6e042), ROM_BIOS(3) )
+ ROM_SYSTEM_BIOS(4, "gd5434pciv124", "CL-GD543x PCI VGA BIOS Version 1.24")
+ ROMX_LOAD("1.24.bin", 0x00000,0x8000, CRC(174fa427) SHA1(3e490f3cc3af33dbfac6ff3ddac5e90bdc895646), ROM_BIOS(4) )
+ROM_END
+
+*/
+
+/*
+ Cirrus Logic VL-GD5436 - PCI cards
+
+//Chip: CL-GD5436-I-QC-A - ROM: CL-GD5436 VL/PCI VGA BIOS Version 1.00b - RAM: 1MB, up to 4MB - Connector: DB15 - VESA connector - OSC: 14.31818MHz
+// Jumpers: JG1 Green Control, IRQ9 enable/disable
+ROM_START( clgd5436 )
+ ROM_REGION(0x08000, "clgd5436", 0)
+ ROM_LOAD("5436.vbi", 0x00000, 0x08000, CRC(7737d03e) SHA1(e4d0b4e7262887dc5a6473ea8909fdc13a6a02c1) )
+ROM_END
+
+*/
+
+/*
+ Cirrus Logic CL-GD5440 - PCI cards
+
+// Chip: Cirrus Logic CL-GD5440-J-QC-B - ROM: CL-GD5440 VGA BIOS Version 1.07 - RAM: 1MB, max. 2MB - OSC:14.31818MHz - Connector: DB15 - VESA connector
+ROM_START( clgd5440 )
+ ROM_REGION(0x10000, "clgd5440", 0)
+ ROM_LOAD("bios.bin", 0x00000, 0x10000, CRC(f0d3d0b4) SHA1(620b0727a20b127f5f32576ec54fbc6f9f437ad3) )
+ROM_END
+*/
diff --git a/src/devices/bus/pci/clgd546x_laguna.h b/src/devices/bus/pci/clgd546x_laguna.h
new file mode 100644
index 00000000000..c9cf83d7a1d
--- /dev/null
+++ b/src/devices/bus/pci/clgd546x_laguna.h
@@ -0,0 +1,48 @@
+// license:BSD-3-Clause
+// copyright-holders:Angelo Salese
+#ifndef MAME_BUS_PCI_CLGD546X_LAGUNA_H
+#define MAME_BUS_PCI_CLGD546X_LAGUNA_H
+
+#pragma once
+
+#include "pci_slot.h"
+#include "video/pc_vga_cirrus.h"
+
+class cirrus_gd5465_laguna3d_device : public pci_card_device
+{
+public:
+ cirrus_gd5465_laguna3d_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ void legacy_memory_map(address_map &map);
+ void legacy_io_map(address_map &map);
+
+protected:
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+ virtual void map_extra(uint64_t memory_window_start, uint64_t memory_window_end, uint64_t memory_offset, address_space *memory_space,
+ uint64_t io_window_start, uint64_t io_window_end, uint64_t io_offset, address_space *io_space) override;
+
+ virtual void config_map(address_map &map) override;
+
+ virtual void mmio_map(address_map &map);
+ virtual void vram_aperture_map(address_map &map);
+private:
+ required_device<cirrus_gd5446_vga_device> m_vga;
+ required_memory_region m_vga_rom;
+
+ u8 vram_r(offs_t offset);
+ void vram_w(offs_t offset, uint8_t data);
+
+// u32 unmap_log_r(offs_t offset, u32 mem_mask = ~0);
+// void unmap_log_w(offs_t offset, u32 data, u32 mem_mask = ~0);
+
+ bool m_vga_legacy_enable = false;
+};
+
+DECLARE_DEVICE_TYPE(GD5465_LAGUNA3D, cirrus_gd5465_laguna3d_device)
+
+#endif // MAME_BUS_PCI_CLGD546X_LAGUNA_H
diff --git a/src/devices/bus/pci/ds2416.cpp b/src/devices/bus/pci/ds2416.cpp
new file mode 100644
index 00000000000..ad050d22a4c
--- /dev/null
+++ b/src/devices/bus/pci/ds2416.cpp
@@ -0,0 +1,23 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+
+#include "emu.h"
+#include "ds2416.h"
+
+DEFINE_DEVICE_TYPE(DS2416, ds2416_device, "ds2416", "Yamaha DS2416")
+
+ds2416_device::ds2416_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : ymp21_device(mconfig, DS2416, tag, owner, clock)
+{
+ set_ids(0x10732000, 0x00, 0x040100, 0x10732000);
+}
+
+void ds2416_device::device_start()
+{
+ ymp21_device::device_start();
+}
+
+void ds2416_device::device_reset()
+{
+ ymp21_device::device_reset();
+}
diff --git a/src/devices/bus/pci/ds2416.h b/src/devices/bus/pci/ds2416.h
new file mode 100644
index 00000000000..2193a7e2720
--- /dev/null
+++ b/src/devices/bus/pci/ds2416.h
@@ -0,0 +1,22 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+
+#ifndef MAME_BUS_PCI_DS2416_H
+#define MAME_BUS_PCI_DS2416_H
+
+#pragma once
+
+#include "ymp21.h"
+
+class ds2416_device : public ymp21_device {
+public:
+ ds2416_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
+
+protected:
+ virtual void device_start() override;
+ virtual void device_reset() override;
+};
+
+DECLARE_DEVICE_TYPE(DS2416, ds2416_device)
+
+#endif
diff --git a/src/devices/bus/pci/ess_maestro.cpp b/src/devices/bus/pci/ess_maestro.cpp
new file mode 100644
index 00000000000..a6a3107d1ac
--- /dev/null
+++ b/src/devices/bus/pci/ess_maestro.cpp
@@ -0,0 +1,117 @@
+// license:BSD-3-Clause
+// copyright-holders:
+/**************************************************************************************************
+
+ESS Solo-1/Maestro audio PCI cards
+
+- PCI rev 2.2, APM 1.2, ACPI 1.0, PPMI 1.0;
+- ESFM (SoundBlaster clone);
+- Spatializer VBX 3-D as DSP core;
+- 2x game ports;
+- i2s Zoom Video port for MPEG audio;
+- Known to have a poor SnR ratio (around -64 dB)
+
+- Required by misc/gammagic.cpp
+- Embedded on Chaintech 6ESA-2-E100N (Slot 1, I440EX / PIIX4E)
+- Embedded on ASUS ME-99 (Socket 370, SiS620 / SiS5595)
+
+**************************************************************************************************/
+
+#include "emu.h"
+#include "ess_maestro.h"
+
+#define LOG_WARN (1U << 1)
+
+#define VERBOSE (LOG_GENERAL | LOG_WARN)
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+#define LOGWARN(...) LOGMASKED(LOG_WARN, __VA_ARGS__)
+
+// ES1938 Solo-1
+DEFINE_DEVICE_TYPE(ES1946_SOLO1E, es1946_solo1e_device, "es1946_solo1e", "ES1938/ES1946/ES1969 Solo-1 Audiodrive")
+// ES1969 Solo-1
+// ES1948 Maestro-1
+// ES1968 Maestro-2
+// ES1978 Maestro-2E
+
+
+es1946_solo1e_device::es1946_solo1e_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : pci_card_device(mconfig, type, tag, owner, clock)
+{
+ // TODO: subvendor from EEPROM
+ set_ids(0x125d1969, 0x01, 0x040100, 0x125d1969);
+}
+
+es1946_solo1e_device::es1946_solo1e_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : es1946_solo1e_device(mconfig, ES1946_SOLO1E, tag, owner, clock)
+{
+}
+
+void es1946_solo1e_device::device_add_mconfig(machine_config &config)
+{
+
+}
+
+void es1946_solo1e_device::device_start()
+{
+ pci_card_device::device_start();
+
+ add_map(64, M_IO, FUNC(es1946_solo1e_device::extended_map));
+ add_map(16, M_IO, FUNC(es1946_solo1e_device::sb_map));
+ add_map(16, M_IO, FUNC(es1946_solo1e_device::vcbase_map));
+ add_map( 4, M_IO, FUNC(es1946_solo1e_device::mpu_map));
+ add_map( 4, M_IO, FUNC(es1946_solo1e_device::gameport_map));
+
+ // INTA#
+ intr_pin = 1;
+}
+
+void es1946_solo1e_device::device_reset()
+{
+ pci_card_device::device_reset();
+
+ command = 0x0000;
+ // ACPI capable, Fast back-to-back, medium DEVSEL#
+ status = 0x0290;
+ // TODO: min_gnt 0x02, max_lat = 0x18
+
+ remap_cb();
+}
+
+uint8_t es1946_solo1e_device::capptr_r()
+{
+ return 0xc0;
+}
+
+void es1946_solo1e_device::config_map(address_map &map)
+{
+ pci_card_device::config_map(map);
+// map(0x40, 0x41) Legacy Audio Control
+// map(0x50, 0x53) ES1946 Config
+// map(0x60, 0x61) DDMA Control
+ // ACPI
+ map(0xc0, 0xc0).lr8(NAME([] () { return 0x01; }));
+ map(0xc1, 0xc1).lr8(NAME([] () { return 0x00; })); // NULL pointer
+// map(0xc2, 0xc3) Power Management Capabilities
+// map(0xc4, 0xc5) Power Management Control/Status
+}
+
+void es1946_solo1e_device::extended_map(address_map &map)
+{
+}
+void es1946_solo1e_device::sb_map(address_map &map)
+{
+}
+
+void es1946_solo1e_device::vcbase_map(address_map &map)
+{
+}
+
+void es1946_solo1e_device::mpu_map(address_map &map)
+{
+}
+
+void es1946_solo1e_device::gameport_map(address_map &map)
+{
+}
diff --git a/src/devices/bus/pci/ess_maestro.h b/src/devices/bus/pci/ess_maestro.h
new file mode 100644
index 00000000000..bb65bc9ec8e
--- /dev/null
+++ b/src/devices/bus/pci/ess_maestro.h
@@ -0,0 +1,44 @@
+// license:BSD-3-Clause
+// copyright-holders:
+
+#ifndef MAME_BUS_PCI_ESS_MAESTRO_H
+#define MAME_BUS_PCI_ESS_MAESTRO_H
+
+#pragma once
+
+#include "pci_slot.h"
+
+class es1946_solo1e_device : public pci_card_device
+{
+public:
+ es1946_solo1e_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ static constexpr feature_type unemulated_features() { return feature::SOUND; }
+
+protected:
+ es1946_solo1e_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+
+// virtual const tiny_rom_entry *device_rom_region() const override;
+
+// virtual void map_extra(uint64_t memory_window_start, uint64_t memory_window_end, uint64_t memory_offset, address_space *memory_space,
+// uint64_t io_window_start, uint64_t io_window_end, uint64_t io_offset, address_space *io_space) override;
+
+ virtual void config_map(address_map &map) override;
+
+ virtual u8 capptr_r() override;
+
+private:
+ void extended_map(address_map &map);
+ void sb_map(address_map &map);
+ void vcbase_map(address_map &map);
+ void mpu_map(address_map &map);
+ void gameport_map(address_map &map);
+};
+
+DECLARE_DEVICE_TYPE(ES1946_SOLO1E, es1946_solo1e_device)
+
+#endif // MAME_BUS_PCI_ESS_MAESTRO_H
diff --git a/src/devices/bus/pci/geforce.cpp b/src/devices/bus/pci/geforce.cpp
new file mode 100644
index 00000000000..7ebe882ede4
--- /dev/null
+++ b/src/devices/bus/pci/geforce.cpp
@@ -0,0 +1,114 @@
+// license:BSD-3-Clause
+// copyright-holders: Angelo Salese
+/**************************************************************************************************
+
+nVidia NV10 "Celsius"
+a.k.a. first gen GeForce
+
+TODO:
+- Compared to NV5 VGA controller extensively writes to extended register $40;
+- All "elsa" BIOSes prompt user to "buy the card", copy protection related to EDID?
+- geforce256 DDR "creative" BIOS draws garbage for RAM detection during POST;
+
+**************************************************************************************************/
+
+#include "emu.h"
+#include "geforce.h"
+
+DEFINE_DEVICE_TYPE(GEFORCE256, geforce256_device, "geforce256", "nVidia GeForce 256 SDR (NV10)")
+DEFINE_DEVICE_TYPE(GEFORCE256_DDR, geforce256_ddr_device, "geforce256ddr", "nVidia GeForce 256 DDR (NV10)")
+//DEFINE_DEVICE_TYPE(GEFORCE256_ULTRA, geforce256_ultra_device, "geforce256ultra", "nVidia GeForce 256 Ultra (NV10)")
+DEFINE_DEVICE_TYPE(QUADRO, quadro_device, "quadro", "nVidia Quadro (NV10)")
+
+geforce256_device::geforce256_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : rivatnt2_device(mconfig, type, tag, owner, clock)
+{
+}
+
+geforce256_device::geforce256_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : geforce256_device(mconfig, GEFORCE256, tag, owner, clock)
+{
+ // 0x0100 GeForce 256 SDR
+ // 0x0101 ^ DDR
+ // 0x0102 ^ Ultra
+ // 0x0103 Quadro
+ // ELSA Synergy Force subvendor id
+ set_ids_agp(0x10de0100, 0x00, 0x10480c48);
+}
+
+
+ROM_START( geforce256 )
+ ROM_REGION32_LE( 0x10000, "vga_rom", ROMREGION_ERASEFF )
+ ROM_SYSTEM_BIOS( 0, "elsa", "ELSA Synergy Force (Ver 7.03.00 01/11/00)" )
+ ROMX_LOAD( "nv10.bin", 0x0000, 0xac00, BAD_DUMP CRC(3525816d) SHA1(6fef6773dd1b18148890f8c3d45f988e5e06b50d), ROM_BIOS(0) )
+ROM_END
+
+const tiny_rom_entry *geforce256_device::device_rom_region() const
+{
+ return ROM_NAME(geforce256);
+}
+
+void geforce256_device::device_start()
+{
+ pci_card_device::device_start();
+
+ add_map( 16*1024*1024, M_MEM, FUNC(geforce256_device::mmio_map));
+ add_map(128*1024*1024, M_MEM, FUNC(geforce256_device::vram_aperture_map));
+
+ add_rom((u8 *)m_vga_rom->base(), 0x10000);
+ expansion_rom_base = 0xc0000;
+
+ // INTA#
+ intr_pin = 1;
+ save_item(NAME(m_vga_legacy_enable));
+}
+
+/********************************************/
+
+geforce256_ddr_device::geforce256_ddr_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : geforce256_device(mconfig, GEFORCE256_DDR, tag, owner, clock)
+{
+ // device ID 0x10de nVidia
+ // TODO: Rev A6
+ set_ids_agp(0x10de0101, 0x00, 0x10de0101);
+}
+
+ROM_START( geforce256_ddr )
+ ROM_REGION32_LE( 0x10000, "vga_rom", ROMREGION_ERASEFF )
+ ROM_SYSTEM_BIOS( 0, "creative", "Creative GeForce CT6971 AGP (Ver 2.10.4.02.04)" )
+ ROMX_LOAD( "creative.rom", 0x000000, 0x009800, CRC(fd956e0b) SHA1(aaac61e99193221280c5913cf3ca503e5b5ea408), ROM_BIOS(0) )
+ROM_END
+
+const tiny_rom_entry *geforce256_ddr_device::device_rom_region() const
+{
+ return ROM_NAME(geforce256_ddr);
+}
+
+/********************************************/
+
+// TODO: GeForce 256 Ultra
+// set_ids_agp(0x10de0102, 0x00, 0x10de0102);
+
+/********************************************/
+
+quadro_device::quadro_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : geforce256_device(mconfig, QUADRO, tag, owner, clock)
+{
+ // device ID 0x10de nVidia
+ set_ids_agp(0x10de0103, 0x00, 0x10de0103);
+}
+
+ROM_START( quadro )
+ ROM_REGION32_LE( 0x10000, "vga_rom", ROMREGION_ERASEFF )
+ // NB: difference between these two is type of RAM used (SDR vs. DDR) and
+ // interface type (AGP x4 vs. Pro)
+ ROM_SYSTEM_BIOS( 0, "elsa", "Elsa GLoria II (Ver 7.02.02)" )
+ ROMX_LOAD( "elsagloriaii.bin", 0x000000, 0x00ac00, CRC(78a6fbad) SHA1(5517fefc314bd34de7839fb8077aeb252689595d), ROM_BIOS(0) )
+ ROM_SYSTEM_BIOS( 1, "elsapro", "Elsa GLoria II Pro (Ver 7.02.00)" )
+ ROMX_LOAD( "elsagloriaiipro.bin", 0x000000, 0x00ac00, CRC(b4ef6426) SHA1(006b72eb2bcb549686e4e39f8ca17972435178e4), ROM_BIOS(1) )
+ROM_END
+
+const tiny_rom_entry *quadro_device::device_rom_region() const
+{
+ return ROM_NAME(quadro);
+}
diff --git a/src/devices/bus/pci/geforce.h b/src/devices/bus/pci/geforce.h
new file mode 100644
index 00000000000..2cf2e98edea
--- /dev/null
+++ b/src/devices/bus/pci/geforce.h
@@ -0,0 +1,52 @@
+// license:BSD-3-Clause
+// copyright-holders: Angelo Salese
+
+#ifndef MAME_BUS_PCI_GEFORCE_H
+#define MAME_BUS_PCI_GEFORCE_H
+
+#pragma once
+
+#include "rivatnt.h"
+
+#include "machine/pci.h"
+#include "video/pc_vga_nvidia.h"
+
+
+class geforce256_device : public rivatnt2_device
+{
+public:
+ geforce256_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ geforce256_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_start() override;
+};
+
+class geforce256_ddr_device : public geforce256_device
+{
+public:
+ geforce256_ddr_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual const tiny_rom_entry *device_rom_region() const override;
+};
+
+class quadro_device : public geforce256_device
+{
+public:
+ quadro_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual const tiny_rom_entry *device_rom_region() const override;
+};
+
+
+DECLARE_DEVICE_TYPE(GEFORCE256, geforce256_device)
+DECLARE_DEVICE_TYPE(GEFORCE256_DDR, geforce256_ddr_device)
+//DECLARE_DEVICE_TYPE(GEFORCE256_ULTRA, geforce256_ultra_device)
+DECLARE_DEVICE_TYPE(QUADRO, quadro_device)
+
+
+#endif // MAME_BUS_PCI_GEFORCE_H
diff --git a/src/devices/bus/pci/mga2064w.cpp b/src/devices/bus/pci/mga2064w.cpp
new file mode 100644
index 00000000000..835fc7b5406
--- /dev/null
+++ b/src/devices/bus/pci/mga2064w.cpp
@@ -0,0 +1,720 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert, Angelo Salese
+
+#include "emu.h"
+#include "mga2064w.h"
+
+#define LOG_WARN (1U << 1)
+#define LOG_ALIAS (1U << 2) // log mgabase1 index setups thru the back door
+#define LOG_DRAW (1U << 3) // log drawing engine accesses
+#define LOG_PIXELXFER (1U << 4) // log drawing pixel writes
+
+#define VERBOSE (LOG_GENERAL | LOG_WARN | LOG_DRAW)
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+#define LOGWARN(...) LOGMASKED(LOG_WARN, __VA_ARGS__)
+#define LOGALIAS(...) LOGMASKED(LOG_ALIAS, __VA_ARGS__)
+#define LOGDRAW(...) LOGMASKED(LOG_DRAW, __VA_ARGS__)
+#define LOGPIXELXFER(...) LOGMASKED(LOG_PIXELXFER, __VA_ARGS__)
+
+DEFINE_DEVICE_TYPE(MGA2064W, mga2064w_device, "mga2064w", "Matrox Millennium \"IS-STORM / MGA-2064W\"")
+
+mga2064w_device::mga2064w_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : pci_card_device(mconfig, MGA2064W, tag, owner, clock)
+ , device_memory_interface(mconfig, *this)
+ , m_svga(*this, "svga")
+ , m_vga_rom(*this, "vga_rom")
+{
+ set_ids(0x102b0519, 0x01, 0x030000, 0x00000000);
+ m_mgabase1_real_space_config = address_space_config("mgabase1_regs", ENDIANNESS_LITTLE, 32, 14, 0, address_map_constructor(FUNC(mga2064w_device::mgabase1_map), this));
+}
+
+ROM_START( mga2064w )
+ ROM_REGION32_LE( 0x10000, "vga_rom", ROMREGION_ERASEFF )
+ ROM_SYSTEM_BIOS( 0, "rev3", "Matrox Power Graphics Accelerator V2.4 IS-MGA-2064W R3" )
+ ROMX_LOAD( "rev3.bin", 0x000000, 0x010000, CRC(cb623dab) SHA1(4dc10755613a8fa9599331d78995cfb15145440b), ROM_BIOS(0) )
+ // TODO: verify label naming for these
+ ROM_SYSTEM_BIOS( 1, "rev2", "Matrox Power Graphics Accelerator V1.9 IS-MGA-2064W R2 2MB" )
+ ROMX_LOAD( "rev2_2mb.bin", 0x000000, 0x010000, CRC(253c352b) SHA1(a5cd7e1c4903fcc89ea04cc1911b8d010e6513d1), ROM_BIOS(1) )
+ ROM_SYSTEM_BIOS( 2, "rev2_storm", "Matrox Power Graphics Accelerator V1.9 IS-STORM R2 (vbi)" )
+ ROMX_LOAD( "rev2_storm4mb.vbi", 0x000000, 0x008000, CRC(35660abe) SHA1(36ec630507548e1ef5fa7fdd07852d936fb614e5), ROM_BIOS(2) )
+ ROM_SYSTEM_BIOS( 3, "rev2_isstorm", "Matrox Power Graphics Accelerator V1.9 IS-STORM R2" )
+ ROMX_LOAD( "matroxisstormr2.bin", 0x000000, 0x010000, CRC(0cfceda4) SHA1(26a4fe291c738b4b138b522beb37b7db1b639634), ROM_BIOS(3) )
+ ROM_SYSTEM_BIOS( 4, "rev2_r2", "Matrox Power Graphics Accelerator V1.9 IS-MGA-2064W R2" )
+ ROMX_LOAD( "matrox2064wr2.bin", 0x000000, 0x010000, CRC(79920e74) SHA1(d62d6a57c75f2266e3d0f85916f366d62ad56ce4), ROM_BIOS(4) )
+ROM_END
+
+const tiny_rom_entry *mga2064w_device::device_rom_region() const
+{
+ return ROM_NAME(mga2064w);
+}
+
+void mga2064w_device::device_add_mconfig(machine_config &config)
+{
+ screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
+ screen.set_raw(XTAL(25'174'800), 900, 0, 640, 526, 0, 480);
+ screen.set_screen_update(m_svga, FUNC(matrox_vga_device::screen_update));
+
+ MATROX_VGA(config, m_svga, 0);
+ m_svga->set_screen("screen");
+ m_svga->set_vram_size(8*1024*1024);
+}
+
+void mga2064w_device::device_start()
+{
+ pci_card_device::device_start();
+ // NB: following is swapped on G400
+ add_map( 16*1024, M_MEM, FUNC(mga2064w_device::mgabase1_map));
+ add_map(8*1024*1024, M_MEM, FUNC(mga2064w_device::mgabase2_map));
+ // add_rom_from_region();
+
+ add_rom((u8 *)m_vga_rom->base(), 0x10000);
+}
+
+void mga2064w_device::device_reset()
+{
+ pci_card_device::device_reset();
+
+ // INTA#
+ intr_pin = 1;
+ m_mgabase1_real_index = 0;
+ m_dwgreg.state = DRAW_IDLE;
+}
+
+device_memory_interface::space_config_vector mga2064w_device::memory_space_config() const
+{
+ return space_config_vector {
+ std::make_pair(AS_IO, &m_mgabase1_real_space_config)
+ };
+}
+
+void mga2064w_device::config_map(address_map &map)
+{
+ pci_card_device::config_map(map);
+// map(0x40, 0x43) OPTION
+ map(0x44, 0x47).rw(FUNC(mga2064w_device::mga_index_r), FUNC(mga2064w_device::mga_index_w));
+ map(0x48, 0x4b).rw(FUNC(mga2064w_device::mga_data_r), FUNC(mga2064w_device::mga_data_w));
+}
+
+void mga2064w_device::mgabase1_map(address_map &map)
+{
+ map(0x0000, 0x1bff).rw(FUNC(mga2064w_device::dmawin_idump_r), FUNC(mga2064w_device::dmawin_iload_w));
+ map(0x1c00, 0x1dff).m(FUNC(mga2064w_device::dwgreg_map));
+// map(0x1e00, 0x1eff) HSTREG Host registers
+ map(0x1e10, 0x1e13).r(FUNC(mga2064w_device::fifo_status_r));
+ map(0x1e14, 0x1e17).r(FUNC(mga2064w_device::status_r));
+// map(0x1e18, 0x1e1b) ICLEAR
+// map(0x1e1c, 0x1e1f) IEN
+ map(0x1e20, 0x1e23).r(m_svga, FUNC(matrox_vga_device::vcount_r));
+// map(0x1e40, 0x1e43) Reset
+// map(0x1e54, 0x1e57) OPMODE
+// map(0x1f00, 0x1fff) VGA CRTC linear I/O
+ map(0x1fb0, 0x1fdf).m(m_svga, FUNC(matrox_vga_device::io_map));
+ map(0x3c00, 0x3c1f).m(m_svga, FUNC(matrox_vga_device::ramdac_ext_map));
+// map(0x3e00, 0x3fff) EXPDEV Expansion bus
+}
+
+void mga2064w_device::mgabase2_map(address_map &map)
+{
+ map(0x000000, 0x7fffff).rw(m_svga, FUNC(matrox_vga_device::mem_linear_r), FUNC(matrox_vga_device::mem_linear_w));
+}
+
+// assume all registers to work with dword accesses only
+// all signed registers are in two's complement
+// TODO: accessing 0x1dxx starts the drawing engine
+// will otherwise treat iload / idump access as register access,
+// it's also necessary for anything like BMONOLEF to work at least.
+void mga2064w_device::dwgreg_map(address_map &map)
+{
+ // DWGCTL
+ map(0x0000, 0x0003).w(FUNC(mga2064w_device::dwgctl_w));
+ // MACCESS
+ map(0x0004, 0x0007).w(FUNC(mga2064w_device::maccess_w));
+// map(0x0008, 0x000b) <reserved> MCTLWTST
+ // ZORG
+ map(0x000c, 0x000f).lw32(
+ NAME([this] (offs_t offset, u32 data, u32 mem_mask) {
+ // must be multiple of 512
+ m_dwgreg.zorg = data & 0x7fffff;
+ LOGDRAW("dwgreg: ZORG %08x & %08x\n", data, mem_mask);
+ })
+ );
+ // PAT0 / PAT1
+ map(0x0010, 0x0017).lw32(
+ NAME([this] (offs_t offset, u32 data, u32 mem_mask) {
+ LOGDRAW("dwgreg: PAT%d %08x & %08x\n", offset, data, mem_mask);
+ // TODO: alternate way to load SRC registers, in 8x8 Windows format
+ })
+ );
+ // PLNWT
+ map(0x001c, 0x001f).lw32(
+ NAME([this] (offs_t offset, u32 data, u32 mem_mask) {
+ LOGDRAW("dwgreg: PLNWT %08x & %08x\n", data, mem_mask);
+ COMBINE_DATA(&m_dwgreg.plnwt);
+ })
+ );
+ // BCOL / backcol
+ map(0x0020, 0x0023).lw32(
+ NAME([this] (offs_t offset, u32 data, u32 mem_mask) {
+ LOGDRAW("dwgreg: BCOL %08x & %08x\n", data, mem_mask);
+ COMBINE_DATA(&m_dwgreg.bcol);
+ })
+ );
+ // FCOL / forcol
+ map(0x0024, 0x0027).lw32(
+ NAME([this] (offs_t offset, u32 data, u32 mem_mask) {
+ LOGDRAW("dwgreg: FCOL %08x & %08x\n", data, mem_mask);
+ COMBINE_DATA(&m_dwgreg.fcol);
+ })
+ );
+// map(0x002c, 0x002f) <reserved> SRCBLT
+ // SRC0-3
+ map(0x0030, 0x003f).lw32(
+ NAME([this] (offs_t offset, u32 data, u32 mem_mask) {
+ LOGDRAW("dwgreg: SRC[%01d] -> %08x & %08x\n", offset, data, mem_mask);
+ COMBINE_DATA(&m_dwgreg.src[offset]);
+ })
+ );
+ // XYSTRT
+ map(0x0040, 0x0043).lw32(
+ NAME([this] (offs_t offset, u32 data, u32 mem_mask) {
+ LOGDRAW("dwgreg: XYSTRT %08x & %08x\n", data, mem_mask);
+ // TODO: alternate way to load AR5 / AR6 / XDST / YDST
+ })
+ );
+ // XYEND
+ map(0x0044, 0x0047).lw32(
+ NAME([this] (offs_t offset, u32 data, u32 mem_mask) {
+ LOGDRAW("dwgreg: XYEND %08x & %08x\n", data, mem_mask);
+ // TODO: alternate way to load AR0 / AR2
+ })
+ );
+ // SHIFT
+ map(0x0050, 0x0053).lw32(
+ NAME([this] (offs_t offset, u32 data, u32 mem_mask) {
+ LOGDRAW("dwgreg: SHIFT %08x & %08x\n", data, mem_mask);
+ LOGDRAW("\tfuncnt %d|x_off %d|y_off %d|stylelen %d|funoff %d\n"
+ , data & 0x7f
+ // funcnt and x_off / y_off are shared, x_off must really be with bit 3 off
+ , data & 0x0f
+ , (data & 0x30) >> 4
+ // stylelen and funoff are shared
+ , (data >> 16) & 0x7f
+ , (data >> 16) & 0x3f
+ );
+ // TODO: related to PAT0 / PAT1 registers
+ })
+ );
+ // SGN
+ map(0x0058, 0x005b).lw32(
+ NAME([this] (offs_t offset, u32 data, u32 mem_mask) {
+ LOGDRAW("dwgreg: SGN %08x & %08x\n", data, mem_mask);
+ LOGDRAW("\tsdydxl %s|scanleft %d|sdxl %s|sdy %s|sdxr %d\n"
+ , BIT(data, 0) ? "x major axis" : "y major axis"
+ // sdydxl and scanleft are shared
+ , BIT(data, 0)
+ , BIT(data, 1) ? "-x delta" : "+x delta"
+ , BIT(data, 2) ? "-y delta" : "+y delta"
+ , BIT(data, 5) ? "-x delta" : "+x delta"
+ );
+ })
+ );
+ // LEN
+ map(0x005c, 0x005f).lw32(
+ NAME([this] (offs_t offset, u32 data, u32 mem_mask) {
+ m_dwgreg.len = data & 0xffff;
+ LOGDRAW("dwgreg: LEN %08x & %08x %d\n", data, mem_mask, m_dwgreg.len);
+ })
+ );
+ // AR0-6
+ // TODO: documentation for each reg
+ map(0x0060, 0x007b).lw32(
+ NAME([this] (offs_t offset, u32 data, u32 mem_mask) {
+ LOGDRAW("dwgreg: AR[%01d] -> %08x & %08x\n", offset, data, mem_mask);
+ COMBINE_DATA(&m_dwgreg.ar[offset]);
+ })
+ );
+ // CXBNDRY
+ map(0x0080, 0x0083).lw32(
+ NAME([this] (offs_t offset, u32 data, u32 mem_mask) {
+ m_dwgreg.cxleft = data & 0x7ff;
+ m_dwgreg.cxright = (data >> 16) & 0x7ff;
+ LOGDRAW("dwgreg: CXBNDRY %08x & %08x (CXLEFT %d|CXRIGHT %d)\n"
+ , data, mem_mask
+ , m_dwgreg.cxleft, m_dwgreg.cxright
+ );
+ })
+ );
+ // FXBNDRY
+ map(0x0084, 0x0087).select(0x100).lw32(
+ NAME([this] (offs_t offset, u32 data, u32 mem_mask) {
+ // signed 16-bit
+ m_dwgreg.fxleft = (s16)(data & 0xffff);
+ m_dwgreg.fxright = (s16)(data >> 16);
+ LOGDRAW("dwgreg: FXBNDRY %08x & %08x (FXLEFT %d|FXRIGHT %d)\n"
+ , data, mem_mask
+ , m_dwgreg.fxleft, m_dwgreg.fxright
+ );
+ if (BIT(offset, 6))
+ draw_trigger();
+ })
+ );
+ // YDSTLEN
+ map(0x0088, 0x008b).select(0x100).lw32(
+ NAME([this] (offs_t offset, u32 data, u32 mem_mask) {
+ // alternative way to access YDST (bits 31-16) and LEN (15-0) with a single dword
+ m_dwgreg.len = data & 0xffff;
+ // TODO: YDST bits 31-16 with signed conversion
+ m_dwgreg.ydst = util::sext(data >> 16, 15);
+ LOGDRAW("dwgreg: YDSTLEN %08x & %08x (YDST %d|LEN %d)\n"
+ , data, mem_mask
+ , data >> 16, m_dwgreg.len
+ );
+ if (BIT(offset, 6))
+ draw_trigger();
+ })
+ );
+ // PITCH
+ map(0x008c, 0x008f).lw32(
+ NAME([this] (offs_t offset, u32 data, u32 mem_mask) {
+ m_dwgreg.pitch = data & 0xfff;
+ LOGDRAW("dwgreg: PITCH %08x & %08x %d|ylin %d %s\n"
+ , data, mem_mask
+ , m_dwgreg.pitch
+ , BIT(data, 15), BIT(data, 15) ? "linear format" : "xy format"
+ );
+ })
+ );
+ // YDST
+ map(0x0090, 0x0093).lw32(
+ NAME([this] (offs_t offset, u32 data, u32 mem_mask) {
+ // FIXME: signed 22-bits
+ m_dwgreg.ydst = data & 0x3fffff;
+ m_dwgreg.sellin = (data >> 29) & 7;
+ // TODO: depends on ylin for bit meaning
+ LOGDRAW("dwgreg: YDST %08x & %08x|ydst %08x|sellin %d\n"
+ , data, mem_mask
+ , m_dwgreg.ydst
+ , m_dwgreg.sellin
+ );
+ })
+ );
+ // YDSTORG
+ map(0x0094, 0x0097).lw32(
+ NAME([this] (offs_t offset, u32 data, u32 mem_mask) {
+ // unsigned 23-bit
+ m_dwgreg.ydstorg = data & 0x7fffff;
+ LOGDRAW("dwgreg: YDSTORG %08x & %08x %d\n"
+ , data, mem_mask
+ , m_dwgreg.ydstorg
+ );
+ })
+ );
+ // YTOP / cytop
+ map(0x0098, 0x009b).lw32(
+ NAME([this] (offs_t offset, u32 data, u32 mem_mask) {
+ // unsigned 23-bit
+ m_dwgreg.cytop = data & 0x7fffff;
+ LOGDRAW("dwgreg: YTOP %08x & %08x\n", data, mem_mask);
+ })
+ );
+ // YBOT / cybot
+ map(0x009c, 0x009f).lw32(
+ NAME([this] (offs_t offset, u32 data, u32 mem_mask) {
+ // unsigned 23-bit
+ m_dwgreg.cybot = data & 0x7fffff;
+ LOGDRAW("dwgreg: YBOT %08x & %08x\n", data, mem_mask);
+ })
+ );
+ // CXLEFT
+ map(0x00a0, 0x00a3).lw32(
+ NAME([this] (offs_t offset, u32 data, u32 mem_mask) {
+ m_dwgreg.cxleft = data & 0x7ff;
+ LOGDRAW("dwgreg: CXLEFT %08x & %08x %d\n"
+ , data, mem_mask
+ , m_dwgreg.cxleft
+ );
+ })
+ );
+ // CXRIGHT
+ map(0x00a4, 0x00a7).lw32(
+ NAME([this] (offs_t offset, u32 data, u32 mem_mask) {
+ m_dwgreg.cxright = data & 0x7ff;
+ LOGDRAW("dwgreg: CXRIGHT %08x & %08x %d\n"
+ , data, mem_mask
+ , m_dwgreg.cxright
+ );
+ })
+ );
+ // FXLEFT
+ map(0x00a8, 0x00ab).lw32(
+ NAME([this] (offs_t offset, u32 data, u32 mem_mask) {
+ // signed 16-bit
+ m_dwgreg.fxleft = (s16)(data & 0xffff);
+ LOGDRAW("dwgreg: FXLEFT %08x & %08x %d\n"
+ , data, mem_mask
+ , m_dwgreg.fxleft
+ );
+ })
+ );
+ // FXRIGHT
+ map(0x00ac, 0x00af).lw32(
+ NAME([this] (offs_t offset, u32 data, u32 mem_mask) {
+ // signed 16-bit
+ m_dwgreg.fxright = (s16)(data & 0xffff);
+ LOGDRAW("dwgreg: FXRIGHT %08x & %08x %d\n"
+ , data, mem_mask
+ , m_dwgreg.fxright
+ );
+ })
+ );
+ // XDST
+ map(0x00b0, 0x00b3).lw32(
+ NAME([this] (offs_t offset, u32 data, u32 mem_mask) {
+ // signed 16-bit
+ m_dwgreg.xdst = (s16)(data & 0xffff);
+ LOGDRAW("dwgreg: XDST %08x & %08x %d\n"
+ , data, mem_mask
+ , m_dwgreg.xdst
+ );
+ })
+ );
+ // DR0-DR15 (DR1-5-9-13 <reserved>)
+ map(0x00c0, 0x00ff).lw32(
+ NAME([this] (offs_t offset, u32 data, u32 mem_mask) {
+ LOGDRAW("dwgreg: DR[%01d] -> %08x\n", offset, data, mem_mask);
+ if ((offset & 3) == 1)
+ {
+ LOGWARN("dwgreg: attempt to setup reserved DR%01d (ignored)\n", offset);
+ return;
+ }
+ COMBINE_DATA(&m_dwgreg.dr[offset]);
+ })
+ );
+}
+
+void mga2064w_device::dwgctl_w(offs_t offset, u32 data, u32 mem_mask)
+{
+ COMBINE_DATA(&m_dwgreg.dwgctl);
+ LOGDRAW("dwgreg: DWGCTL -> %08x & %08x\n", data, mem_mask);
+ const char *const opcode_mnemonics[16] = {
+ "LINE_OPEN", "AUTOLINE_OPEN", "LINE_CLOSE", "AUTOLINE_CLOSE",
+ "TRAP", "TEXTURE_TRAP", "<reserved>", "<reserved>",
+ "BITBLT", "ILOAD", "IDUMP", "<reserved>",
+ "FBITBLIT", "ILOAD_SCALE", "<reserved>", "ILOAD_FILTER"
+ };
+ const char *const atype_mnemonics[8] = {
+ "RPL", "RSTR", "<reserved>", "ZI",
+ "BLK", "<reserved>", "<reserved>", "I"
+ };
+ const char *const zmode_mnemonics[8] = {
+ "NOZCMP", "<reserved>", "ZE", "ZNE",
+ "ZLT", "ZLTE", "ZGT", "ZGTE"
+ };
+ const char *const bop_mnemonics[16] = {
+ "0", "~(D | S)", "D & ~S", "~S",
+ "(~D) & S", "~D", "D ^ S", "~(D & S)",
+ "D & S", "~(D ^ S)", "D", "D | ~S",
+ "S", "(~D) | S", "D | S", "1"
+ };
+ const char *const bltmod_mnemonics[16] = {
+ "BMONOLEF", "BPLAN", "BFCOL", "BU32BGR",
+ "BMONOWF", "<reserved>", "<reserved>", "BU32RGB",
+ "<reserved>", "<reserved>", "<reserved>", "BU24BGR",
+ "<reserved>", "<reserved>", "BUYUV", "BU24RGB"
+ };
+ LOGDRAW("\topcod %02x %s|atype %02x %s|%s mode|zmode %02x %s|\n"
+ , m_dwgreg.dwgctl & 0xf, opcode_mnemonics[m_dwgreg.dwgctl & 0xf]
+ , (m_dwgreg.dwgctl >> 4) & 7, atype_mnemonics[(m_dwgreg.dwgctl >> 4) & 7]
+ , BIT(m_dwgreg.dwgctl, 7) ? "linear bitblt" : "xy bitblt"
+ , (m_dwgreg.dwgctl >> 8) & 7, zmode_mnemonics[(m_dwgreg.dwgctl >> 8) & 7]
+ );
+ LOGDRAW("\tbop %02x %s|bltmod %02x %s|pattern %d|transc %d|\n"
+ , (m_dwgreg.dwgctl >> 16) & 0xf, bop_mnemonics[(m_dwgreg.dwgctl >> 16) & 0xf]
+ , (m_dwgreg.dwgctl >> 25) & 0xf, bltmod_mnemonics[(m_dwgreg.dwgctl >> 25) & 0xf]
+ , BIT(m_dwgreg.dwgctl, 29)
+ , BIT(m_dwgreg.dwgctl, 30)
+ );
+ LOGDRAW("\tsolid %d|arzero %d|sgnzero %d|shftzero %d|trans %02x|\n"
+ , BIT(m_dwgreg.dwgctl, 11)
+ , BIT(m_dwgreg.dwgctl, 12)
+ , BIT(m_dwgreg.dwgctl, 13)
+ , BIT(m_dwgreg.dwgctl, 14)
+ , (m_dwgreg.dwgctl >> 20) & 0xf
+ );
+}
+
+void mga2064w_device::maccess_w(offs_t offset, u32 data, u32 mem_mask)
+{
+ const char *const pwidth_mnemonics[4] = {
+ "PW8", "PW16", "PW32", "PW16"
+ };
+ COMBINE_DATA(&m_dwgreg.maccess);
+ LOGDRAW("dwgreg: MACCESS %08x & %08x\n", data, mem_mask);
+ LOGDRAW("\tpwidth %d %s|memreset %d|dither %d|dit555 %d\n"
+ , m_dwgreg.maccess & 3, pwidth_mnemonics[m_dwgreg.maccess & 3]
+ , BIT(m_dwgreg.maccess, 15)
+ // nodither, flipped for convenience
+ , !BIT(m_dwgreg.maccess, 30)
+ , BIT(m_dwgreg.maccess, 31)
+ );
+}
+/*
+ * MGABASE1 + 1e10h FIFO Status (r/o)
+ *
+ * ---- -x-- ---- ---- BEMPTY Bus FIFO empty
+ * ---- --x- ---- ---- BFULL Bus FIFO full
+ * ---- ---- ---x xxxx FIFOCOUNT free locations in FIFO (max: 32)
+ */
+u32 mga2064w_device::fifo_status_r()
+{
+ return (1 << 9) | 32;
+}
+
+/*
+ * MGABASE1 + 1e14h Status (r/o)
+ *
+ * ---- ---- ---- ---x ---- ---- ---- ---- DWGENGSTS
+ * ---- ---- ---- ---- ---- ---- -x-- ---- EXTPEN
+ * ---- ---- ---- ---- ---- ---- --x- ---- VLINEPEN
+ * ---- ---- ---- ---- ---- ---- ---x ---- VSYNCPEN
+ * ---- ---- ---- ---- ---- ---- ---- x--- VSYNCSTS
+ * ---- ---- ---- ---- ---- ---- ---- -x-- PICKPEN
+ */
+u32 mga2064w_device::status_r()
+{
+ return m_svga->vsync_status() << 3;
+}
+
+void mga2064w_device::draw_trigger()
+{
+ LOGDRAW("\tstart trigger\n");
+ const u8 opcod = m_dwgreg.dwgctl & 0xf;
+ const u8 bop = (m_dwgreg.dwgctl >> 16) & 0xf;
+ const u8 bltmod = (m_dwgreg.dwgctl >> 25) & 0xf;
+
+ if (bop != 0xc)
+ return;
+
+ const s32 ystart = m_dwgreg.ydst;
+ const s32 yend = ystart + m_dwgreg.len;
+ const s32 xstart = m_dwgreg.fxleft;
+ const s32 xend = m_dwgreg.fxright;
+
+ if (m_dwgreg.state != DRAW_IDLE)
+ LOGWARN("\t(in-flight! %d)\n", m_dwgreg.state);
+
+ m_dwgreg.state = DRAW_IDLE;
+
+ switch(opcod)
+ {
+ // TRAP / RECT
+ case 4:
+ {
+ if (BIT(m_dwgreg.dwgctl, 7))
+ {
+ LOGWARN("\tTRAP in linear mode (unemulated)\n");
+ return;
+ }
+ for (int y = ystart; y < yend; y++)
+ {
+ for (int x = xstart; x < xend; x++)
+ {
+ m_svga->write_memory(x + (y * m_dwgreg.pitch), m_dwgreg.fcol & 0xff);
+ }
+ }
+ break;
+ }
+ // BITBLT
+ case 8:
+ {
+ if (BIT(m_dwgreg.dwgctl, 7))
+ {
+ // BMONOLEF only for now
+ if (bltmod)
+ return;
+
+ const u32 source_base = m_dwgreg.ar[3] & 0xffffff;
+ const s32 source_pitch = util::sext(m_dwgreg.ar[5], 17);
+ int src_x = 0;
+ int src_y = 0;
+ for (int y = ystart; y < yend; y ++, src_y ++)
+ {
+ for (int x = xstart; x < xend; x+=8, src_x ++)
+ {
+ const u32 char_position = (src_x + src_y * source_pitch);
+ const u8 char_data = m_svga->read_memory(source_base + char_position);
+ for (int xi = 0; xi < 8; xi ++)
+ {
+ const u8 pen_dot = (char_data >> (7-xi)) & 1;
+
+ u8 color_pen = (pen_dot ? m_dwgreg.fcol : m_dwgreg.bcol) & 0xff;
+ m_svga->write_memory((x + xi) + m_dwgreg.pitch * y, color_pen);
+ }
+
+ }
+ }
+ }
+ else
+ {
+ const u32 source_base = m_dwgreg.ar[3] & 0xffffff;
+ const s32 source_pitch = util::sext(m_dwgreg.ar[5], 17);
+ int src_x = 0;
+ int src_y = 0;
+ for (int y = ystart; y < yend; y++, src_y++)
+ {
+ for (int x = xstart; x < xend; x++, src_x++)
+ {
+ u8 color_pen = m_svga->read_memory(source_base + (source_pitch * src_y) + src_x);
+ m_svga->write_memory(x + y * m_dwgreg.pitch, color_pen);
+ }
+ }
+ }
+ break;
+ }
+ // ILOAD
+ case 9:
+ m_dwgreg.state = DRAW_ILOAD;
+ m_dwgreg.current_x = 0;
+ m_dwgreg.current_y = 0;
+ break;
+ // IDUMP
+ case 0xa:
+ m_dwgreg.state = DRAW_IDUMP;
+ m_dwgreg.current_x = 0;
+ m_dwgreg.current_y = 0;
+ break;
+ }
+
+ LOGDRAW("\n");
+}
+
+u32 mga2064w_device::dmawin_idump_r(offs_t offset, u32 mem_mask)
+{
+ u32 res = 0;
+ LOGPIXELXFER("dmawin_idump_r [%08x] & %08x %d %d (state %d)\n", offset * 4, mem_mask, m_dwgreg.current_x, m_dwgreg.current_y, m_dwgreg.state);
+ switch(m_dwgreg.state)
+ {
+ case DRAW_IDUMP:
+ {
+ const u32 y_base = m_dwgreg.pitch * (m_dwgreg.current_y + m_dwgreg.ydst);
+ const u32 x_base = m_dwgreg.current_x + m_dwgreg.fxleft;
+
+ for (int xi = 0; xi < 4; xi ++)
+ res |= m_svga->read_memory((y_base) + (x_base + xi)) << (xi * 8);
+ m_dwgreg.current_x += 4;
+ if (m_dwgreg.current_x > m_dwgreg.ar[0])
+ {
+ m_dwgreg.current_x = 0;
+ m_dwgreg.current_y ++;
+ if (m_dwgreg.current_y > m_dwgreg.len)
+ m_dwgreg.state = DRAW_IDLE;
+ }
+
+ return res;
+ }
+ default:
+ LOGWARN("Unemulated IDUMP read state [%08x] mem_mask %08x\n", offset * 4, mem_mask);
+ res = 0xdeadbeef;
+ break;
+ }
+ return res;
+}
+
+void mga2064w_device::dmawin_iload_w(offs_t offset, u32 data, u32 mem_mask)
+{
+ // assume dword accesses unless something dull proves otherwise
+ LOGPIXELXFER("dmawin_iload_w [%08x] %08x & %08x %d %d (state %d)\n", offset * 4, data, mem_mask, m_dwgreg.current_x, m_dwgreg.current_y, m_dwgreg.state);
+ switch(m_dwgreg.state)
+ {
+ case DRAW_ILOAD:
+ {
+ const u32 y_base = m_dwgreg.pitch * (m_dwgreg.current_y + m_dwgreg.ydst);
+ const u32 x_base = m_dwgreg.current_x + m_dwgreg.fxleft;
+
+ for (int xi = 0; xi < 4; xi++)
+ {
+ u8 color_pen = (data >> (8 * xi)) & 0xff;
+ m_svga->write_memory((y_base) + (x_base + xi), color_pen);
+ }
+ m_dwgreg.current_x += 4;
+ if (m_dwgreg.current_x > m_dwgreg.ar[0])
+ {
+ m_dwgreg.current_x = 0;
+ m_dwgreg.current_y ++;
+ // Note: this is unnecessary, really changes with OPMODE
+ if (m_dwgreg.current_y > m_dwgreg.len)
+ m_dwgreg.state = DRAW_IDLE;
+ }
+
+ break;
+ }
+ default:
+ LOGWARN("Unemulated ILOAD write state [%08x] %08x & %08x\n", offset * 4, data, mem_mask);
+ break;
+ }
+}
+
+// TODO: this should really be a subclass of VGA
+void mga2064w_device::legacy_memory_map(address_map &map)
+{
+ map(0xa0000, 0xbffff).rw(FUNC(mga2064w_device::vram_r), FUNC(mga2064w_device::vram_w));
+}
+
+void mga2064w_device::legacy_io_map(address_map &map)
+{
+ map(0, 0x02f).m(m_svga, FUNC(matrox_vga_device::io_map));
+}
+
+uint8_t mga2064w_device::vram_r(offs_t offset)
+{
+ return downcast<matrox_vga_device *>(m_svga.target())->mem_r(offset);
+}
+
+void mga2064w_device::vram_w(offs_t offset, uint8_t data)
+{
+ downcast<matrox_vga_device *>(m_svga.target())->mem_w(offset, data);
+}
+
+void mga2064w_device::map_extra(uint64_t memory_window_start, uint64_t memory_window_end, uint64_t memory_offset, address_space *memory_space,
+ uint64_t io_window_start, uint64_t io_window_end, uint64_t io_offset, address_space *io_space)
+{
+ // TODO: both can be disabled thru config options
+ {
+ memory_space->install_readwrite_handler(0xa0000, 0xbffff, read8sm_delegate(*this, FUNC(mga2064w_device::vram_r)), write8sm_delegate(*this, FUNC(mga2064w_device::vram_w)));
+
+ io_space->install_device(0x03b0, 0x03df, *this, &mga2064w_device::legacy_io_map);
+ }
+}
+
+/*
+ * MGA_INDEX / MGA_DATA
+ * aliases for accessing mgabase1 thru PCI config space
+ * i.e. a backdoor for x86 in real mode
+ */
+
+u32 mga2064w_device::mga_index_r()
+{
+ LOGALIAS("MGA_INDEX read\n");
+ return m_mgabase1_real_index & 0x3ffc;
+}
+
+void mga2064w_device::mga_index_w(offs_t offset, u32 data, u32 mem_mask)
+{
+ // VESA BIOS sets up $3c0a while accessing with mask 0x00ff0000
+ // bits 0-1 are reserved and don't respond, assume mistake
+ LOGALIAS("MGA_INDEX write %08x %08x\n", data, mem_mask);
+ COMBINE_DATA(&m_mgabase1_real_index);
+ m_mgabase1_real_index &= 0x3ffc;
+}
+
+u32 mga2064w_device::mga_data_r(offs_t offset, u32 mem_mask)
+{
+ return space(AS_IO).read_dword(m_mgabase1_real_index, mem_mask);
+}
+
+void mga2064w_device::mga_data_w(offs_t offset, u32 data, u32 mem_mask)
+{
+ space(AS_IO).write_dword(m_mgabase1_real_index, data, mem_mask);
+}
diff --git a/src/devices/bus/pci/mga2064w.h b/src/devices/bus/pci/mga2064w.h
new file mode 100644
index 00000000000..b092ebf7e32
--- /dev/null
+++ b/src/devices/bus/pci/mga2064w.h
@@ -0,0 +1,97 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert, Angelo Salese
+#ifndef MAME_BUS_PCI_MGA2064W_H
+#define MAME_BUS_PCI_MGA2064W_H
+
+#pragma once
+
+#include "pci_slot.h"
+
+#include "video/pc_vga_matrox.h"
+
+
+class mga2064w_device : public pci_card_device, public device_memory_interface {
+public:
+ mga2064w_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ void legacy_memory_map(address_map &map);
+ void legacy_io_map(address_map &map);
+
+protected:
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual space_config_vector memory_space_config() const override;
+
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+ virtual void map_extra(uint64_t memory_window_start, uint64_t memory_window_end, uint64_t memory_offset, address_space *memory_space,
+ uint64_t io_window_start, uint64_t io_window_end, uint64_t io_offset, address_space *io_space) override;
+ virtual void config_map(address_map &map) override;
+
+ void mgabase1_map(address_map &map);
+ void mgabase2_map(address_map &map);
+
+ void dwgreg_map(address_map &map);
+
+ u32 dmawin_idump_r(offs_t offset, u32 mem_mask = ~0);
+ void dmawin_iload_w(offs_t offset, u32 data, u32 mem_mask = ~0);
+
+ required_device<matrox_vga_device> m_svga;
+ required_memory_region m_vga_rom;
+private:
+ u8 vram_r(offs_t offset);
+ void vram_w(offs_t offset, uint8_t data);
+
+ address_space_config m_mgabase1_real_space_config;
+ u32 mga_index_r();
+ void mga_index_w(offs_t offset, u32 data, u32 mem_mask = ~0);
+ u32 mga_data_r(offs_t offset, u32 mem_mask = ~0);
+ void mga_data_w(offs_t offset, u32 data, u32 mem_mask = ~0);
+ u32 m_mgabase1_real_index = 0;
+
+ u32 status_r();
+ u32 fifo_status_r();
+
+ // DWGREG section
+ void dwgctl_w(offs_t offset, u32 data, u32 mem_mask = ~0);
+ void maccess_w(offs_t offset, u32 data, u32 mem_mask = ~0);
+ enum drawing_state_t {
+ DRAW_IDLE,
+ DRAW_ILOAD,
+ DRAW_IDUMP
+ };
+
+ struct {
+ u32 src[4]{};
+ u32 dr[16]{};
+ u32 ar[7]{};
+ u32 dwgctl = 0;
+ u32 maccess = 0;
+ u32 zorg = 0;
+ u32 plnwt = 0;
+ u16 pitch = 0;
+ u16 len = 0;
+ u32 cytop = 0;
+ u32 cybot = 0;
+ u16 cxleft = 0;
+ u16 cxright = 0;
+ s16 fxleft = 0;
+ s16 fxright = 0;
+ s16 xdst = 0;
+ s32 ydst = 0;
+ u32 ydstorg = 0;
+ u32 bcol = 0;
+ u32 fcol = 0;
+ u8 sellin = 0;
+ drawing_state_t state;
+ s32 current_x, current_y;
+ } m_dwgreg;
+
+ void draw_trigger();
+};
+
+DECLARE_DEVICE_TYPE(MGA2064W, mga2064w_device);
+
+#endif // MAME_BUS_PCI_MGA2064W_H
diff --git a/src/devices/bus/pci/opti82c861.cpp b/src/devices/bus/pci/opti82c861.cpp
new file mode 100644
index 00000000000..fbbd52ca3b0
--- /dev/null
+++ b/src/devices/bus/pci/opti82c861.cpp
@@ -0,0 +1,81 @@
+// license:BSD-3-Clause
+// copyright-holders: R. Belmont
+/*
+ OPTi 82C861 "FireLink" USB 1.1 OHCI controller
+ Skeleton by R. Belmont
+*/
+
+#include "emu.h"
+#include "opti82c861.h"
+
+#define LOG_REGISTERS (1U << 1)
+
+#define VERBOSE (LOG_GENERAL)
+#include "logmacro.h"
+
+DEFINE_DEVICE_TYPE(OPTI_82C861, opti_82c861_device, "opti82c861", "OPTi 82C861 \"FireLink\" USB OHCI controller")
+
+opti_82c861_device::opti_82c861_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : pci_card_device(mconfig, type, tag, owner, clock)
+{
+}
+
+opti_82c861_device::opti_82c861_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : opti_82c861_device(mconfig, OPTI_82C861, tag, owner, clock)
+{
+}
+
+void opti_82c861_device::mem_map(address_map& map)
+{
+ // HcRevision: OpenHCI v1.0 with legacy support
+ map(0x000, 0x003).lr32(NAME([]() { return 0x00000110; }));
+ map(0x048, 0x04b).lrw32(
+ NAME([this] () {
+ // 2 downstream ports (always?)
+ return (m_HcRhDescriptorA & 0xff001b00) | 0x02;
+ }),
+ NAME([this] (offs_t offset, u32 data, u32 mem_mask) {
+ COMBINE_DATA(&m_HcRhDescriptorA);
+ if (ACCESSING_BITS_24_31)
+ LOG("HcRhDescriptorA: set Power-On to Power-Good Time %d msec\n", (m_HcRhDescriptorA >> 24) * 2);
+ if (ACCESSING_BITS_8_15)
+ LOG("HcRhDescriptorA: set status %02x\n", (m_HcRhDescriptorA & 0x1b00) >> 8);
+ })
+ );
+}
+
+void opti_82c861_device::config_map(address_map &map)
+{
+ pci_card_device::config_map(map);
+// map(0x4e, 0x4e) i2c Control Register
+// map(0x50, 0x50) PCI Host Feature Control Register
+// map(0x51, 0x51) Interrupt Assignment Register
+// map(0x52, 0x52) Strap Option Enable
+// map(0x54, 0x57) IRQ Driveback Address Register
+// map(0x6c, 0x6f) Test Mode Enable Register
+}
+
+void opti_82c861_device::device_start()
+{
+ pci_card_device::device_start();
+ set_ids(0x1045c861, 0x10, 0x0c0310, 0);
+ revision = 0x10;
+ add_map(0x1000, M_MEM, FUNC(opti_82c861_device::mem_map)); // 4KiB memory map
+
+ command = 0;
+ // fast back-to-back, medium DEVSEL#
+ status = 0x0280;
+ intr_pin = 1;
+ intr_line = 0;
+}
+
+void opti_82c861_device::device_reset()
+{
+ pci_card_device::device_reset();
+ m_HcRhDescriptorA = 0x01000000;
+}
+
+void opti_82c861_device::map_extra(uint64_t memory_window_start, uint64_t memory_window_end, uint64_t memory_offset, address_space *memory_space,
+ uint64_t io_window_start, uint64_t io_window_end, uint64_t io_offset, address_space *io_space)
+{
+}
diff --git a/src/devices/bus/pci/opti82c861.h b/src/devices/bus/pci/opti82c861.h
new file mode 100644
index 00000000000..dfb79221fa9
--- /dev/null
+++ b/src/devices/bus/pci/opti82c861.h
@@ -0,0 +1,33 @@
+// license:BSD-3-Clause
+// copyright-holders: R. Belmont
+
+#ifndef MAME_BUS_PCI_OPTI82C861_H
+#define MAME_BUS_PCI_OPTI82C861_H
+
+#pragma once
+
+#include "pci_slot.h"
+
+class opti_82c861_device : public pci_card_device
+{
+public:
+ opti_82c861_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+ opti_82c861_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ void mem_map(address_map &map);
+
+protected:
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ void map_extra(u64 memory_window_start, u64 memory_window_end, u64 memory_offset, address_space *memory_space,
+ u64 io_window_start, u64 io_window_end, u64 io_offset, address_space *io_space) override;
+ void config_map(address_map &map) override;
+
+private:
+ u32 m_HcRhDescriptorA = 0;
+};
+
+DECLARE_DEVICE_TYPE(OPTI_82C861, opti_82c861_device)
+
+#endif
diff --git a/src/devices/bus/pci/oti_spitfire.cpp b/src/devices/bus/pci/oti_spitfire.cpp
new file mode 100644
index 00000000000..a3e6ecbf7b9
--- /dev/null
+++ b/src/devices/bus/pci/oti_spitfire.cpp
@@ -0,0 +1,146 @@
+// license:BSD-3-Clause
+// copyright-holders:Angelo Salese
+/**************************************************************************************************
+
+OAK OTI Spitfire PCI cards
+
+VBE 1.2, XGA
+
+TODO:
+- can strap base class and header to be multifunction
+
+**************************************************************************************************/
+
+#include "emu.h"
+#include "oti_spitfire.h"
+
+#define LOG_WARN (1U << 1)
+
+#define VERBOSE (LOG_GENERAL | LOG_WARN)
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+#define LOGWARN(...) LOGMASKED(LOG_WARN, __VA_ARGS__)
+
+
+//OTI-64105
+//OTI-64107
+DEFINE_DEVICE_TYPE(OTI64111_PCI, oti64111_pci_device, "oti64111_pci", "OTI-64111 \"Spitfire\"")
+//OTI-64217
+//OTI-64317
+
+
+oti64111_pci_device::oti64111_pci_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : pci_card_device(mconfig, type, tag, owner, clock)
+ , m_svga(*this, "svga")
+ , m_vga_rom(*this, "vga_rom")
+{
+ // Rev C
+ set_ids(0x104e0111, 0x30, 0x030000, 0x104e0111);
+}
+
+oti64111_pci_device::oti64111_pci_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : oti64111_pci_device(mconfig, OTI64111_PCI, tag, owner, clock)
+{
+}
+
+ROM_START( oti64111 )
+ ROM_REGION32_LE( 0x8000, "vga_rom", ROMREGION_ERASEFF )
+ ROM_SYSTEM_BIOS( 0, "spitfire", "v111.20 10/10/96" )
+ ROMX_LOAD( "ot64111spitfire.vbi", 0x0000, 0x8000, CRC(fb031e98) SHA1(16826d93bc2a09d91b52cca3f72447501daee2d2), ROM_BIOS(0) )
+ROM_END
+
+const tiny_rom_entry *oti64111_pci_device::device_rom_region() const
+{
+ return ROM_NAME(oti64111);
+}
+
+void oti64111_pci_device::device_add_mconfig(machine_config &config)
+{
+ screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
+ screen.set_raw(XTAL(25'174'800), 900, 0, 640, 526, 0, 480);
+ screen.set_screen_update(m_svga, FUNC(oak_oti111_vga_device::screen_update));
+
+ OTI111(config, m_svga, 0);
+ m_svga->set_screen("screen");
+ m_svga->set_vram_size(4*1024*1024);
+}
+
+void oti64111_pci_device::device_start()
+{
+ pci_card_device::device_start();
+
+ add_map( 256, M_MEM, FUNC(oti64111_pci_device::mmio_map));
+ add_map(8*1024*1024, M_MEM, FUNC(oti64111_pci_device::vram_aperture_map));
+ add_map( 256, M_IO, FUNC(oti64111_pci_device::extio_map));
+
+ add_rom((u8 *)m_vga_rom->base(), 0x8000);
+ expansion_rom_base = 0xc0000;
+
+ // INTA#
+ intr_pin = 1;
+
+ // TODO: (default?) min_gnt = 0xff, max_lat = 0x01
+}
+
+void oti64111_pci_device::device_reset()
+{
+ pci_card_device::device_reset();
+
+ // enable address/data stepping, enable bus snoop for palette regs
+ command = 0x00a0;
+ // fast back-to-back, medium DEVSEL#
+ status = 0x0280;
+
+ remap_cb();
+}
+
+void oti64111_pci_device::config_map(address_map &map)
+{
+ pci_card_device::config_map(map);
+}
+
+void oti64111_pci_device::mmio_map(address_map &map)
+{
+ map(0x00, 0x7f).rw(m_svga, FUNC(oak_oti111_vga_device::xga_read), FUNC(oak_oti111_vga_device::xga_write));
+ map(0x80, 0xbf).m(m_svga, FUNC(oak_oti111_vga_device::multimedia_map));
+}
+
+void oti64111_pci_device::vram_aperture_map(address_map &map)
+{
+ map(0x000000, 0x7fffff).rw(m_svga, FUNC(oak_oti111_vga_device::mem_linear_r), FUNC(oak_oti111_vga_device::mem_linear_w));
+}
+
+void oti64111_pci_device::extio_map(address_map &map)
+{
+ map(0x00e0, 0x00ef).m(m_svga, FUNC(oak_oti111_vga_device::ramdac_mmio_map));
+}
+
+void oti64111_pci_device::legacy_io_map(address_map &map)
+{
+ map(0, 0x02f).m(m_svga, FUNC(oak_oti111_vga_device::io_map));
+}
+
+uint8_t oti64111_pci_device::vram_r(offs_t offset)
+{
+ return downcast<oak_oti111_vga_device *>(m_svga.target())->mem_r(offset);
+}
+
+void oti64111_pci_device::vram_w(offs_t offset, uint8_t data)
+{
+ downcast<oak_oti111_vga_device *>(m_svga.target())->mem_w(offset, data);
+}
+
+void oti64111_pci_device::map_extra(uint64_t memory_window_start, uint64_t memory_window_end, uint64_t memory_offset, address_space *memory_space,
+ uint64_t io_window_start, uint64_t io_window_end, uint64_t io_offset, address_space *io_space)
+{
+ if (BIT(command, 1))
+ {
+ memory_space->install_readwrite_handler(0xa0000, 0xbffff, read8sm_delegate(*this, FUNC(oti64111_pci_device::vram_r)), write8sm_delegate(*this, FUNC(oti64111_pci_device::vram_w)));
+ }
+
+ if (BIT(command, 0))
+ {
+ io_space->install_device(0x03b0, 0x03df, *this, &oti64111_pci_device::legacy_io_map);
+ }
+}
diff --git a/src/devices/bus/pci/oti_spitfire.h b/src/devices/bus/pci/oti_spitfire.h
new file mode 100644
index 00000000000..46b63764c59
--- /dev/null
+++ b/src/devices/bus/pci/oti_spitfire.h
@@ -0,0 +1,48 @@
+// license:BSD-3-Clause
+// copyright-holders:Angelo Salese
+
+#ifndef MAME_BUS_PCI_OTI_SPITFIRE_PCI_H
+#define MAME_BUS_PCI_OTI_SPITFIRE_PCI_H
+
+#pragma once
+
+#include "pci_slot.h"
+#include "video/pc_vga_oak.h"
+
+class oti64111_pci_device : public pci_card_device
+{
+public:
+ oti64111_pci_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ static constexpr feature_type imperfect_features() { return feature::GRAPHICS; }
+
+ void legacy_io_map(address_map &map);
+
+protected:
+ oti64111_pci_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+ virtual void map_extra(uint64_t memory_window_start, uint64_t memory_window_end, uint64_t memory_offset, address_space *memory_space,
+ uint64_t io_window_start, uint64_t io_window_end, uint64_t io_offset, address_space *io_space) override;
+
+ virtual void config_map(address_map &map) override;
+
+ required_device<oak_oti111_vga_device> m_svga;
+ required_memory_region m_vga_rom;
+private:
+ void mmio_map(address_map &map);
+ void vram_aperture_map(address_map &map);
+ void extio_map(address_map &map);
+
+ u8 vram_r(offs_t offset);
+ void vram_w(offs_t offset, uint8_t data);
+};
+
+DECLARE_DEVICE_TYPE(OTI64111_PCI, oti64111_pci_device)
+
+#endif // MAME_BUS_PCI_OTI_SPITFIRE_PCI_H
diff --git a/src/devices/bus/pci/pci_slot.cpp b/src/devices/bus/pci/pci_slot.cpp
new file mode 100644
index 00000000000..1a7ef5b760f
--- /dev/null
+++ b/src/devices/bus/pci/pci_slot.cpp
@@ -0,0 +1,177 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+
+// Generic PCI card port
+
+#include "emu.h"
+#include "pci_slot.h"
+
+#include "aha2940au.h"
+#include "audiowerk2.h"
+#include "clgd5446.h"
+#include "clgd546x_laguna.h"
+#include "ds2416.h"
+#include "ess_maestro.h"
+#include "geforce.h"
+#include "mga2064w.h"
+#include "opti82c861.h"
+#include "oti_spitfire.h"
+#include "pdc20262.h"
+#include "promotion.h"
+#include "riva128.h"
+#include "rivatnt.h"
+#include "rtl8029as_pci.h"
+#include "rtl8139_pci.h"
+#include "sis6326.h"
+#include "sonicvibes.h"
+#include "sw1000xg.h"
+#include "virge_pci.h"
+#include "vision.h"
+#include "vt6306.h"
+#include "wd9710_pci.h"
+#include "zr36057.h"
+
+
+DEFINE_DEVICE_TYPE(PCI_SLOT, pci_slot_device, "pci_slot", "PCI extension motherboard port")
+
+pci_slot_device::pci_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, PCI_SLOT, tag, owner, clock),
+ device_single_card_slot_interface<pci_card_interface>(mconfig, *this)
+{
+}
+
+pci_slot_device::~pci_slot_device()
+{
+}
+
+void pci_slot_device::device_start()
+{
+}
+
+u8 pci_slot_device::get_slot() const
+{
+ return m_slot;
+}
+
+pci_card_device *pci_slot_device::get_card() const
+{
+ return dynamic_cast<pci_card_device *>(get_card_device());
+}
+
+pci_card_interface::pci_card_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "pci_card"),
+ m_pci_slot(dynamic_cast<pci_slot_device *>(device.owner())) // Beware, the owner may not be a pci_slot_device, in which case the cast returns nullptr
+{
+}
+
+pci_card_device::pci_card_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
+ pci_device(mconfig, type, tag, owner, clock),
+ pci_card_interface(mconfig, *this)
+{
+}
+
+pci_card_device::~pci_card_device()
+{
+}
+
+void pci_card_device::device_start()
+{
+ pci_device::device_start();
+
+ if(m_pci_slot)
+ m_pci_slot->get_irq_map(m_irq_map);
+
+ m_pin_state = 0;
+ save_item(NAME(m_pin_state));
+}
+
+void pci_card_device::device_reset()
+{
+ pci_device::device_reset();
+
+ for(int i=0; i != 4; i++)
+ if(m_pin_state & (1 << i))
+ m_pci_root->irq_pin_w(m_irq_map[i], 0);
+ m_pin_state = 0;
+}
+
+void pci_card_device::irq_pin_w(offs_t line, int state)
+{
+ state = state != 0;
+ int pstate = (m_pin_state >> line) & 1;
+ if(pstate == state)
+ return;
+ m_pin_state = (m_pin_state & ~(1 << line)) | (state << line);
+
+ m_pci_root->irq_pin_w(m_irq_map[line], state);
+}
+
+void pci_cards(device_slot_interface &device)
+{
+ // 0x00 - backward compatible pre-class code
+// device.option_add("voodoo1", VOODOO_1_PCI);
+ device.option_add("vision864", VISION864_PCI);
+ device.option_add("vision964", VISION964_PCI);
+
+ // 0x01 - mass storage controllers
+ device.option_add("aha2940au", AHA2940AU);
+ device.option_add("pdc20262", PDC20262);
+
+ // 0x02 - network controllers
+ device.option_add("rtl8029as", RTL8029AS_PCI);
+ device.option_add("rtl8139", RTL8139_PCI);
+
+ // 0x03 - display controllers
+ device.option_add("vision968", VISION968_PCI);
+ device.option_add("virge", VIRGE_PCI);
+ device.option_add("virgedx", VIRGEDX_PCI);
+ device.option_add("mga2064w", MGA2064W);
+ device.option_add("promotion3210", PROMOTION3210);
+ device.option_add("gd5446", GD5446_PCI);
+ device.option_add("oti64111", OTI64111_PCI);
+ device.option_add("wd9710", WD9710_PCI);
+
+ // 0x04 - multimedia controllers
+ device.option_add("sw1000xg", SW1000XG);
+ device.option_add("ds2416", DS2416);
+ device.option_add("sonicvibes", SONICVIBES);
+ device.option_add("ess_solo1", ES1946_SOLO1E);
+ device.option_add("zr36057", ZR36057_PCI);
+ device.option_add("audiowerk2", AUDIOWERK2);
+
+ // 0x05 - memory controllers
+ // 0x06 - bridge devices
+ // 0x07 - simple communication controllers
+ // 0x08 - generic system peripherals
+ // 0x09 - input devices
+ // 0x0a - docking stations
+ // 0x0b - processors
+ // 0x0c - Serial Bus controllers
+ device.option_add("vt6306", VT6306_PCI);
+ device.option_add("opti82c861", OPTI_82C861);
+
+ // 0x0d - wireless controllers
+ // 0x0e - Intelligent I/O controllers
+ // 0x0f - Satellite Communication controllers
+ // 0x10 - Encryption/Decryption controllers
+ // 0x11 - Data acquisition and signal processing controllers
+ // 0x12 - Processing accelerators
+ // 0x13 - Debug
+}
+
+// assume all natively with class code 03
+void agp_cards(device_slot_interface &device)
+{
+ device.option_add("riva128", RIVA128);
+ device.option_add("riva128zx", RIVA128ZX);
+ device.option_add("rivatnt", RIVATNT);
+ device.option_add("rivatnt2", RIVATNT2);
+ device.option_add("rivatnt2_ultra", RIVATNT2_ULTRA);
+ device.option_add("vanta", VANTA);
+ device.option_add("rivatnt2_m64", RIVATNT2_M64);
+ device.option_add("geforce256", GEFORCE256);
+ device.option_add("geforce256_ddr", GEFORCE256_DDR);
+ device.option_add("quadro", QUADRO);
+ device.option_add("laguna3d", GD5465_LAGUNA3D);
+ device.option_add("sis6326_agp", SIS6326_AGP);
+}
diff --git a/src/devices/bus/pci/pci_slot.h b/src/devices/bus/pci/pci_slot.h
new file mode 100644
index 00000000000..7c8c17ff320
--- /dev/null
+++ b/src/devices/bus/pci/pci_slot.h
@@ -0,0 +1,92 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+
+// Generic PCI card port
+
+#ifndef MAME_BUS_PCI_PCI_SLOT_H
+#define MAME_BUS_PCI_PCI_SLOT_H
+
+#include "machine/pci.h"
+
+#include <array>
+
+
+class pci_card_interface;
+
+class pci_slot_device: public device_t, public device_single_card_slot_interface<pci_card_interface>
+{
+public:
+ friend class pci_card_interface;
+
+ template <typename T>
+ pci_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, T &&opts, u8 slot, u8 irqa, u8 irqb, u8 irqc, u8 irqd, const char *dflt)
+ : pci_slot_device(mconfig, tag, owner, (uint32_t)0)
+ {
+ option_reset();
+ opts(*this);
+ set_default_option(dflt);
+ set_fixed(false);
+ m_slot = slot;
+ m_irq[0] = irqa;
+ m_irq[1] = irqb;
+ m_irq[2] = irqc;
+ m_irq[3] = irqd;
+ }
+
+ pci_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);
+
+ virtual ~pci_slot_device();
+
+ u8 get_slot() const;
+ class pci_card_device *get_card() const;
+
+ void get_irq_map(std::array<u8, 4> &map) const { map = m_irq; }
+
+protected:
+ virtual void device_start() override;
+
+private:
+ std::array<u8, 4> m_irq;
+ u8 m_slot;
+};
+
+
+class pci_card_interface : public device_interface
+{
+protected:
+ pci_slot_device *const m_pci_slot;
+
+ pci_card_interface(const machine_config &mconfig, device_t &device);
+};
+
+
+class pci_card_device : public pci_device, public pci_card_interface
+{
+public:
+ virtual ~pci_card_device();
+
+ void set_irq_map(u8 irqa, u8 irqb = 0xff, u8 irqc = 0xff, u8 irqd = 0xff) {
+ m_irq_map[0] = irqa;
+ m_irq_map[1] = irqb;
+ m_irq_map[2] = irqc;
+ m_irq_map[3] = irqd;
+ }
+
+protected:
+ u8 m_pin_state;
+ std::array<u8, 4> m_irq_map;
+
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ pci_card_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ void irq_pin_w(offs_t line, int state);
+};
+
+DECLARE_DEVICE_TYPE(PCI_SLOT, pci_slot_device)
+
+void pci_cards(device_slot_interface &device);
+void agp_cards(device_slot_interface &device);
+
+#endif
diff --git a/src/devices/bus/pci/pdc20262.cpp b/src/devices/bus/pci/pdc20262.cpp
new file mode 100644
index 00000000000..f2655815a74
--- /dev/null
+++ b/src/devices/bus/pci/pdc20262.cpp
@@ -0,0 +1,263 @@
+// license:BSD-3-Clause
+// copyright-holders: Angelo Salese
+/**************************************************************************************************
+
+Promise PDC20262 FastTrak66/UDMA66 IDE controller
+
+No documentation, ATA4 complaint
+
+TODO:
+- how it sets compatible/native modes? Subvendor ID list suggests it can switch at will;
+- Install win9x driver causes huge loading hiccups, eventually freezes by accessing drive with
+ explorer.exe (enable UDMA?). For common use is **suggested** to not install them.
+- Reportedly has issues with very big HDDs, pinpoint limit and assuming there isn't an issue here.
+\- Tested with Seagate Barracuda ST380021A -chs=158816,16,63 (expected: 80GB, actual: 13655MB)
+- Marketed as RAID card, verify;
+\- Gets classified as SCSI controller in win9x device manager;
+- ID and hookup Flash ROM type;
+- PME 1.0 support (no low power states D1/D2, no PME#)
+
+**************************************************************************************************/
+
+#include "emu.h"
+#include "pdc20262.h"
+
+#define LOG_WARN (1U << 1)
+
+#define VERBOSE (LOG_GENERAL | LOG_WARN)
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+#define LOGWARN(...) LOGMASKED(LOG_WARN, __VA_ARGS__)
+
+
+DEFINE_DEVICE_TYPE(PDC20262, pdc20262_device, "pdc20262", "Promise PDC20262 FastTrak66 EIDE controller")
+
+
+
+pdc20262_device::pdc20262_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : pci_card_device(mconfig, type, tag, owner, clock)
+ , m_ide1(*this, "ide1")
+ , m_ide2(*this, "ide2")
+ , m_irqs(*this, "irqs")
+ // HACK: how to get to get_pci_busmaster_space()?
+ , m_bus_master_space(*this, ":maincpu", 0)
+ , m_bios_rom(*this, "bios_rom")
+{
+ // Subsystems:
+ // 105a 4d30 Ultra Device on SuperTrak
+ // 105a 4d33 Ultra66
+ // 105a 4d39 FastTrak66
+ // class code is trusted, bp 0xca09c
+ // assume revision depending on BIOS
+ set_ids(0x105a4d38, 0x02, 0x018000, 0x105a4d33);
+}
+
+pdc20262_device::pdc20262_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : pdc20262_device(mconfig, PDC20262, tag, owner, clock)
+{
+}
+
+ROM_START( pdc20262 )
+ ROM_REGION32_LE( 0x8000, "bios_rom", ROMREGION_ERASEFF )
+ ROM_DEFAULT_BIOS("v200")
+
+ ROM_SYSTEM_BIOS( 0, "v200", "Promise Ultra66 BIOS v2.00 (Build 18)" )
+ ROMX_LOAD( "ul200b18.bin", 0x0000, 0x4000, CRC(71e48d73) SHA1(84d8c72118a3e26181573412e2cbb859691672de), ROM_BIOS(0) )
+ ROM_SYSTEM_BIOS( 1, "v114", "Promise Ultra66 BIOS v1.14 (Build 0728)" )
+ ROMX_LOAD( "ul114b0728.bin", 0x0000, 0x4000, CRC(a71f0c3d) SHA1(ace4872c6060e9dd8458540c0f3193d1a9b4321a), ROM_BIOS(1) )
+
+ // v1.12 known to exist
+ROM_END
+
+const tiny_rom_entry *pdc20262_device::device_rom_region() const
+{
+ return ROM_NAME(pdc20262);
+}
+
+
+void pdc20262_device::device_add_mconfig(machine_config &config)
+{
+ INPUT_MERGER_ANY_HIGH(config, m_irqs).output_handler().set([this] (int state) {
+ irq_pin_w(0, state);
+ });
+
+ BUS_MASTER_IDE_CONTROLLER(config, m_ide1).options(ata_devices, "hdd", nullptr, false);
+ m_ide1->irq_handler().set([this] (int state) {
+ m_irq_state &= ~0x4;
+ m_irq_state |= (state << 2);
+ m_irqs->in_w<0>(state);
+ });
+ m_ide1->set_bus_master_space(m_bus_master_space);
+
+ BUS_MASTER_IDE_CONTROLLER(config, m_ide2).options(ata_devices, nullptr, nullptr, false);
+ m_ide2->irq_handler().set([this] (int state) {
+ m_irq_state &= ~0x40;
+ m_irq_state |= (state << 6);
+ m_irqs->in_w<1>(state);
+ });
+ m_ide2->set_bus_master_space(m_bus_master_space);
+}
+
+// $1f0
+void pdc20262_device::ide1_command_map(address_map &map)
+{
+ map(0, 7).rw(FUNC(pdc20262_device::ide1_read32_cs0_r), FUNC(pdc20262_device::ide1_write32_cs0_w));
+}
+
+// $3f4
+void pdc20262_device::ide1_control_map(address_map &map)
+{
+ map(2, 2).rw(FUNC(pdc20262_device::ide1_read_cs1_r), FUNC(pdc20262_device::ide1_write_cs1_w));
+}
+
+// $170
+void pdc20262_device::ide2_command_map(address_map &map)
+{
+ map(0, 7).rw(FUNC(pdc20262_device::ide2_read32_cs0_r), FUNC(pdc20262_device::ide2_write32_cs0_w));
+}
+
+// $374
+void pdc20262_device::ide2_control_map(address_map &map)
+{
+ map(2, 2).rw(FUNC(pdc20262_device::ide2_read_cs1_r), FUNC(pdc20262_device::ide2_write_cs1_w));
+}
+
+void pdc20262_device::bus_master_ide_control_map(address_map &map)
+{
+ map(0x00, 0x07).rw(m_ide1, FUNC(bus_master_ide_controller_device::bmdma_r), FUNC(bus_master_ide_controller_device::bmdma_w));
+ map(0x08, 0x0f).rw(m_ide2, FUNC(bus_master_ide_controller_device::bmdma_r), FUNC(bus_master_ide_controller_device::bmdma_w));
+
+ map(0x11, 0x11).lrw8(
+ NAME([this] () {
+ return m_clock;
+ }),
+ NAME([this] (u8 data) {
+ LOG("extra $11: Clock set %02x\n", data);
+ m_clock = data;
+ })
+ );
+
+// map(0x1a, 0x1a) Primary Mode
+// map(0x1b, 0x1b) Secondary Mode
+/*
+ * upper nibble secondary, lower primary
+ *
+ * x--- error
+ * -x-- irq
+ * --x- FIFO full
+ * ---x FIFO empty
+ */
+ map(0x1d, 0x1d).lr8(
+ NAME([this] () {
+ // FIXME: definitely requires a FIFO i/f
+ return m_irq_state | 1;
+ })
+ );
+// map(0x1f, 0x1f) Ultra DMA speed flag
+}
+
+void pdc20262_device::extra_map(address_map &map)
+{
+ // TODO: should be memory mapped versions of above, *nix driver seems to use this
+// map(0x00, 0x07).m(*this, FUNC(pdc20262_device::ide1_command_map)));
+// ...
+}
+
+void pdc20262_device::device_start()
+{
+ pci_card_device::device_start();
+
+ add_map(8, M_IO, FUNC(pdc20262_device::ide1_command_map));
+ add_map(4, M_IO, FUNC(pdc20262_device::ide1_control_map));
+ add_map(8, M_IO, FUNC(pdc20262_device::ide2_command_map));
+ add_map(4, M_IO, FUNC(pdc20262_device::ide2_control_map));
+ add_map(32, M_IO, FUNC(pdc20262_device::bus_master_ide_control_map));
+ // TODO: unknown size (a lot larger?), to be verified later thru PnP
+ add_map(64, M_MEM, FUNC(pdc20262_device::extra_map));
+
+ add_rom((u8 *)m_bios_rom->base(), 0x4000);
+ expansion_rom_base = 0xc8000;
+
+ // INTA#
+ intr_pin = 1;
+}
+
+void pdc20262_device::device_reset()
+{
+ pci_card_device::device_reset();
+
+ command = 0x0000;
+ command_mask = 7;
+ status = 0x0210;
+
+ remap_cb();
+}
+
+void pdc20262_device::config_map(address_map &map)
+{
+ pci_card_device::config_map(map);
+ // latency timer
+ map(0x0d, 0x0d).lr8(NAME([] () { return 0x01; }));
+ // TODO: everything, starting from capptr_r override
+}
+
+/*
+ * Start of legacy handling, to be moved out
+ */
+
+uint32_t pdc20262_device::ide1_read32_cs0_r(offs_t offset, uint32_t mem_mask)
+{
+ if (!(command & 1))
+ return 0xffffffff;
+ return m_ide1->read_cs0(offset, mem_mask);
+}
+
+void pdc20262_device::ide1_write32_cs0_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ if (!(command & 1))
+ return;
+ m_ide1->write_cs0(offset, data, mem_mask);
+}
+
+uint32_t pdc20262_device::ide2_read32_cs0_r(offs_t offset, uint32_t mem_mask)
+{
+ if (!(command & 1))
+ return 0xffffffff;
+ return m_ide2->read_cs0(offset, mem_mask);
+}
+
+void pdc20262_device::ide2_write32_cs0_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ if (!(command & 1))
+ return;
+ m_ide2->write_cs0(offset, data, mem_mask);
+}
+
+uint8_t pdc20262_device::ide1_read_cs1_r()
+{
+ if (!(command & 1))
+ return 0xff;
+ return m_ide1->read_cs1(1, 0xff0000) >> 16;
+}
+
+void pdc20262_device::ide1_write_cs1_w(uint8_t data)
+{
+ if (!(command & 1))
+ return;
+ m_ide1->write_cs1(1, data << 16, 0xff0000);
+}
+
+uint8_t pdc20262_device::ide2_read_cs1_r()
+{
+ if (!(command & 1))
+ return 0xff;
+ return m_ide2->read_cs1(1, 0xff0000) >> 16;
+}
+
+void pdc20262_device::ide2_write_cs1_w(uint8_t data)
+{
+ if (!(command & 1))
+ return;
+ m_ide2->write_cs1(1, data << 16, 0xff0000);
+}
diff --git a/src/devices/bus/pci/pdc20262.h b/src/devices/bus/pci/pdc20262.h
new file mode 100644
index 00000000000..f448894eb03
--- /dev/null
+++ b/src/devices/bus/pci/pdc20262.h
@@ -0,0 +1,65 @@
+// license:BSD-3-Clause
+// copyright-holders: Angelo Salese
+
+#ifndef MAME_BUS_PCI_PDC20262_H
+#define MAME_BUS_PCI_PDC20262_H
+
+#pragma once
+
+#include "pci_slot.h"
+#include "machine/idectrl.h"
+#include "machine/input_merger.h"
+
+class pdc20262_device : public pci_card_device
+{
+public:
+ pdc20262_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ static constexpr feature_type imperfect_features() { return feature::DISK; }
+
+protected:
+ pdc20262_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+// virtual void map_extra(uint64_t memory_window_start, uint64_t memory_window_end, uint64_t memory_offset, address_space *memory_space,
+// uint64_t io_window_start, uint64_t io_window_end, uint64_t io_offset, address_space *io_space) override;
+
+ virtual void config_map(address_map &map) override;
+
+private:
+ void ide1_command_map(address_map &map);
+ void ide1_control_map(address_map &map);
+ void ide2_command_map(address_map &map);
+ void ide2_control_map(address_map &map);
+ void bus_master_ide_control_map(address_map &map);
+ void extra_map(address_map &map);
+
+// virtual void device_config_complete() override;
+
+ required_device<bus_master_ide_controller_device> m_ide1;
+ required_device<bus_master_ide_controller_device> m_ide2;
+ required_device<input_merger_device> m_irqs;
+ required_address_space m_bus_master_space;
+ required_memory_region m_bios_rom;
+
+ u8 m_clock = 0;
+ u8 m_irq_state = 0;
+
+ uint32_t ide1_read32_cs0_r(offs_t offset, uint32_t mem_mask = ~0);
+ void ide1_write32_cs0_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
+ uint32_t ide2_read32_cs0_r(offs_t offset, uint32_t mem_mask = ~0);
+ void ide2_write32_cs0_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
+ uint8_t ide1_read_cs1_r();
+ void ide1_write_cs1_w(uint8_t data);
+ uint8_t ide2_read_cs1_r();
+ void ide2_write_cs1_w(uint8_t data);
+};
+
+DECLARE_DEVICE_TYPE(PDC20262, pdc20262_device)
+
+#endif // MAME_BUS_PCI_PDC20262_H
diff --git a/src/devices/bus/pci/promotion.cpp b/src/devices/bus/pci/promotion.cpp
new file mode 100644
index 00000000000..68396af870b
--- /dev/null
+++ b/src/devices/bus/pci/promotion.cpp
@@ -0,0 +1,153 @@
+// license:BSD-3-Clause
+// copyright-holders:
+/**************************************************************************************************
+
+Alliance Semiconductor ProMotion family
+
+- aT3D is the 2d base of 3dfx Voodoo Rush on Hercules Stingray 128/3D cards at least
+ (thru THP i/f, reportedly slow)
+- On its own aT3D is infamously known to be a terrible 3D card
+ cfr. https://www.youtube.com/watch?v=vCz-rSlSREA
+
+TODO:
+- Requires own family of VGA based devices;
+- Catch is that said device mirrors the PCI space in memory mapped regs, along with the
+ (more or less) typical SVGA regs of the mid-90s;
+- Black screens when mounted;
+- Bare documentation, covering pinout and register names only. aT3D datasheet available for
+crosschecking;
+
+**************************************************************************************************/
+
+#include "emu.h"
+#include "promotion.h"
+
+#define LOG_WARN (1U << 1)
+
+#define VERBOSE (LOG_GENERAL | LOG_WARN)
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+#define LOGWARN(...) LOGMASKED(LOG_WARN, __VA_ARGS__)
+
+
+DEFINE_DEVICE_TYPE(PROMOTION3210, promotion3210_device, "promotion3210", "Alliance Semiconductor ProMotion 3210")
+//DEFINE_DEVICE_TYPE(PROMOTION6410, promotion6410_device, "promotion6410", "Alliance Semiconductor ProMotion 6410")
+//DEFINE_DEVICE_TYPE(PROMOTION6422, promotion6422_device, "promotion6422", "Alliance Semiconductor ProMotion 6422")
+//DEFINE_DEVICE_TYPE(PROMOTION6424, promotion6424_device, "promotion6424", "Alliance Semiconductor ProMotion 6424")
+// Alias of above?
+//DEFINE_DEVICE_TYPE(PROMOTIONAT24, promotionat24_device, "promotionat24", "Alliance Semiconductor ProMotion aT24")
+//DEFINE_DEVICE_TYPE(PROMOTIONAT3D, promotionat3d_device, "promotionat3d", "Alliance Semiconductor ProMotion aT3D")
+//DEFINE_DEVICE_TYPE(PROMOTIONAT25, promotionat25_device, "promotionat25", "Alliance Semiconductor ProMotion aT25")
+
+
+promotion3210_device::promotion3210_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : pci_card_device(mconfig, type, tag, owner, clock)
+ , m_vga(*this, "vga")
+ , m_vga_rom(*this, "vga_rom")
+{
+ // vendor ID 0x1142 Alliance Semiconductor Corporation
+ // subvendor unknown
+ set_ids(0x11423210, 0x00, 0x030000, 0x11423210);
+}
+
+promotion3210_device::promotion3210_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : promotion3210_device(mconfig, PROMOTION3210, tag, owner, clock)
+{
+}
+
+ROM_START( promotion3210 )
+ ROM_REGION32_LE( 0x8000, "vga_rom", ROMREGION_ERASEFF )
+ ROM_SYSTEM_BIOS( 0, "miro", "miro Video 12PD" )
+ ROMX_LOAD( "mirovideo12pd.vbi", 0x0000, 0x8000, CRC(46041709) SHA1(bd43f05ae7ddb4bbf515132b72b32719b60e6950), ROM_BIOS(0) )
+ROM_END
+
+const tiny_rom_entry *promotion3210_device::device_rom_region() const
+{
+ return ROM_NAME(promotion3210);
+}
+
+void promotion3210_device::device_add_mconfig(machine_config &config)
+{
+ screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
+ screen.set_raw(XTAL(25'174'800), 900, 0, 640, 526, 0, 480);
+ screen.set_screen_update(m_vga, FUNC(vga_device::screen_update));
+
+ PROMOTION_VGA(config, m_vga, 0);
+ m_vga->set_screen("screen");
+ // TODO: configurable between 1 and 4 MB (2x EDO slots on board)
+ // Only known OEM Board (Miro) has 1MB
+ m_vga->set_vram_size(1*1024*1024);
+
+ // AT&T ATT20C408-13 PrecisionDAC
+ // Reused by ATI Mach64?
+}
+
+void promotion3210_device::device_start()
+{
+ pci_card_device::device_start();
+
+ add_map( 4*1024*1024, M_MEM, FUNC(promotion3210_device::vram_aperture_map));
+
+ add_rom((u8 *)m_vga_rom->base(), 0x8000);
+ expansion_rom_base = 0xc0000;
+
+ // INTA#
+ intr_pin = 1;
+}
+
+void promotion3210_device::device_reset()
+{
+ pci_card_device::device_reset();
+
+ // TODO: to be checked
+ command = 0x0000;
+ status = 0x0000;
+ command_mask = 0x23;
+
+ remap_cb();
+}
+
+// bare mapping, except for stuff being mirrored at memory-mapped offsets
+void promotion3210_device::config_map(address_map &map)
+{
+ pci_card_device::config_map(map);
+}
+
+void promotion3210_device::vram_aperture_map(address_map &map)
+{
+
+}
+
+// TODO: this should really be a subclass of VGA
+void promotion3210_device::legacy_memory_map(address_map &map)
+{
+ map(0xa0000, 0xbffff).rw(FUNC(promotion3210_device::vram_r), FUNC(promotion3210_device::vram_w));
+}
+
+void promotion3210_device::legacy_io_map(address_map &map)
+{
+ map(0, 0x02f).m(m_vga, FUNC(vga_device::io_map));
+}
+
+uint8_t promotion3210_device::vram_r(offs_t offset)
+{
+ return downcast<vga_device *>(m_vga.target())->mem_r(offset);
+}
+
+void promotion3210_device::vram_w(offs_t offset, uint8_t data)
+{
+ downcast<vga_device *>(m_vga.target())->mem_w(offset, data);
+}
+
+void promotion3210_device::map_extra(uint64_t memory_window_start, uint64_t memory_window_end, uint64_t memory_offset, address_space *memory_space,
+ uint64_t io_window_start, uint64_t io_window_end, uint64_t io_offset, address_space *io_space)
+{
+// if (1)
+ {
+ memory_space->install_readwrite_handler(0xa0000, 0xbffff, read8sm_delegate(*this, FUNC(promotion3210_device::vram_r)), write8sm_delegate(*this, FUNC(promotion3210_device::vram_w)));
+
+ io_space->install_device(0x03b0, 0x03df, *this, &promotion3210_device::legacy_io_map);
+ //memory_space->install_rom(0xc0000, 0xcffff, (void *)expansion_rom);
+ }
+}
diff --git a/src/devices/bus/pci/promotion.h b/src/devices/bus/pci/promotion.h
new file mode 100644
index 00000000000..11a20f94269
--- /dev/null
+++ b/src/devices/bus/pci/promotion.h
@@ -0,0 +1,49 @@
+// license:BSD-3-Clause
+// copyright-holders:
+
+#ifndef MAME_BUS_PCI_PROMOTION_H
+#define MAME_BUS_PCI_PROMOTION_H
+
+#pragma once
+
+#include "pci_slot.h"
+
+#include "video/pc_vga_alliance.h"
+
+
+class promotion3210_device : public pci_card_device
+{
+public:
+ promotion3210_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ void legacy_memory_map(address_map &map);
+ void legacy_io_map(address_map &map);
+
+ static constexpr feature_type unemulated_features() { return feature::GRAPHICS; }
+
+protected:
+ promotion3210_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+ virtual void map_extra(uint64_t memory_window_start, uint64_t memory_window_end, uint64_t memory_offset, address_space *memory_space,
+ uint64_t io_window_start, uint64_t io_window_end, uint64_t io_offset, address_space *io_space) override;
+
+ virtual void config_map(address_map &map) override;
+
+ required_device<promotion_vga_device> m_vga;
+ required_memory_region m_vga_rom;
+private:
+ u8 vram_r(offs_t offset);
+ void vram_w(offs_t offset, uint8_t data);
+
+ void vram_aperture_map(address_map &map);
+};
+
+DECLARE_DEVICE_TYPE(PROMOTION3210, promotion3210_device)
+
+#endif // MAME_BUS_PCI_PROMOTION_H
diff --git a/src/devices/bus/pci/riva128.cpp b/src/devices/bus/pci/riva128.cpp
new file mode 100644
index 00000000000..e1a41a4818a
--- /dev/null
+++ b/src/devices/bus/pci/riva128.cpp
@@ -0,0 +1,250 @@
+// license:BSD-3-Clause
+// copyright-holders: Angelo Salese
+// thanks-to: Marcelina Koscielnicka
+/**************************************************************************************************
+
+nVidia NV3/NV3T Riva 128
+
+TODO:
+- Windows 98 punts device detection by attempting to modify the (supposedly) PMC ID.
+- Maybe the card is supposed to send an INTA trap on the write attempt?
+
+References:
+- https://envytools.readthedocs.io/en/latest/hw/mmio.html?highlight=mmio#nv3-g80-mmio-map
+
+**************************************************************************************************/
+
+#include "emu.h"
+#include "riva128.h"
+
+#define LOG_WARN (1U << 1)
+#define LOG_TODO (1U << 2) // log unimplemented registers
+
+#define VERBOSE (LOG_GENERAL | LOG_WARN | LOG_TODO)
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+#define LOGWARN(...) LOGMASKED(LOG_WARN, __VA_ARGS__)
+#define LOGTODO(...) LOGMASKED(LOG_TODO, __VA_ARGS__)
+
+
+DEFINE_DEVICE_TYPE(RIVA128, riva128_device, "riva128", "SGS-Thompson/nVidia Riva 128 (NV3)")
+DEFINE_DEVICE_TYPE(RIVA128ZX, riva128zx_device, "riva128zx", "SGS-Thompson/nVidia Riva 128 ZX (NV3T)")
+
+riva128_device::riva128_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : pci_card_device(mconfig, type, tag, owner, clock)
+ , m_svga(*this, "svga")
+ , m_vga_rom(*this, "vga_rom")
+{
+ // device ID 0x12d2 SGS-Thompson/nVidia joint venture
+ // 0x0018 RIVA 128 (NV3)
+ // 0x0019 RIVA 128 ZX (NV3T)
+ // TODO: STB uses 0x10b4xxxx, unknown for ASUS
+ set_ids_agp(0x12d20018, 0x00, 0x10921092);
+}
+
+riva128_device::riva128_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : riva128_device(mconfig, RIVA128, tag, owner, clock)
+{
+}
+
+ROM_START( riva128 )
+ ROM_REGION32_LE( 0x8000, "vga_rom", ROMREGION_ERASEFF )
+ ROM_SYSTEM_BIOS( 0, "diamond", "Diamond Viper V330 1.62-CO 01/14/98" )
+ ROMX_LOAD( "diamond_v330_rev-e.vbi", 0x0000, 0x8000, CRC(68686ddc) SHA1(cd2e299acd79624c7d82ce3317004c96bd4e36f7), ROM_BIOS(0) )
+ ROM_SYSTEM_BIOS( 1, "asus", "ASUS AGP/3DP-V3000 1.51B 09/06/97" )
+ ROMX_LOAD( "riva128_asus.vbi", 0x0000, 0x8000, CRC(cc57586f) SHA1(5e6ec14c66ec38b21013ee6b7582f6b6a4586e2e), ROM_BIOS(1) )
+ ROM_SYSTEM_BIOS( 2, "stb", "STB Velocity 128 AGP 1.82 12/17/97" )
+ ROMX_LOAD( "riva128_stb.vbi", 0x0000, 0x8000, CRC(80da0245) SHA1(894c855c6d676de0d04d396f7e93a0e6cb98a4b3), ROM_BIOS(2) )
+ROM_END
+
+const tiny_rom_entry *riva128_device::device_rom_region() const
+{
+ return ROM_NAME(riva128);
+}
+
+void riva128_device::device_add_mconfig(machine_config &config)
+{
+ screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
+ screen.set_raw(XTAL(25'174'800), 900, 0, 640, 526, 0, 480);
+ screen.set_screen_update(m_svga, FUNC(nvidia_nv3_vga_device::screen_update));
+
+ NVIDIA_NV3_VGA(config, m_svga, 0);
+ m_svga->set_screen("screen");
+ // FIXME: shared RAM
+ // reports as 4MB in AIDA16
+ m_svga->set_vram_size(4*1024*1024);
+}
+
+void riva128_device::device_start()
+{
+ pci_card_device::device_start();
+
+ add_map( 16*1024*1024, M_MEM, FUNC(riva128_device::mmio_map));
+ add_map(128*1024*1024, M_MEM, FUNC(riva128_device::vram_aperture_map));
+ // indirect memory access I/Os (NV3 only)
+ add_map(0x100, M_IO, FUNC(riva128_device::indirect_io_map));
+ // TODO: Windows 98 expects an extra range mapped at 0x10000000-0x10007fff
+
+ add_rom((u8 *)m_vga_rom->base(), 0x8000);
+ expansion_rom_base = 0xc0000;
+
+ // INTA#
+ intr_pin = 1;
+ save_item(NAME(m_vga_legacy_enable));
+}
+
+void riva128_device::device_reset()
+{
+ pci_card_device::device_reset();
+
+ // TODO: to be checked
+ command = 0x0000;
+ status = 0x0000;
+
+ m_vga_legacy_enable = true;
+ m_main_scratchpad_id = 0x00030310;
+ remap_cb();
+}
+
+// TODO: counter-check everything
+void riva128_device::config_map(address_map &map)
+{
+ pci_card_device::config_map(map);
+ map(0x34, 0x34).lr8(NAME([] () { return 0x44; }));
+
+// map(0x40, 0x43) subsystem ID alias (writeable)
+// map(0x44, 0x4f) AGP i/f
+// map(0x50, 0x53) ROM shadow enable
+ map(0x54, 0x57).lrw8(
+ NAME([this] (offs_t offset) { return m_vga_legacy_enable; }),
+ NAME([this] (offs_t offset, u32 data, u32 mem_mask) {
+ if (ACCESSING_BITS_0_7)
+ {
+ m_vga_legacy_enable = BIT(data, 0);
+ remap_cb();
+ }
+ //printf("- %s VGA control %08x & %08x\n", m_vga_legacy_enable ? "Enable" : "Disable", data, mem_mask);
+ })
+ );
+ map(0x58, 0x58).lr8(NAME([] () { return 0x00; }));
+
+}
+
+void riva128_device::mmio_map(address_map &map)
+{
+ map(0x00000000, 0x00ffffff).rw(FUNC(riva128_device::unmap_log_r), FUNC(riva128_device::unmap_log_w));
+ map(0x00000000, 0x00000003).lrw32(
+ NAME([this] (offs_t offset) {
+ machine().debug_break();
+ LOGTODO("MMIO ID readback\n");
+ return m_main_scratchpad_id;
+ //return 0x00030310;
+ }),
+ NAME([this] (offs_t offset, u32 data, u32 mem_mask) {
+ COMBINE_DATA(&m_main_scratchpad_id);
+ })
+ );
+// map(0x00000000, 0x00000fff) PMC card master control
+// map(0x00001000, 0x00001fff) PBUS bus control
+// map(0x00002000, 0x00003fff) PFIFO
+// map(0x00007000, 0x00007***) PRMA real mode BAR Access
+// map(0x00009000, 0x00009***) PTIMER
+// map(0x000a0000, 0x000bffff) PRMFB legacy VGA memory
+// map(0x000c0000, 0x000c****) PRMVIO VGA sequencer & VGA gfx regs (multiple on NV40+)
+// map(0x00100000, 0x0010*fff) PFB memory interface
+// map(0x00110000, 0x0011ffff) PROM ROM access window
+// map(0x00120000, 0x0012ffff) PALT External memory access window
+// map(0x00400000, 0x00400fff) PGRAPH 2d/3d graphics engine
+// map(0x00401000, 0x00401***) PDMA system memory DMA engine (NV3/NV4 only)
+// map(0x00600000, 0x00600***) PCRTC CRTC controls (on NV4+ only?)
+// map(0x00601000, 0x0060****) PRMCIO VGA CRTC controls
+// map(0x00680000, 0x0068****) PRAMDAC
+// map(0x00681000, 0x00681***) VGA DAC registers
+// map(0x00800000, 0x00******) PFIFO MMIO submission area
+}
+
+void riva128_device::vram_aperture_map(address_map &map)
+{
+
+}
+
+void riva128_device::indirect_io_map(address_map &map)
+{
+
+}
+
+u32 riva128_device::unmap_log_r(offs_t offset, u32 mem_mask)
+{
+ LOGTODO("MMIO Unemulated [%08x] & %08x R\n", offset * 4, mem_mask);
+ return 0;
+}
+
+void riva128_device::unmap_log_w(offs_t offset, u32 data, u32 mem_mask)
+{
+ LOGTODO("MMIO Unemulated [%08x] %08x & %08x W\n", offset * 4, data, mem_mask);
+}
+
+
+// TODO: this should really be a subclass of VGA
+void riva128_device::legacy_memory_map(address_map &map)
+{
+ map(0xa0000, 0xbffff).rw(FUNC(riva128_device::vram_r), FUNC(riva128_device::vram_w));
+}
+
+void riva128_device::legacy_io_map(address_map &map)
+{
+ map(0, 0x02f).m(m_svga, FUNC(nvidia_nv3_vga_device::io_map));
+}
+
+uint8_t riva128_device::vram_r(offs_t offset)
+{
+ return downcast<nvidia_nv3_vga_device *>(m_svga.target())->mem_r(offset);
+}
+
+void riva128_device::vram_w(offs_t offset, uint8_t data)
+{
+ downcast<nvidia_nv3_vga_device *>(m_svga.target())->mem_w(offset, data);
+}
+
+void riva128_device::map_extra(uint64_t memory_window_start, uint64_t memory_window_end, uint64_t memory_offset, address_space *memory_space,
+ uint64_t io_window_start, uint64_t io_window_end, uint64_t io_offset, address_space *io_space)
+{
+ if (m_vga_legacy_enable)
+ {
+ memory_space->install_readwrite_handler(0xa0000, 0xbffff, read8sm_delegate(*this, FUNC(riva128_device::vram_r)), write8sm_delegate(*this, FUNC(riva128_device::vram_w)));
+
+ io_space->install_device(0x03b0, 0x03df, *this, &riva128_device::legacy_io_map);
+ //memory_space->install_rom(0xc0000, 0xcffff, (void *)expansion_rom);
+ }
+}
+
+/********************************************
+ *
+ * Riva 128ZX overrides
+ *
+ *******************************************/
+
+riva128zx_device::riva128zx_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : riva128_device(mconfig, RIVA128ZX, tag, owner, clock)
+{
+ // $54-$57 in ROM for subvendor ID (if FBA[1] config is 1)
+ set_ids_agp(0x12d20019, 0x00, 0x12d20019);
+}
+
+ROM_START( riva128zx )
+ ROM_REGION32_LE( 0x8000, "vga_rom", ROMREGION_ERASEFF )
+ ROM_SYSTEM_BIOS( 0, "asus", "ASUS AGP-V3000 ZX TV (V1.70D.03)" )
+ ROMX_LOAD( "asus_agp-v3000zx.vbi", 0x000000, 0x008000, CRC(8319de18) SHA1(837fe8afdf03196550c51ff4987e7f25cc75222c), ROM_BIOS(0) )
+ // TODO: confirm if this is really a 128ZX
+ // (underlying ROM PCIR has 0x0018 not 0x0019)
+ ROM_SYSTEM_BIOS( 1, "elsa", "ELSA VICTORY Erazor/LT (Ver. 1.58.00)" )
+ ROMX_LOAD( "elsa.vbi", 0x000000, 0x008000, CRC(8dd4627a) SHA1(cfb10d9a370a951f9ed23719b2c5fa79c9e49668), ROM_BIOS(1) )
+ ROM_SYSTEM_BIOS( 2, "creative", "Creative Graphics Blaster Riva 128ZX (V1.72.3D)" )
+ ROMX_LOAD( "creative_ct6730.vbi", 0x000000, 0x008000, CRC(72f03a0e) SHA1(7126c4c4d20c48848defc5dd05f0d5b698948015), ROM_BIOS(2) )
+ROM_END
+
+const tiny_rom_entry *riva128zx_device::device_rom_region() const
+{
+ return ROM_NAME(riva128zx);
+}
diff --git a/src/devices/bus/pci/riva128.h b/src/devices/bus/pci/riva128.h
new file mode 100644
index 00000000000..a16a1ad5357
--- /dev/null
+++ b/src/devices/bus/pci/riva128.h
@@ -0,0 +1,65 @@
+// license:BSD-3-Clause
+// copyright-holders: Angelo Salese
+
+#ifndef MAME_BUS_PCI_RIVA128_H
+#define MAME_BUS_PCI_RIVA128_H
+
+#pragma once
+
+#include "pci_slot.h"
+#include "video/pc_vga_nvidia.h"
+
+
+class riva128_device : public pci_card_device
+{
+public:
+ riva128_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ void legacy_memory_map(address_map &map);
+ void legacy_io_map(address_map &map);
+
+protected:
+ riva128_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+ virtual void map_extra(uint64_t memory_window_start, uint64_t memory_window_end, uint64_t memory_offset, address_space *memory_space,
+ uint64_t io_window_start, uint64_t io_window_end, uint64_t io_offset, address_space *io_space) override;
+
+ virtual void config_map(address_map &map) override;
+
+ virtual void mmio_map(address_map &map);
+ virtual void vram_aperture_map(address_map &map);
+ virtual void indirect_io_map(address_map &map);
+
+ required_device<nvidia_nv3_vga_device> m_svga;
+ required_memory_region m_vga_rom;
+
+ bool m_vga_legacy_enable = false;
+private:
+ u8 vram_r(offs_t offset);
+ void vram_w(offs_t offset, uint8_t data);
+
+ u32 unmap_log_r(offs_t offset, u32 mem_mask = ~0);
+ void unmap_log_w(offs_t offset, u32 data, u32 mem_mask = ~0);
+
+ u32 m_main_scratchpad_id = 0;
+};
+
+class riva128zx_device : public riva128_device
+{
+public:
+ riva128zx_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual const tiny_rom_entry *device_rom_region() const override;
+};
+
+DECLARE_DEVICE_TYPE(RIVA128, riva128_device)
+DECLARE_DEVICE_TYPE(RIVA128ZX, riva128zx_device)
+
+#endif // MAME_BUS_PCI_RIVA128_H
diff --git a/src/devices/bus/pci/rivatnt.cpp b/src/devices/bus/pci/rivatnt.cpp
new file mode 100644
index 00000000000..5eca413fa4e
--- /dev/null
+++ b/src/devices/bus/pci/rivatnt.cpp
@@ -0,0 +1,231 @@
+// license:BSD-3-Clause
+// copyright-holders: Angelo Salese
+/**************************************************************************************************
+
+nVidia NV4 TNT
+nVidia NV5 TNT2
+
+TODO:
+- Pinpoint where "Vanta LT" and "RIVA TNT2 Pro" collocates;
+- rivatnt2_ultra, rivatnt2_m64 and vanta enables external clock, failing $3da VRetrace checks next;
+- rivatnt2_m64 inno3d/ct6980 BIOSes (at least) fails booting doing a i2c-like check to $36/$37
+ (ddc?). This pattern is also seen in later Geforce 256 cards.
+
+**************************************************************************************************/
+
+#include "emu.h"
+#include "rivatnt.h"
+
+#define LOG_WARN (1U << 1)
+#define LOG_TODO (1U << 2) // log unimplemented registers
+
+#define VERBOSE (LOG_GENERAL | LOG_WARN | LOG_TODO)
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+#define LOGWARN(...) LOGMASKED(LOG_WARN, __VA_ARGS__)
+#define LOGTODO(...) LOGMASKED(LOG_TODO, __VA_ARGS__)
+
+
+DEFINE_DEVICE_TYPE(RIVATNT, rivatnt_device, "rivatnt", "nVidia Riva TNT (NV4)")
+DEFINE_DEVICE_TYPE(RIVATNT2, rivatnt2_device, "rivatnt2", "nVidia Riva TNT2 (NV5)")
+DEFINE_DEVICE_TYPE(RIVATNT2_ULTRA, rivatnt2_ultra_device, "rivatnt2_ultra","nVidia Riva TNT2 Ultra (NV5)")
+DEFINE_DEVICE_TYPE(VANTA, vanta_device, "vanta", "nVidia Vanta (NV5)")
+DEFINE_DEVICE_TYPE(RIVATNT2_M64, rivatnt2_model64_device,"rivatnt2_m64", "nVidia Riva TNT2 Model 64 (NV5)")
+
+
+rivatnt_device::rivatnt_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : riva128_device(mconfig, type, tag, owner, clock)
+{
+
+}
+
+rivatnt_device::rivatnt_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : rivatnt_device(mconfig, RIVATNT, tag, owner, clock)
+{
+ // device ID 0x10de nVidia
+ // TODO: revision (A5 for Creative card)
+ // 0x11021016 for Creative Graphics Blaster RIVATNT
+ // 0x1092xxxx for Diamond Viper V550
+ // 0x10b427xx for STB
+ set_ids_agp(0x10de0020, 0x00, 0x10de0020);
+}
+
+ROM_START( rivatnt )
+ ROM_REGION32_LE( 0x8800, "vga_rom", ROMREGION_ERASEFF )
+ ROM_SYSTEM_BIOS( 0, "creative", "Creative Graphics Blaster RIVA TNT (V2.04.6.18)" )
+ ROMX_LOAD( "nv4_creative.rom", 0x0000, 0x8000, CRC(fe527a82) SHA1(2bb22bbaa7d2b61bce403f3163197abef85abdaa), ROM_BIOS(0) )
+ ROM_SYSTEM_BIOS( 1, "stb", "STB Velocity 4400 (ver. 1.01)" )
+ ROMX_LOAD( "nv4_stb_velocity.rom", 0x0000, 0x8000, CRC(d5251dc9) SHA1(eac26ac45e1cdcf020041586fb4216fd8166c2da), ROM_BIOS(1) )
+ ROM_SYSTEM_BIOS( 2, "diamondb", "Diamond Viper V550 (Rev B, v1.95e)" )
+ ROMX_LOAD( "nv4_diamond_revb.rom", 0x0000, 0x8800, CRC(8d860d99) SHA1(12b183cacc29cf8229da1b84b5f640f2f0722828), ROM_BIOS(2) )
+ ROM_SYSTEM_BIOS( 3, "diamonda", "Diamond Viper V550 (Rev A, v1.93e)" )
+ ROMX_LOAD( "nv4_diamond_reva.rom", 0x0000, 0x8800, CRC(333ca8e3) SHA1(602ba5812e608bb7275336e9abab4b822f7b1b98), ROM_BIOS(3) )
+ROM_END
+
+const tiny_rom_entry *rivatnt_device::device_rom_region() const
+{
+ return ROM_NAME(rivatnt);
+}
+
+// NV4 removes the indirect_io_map from NV3
+void rivatnt_device::device_start()
+{
+ pci_card_device::device_start();
+
+ add_map( 16*1024*1024, M_MEM, FUNC(rivatnt_device::mmio_map));
+ add_map(128*1024*1024, M_MEM, FUNC(rivatnt_device::vram_aperture_map));
+
+ add_rom((u8 *)m_vga_rom->base(), 0x8000);
+ expansion_rom_base = 0xc0000;
+
+ // INTA#
+ intr_pin = 1;
+ save_item(NAME(m_vga_legacy_enable));
+}
+
+/********************************************
+ *
+ * Riva TNT2 overrides
+ *
+ *******************************************/
+
+rivatnt2_device::rivatnt2_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : rivatnt_device(mconfig, type, tag, owner, clock)
+{
+}
+
+rivatnt2_device::rivatnt2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : rivatnt2_device(mconfig, RIVATNT2, tag, owner, clock)
+{
+ // device ID 0x10de nVidia
+ set_ids_agp(0x10de0028, 0x00, 0x10de0028);
+}
+
+ROM_START( rivatnt2 )
+ ROM_REGION32_LE( 0x10000, "vga_rom", ROMREGION_ERASEFF )
+ // Despite the versioning it claims to be (C) 1999-2001
+ ROM_SYSTEM_BIOS( 0, "leadtek", "Leadtek WinFast 3D S320 II (V99.04.12)" )
+ ROMX_LOAD( "rivatnt2leadteks320ii.bin", 0x000000, 0x010000, CRC(f1379a55) SHA1(1ea0216df1fee9ee1bcd66c26adafbbdb6a0f1f1), ROM_BIOS(0) )
+ ROM_SYSTEM_BIOS( 1, "diamond", "Diamond Viper V770 (202L4A00)")
+ ROMX_LOAD( "nv5diamond.bin", 0x000000, 0x009c00, CRC(ac6c48ff) SHA1(709632adf1e156fab3af0723b73a1e6c2c39e987), ROM_BIOS(1) )
+ROM_END
+
+const tiny_rom_entry *rivatnt2_device::device_rom_region() const
+{
+ return ROM_NAME(rivatnt2);
+}
+
+// All NV5 definitely wants 64K ROM BIOS (would fail CRC checks)
+void rivatnt2_device::device_start()
+{
+ pci_card_device::device_start();
+
+ add_map( 16*1024*1024, M_MEM, FUNC(rivatnt2_device::mmio_map));
+ add_map(128*1024*1024, M_MEM, FUNC(rivatnt2_device::vram_aperture_map));
+
+ add_rom((u8 *)m_vga_rom->base(), 0x10000);
+ expansion_rom_base = 0xc0000;
+
+ // INTA#
+ intr_pin = 1;
+ save_item(NAME(m_vga_legacy_enable));
+}
+
+/********************************************/
+
+rivatnt2_ultra_device::rivatnt2_ultra_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : rivatnt2_device(mconfig, RIVATNT2_ULTRA, tag, owner, clock)
+{
+ // device ID 0x10de nVidia
+ set_ids_agp(0x10de0029, 0x00, 0x10de0029);
+}
+
+ROM_START( rivatnt2_ultra )
+ ROM_REGION32_LE( 0x10000, "vga_rom", ROMREGION_ERASEFF )
+ ROM_SYSTEM_BIOS( 0, "creative", "Creative 3D Blaster RIVA TNT2 Ultra AGP" )
+ ROMX_LOAD( "creative.bin", 0x000000, 0x010000, CRC(cf3828ce) SHA1(733d8c3f179f89f0e238ffb95717c0fafd1053aa), ROM_BIOS(0) )
+ROM_END
+
+const tiny_rom_entry *rivatnt2_ultra_device::device_rom_region() const
+{
+ return ROM_NAME(rivatnt2_ultra);
+}
+
+/********************************************/
+
+vanta_device::vanta_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : rivatnt2_device(mconfig, VANTA, tag, owner, clock)
+{
+ // device ID 0x10de nVidia
+ set_ids_agp(0x10de002c, 0x00, 0x10de002c);
+}
+
+// TODO: None of the Vanta BIOSes returns a real vendor inside, confirm OEM card names
+ROM_START( vanta )
+ ROM_REGION32_LE( 0x10000, "vga_rom", ROMREGION_ERASEFF )
+ ROM_SYSTEM_BIOS( 0, "inno3d", "InnoVISION Inno3D Vanta (V2.05.13)" )
+ ROMX_LOAD( "inno3d_nv5.bin", 0x000000, 0x00a800, CRC(9574114f) SHA1(f0e684bca6cc9c1e51a91dccdd5f216b16ea4fe1), ROM_BIOS(0) )
+ ROM_SYSTEM_BIOS( 1, "pine", "Pine Vanta (V2.05.17.04.00)" )
+ ROMX_LOAD( "pine_pci_nv5.rom", 0x000000, 0x00a800, CRC(9c24202a) SHA1(417644f744b2cd54c0b81e8982e81336907f355e), ROM_BIOS(1) )
+ // "Vanta LT"?
+ ROM_SYSTEM_BIOS( 2, "compaq", "Compaq Vanta-16 (V3.05.00.10.45)" )
+ ROMX_LOAD( "nv5_compaq_vantalt.rom", 0x000000, 0x009800, CRC(64800741) SHA1(b28a56bcf466fcd9308541acaa1c7c94f493149a), ROM_BIOS(2) )
+ROM_END
+
+const tiny_rom_entry *vanta_device::device_rom_region() const
+{
+ return ROM_NAME(vanta);
+}
+
+/********************************************/
+
+rivatnt2_model64_device::rivatnt2_model64_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : rivatnt2_device(mconfig, RIVATNT2_M64, tag, owner, clock)
+{
+ // device ID 0x10de nVidia
+ set_ids_agp(0x10de002d, 0x00, 0x10de002d);
+}
+
+ROM_START( rivatnt2_m64 )
+ ROM_REGION32_LE( 0x20000, "vga_rom", ROMREGION_ERASEFF )
+ ROM_SYSTEM_BIOS( 0, "asus", "ASUS AGP-V3800M (V3.05.00.10.31)" )
+ ROMX_LOAD( "asus_125-143mhz32mb.rom", 0x000000, 0x00b000, CRC(be95dc0c) SHA1(35c367b4f9d2db1bfca6d829744d9ffbd2db6e8a), ROM_BIOS(0) )
+ ROM_SYSTEM_BIOS( 1, "ct6980", "Creative CT6984 AGP (V2.05.4.17.03)" )
+ ROMX_LOAD( "creativect6980_125-125mhz.rom", 0x000000, 0x009400, CRC(6a50c279) SHA1(a81105745cc1b80c720a7e3b3216507d61e4e120), ROM_BIOS(1) )
+ ROM_SYSTEM_BIOS( 2, "inno3d", "InnoVISION Inno3D TNT2 M64 (V2.05.13)" )
+ ROMX_LOAD( "inno3dpci_125-125mhz.bin", 0x000000, 0x010000, CRC(08ba7718) SHA1(479cc1cb12bdddc87174c71382b55f932a9a9610), ROM_BIOS(2) )
+ ROM_SYSTEM_BIOS( 3, "cm64a", "PowerColor CM64A (V2.05.13)" )
+ ROMX_LOAD( "cm64a_120-125mhz.rom", 0x000000, 0x00a800, CRC(d087e5fa) SHA1(230475f5385feda97c29d52723ec96bad2be6e08), ROM_BIOS(3) )
+ ROM_SYSTEM_BIOS( 4, "leadtek", "Leadtek 16MB AGP (V3.05.00.10.56)" )
+ ROMX_LOAD( "leadtek16mb_125-143mhz.rom", 0x000000, 0x009800, CRC(71e060e5) SHA1(4057e940ab2bc0bdc3a286dfc71bcb50342fce13), ROM_BIOS(4) )
+ ROM_SYSTEM_BIOS( 5, "pine", "Pine VARM645PS (V3.05.00.10.00)" )
+ ROMX_LOAD( "pine_pv-t02a-br_125-143mhz.rom", 0x000000, 0x00b000, CRC(0212415b) SHA1(3c34c9bc7e8d521d6d8c8f51959b75378a73eef7), ROM_BIOS(5) )
+ // TODO: unsure about the card name for these
+ ROM_SYSTEM_BIOS( 6, "manli", "Manli RIVA TNT2 M64 (V2.05.19.03.00)" )
+ ROMX_LOAD( "manli_135-135mhz.rom", 0x000000, 0x00a800, CRC(d182f4d4) SHA1(e8615cceb3fd3c1bffdb2987313729b367b2deef), ROM_BIOS(6) )
+ ROM_SYSTEM_BIOS( 7, "msi", "MSI RIVA TNT2 M64 (V2.05.20.02.25)" )
+ ROMX_LOAD( "msi_ms-8808_125-150mhz.rom", 0x000000, 0x00a800, CRC(f204caa2) SHA1(7642f27235754d9a8d64e799a6b20017444b7722), ROM_BIOS(7) )
+ ROM_SYSTEM_BIOS( 8, "sparkle", "Sparkle RIVA TNT2 M64 (V3.05.00.10.00)" )
+ ROMX_LOAD( "sparkle_sp5300_125-125mhz.rom", 0x000000, 0x00b400, CRC(518e9e79) SHA1(f6232418e0dd08f04ac5c6ace4e0d4ec06290d48), ROM_BIOS(8) )
+ // Originally posted in misc/ez2d.cpp
+ ROM_SYSTEM_BIOS( 9, "unknown", "nVidia RIVA TNT2 M64 (V2.05.20.02.80)" )
+ ROMX_LOAD( "62090211.rom", 0x000000, 0x00b000, CRC(5669135b) SHA1(b704ce0d20b71e40563d12bcc45bd1240227be74), ROM_BIOS(9) )
+ // Provided inside ez2dm HDD image
+ // "V10.26.19.99"
+ ROM_SYSTEM_BIOS( 10, "winfast_oem", "Leadtek WinFast 3D 325 OEM (V4.8)" )
+ ROMX_LOAD( "w2137.rom", 0x000000, 0x010000, CRC(3b7986ff) SHA1(529a79296c914a2dcdd568221b9aac914869bade), ROM_BIOS(10) )
+
+ // following is just an alias of "inno3dpci_125-125mhz.bin" with empty data in the 0x10000-0x1ffff bank (likely inaccessible too)
+ // rivatnt2m64inno3d.BIN 1xxxxxxxxxxxxxxxx = 0x00
+ // inno3dpci_125-125mhz.bin rivatnt2m64inno3d.BIN [1/2] IDENTICAL
+// ROMX_LOAD( "rivatnt2m64inno3d.bin", 0x000000, 0x020000, CRC(7241c671) SHA1(24f6f1fbcd3d42ec354185697f8e856d876e2a50), ROM_BIOS(0) )
+
+// "rivatnt2m64.bin" is another alias
+// inno3dpci_125-125mhz.bin rivatnt2m64.BIN IDENTICAL
+ROM_END
+
+const tiny_rom_entry *rivatnt2_model64_device::device_rom_region() const
+{
+ return ROM_NAME(rivatnt2_m64);
+}
diff --git a/src/devices/bus/pci/rivatnt.h b/src/devices/bus/pci/rivatnt.h
new file mode 100644
index 00000000000..97e77675368
--- /dev/null
+++ b/src/devices/bus/pci/rivatnt.h
@@ -0,0 +1,73 @@
+// license:BSD-3-Clause
+// copyright-holders: Angelo Salese
+
+#ifndef MAME_BUS_VIDEO_RIVATNT_H
+#define MAME_BUS_VIDEO_RIVATNT_H
+
+#pragma once
+
+#include "riva128.h"
+
+#include "machine/pci.h"
+#include "video/pc_vga_nvidia.h"
+
+
+class rivatnt_device : public riva128_device
+{
+public:
+ rivatnt_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ rivatnt_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_start() override;
+};
+
+class rivatnt2_device : public rivatnt_device
+{
+public:
+ rivatnt2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ rivatnt2_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_start() override;
+};
+
+class rivatnt2_ultra_device : public rivatnt2_device
+{
+public:
+ rivatnt2_ultra_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual const tiny_rom_entry *device_rom_region() const override;
+};
+
+class vanta_device : public rivatnt2_device
+{
+public:
+ vanta_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual const tiny_rom_entry *device_rom_region() const override;
+};
+
+class rivatnt2_model64_device : public rivatnt2_device
+{
+public:
+ rivatnt2_model64_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual const tiny_rom_entry *device_rom_region() const override;
+};
+
+DECLARE_DEVICE_TYPE(RIVATNT, rivatnt_device)
+DECLARE_DEVICE_TYPE(RIVATNT2, rivatnt2_device)
+DECLARE_DEVICE_TYPE(RIVATNT2_ULTRA, rivatnt2_ultra_device)
+DECLARE_DEVICE_TYPE(VANTA, vanta_device)
+DECLARE_DEVICE_TYPE(RIVATNT2_M64, rivatnt2_model64_device)
+
+
+#endif
diff --git a/src/devices/bus/pci/rtl8029as_pci.cpp b/src/devices/bus/pci/rtl8029as_pci.cpp
new file mode 100644
index 00000000000..6f322d21f0b
--- /dev/null
+++ b/src/devices/bus/pci/rtl8029as_pci.cpp
@@ -0,0 +1,79 @@
+// license:BSD-3-Clause
+// copyright-holders:
+/***************************************************************************************************
+
+Realtek RTL8029AS based Network cards
+
+List of OEM cards:
+- D-Link SN-3200 (ibm5170:s3200pci)
+- ...
+
+TODO:
+- Understand how it manages "config pages" (-> 4 views);
+- Bridge with NE2000;
+- 93C46 EEPROM;
+- Optional ROMs for RTL8029AS extended modes;
+
+***************************************************************************************************/
+
+#include "emu.h"
+#include "rtl8029as_pci.h"
+
+#define LOG_WARN (1U << 1)
+
+#define VERBOSE (LOG_GENERAL | LOG_WARN)
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+#define LOGWARN(...) LOGMASKED(LOG_WARN, __VA_ARGS__)
+
+
+DEFINE_DEVICE_TYPE(RTL8029AS_PCI, rtl8029as_pci_device, "rtl8029as_pci", "Realtek RTL8029AS Full-Duplex Ethernet")
+
+
+
+rtl8029as_pci_device::rtl8029as_pci_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : pci_card_device(mconfig, type, tag, owner, clock)
+{
+ set_ids(0x10ec8029, 0x00, 0x020000, 0x10ec8029);
+}
+
+rtl8029as_pci_device::rtl8029as_pci_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : rtl8029as_pci_device(mconfig, RTL8029AS_PCI, tag, owner, clock)
+{
+}
+
+void rtl8029as_pci_device::device_add_mconfig(machine_config &config)
+{
+
+}
+
+void rtl8029as_pci_device::device_start()
+{
+ pci_card_device::device_start();
+
+ // TODO: verify 16 being of the right size
+ // documentation puts 3 bits in BAR0 as size but then all the "pages" are 16,
+ // then one note also claims 32 bytes wtf
+// add_map( 16, M_IO, FUNC(rtl8029as_pci_device::map));
+
+ // INTA#
+ intr_pin = 1;
+}
+
+void rtl8029as_pci_device::device_reset()
+{
+ pci_card_device::device_reset();
+
+ // Not indicated, assume zeroed
+ command = 0x0000;
+ // medium DEVSELB
+ status = 0x0200;
+
+ remap_cb();
+}
+
+void rtl8029as_pci_device::config_map(address_map &map)
+{
+ pci_card_device::config_map(map);
+}
diff --git a/src/devices/bus/pci/rtl8029as_pci.h b/src/devices/bus/pci/rtl8029as_pci.h
new file mode 100644
index 00000000000..103b5198b68
--- /dev/null
+++ b/src/devices/bus/pci/rtl8029as_pci.h
@@ -0,0 +1,38 @@
+// license:BSD-3-Clause
+// copyright-holders:
+
+#ifndef MAME_BUS_PCI_RTL8029AS_PCI_H
+#define MAME_BUS_PCI_RTL8029AS_PCI_H
+
+#pragma once
+
+#include "pci_slot.h"
+
+class rtl8029as_pci_device : public pci_card_device
+{
+public:
+ rtl8029as_pci_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ static constexpr feature_type unemulated_features() { return feature::LAN; }
+
+protected:
+ rtl8029as_pci_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+
+// virtual const tiny_rom_entry *device_rom_region() const override;
+
+// virtual void map_extra(uint64_t memory_window_start, uint64_t memory_window_end, uint64_t memory_offset, address_space *memory_space,
+// uint64_t io_window_start, uint64_t io_window_end, uint64_t io_offset, address_space *io_space) override;
+
+ virtual void config_map(address_map &map) override;
+
+private:
+ // ...
+};
+
+DECLARE_DEVICE_TYPE(RTL8029AS_PCI, rtl8029as_pci_device)
+
+#endif // MAME_NETWORK_RTL8029AS_PCI_H
diff --git a/src/devices/bus/pci/rtl8139_pci.cpp b/src/devices/bus/pci/rtl8139_pci.cpp
new file mode 100644
index 00000000000..d78bbf7e70c
--- /dev/null
+++ b/src/devices/bus/pci/rtl8139_pci.cpp
@@ -0,0 +1,86 @@
+// license:BSD-3-Clause
+// copyright-holders:
+/**************************************************************************************************
+
+Realtek RTL8139C / RTL8139D / RTL8129 (?) PCI ethernet cards
+
+Second gen of Realtek network cards, driving away from the NE2000 design in '8029AS.
+'8139 is considerably popular, being the base of:
+- QEMU Virtual Machine;
+- Dreamcast BroadBand Adapter, thru a G2-to-PCI bridge codenamed GAPS (Sega ID 315-6170).
+https://github.com/sizious/dcload-ip/tree/master
+- And a gazillion of other OEM versions, a partial list at:
+https://admin.pci-ids.ucw.cz/read/PC/10ec/8139
+
+**************************************************************************************************/
+
+#include "emu.h"
+#include "rtl8139_pci.h"
+
+#define LOG_WARN (1U << 1)
+
+#define VERBOSE (LOG_GENERAL | LOG_WARN)
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+#define LOGWARN(...) LOGMASKED(LOG_WARN, __VA_ARGS__)
+
+
+// RTL8129 (?)
+DEFINE_DEVICE_TYPE(RTL8139_PCI, rtl8139_pci_device, "rtl8139_pci", "Realtek RTL8139 PCI Fast Ethernet Adapter card")
+// RTL8139A
+// RTL8139A-G
+// RTL8139B
+// RTL8130
+// RTL8139C
+// RTL8139C+
+// RTL8100
+// RTL8100B / RTL8139D
+// RTL8101
+
+rtl8139_pci_device::rtl8139_pci_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : pci_card_device(mconfig, type, tag, owner, clock)
+{
+ // NOTE: later cards actually pick ups device ID from EEPROM, falling back to 0x8139 if there isn't one
+ // Presumably HWVERID in I/O space tells what kind of device it really is
+ // TODO: pci-ids shows 0139 as 8139 alias
+ // TODO: RTL8139C datasheet claims 8129h as default, assume typo for now
+ set_ids(0x10ec8139, 0x00, 0x020000, 0x10ec8139);
+}
+
+rtl8139_pci_device::rtl8139_pci_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : rtl8139_pci_device(mconfig, RTL8139_PCI, tag, owner, clock)
+{
+}
+
+void rtl8139_pci_device::device_add_mconfig(machine_config &config)
+{
+
+}
+
+void rtl8139_pci_device::device_start()
+{
+ pci_card_device::device_start();
+
+// add_map( 256, M_IO, FUNC(rtl8139_pci_device::ioar_map));
+// add_map( 256, M_MEM, FUNC(rtl8139_pci_device::memar_map));
+
+ // INTA#
+ intr_pin = 1;
+}
+
+void rtl8139_pci_device::device_reset()
+{
+ pci_card_device::device_reset();
+
+ // TODO: strapping options for both command and status
+ command = 0x0000;
+ status = 0x0200;
+
+ remap_cb();
+}
+
+void rtl8139_pci_device::config_map(address_map &map)
+{
+ pci_card_device::config_map(map);
+}
diff --git a/src/devices/bus/pci/rtl8139_pci.h b/src/devices/bus/pci/rtl8139_pci.h
new file mode 100644
index 00000000000..fd46b599726
--- /dev/null
+++ b/src/devices/bus/pci/rtl8139_pci.h
@@ -0,0 +1,38 @@
+// license:BSD-3-Clause
+// copyright-holders:
+
+#ifndef MAME_BUS_PCI_RTL8129_PCI_H
+#define MAME_BUS_PCI_RTL8129_PCI_H
+
+#pragma once
+
+#include "pci_slot.h"
+
+class rtl8139_pci_device : public pci_card_device
+{
+public:
+ rtl8139_pci_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ static constexpr feature_type unemulated_features() { return feature::LAN; }
+
+protected:
+ rtl8139_pci_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+
+// virtual const tiny_rom_entry *device_rom_region() const override;
+
+// virtual void map_extra(uint64_t memory_window_start, uint64_t memory_window_end, uint64_t memory_offset, address_space *memory_space,
+// uint64_t io_window_start, uint64_t io_window_end, uint64_t io_offset, address_space *io_space) override;
+
+ virtual void config_map(address_map &map) override;
+
+private:
+ // ...
+};
+
+DECLARE_DEVICE_TYPE(RTL8139_PCI, rtl8139_pci_device)
+
+#endif // MAME_NETWORK_RTL8129_PCI_H
diff --git a/src/devices/bus/pci/sis6326.cpp b/src/devices/bus/pci/sis6326.cpp
new file mode 100644
index 00000000000..d08001ac4a7
--- /dev/null
+++ b/src/devices/bus/pci/sis6326.cpp
@@ -0,0 +1,202 @@
+// license:BSD-3-Clause
+// copyright-holders: Angelo Salese
+/**************************************************************************************************
+
+SiS 6326
+
+**************************************************************************************************/
+
+#include "emu.h"
+#include "sis6326.h"
+
+#define LOG_WARN (1U << 1)
+#define LOG_AGP (1U << 2)
+
+#define VERBOSE (LOG_GENERAL | LOG_WARN | LOG_AGP)
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+#define LOGWARN(...) LOGMASKED(LOG_WARN, __VA_ARGS__)
+#define LOGAGP(...) LOGMASKED(LOG_AGP, __VA_ARGS__)
+
+
+DEFINE_DEVICE_TYPE(SIS6326_AGP, sis6326_agp_device, "sis6326_agp", "SiS 6326 AGP card")
+
+
+
+sis6326_agp_device::sis6326_agp_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : pci_card_device(mconfig, type, tag, owner, clock)
+ , m_vga(*this, "vga")
+ , m_vga_rom(*this, "vga_rom")
+{
+ set_ids(0x10396326, 0xa0, 0x030000, 0x10396326);
+}
+
+sis6326_agp_device::sis6326_agp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : sis6326_agp_device(mconfig, SIS6326_AGP, tag, owner, clock)
+{
+}
+
+ROM_START( sis6326agp )
+ ROM_REGION32_LE( 0x10000, "vga_rom", ROMREGION_ERASEFF )
+ // Default is AOpen for supporting OpenGL
+ ROM_DEFAULT_BIOS("aopen")
+
+ ROM_SYSTEM_BIOS( 0, "aopen", "AOpen PA50V 2.25" )
+ ROMX_LOAD( "aopenpa50v.vbi", 0x000000, 0x008000, CRC(6c4c7518) SHA1(36bb29a23d565e34d548701acc248d50c99d7da4), ROM_BIOS(0) )
+ ROM_SYSTEM_BIOS( 1, "3dpro", "3DPro 4MB EDO 1.06" )
+ ROMX_LOAD( "3dpro4mbedo.bin", 0x000000, 0x010000, CRC(f04b374c) SHA1(6eb96f7517df6eb566c615c2ab9ec5567035b6a5), ROM_BIOS(1) )
+ ROM_SYSTEM_BIOS( 2, "siso", "SiS6326 4MB 1.21d" )
+ ROMX_LOAD( "4mbsdr.vbi", 0x000000, 0x00c000, CRC(a5f8c7f7) SHA1(9e5cfcf8d34e0c5829343179c87fb2b97f7a7f9c), ROM_BIOS(2) )
+ ROM_SYSTEM_BIOS( 3, "sis", "SiS6326 4MB 1.25" )
+ ROMX_LOAD( "sis6326agp.bin", 0x000000, 0x010000, CRC(a671255c) SHA1(332ab9499142e8f7a235afe046e8e8d21a28580d), ROM_BIOS(3) )
+
+ // basically identical to siso
+// ROM_SYSTEM_BIOS( 3, "sisvbi", "SiS6326 4MB PCI 1.21d" )
+// ROMX_LOAD( "4mb_pci.vbi", 0x000000, 0x00c000, CRC(8fca47be) SHA1(7ce995ec0d8b9ac4f0f40ccd0a61d7fc209d313f), ROM_BIOS(3) )
+ROM_END
+
+const tiny_rom_entry *sis6326_agp_device::device_rom_region() const
+{
+ return ROM_NAME(sis6326agp);
+}
+
+void sis6326_agp_device::device_add_mconfig(machine_config &config)
+{
+ screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
+ screen.set_raw(XTAL(25'174'800), 900, 0, 640, 526, 0, 480);
+ screen.set_screen_update(m_vga, FUNC(sis6236_vga_device::screen_update));
+
+ // TODO: barely similar, to be changed.
+ SIS6236_VGA(config, m_vga, 0);
+ m_vga->set_screen("screen");
+ // 4MB, max 8MB
+ m_vga->set_vram_size(4*1024*1024);
+}
+
+void sis6326_agp_device::device_start()
+{
+ pci_card_device::device_start();
+
+ add_map(4*1024*1024, M_MEM, FUNC(sis6326_agp_device::vram_aperture_map));
+ add_map(64*1024, M_MEM, FUNC(sis6326_agp_device::mmio_map));
+ add_map(16, M_IO, FUNC(sis6326_agp_device::vmi_map));
+
+ add_rom((u8 *)m_vga_rom->base(), 0x10000);
+ expansion_rom_base = 0xc0000;
+
+ // INTA#
+ // TODO: SRE D3 can strap this to no irq pin
+ intr_pin = 1;
+}
+
+void sis6326_agp_device::device_reset()
+{
+ pci_card_device::device_reset();
+
+ // doc makes multiple ninja jumps in messing up these defaults
+ // bus master (hardwired)
+ command = 0x0004;
+ command_mask = 0x23;
+ // medium DEVSEL#, 66 MHz capable, has capabilities list
+ status = 0x0230;
+
+ remap_cb();
+}
+
+u8 sis6326_agp_device::capptr_r()
+{
+ return 0x50;
+}
+
+u32 sis6326_agp_device::agp_command_r(offs_t offset, uint32_t mem_mask)
+{
+ LOGAGP("Read AGP command [$58] %d %d %08x\n", m_agp.enable, m_agp.data_rate, mem_mask);
+ // TODO: enable gets cleared by AGP_RESET, or even from PCI RST#
+ return m_agp.enable << 8 | (m_agp.data_rate & 7);
+}
+
+void sis6326_agp_device::agp_command_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGAGP("Write AGP command [$c8] %08x & %08x\n", data, mem_mask);
+
+ if (ACCESSING_BITS_8_15)
+ {
+ m_agp.enable = bool(BIT(m_agp.enable, 8));
+ LOGAGP("- AGP_ENABLE = %d\n", m_agp.enable);
+ }
+
+ if (ACCESSING_BITS_0_7)
+ {
+ // quick checker, to be translated into an AGP interface
+ std::map<u8, std::string> agp_transfer_rates = {
+ { 0, "(illegal 0)" },
+ { 1, "1X" },
+ { 2, "2X" },
+ { 3, "(illegal 3)" }
+ };
+
+ // make sure the AGP DATA_RATE specs are honored
+ const u8 data_rate = data & 3;
+ LOGAGP("- DATA_RATE = %s enabled=%d\n", agp_transfer_rates.at(data_rate), m_agp.enable);
+ m_agp.data_rate = data_rate;
+ }
+}
+
+void sis6326_agp_device::config_map(address_map &map)
+{
+ pci_card_device::config_map(map);
+ // AGP
+ map(0x50, 0x53).lr32(NAME([] () { return 0x00105c02; } ));
+ map(0x54, 0x57).lr32(NAME([] () { return 0x01000003; } ));
+ map(0x58, 0x5b).rw(FUNC(sis6326_agp_device::agp_command_r), FUNC(sis6326_agp_device::agp_command_w));
+ map(0x5c, 0x5f).lr32(NAME([] () { return 0x00000000; } )); // NULL terminator
+}
+
+void sis6326_agp_device::vram_aperture_map(address_map &map)
+{
+ map(0x0000000, 0x3ffffff).rw(m_vga, FUNC(sis6236_vga_device::mem_linear_r), FUNC(sis6236_vga_device::mem_linear_w));
+}
+
+void sis6326_agp_device::mmio_map(address_map &map)
+{
+}
+
+void sis6326_agp_device::vmi_map(address_map &map)
+{
+}
+
+// TODO: this should really be a subclass of VGA
+void sis6326_agp_device::legacy_memory_map(address_map &map)
+{
+ map(0xa0000, 0xbffff).rw(FUNC(sis6326_agp_device::vram_r), FUNC(sis6326_agp_device::vram_w));
+}
+
+void sis6326_agp_device::legacy_io_map(address_map &map)
+{
+ map(0, 0x02f).m(m_vga, FUNC(sis6236_vga_device::io_map));
+}
+
+uint8_t sis6326_agp_device::vram_r(offs_t offset)
+{
+ return downcast<sis6236_vga_device *>(m_vga.target())->mem_r(offset);
+}
+
+void sis6326_agp_device::vram_w(offs_t offset, uint8_t data)
+{
+ downcast<sis6236_vga_device *>(m_vga.target())->mem_w(offset, data);
+}
+
+void sis6326_agp_device::map_extra(uint64_t memory_window_start, uint64_t memory_window_end, uint64_t memory_offset, address_space *memory_space,
+ uint64_t io_window_start, uint64_t io_window_end, uint64_t io_offset, address_space *io_space)
+{
+ if (BIT(command, 1))
+ {
+ memory_space->install_readwrite_handler(0xa0000, 0xbffff, read8sm_delegate(*this, FUNC(sis6326_agp_device::vram_r)), write8sm_delegate(*this, FUNC(sis6326_agp_device::vram_w)));
+ }
+
+ if (BIT(command, 0))
+ {
+ io_space->install_device(0x03b0, 0x03df, *this, &sis6326_agp_device::legacy_io_map);
+ }
+}
diff --git a/src/devices/bus/pci/sis6326.h b/src/devices/bus/pci/sis6326.h
new file mode 100644
index 00000000000..114e2bedde8
--- /dev/null
+++ b/src/devices/bus/pci/sis6326.h
@@ -0,0 +1,59 @@
+// license:BSD-3-Clause
+// copyright-holders: Angelo Salese
+
+#ifndef MAME_BUS_PCI_SIS6326_H
+#define MAME_BUS_PCI_SIS6326_H
+
+#pragma once
+
+#include "pci_slot.h"
+#include "video/pc_vga_sis.h"
+
+class sis6326_agp_device : public pci_card_device
+{
+public:
+ sis6326_agp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ static constexpr feature_type unemulated_features() { return feature::GRAPHICS; }
+
+protected:
+ sis6326_agp_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+ virtual void map_extra(uint64_t memory_window_start, uint64_t memory_window_end, uint64_t memory_offset, address_space *memory_space,
+ uint64_t io_window_start, uint64_t io_window_end, uint64_t io_offset, address_space *io_space) override;
+
+ virtual void config_map(address_map &map) override;
+
+ virtual u8 capptr_r() override;
+
+ void vram_aperture_map(address_map &map);
+ void mmio_map(address_map &map);
+ void vmi_map(address_map &map);
+private:
+ required_device<sis6236_vga_device> m_vga;
+ required_memory_region m_vga_rom;
+
+ void legacy_memory_map(address_map &map);
+ void legacy_io_map(address_map &map);
+
+ u8 vram_r(offs_t offset);
+ void vram_w(offs_t offset, uint8_t data);
+
+ struct {
+ bool enable = false;
+ u8 data_rate = 0;
+ } m_agp;
+
+ u32 agp_command_r(offs_t offset, uint32_t mem_mask);
+ void agp_command_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
+};
+
+DECLARE_DEVICE_TYPE(SIS6326_AGP, sis6326_agp_device)
+
+#endif // MAME_BUS_PCI_SIS6326_H
diff --git a/src/devices/bus/pci/sonicvibes.cpp b/src/devices/bus/pci/sonicvibes.cpp
new file mode 100644
index 00000000000..6b1f0398824
--- /dev/null
+++ b/src/devices/bus/pci/sonicvibes.cpp
@@ -0,0 +1,163 @@
+// license:BSD-3-Clause
+// copyright-holders:Angelo Salese
+/**************************************************************************************************
+
+S3 Sonic Vibes 86C617 multimedia audio based chipset
+
+First (and only) S3 audio card.
+
+Known subvendor ID cards (from dosdays.co.uk, TODO: subvendor IDs):
+- Turtle Beach Daytona - line out jack, 32Kx8 SRAM chip for reverb effects
+- Aztech SC128 3D (FCC ID: I38-SN97126) - line out jack, no SRAM chip for reverb effects
+- ExpertColor MED6617 - no line out jack, no SRAM chip for reverb effects
+- GVC Media Technology card (FCC ID: M4CS0027) - line out jack, 32Kx8 SRAM chip for reverb effects
+- Ennyah 3D PCI Sound - appears to just be a rebadged ExpertColor MED6617.
+
+Notes:
+- Phoenix BIOSes (such as the one in pcipc) do not set up PnP properly, specifically mapping all
+ the BARs to $fc** ranges in DOS. To fix user needs to preload s3legacy.exe driver, available in
+ ibm5170_cdrom:s3drv21
+
+TODO:
+- Complete BAR mapping and base device hookup;
+- Implement IRQ and DMA routing;
+- Verify that DSP is different than SB Pro;
+- Optional wavetable ROMs (ibm5170_cdrom:s3drv21 have it)
+
+**************************************************************************************************/
+
+#include "emu.h"
+#include "sonicvibes.h"
+
+#include "speaker.h"
+
+#define LOG_WARN (1U << 1)
+
+#define VERBOSE (LOG_GENERAL | LOG_WARN)
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+#define LOGWARN(...) LOGMASKED(LOG_WARN, __VA_ARGS__)
+
+
+// Documentation spells "SonicVibes", on-chip markings says "Sonic Vibes" instead
+DEFINE_DEVICE_TYPE(SONICVIBES, sonicvibes_device, "sonicvibes", "S3 Sonic Vibes 86C617")
+
+
+
+sonicvibes_device::sonicvibes_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : pci_card_device(mconfig, type, tag, owner, clock)
+ , m_opl3(*this, "opl3")
+ , m_joy(*this, "pc_joy")
+{
+ // TODO: return actual subvendor ID
+ set_ids(0x5333ca00, 0x00, 0x040100, 0x5333ca00);
+}
+
+// FIXME: subvendor cards eventually need subclassing, relies on above
+sonicvibes_device::sonicvibes_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : sonicvibes_device(mconfig, SONICVIBES, tag, owner, clock)
+{
+}
+
+void sonicvibes_device::device_add_mconfig(machine_config &config)
+{
+ SPEAKER(config, "lspeaker").front_left();
+ SPEAKER(config, "rspeaker").front_right();
+
+ // TODO: (barely visible) only 24'576 xtal on a Turtle Beach PCB, is it really 12-ish MHz?
+ YMF262(config, m_opl3, XTAL(14'318'181));
+ m_opl3->add_route(0, "lspeaker", 1.0);
+ m_opl3->add_route(1, "rspeaker", 1.0);
+ m_opl3->add_route(2, "lspeaker", 1.0);
+ m_opl3->add_route(3, "rspeaker", 1.0);
+
+// DAC_16BIT_R2R(config, m_ldac, 0).add_route(ALL_OUTPUTS, "lspeaker", 0.5); // unknown DAC
+// DAC_16BIT_R2R(config, m_rdac, 0).add_route(ALL_OUTPUTS, "rspeaker", 0.5); // unknown DAC
+
+ PC_JOY(config, m_joy);
+
+// MIDI_PORT(config, "mdin", midiin_slot, "midiin").rxd_handler().set(FUNC(sb_device::midi_rx_w));
+// MIDI_PORT(config, "mdout", midiout_slot, "midiout");
+}
+
+void sonicvibes_device::device_start()
+{
+ pci_card_device::device_start();
+
+ add_map( 16, M_IO, FUNC(sonicvibes_device::games_legacy_map));
+ add_map( 16, M_IO, FUNC(sonicvibes_device::enhanced_map));
+ add_map( 4, M_IO, FUNC(sonicvibes_device::fm_map));
+ add_map( 4, M_IO, FUNC(sonicvibes_device::midi_map));
+ add_map( 8, M_IO, FUNC(sonicvibes_device::gameport_map));
+
+ // INTA#
+ intr_pin = 1;
+}
+
+void sonicvibes_device::device_reset()
+{
+ pci_card_device::device_reset();
+
+ command = 0x0000;
+ // medium DEVSEL / User Definable Features
+ status = 0x0240;
+
+ remap_cb();
+}
+
+void sonicvibes_device::config_map(address_map &map)
+{
+ pci_card_device::config_map(map);
+// map(0x40, 0x43) DMA_A
+// map(0x48, 0x4b) DMA_C
+ map(0x50, 0x53).lr32(
+ NAME([this] () {
+ LOGWARN("Read reserved register $50\n");
+ return 0x00010000;
+ })
+ );
+// map(0x60, 0x63) Wavetable Memory Base
+}
+
+// 220h
+void sonicvibes_device::games_legacy_map(address_map &map)
+{
+ map(0x00, 0x03).rw(m_opl3, FUNC(ymf262_device::read), FUNC(ymf262_device::write));
+// map(0x04, 0x04) Mixer Register Index (w/o)
+// map(0x05, 0x05) Mixer Register Data
+// map(0x06, 0x06) Reset
+ map(0x08, 0x09).rw(m_opl3, FUNC(ymf262_device::read), FUNC(ymf262_device::write));
+// map(0x0a, 0x0a) Input Data (r/o)
+// map(0x0c, 0x0c) Write Data/Command (w) Write Buffer Status (r)
+// map(0x0e, 0x0e) Read Output Buffer Status (r/o)
+}
+
+// 530h
+void sonicvibes_device::enhanced_map(address_map &map)
+{
+// map(0x00, 0x00) CODEC/Mixer Control
+// map(0x01, 0x01) CODEC/Mixer Interrupt Mask
+// map(0x02, 0x02) CODEC/Mixer Status (r/o)
+
+// map(0x04, 0x04) CODEC/Mixer Index Address
+// map(0x05, 0x05) CODEC/Mixer Index Data
+}
+
+// 388h
+void sonicvibes_device::fm_map(address_map &map)
+{
+ map(0x00, 0x03).rw(m_opl3, FUNC(ymf262_device::read), FUNC(ymf262_device::write));
+}
+
+// 330h
+void sonicvibes_device::midi_map(address_map &map)
+{
+
+}
+
+// 200h
+void sonicvibes_device::gameport_map(address_map &map)
+{
+ map(0x00, 0x07).rw(m_joy, FUNC(pc_joy_device::joy_port_r), FUNC(pc_joy_device::joy_port_w));
+}
diff --git a/src/devices/bus/pci/sonicvibes.h b/src/devices/bus/pci/sonicvibes.h
new file mode 100644
index 00000000000..5e798c6cdaf
--- /dev/null
+++ b/src/devices/bus/pci/sonicvibes.h
@@ -0,0 +1,44 @@
+// license:BSD-3-Clause
+// copyright-holders:Angelo Salese
+
+#ifndef MAME_BUS_PCI_SONICVIBES_H
+#define MAME_BUS_PCI_SONICVIBES_H
+
+#pragma once
+
+#include "pci_slot.h"
+
+#include "bus/pc_joy/pc_joy.h"
+#include "sound/ymopl.h"
+
+
+class sonicvibes_device : public pci_card_device
+{
+public:
+ sonicvibes_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ static constexpr feature_type unemulated_features() { return feature::SOUND; }
+
+protected:
+ sonicvibes_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+
+ virtual void config_map(address_map &map) override;
+
+private:
+ required_device<ymf262_device> m_opl3;
+ required_device<pc_joy_device> m_joy;
+
+ void games_legacy_map(address_map &map);
+ void enhanced_map(address_map &map);
+ void fm_map(address_map &map);
+ void midi_map(address_map &map);
+ void gameport_map(address_map &map);
+};
+
+DECLARE_DEVICE_TYPE(SONICVIBES, sonicvibes_device)
+
+#endif // MAME_BUS_PCI_SONICVIBES_H
diff --git a/src/devices/bus/pci/sw1000xg.cpp b/src/devices/bus/pci/sw1000xg.cpp
new file mode 100644
index 00000000000..99255915915
--- /dev/null
+++ b/src/devices/bus/pci/sw1000xg.cpp
@@ -0,0 +1,94 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+
+#include "emu.h"
+#include "sw1000xg.h"
+#include "speaker.h"
+
+DEFINE_DEVICE_TYPE(SW1000XG, sw1000xg_device, "sw1000xg", "Yamaha SW1000XG")
+
+sw1000xg_device::sw1000xg_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : ymp21_device(mconfig, SW1000XG, tag, owner, clock),
+ m_maincpu(*this, "maincpu"),
+ m_swp30(*this, "swp30")
+{
+ set_ids(0x10731000, 0x00, 0x040100, 0x10731000);
+}
+
+void sw1000xg_device::device_start()
+{
+ ymp21_device::device_start();
+}
+
+void sw1000xg_device::device_reset()
+{
+ ymp21_device::device_reset();
+
+ m_maincpu->set_input_line(0, ASSERT_LINE);
+}
+
+void sw1000xg_device::h8_map(address_map &map)
+{
+ map(0x000000, 0x0fffff).rom().region("maincpu", 0);
+ map(0x200000, 0x21ffff).ram();
+ map(0x400000, 0x401fff).m(m_swp30, FUNC(swp30_device::map));
+}
+
+void sw1000xg_device::swp30_map(address_map &map)
+{
+ // map(0x000000, 0x1fffff).rom().region("swp30", 0).mirror(0x200000);
+ // map(0x400000, 0x4fffff).rom().region("swp30", 0x800000).mirror(0x300000);
+ // map(0x800000, 0x9fffff).rom().region("swp30", 0x1000000).mirror(0x200000);
+}
+
+#define ROM_LOAD16_WORD_SWAP_BIOS(bios,name,offset,length,hash) \
+ ROMX_LOAD(name, offset, length, hash, ROM_GROUPWORD | ROM_REVERSE | ROM_BIOS(bios))
+
+// a0 cards had firmware 1.00.00
+// b0 cards are known to exist but not dumped yet
+// c0 cards are not proven existing
+// d0 cards started with 1.04.00 and the firmware was upgradeable from the PC
+
+ROM_START( sw1000xg )
+ ROM_REGION( 0x100000, "maincpu", 0 )
+ ROM_DEFAULT_BIOS("v166")
+ ROM_SYSTEM_BIOS( 0, "v166", "v1.06.06" )
+ ROM_LOAD16_WORD_SWAP_BIOS( 0, "1.06.06_xv561d0.ic102", 0x000000, 0x100000, CRC(6734482c) SHA1(dff42c0f0ad0f0ec9587cd2a53ba2b3836b1d587) )
+ ROM_SYSTEM_BIOS( 1, "v161", "v1.06.01" )
+ ROM_LOAD16_WORD_SWAP_BIOS( 1, "1.06.01_xv561d0.ic102", 0x000000, 0x100000, CRC(c788aa9e) SHA1(d0861e9604a8e92f6adfc451e97d62d49d40f033) )
+ ROM_SYSTEM_BIOS( 2, "v152", "v1.05.02" )
+ ROM_LOAD16_WORD_SWAP_BIOS( 2, "1.05.02_xv561d0.ic102", 0x000000, 0x100000, CRC(9152a052) SHA1(20759f4047f8dc3cb21efef538f78393d7a68521) )
+ ROM_SYSTEM_BIOS( 3, "v150", "v1.05.00" )
+ ROM_LOAD16_WORD_SWAP_BIOS( 3, "1.05.00_xv561d0.ic102", 0x000000, 0x100000, CRC(36e199df) SHA1(efe2d3000b49a4a93705fee5ffd5456953ef5a22) )
+ ROM_SYSTEM_BIOS( 4, "v140", "v1.04.00" )
+ ROM_LOAD16_WORD_SWAP_BIOS( 4, "1.04.00_xv561d0.ic102", 0x000000, 0x100000, CRC(9f5bfec8) SHA1(4ced122c8cac7a9c022d86fffe121042ad4be6a2) )
+ ROM_SYSTEM_BIOS( 5, "v100", "v1.00.00" )
+ ROM_LOAD16_WORD_SWAP_BIOS( 5, "1.00.00_xv561a0.ic102", 0x000000, 0x100000, CRC(9b6d8700) SHA1(0bb6c60572b9ed1628fa9e6678e03bd1e47f2a06) )
+
+ ROM_REGION( 0x1400000, "swp30", 0 )
+ ROM_LOAD32_WORD( "xv389a0.ic122", 0x0000000, 0x800000, CRC(92e11205) SHA1(72ec39e03e4e5ddf6137faa798c0ec3c23905855) )
+ ROM_LOAD32_WORD( "xv390a0.ic121", 0x0000002, 0x800000, CRC(cbc80585) SHA1(1903ed7f1292e6117a448fec19e2b712f3815964) )
+ ROM_LOAD32_WORD( "xt445a0-828.ic124", 0x0800000, 0x200000, CRC(225c2280) SHA1(23b5e046fd2e2ac01af3e6dc6357c5c6547b286b) )
+ ROM_LOAD32_WORD( "xt461a0-829.ic123", 0x0800002, 0x200000, CRC(a1d138a3) SHA1(46a7a7225cd7e1818ba551325d2af5ac1bf5b2bf) )
+
+ROM_END
+
+const tiny_rom_entry *sw1000xg_device::device_rom_region() const
+{
+ return ROM_NAME(sw1000xg);
+}
+
+void sw1000xg_device::device_add_mconfig(machine_config &config)
+{
+ H83002(config, m_maincpu, 16_MHz_XTAL);
+ m_maincpu->set_addrmap(AS_PROGRAM, &sw1000xg_device::h8_map);
+
+ SPEAKER(config, "lspeaker").front_left();
+ SPEAKER(config, "rspeaker").front_right();
+
+ SWP30(config, m_swp30);
+ m_swp30->set_addrmap(AS_DATA, &sw1000xg_device::swp30_map);
+ m_swp30->add_route(0, "lspeaker", 1.0);
+ m_swp30->add_route(1, "rspeaker", 1.0);
+}
+
diff --git a/src/devices/bus/pci/sw1000xg.h b/src/devices/bus/pci/sw1000xg.h
new file mode 100644
index 00000000000..1ef7bdf4e2b
--- /dev/null
+++ b/src/devices/bus/pci/sw1000xg.h
@@ -0,0 +1,35 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+
+#ifndef MAME_BUS_PCI_SW1000XG_H
+#define MAME_BUS_PCI_SW1000XG_H
+
+#pragma once
+
+#include "ymp21.h"
+
+#include "cpu/h8/h83002.h"
+#include "sound/swp30.h"
+
+
+class sw1000xg_device : public ymp21_device {
+public:
+ sw1000xg_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
+
+protected:
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override;
+
+private:
+ required_device<h83002_device> m_maincpu;
+ required_device<swp30_device> m_swp30;
+
+ void h8_map(address_map &map);
+ void swp30_map(address_map &map);
+};
+
+DECLARE_DEVICE_TYPE(SW1000XG, sw1000xg_device)
+
+#endif
diff --git a/src/devices/bus/pci/virge_pci.cpp b/src/devices/bus/pci/virge_pci.cpp
new file mode 100644
index 00000000000..ae3d7b56662
--- /dev/null
+++ b/src/devices/bus/pci/virge_pci.cpp
@@ -0,0 +1,251 @@
+// license:BSD-3-Clause
+// copyright-holders:Barry Rodewald
+
+
+#include "emu.h"
+#include "virge_pci.h"
+
+#include "screen.h"
+
+virge_pci_device::virge_pci_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : virge_pci_device(mconfig, VIRGE_PCI, tag, owner, clock)
+{
+}
+
+virge_pci_device::virge_pci_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : pci_card_device(mconfig, type, tag, owner, clock),
+ m_vga(*this, "vga"),
+ m_bios(*this, "bios"),
+ m_screen(*this, finder_base::DUMMY_TAG)
+{
+}
+
+virgedx_pci_device::virgedx_pci_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : virge_pci_device(mconfig, VIRGEDX_PCI, tag, owner, clock)
+{
+}
+
+// TODO: this is repeated in old MMIO mode inside the VGA legacy memory space
+void virge_pci_device::mmio_map(address_map& map)
+{
+ // image transfer ports
+ map(0x0000,0x7fff).w(m_vga, FUNC(s3virge_vga_device::image_xfer));
+
+ //map(0x8180,0x81ff) primary/secondary stream control
+
+ //map(0x8200,0x821f) memory port controller
+ //map(0x8220,0x8227) DMA control
+
+ // MMIO address map
+ map(0x83b0,0x83df).m(m_vga, FUNC(s3virge_vga_device::io_map));
+ map(0x8504,0x8507).rw(m_vga, FUNC(s3virge_vga_device::s3d_sub_status_r), FUNC(s3virge_vga_device::s3d_sub_control_w));
+ map(0x850c,0x850f).r(m_vga, FUNC(s3virge_vga_device::s3d_func_ctrl_r));
+
+ //map(0x8580,0x858b) video DMA
+ //map(0x8590,0x859f) command DMA
+
+ // S3D engine registers
+ map(0xa000,0xb7ff).rw(m_vga, FUNC(s3virge_vga_device::s3d_register_r), FUNC(s3virge_vga_device::s3d_register_w));
+
+ // alternate image transfer ports
+ map(0xd000,0xefff).w(m_vga, FUNC(s3virge_vga_device::image_xfer));
+
+ //map(0xff00, 0xff43) LPB control
+}
+
+void virge_pci_device::lfb_map(address_map& map)
+{
+ map(0x0, 0x00ffffff).rw(m_vga, FUNC(s3virge_vga_device::fb_r), FUNC(s3virge_vga_device::fb_w));
+}
+
+void virge_pci_device::config_map(address_map &map)
+{
+ pci_card_device::config_map(map);
+ map(0x10, 0x13).rw(FUNC(virge_pci_device::base_address_r),FUNC(virge_pci_device::base_address_w));
+}
+
+void virge_pci_device::legacy_io_map(address_map &map)
+{
+ map(0x00, 0x2f).m(m_vga, FUNC(s3virge_vga_device::io_map));
+}
+
+// FIXME: belongs to s3virge_vga_device.
+u32 virge_pci_device::get_vga_linear_address()
+{
+ switch(downcast<s3virge_vga_device *>(m_vga.target())->get_linear_address_size() & 0x03)
+ {
+ case LAW_64K:
+ return downcast<s3virge_vga_device *>(m_vga.target())->get_linear_address() & 0xffff0000;
+
+ case LAW_1MB:
+ return downcast<s3virge_vga_device *>(m_vga.target())->get_linear_address() & 0xfff00000;
+
+ case LAW_2MB:
+ return downcast<s3virge_vga_device *>(m_vga.target())->get_linear_address() & 0xffe00000;
+
+ default:
+ case LAW_4MB:
+ return downcast<s3virge_vga_device *>(m_vga.target())->get_linear_address() & 0xffc00000;
+ }
+}
+
+void virge_pci_device::refresh_linear_window()
+{
+ if(downcast<s3virge_vga_device *>(m_vga.target())->is_linear_address_active())
+ {
+ set_map_flags(0, M_MEM);
+ const u32 get_bar_address = get_vga_linear_address();
+ logerror("Linear window set to 0x%08x\n", get_bar_address);
+ set_map_address(0, get_bar_address);
+ remap_cb();
+ }
+ else
+ {
+ set_map_flags(0, M_MEM | M_DISABLED);
+ remap_cb();
+ }
+}
+
+uint32_t virge_pci_device::base_address_r()
+{
+ return downcast<s3virge_vga_device *>(m_vga.target())->get_linear_address();
+}
+
+void virge_pci_device::base_address_w(offs_t offset, uint32_t data)
+{
+ pci_device::address_base_w(offset,data);
+ // only bits 31-26 are changed here, cfr. page 25-4
+ const u32 new_address = (data & 0xfc000000) | (base_address_r() & 0x3ffffff);
+ downcast<s3virge_vga_device *>(m_vga.target())->set_linear_address(new_address);
+ refresh_linear_window();
+}
+
+void virge_pci_device::linear_config_changed_w(int state)
+{
+ refresh_linear_window();
+ remap_cb();
+}
+
+uint8_t virge_pci_device::vram_r(offs_t offset)
+{
+ return downcast<s3virge_vga_device *>(m_vga.target())->mem_r(offset);
+}
+
+void virge_pci_device::vram_w(offs_t offset, uint8_t data)
+{
+ downcast<s3virge_vga_device *>(m_vga.target())->mem_w(offset, data);
+}
+
+void virge_pci_device::postload()
+{
+ remap_cb();
+}
+
+void virge_pci_device::device_start()
+{
+ set_ids(0x53335631, 0x00, 0x030000, 0x000000);
+ pci_card_device::device_start();
+
+ add_rom(m_bios->base(),0x8000);
+ expansion_rom_base = 0xc0000;
+
+ add_map(64 * 1024 * 1024, M_MEM | M_DISABLED, FUNC(virge_pci_device::lfb_map));
+ set_map_address(0, 0x70000000);
+
+ remap_cb();
+ machine().save().register_postload(save_prepost_delegate(FUNC(virge_pci_device::postload), this));
+}
+
+void virgedx_pci_device::device_start()
+{
+ set_ids(0x53338a01, 0x00, 0x030000, 0x000000);
+ pci_card_device::device_start();
+
+ add_rom(m_bios->base(),0x8000);
+ expansion_rom_base = 0xc0000;
+
+ add_map(64 * 1024 * 1024, M_MEM | M_DISABLED, FUNC(virge_pci_device::lfb_map));
+ set_map_address(0, 0x70000000);
+
+ remap_cb();
+ machine().save().register_postload(save_prepost_delegate(FUNC(virgedx_pci_device::postload), this));
+}
+
+void virge_pci_device::map_extra(uint64_t memory_window_start, uint64_t memory_window_end, uint64_t memory_offset, address_space *memory_space,
+ uint64_t io_window_start, uint64_t io_window_end, uint64_t io_offset, address_space *io_space)
+{
+ memory_space->install_readwrite_handler(0xa0000, 0xbffff, read8sm_delegate(*this, FUNC(virge_pci_device::vram_r)), write8sm_delegate(*this, FUNC(virge_pci_device::vram_w)));
+
+ io_space->install_device(0x03b0, 0x03df, *this, &virge_pci_device::legacy_io_map);
+
+ // NOTE: this looks unrelated to the linear addressing
+ // xubuntu 6.10 and BeOS 3.x definitely wants it this way.
+ if(downcast<s3virge_vga_device *>(m_vga.target())->is_new_mmio_active())
+ {
+ const u32 get_bar_address = get_vga_linear_address() | 0x01000000;
+
+ memory_space->install_device(get_bar_address, get_bar_address | 0xffff, *this, &virge_pci_device::mmio_map);
+ }
+}
+
+void virge_pci_device::device_add_mconfig(machine_config &config)
+{
+ screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
+ screen.set_raw(XTAL(25'174'800), 900, 0, 640, 526, 0, 480);
+ screen.set_screen_update("vga", FUNC(s3virge_vga_device::screen_update));
+
+ S3VIRGE(config, m_vga, 0);
+ m_vga->set_screen("screen");
+ m_vga->set_vram_size(0x400000);
+ m_vga->linear_config_changed().set(FUNC(virge_pci_device::linear_config_changed_w));
+}
+
+void virgedx_pci_device::device_add_mconfig(machine_config &config)
+{
+ screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
+ screen.set_raw(XTAL(25'174'800), 900, 0, 640, 526, 0, 480);
+ screen.set_screen_update("vga", FUNC(s3virge_vga_device::screen_update));
+
+ S3VIRGEDX(config, m_vga, 0);
+ m_vga->set_screen("screen");
+ m_vga->set_vram_size(0x400000);
+ m_vga->linear_config_changed().set(FUNC(virgedx_pci_device::linear_config_changed_w));
+}
+
+
+ROM_START( virge_pci )
+ ROM_REGION(0x8000,"bios", 0)
+ ROM_DEFAULT_BIOS("virge")
+
+ ROM_SYSTEM_BIOS( 0, "virge", "S3 ViRGE v1.00-10" )
+ ROMX_LOAD("pci_m-v_virge-4s3.bin", 0x00000, 0x8000, CRC(d0a0f1de) SHA1(b7b41081974762a199610219bdeab149b7c7143d), ROM_BIOS(0) )
+
+ ROM_SYSTEM_BIOS( 1, "virgeo", "S3 ViRGE v1.00-05" )
+ ROMX_LOAD("s3virge.bin", 0x00000, 0x8000, CRC(a7983a85) SHA1(e885371816d3237f7badd57ccd602cd863c9c9f8), ROM_BIOS(1) )
+ ROM_IGNORE( 0x8000 )
+ROM_END
+
+ROM_START( virgedx_pci )
+ ROM_REGION(0x8000,"bios", 0)
+ ROM_DEFAULT_BIOS("virgedx")
+
+ ROM_SYSTEM_BIOS( 0, "virgedx", "S3 ViRGE/DX v2.01.13" )
+ ROMX_LOAD("s3virgedx.bin", 0x00000, 0x8000, CRC(0da83bd3) SHA1(228a2d644e1732cb5a2eb1291608c7050cf39229), ROM_BIOS(0) )
+
+ ROM_SYSTEM_BIOS( 1, "dms3d2kp", "Diamond Stealth 3D 2000 Pro v3.04" )
+ ROMX_LOAD("virgedxdiamond.bin", 0x00000, 0x8000, CRC(58b0dcda) SHA1(b13ae6b04db6fc05a76d924ddf2efe150b823029), ROM_BIOS(1) )
+ROM_END
+
+const tiny_rom_entry *virge_pci_device::device_rom_region() const
+{
+ return ROM_NAME( virge_pci );
+}
+
+const tiny_rom_entry *virgedx_pci_device::device_rom_region() const
+{
+ return ROM_NAME( virgedx_pci );
+}
+
+DEFINE_DEVICE_TYPE(VIRGE_PCI, virge_pci_device, "virge_pci", "S3 86C325 ViRGE")
+DEFINE_DEVICE_TYPE(VIRGEDX_PCI, virgedx_pci_device, "virgedx_pci", "S3 86C375 ViRGE/DX")
+//VIRGEGX_PCI, /DX with SGRAM/SDRAM support
diff --git a/src/devices/bus/pci/virge_pci.h b/src/devices/bus/pci/virge_pci.h
new file mode 100644
index 00000000000..d820e686514
--- /dev/null
+++ b/src/devices/bus/pci/virge_pci.h
@@ -0,0 +1,93 @@
+// license:BSD-3-Clause
+// copyright-holders:Barry Rodewald
+
+/*
+ * S3 ViRGE 3D accelerator card
+ */
+
+#ifndef MAME_BUS_PCI_VIRGE_PCI_H
+#define MAME_BUS_PCI_VIRGE_PCI_H
+
+#pragma once
+
+#include "pci_slot.h"
+#include "video/s3virge.h"
+
+class virge_pci_device : public pci_card_device
+{
+public:
+ template <typename T>
+ virge_pci_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&screen_tag)
+ : virge_pci_device(mconfig, tag, owner, clock)
+ {
+ set_screen_tag(std::forward<T>(screen_tag));
+ }
+
+ enum
+ {
+ LAW_64K = 0,
+ LAW_1MB,
+ LAW_2MB,
+ LAW_4MB
+ };
+
+ virge_pci_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+ virge_pci_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ void lfb_map(address_map &map);
+ void mmio_map(address_map& map);
+
+ uint8_t vram_r(offs_t offset);
+ void vram_w(offs_t offset, uint8_t data);
+ uint32_t base_address_r();
+ void base_address_w(offs_t offset, uint32_t data);
+
+ void legacy_io_map(address_map &map);
+
+protected:
+ virtual void device_start() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+ virtual void map_extra(uint64_t memory_window_start, uint64_t memory_window_end, uint64_t memory_offset, address_space *memory_space,
+ uint64_t io_window_start, uint64_t io_window_end, uint64_t io_offset, address_space *io_space) override;
+ virtual void config_map(address_map &map) override;
+
+ void postload(void);
+
+ required_device<s3virge_vga_device> m_vga;
+ required_memory_region m_bios;
+ optional_device<screen_device> m_screen;
+
+ void linear_config_changed_w(int state);
+
+private:
+ void refresh_linear_window();
+ u32 get_vga_linear_address();
+};
+
+class virgedx_pci_device : public virge_pci_device
+{
+public:
+ template <typename T>
+ virgedx_pci_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&screen_tag)
+ : virgedx_pci_device(mconfig, tag, owner, clock)
+ {
+ set_screen_tag(std::forward<T>(screen_tag));
+ }
+ virgedx_pci_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual void device_start() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+// required_device<s3virge_vga_device> m_vga;
+// required_memory_region m_bios;
+// optional_device<screen_device> m_screen;
+};
+
+DECLARE_DEVICE_TYPE(VIRGE_PCI, virge_pci_device)
+DECLARE_DEVICE_TYPE(VIRGEDX_PCI, virgedx_pci_device)
+
+#endif
diff --git a/src/devices/bus/pci/vision.cpp b/src/devices/bus/pci/vision.cpp
new file mode 100644
index 00000000000..ab21fecfa68
--- /dev/null
+++ b/src/devices/bus/pci/vision.cpp
@@ -0,0 +1,286 @@
+// license:BSD-3-Clause
+// copyright-holders: Angelo Salese
+/**************************************************************************************************
+
+S3 Vision 864 / 868 / 964 / 968
+
+TODO:
+- Add Vision868
+- Add Trio32/Trio64, pillage roms from isa/svga_s3
+- Make ViRGE to derive from here rather than reinventing the wheel
+
+Notes:
+- Some of these BIOSes are buggy in SDD VBETEST.EXE, doesn't return any video mode,
+ Reportedly mirocrys (vision964) and no9fx771 (vision968) has this inconvenient.
+
+**************************************************************************************************/
+
+#include "emu.h"
+#include "vision.h"
+
+#define LOG_WARN (1U << 1)
+
+#define VERBOSE (LOG_GENERAL | LOG_WARN)
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+#define LOGWARN(...) LOGMASKED(LOG_WARN, __VA_ARGS__)
+
+
+DEFINE_DEVICE_TYPE(VISION864_PCI, vision864_pci_device, "vision864", "S3 86C864 Vision864")
+// Vision868
+DEFINE_DEVICE_TYPE(VISION964_PCI, vision964_pci_device, "vision964", "S3 86C964 Vision964")
+DEFINE_DEVICE_TYPE(VISION968_PCI, vision968_pci_device, "vision968", "S3 86C968 Vision968")
+
+
+
+vision864_pci_device::vision864_pci_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : pci_card_device(mconfig, type, tag, owner, clock)
+ , m_vga(*this, "vga")
+ , m_bios(*this, "bios")
+{
+}
+
+vision864_pci_device::vision864_pci_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : vision864_pci_device(mconfig, VISION864_PCI, tag, owner, clock)
+{
+ // device IDs:
+ // 88c0 = 86c864 DRAM v0
+ // 88c1 = 86c864 DRAM v1
+ // 88c2 = 86c864-P DRAM v2
+ // 88c3 = 86c864-P DRAM v3
+ // NOTE: class code = 0 (backward compatible VGA device)
+ set_ids(0x533388c1, 0x00, 0x000100, 0x00000000);
+}
+
+ROM_START( vision864 )
+ ROM_REGION32_LE( 0x8000, "bios", ROMREGION_ERASEFF )
+ ROM_SYSTEM_BIOS( 0, "vision864", "Phoenix S3 Vision864 1.04-01" )
+ ROMX_LOAD( "bios.bin", 0x0000, 0x8000, CRC(791c9e0d) SHA1(340a64402958d2ee734d929dfce147d9afcf23f4), ROM_BIOS(0) )
+ ROM_IGNORE( 0x8000 )
+ROM_END
+
+const tiny_rom_entry *vision864_pci_device::device_rom_region() const
+{
+ return ROM_NAME(vision864);
+}
+
+void vision864_pci_device::device_add_mconfig(machine_config &config)
+{
+ screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
+ screen.set_raw(XTAL(25'174'800), 900, 0, 640, 526, 0, 480);
+ screen.set_screen_update("vga", FUNC(s3vision864_vga_device::screen_update));
+
+ S3_VISION864_VGA(config, m_vga, 0);
+ m_vga->set_screen("screen");
+ // 1MB, option for 2MB
+ m_vga->set_vram_size(2*1024*1024);
+}
+
+void vision864_pci_device::device_start()
+{
+ pci_card_device::device_start();
+
+// add_map(64 * 1024 * 1024, M_MEM | M_DISABLED, FUNC(vision864_pci_device::lfb_map));
+// set_map_address(0, 0x70000000);
+
+ add_rom((u8 *)m_bios->base(), 0x8000);
+ expansion_rom_base = 0xc0000;
+
+ // TODO: can't read the intr pin reg but still has an INTA#
+}
+
+void vision864_pci_device::device_reset()
+{
+ pci_card_device::device_reset();
+
+ command = 0x0020;
+ command_mask = 0x23;
+ // Medium DEVSEL
+ status = 0x0200;
+
+ remap_cb();
+}
+
+void vision864_pci_device::legacy_io_map(address_map &map)
+{
+ map(0, 0x02f).m(m_vga, FUNC(s3vision864_vga_device::io_map));
+}
+
+uint8_t vision864_pci_device::vram_r(offs_t offset)
+{
+ return downcast<s3vision864_vga_device *>(m_vga.target())->mem_r(offset);
+}
+
+void vision864_pci_device::vram_w(offs_t offset, uint8_t data)
+{
+ downcast<s3vision864_vga_device *>(m_vga.target())->mem_w(offset, data);
+}
+
+void vision864_pci_device::map_extra(uint64_t memory_window_start, uint64_t memory_window_end, uint64_t memory_offset, address_space *memory_space,
+ uint64_t io_window_start, uint64_t io_window_end, uint64_t io_offset, address_space *io_space)
+{
+ if (BIT(command, 1))
+ {
+ memory_space->install_readwrite_handler(0xa0000, 0xbffff, read8sm_delegate(*this, FUNC(vision864_pci_device::vram_r)), write8sm_delegate(*this, FUNC(vision864_pci_device::vram_w)));
+ }
+
+ if (BIT(command, 0))
+ {
+ io_space->install_device(0x03b0, 0x03df, *this, &vision864_pci_device::legacy_io_map);
+ }
+}
+
+/******************
+ *
+ * Vision964
+ *
+ *****************/
+
+vision964_pci_device::vision964_pci_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : vision864_pci_device(mconfig, type, tag, owner, clock)
+{
+}
+
+vision964_pci_device::vision964_pci_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : vision964_pci_device(mconfig, VISION964_PCI, tag, owner, clock)
+{
+ // device IDs:
+ // 88d0-88d1 = 86c964 VRAM v0-1
+ // 88d2-88d3 = 86c964-P VRAM v2-3
+ // NOTE: class code = 0 (backward compatible VGA device)
+ set_ids(0x533388d0, 0x00, 0x000100, 0x00000000);
+}
+
+ROM_START( vision964 )
+ ROM_REGION32_LE( 0x8000, "bios", ROMREGION_ERASEFF )
+ ROM_DEFAULT_BIOS("mirocrys")
+
+ ROM_SYSTEM_BIOS( 0, "mirocrys", "miroCRYSTAL Rev.2.13" )
+ ROMX_LOAD( "mirocrystal.vbi", 0x0000, 0x8000, CRC(d0b0aa1c) SHA1(004e2432c4783f1539a7989e7d9ee422df09e695), ROM_BIOS(0) )
+ROM_END
+
+const tiny_rom_entry *vision964_pci_device::device_rom_region() const
+{
+ return ROM_NAME(vision964);
+}
+
+void vision964_pci_device::device_add_mconfig(machine_config &config)
+{
+ screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
+ screen.set_raw(XTAL(25'174'800), 900, 0, 640, 526, 0, 480);
+ screen.set_screen_update("vga", FUNC(s3vision964_vga_device::screen_update));
+
+ S3_VISION964_VGA(config, m_vga, 0);
+ m_vga->set_screen("screen");
+ // 2MB/4MB/8MB
+ m_vga->set_vram_size(4*1024*1024);
+}
+
+
+/******************
+ *
+ * Vision968
+ *
+ *****************/
+
+vision968_pci_device::vision968_pci_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : vision964_pci_device(mconfig, VISION968_PCI, tag, owner, clock)
+{
+ // device IDs:
+ // 88f0-88f3 = 86c968 RAM v0-3
+ // first device to actually have a real class code
+ set_ids(0x533388f0, 0x00, 0x030000, 0x00000000);
+}
+
+ROM_START( vision968 )
+ ROM_REGION32_LE( 0x8000, "bios", ROMREGION_ERASEFF )
+ ROM_DEFAULT_BIOS("elsaw2k")
+
+ ROM_SYSTEM_BIOS( 0, "no9fx771", "Number Nine 9FX MotionFX 771 v2.45.11" )
+ ROMX_LOAD( "no9motionfx771.bin", 0x0000, 0x8000, CRC(7732e382) SHA1(9ec2fe056712cef39bd8380d406be3c874ea5ec9), ROM_BIOS(0) )
+ ROM_IGNORE( 0x8000 )
+
+ ROM_SYSTEM_BIOS( 1, "elsaw2k", "Elsa Winner 2000Pro/X-8 v1.21.01-B" )
+ ROMX_LOAD( "elsaw20008m.bin", 0x0000, 0x8000, CRC(47563211) SHA1(f51a40956c3e6e7c86851d81f81ba5f77509d361), ROM_BIOS(1) )
+ ROM_IGNORE( 0x8000 )
+
+ ROM_SYSTEM_BIOS( 2, "speamp64", "SPEA/Videoseven V7-Mercury P-64 v1.01-08" )
+ ROMX_LOAD( "spea.bin", 0x0000, 0x8000, CRC(2caeadaf) SHA1(236829f1e6065a2f0ebee91f71891d8402f0ab5a), ROM_BIOS(2) )
+ ROM_IGNORE( 0x8000 )
+ROM_END
+
+const tiny_rom_entry *vision968_pci_device::device_rom_region() const
+{
+ return ROM_NAME(vision968);
+}
+
+void vision968_pci_device::device_add_mconfig(machine_config &config)
+{
+ screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
+ screen.set_raw(XTAL(25'174'800), 900, 0, 640, 526, 0, 480);
+ screen.set_screen_update("vga", FUNC(s3vision968_vga_device::screen_update));
+
+ S3_VISION968_VGA(config, m_vga, 0);
+ m_vga->set_screen("screen");
+ // 2MB/4MB/8MB
+ m_vga->set_vram_size(4*1024*1024);
+// m_vga->linear_config_changed().set(FUNC(s3vision864_vga_device::linear_config_changed_w));
+}
+
+void vision968_pci_device::device_start()
+{
+ pci_card_device::device_start();
+
+// add_map(64 * 1024 * 1024, M_MEM | M_DISABLED, FUNC(vision968_pci_device::lfb_map));
+ add_map(64 * 1024 * 1024, M_MEM, FUNC(vision968_pci_device::lfb_map));
+ set_map_address(0, 0x70000000);
+
+ add_rom((u8 *)m_bios->base(), 0x8000);
+ expansion_rom_base = 0xc0000;
+
+ // INTA#
+ intr_pin = 1;
+}
+
+void vision968_pci_device::device_reset()
+{
+ pci_card_device::device_reset();
+
+ command = 0x0020;
+ command_mask = 0x23;
+ // Adds fast back-to-back
+ status = 0x0280;
+
+ remap_cb();
+}
+
+// TODO: 0x0200'0000 "mirror" (really an endian relocation?)
+void vision968_pci_device::lfb_map(address_map &map)
+{
+ map(0x0000'0000, 0x00ff'ffff).rw(m_vga, FUNC(s3vision864_vga_device::mem_linear_r), FUNC(s3vision864_vga_device::mem_linear_w));
+// map(0x0100'0000, 0x0100'7fff) image transfer data
+ map(0x0100'8000, 0x0100'803f).m(FUNC(vision968_pci_device::config_map));
+// map(0x0100'8100, 0x0100'816f) packed copro regs
+// map(0x0100'82e8, 0x0100'82e8) current ypos
+// map(0x0100'82ea, 0x0100'82ea) current ypos-2
+ map(0x0100'83b0, 0x0100'83df).m(m_vga, FUNC(s3vision968_vga_device::io_map));
+// map(0x0100'8502, 0x0100'8502) (VGA $0102 alias)
+// map(0x0100'8504, 0x0100'8504) (VGA $42e8 alias)
+// map(0x0100'8508, 0x0100'8508) (VGA $46e8 alias)
+// map(0x0100'850c, 0x0100'850c) (VGA $4ae8 alias)
+// map(0x0100'86e8, 0x0100'8eea) PnP copro region
+// map(0x0101'0000, 0x0101'3fff) Pixel formatter data transfer
+// map(0x0101'4000, 0x0101'7fff) Pixel formatter Mask data
+// map(0x0101'8080, 0x0101'809f) Pixel formatter regs
+}
+
+void vision968_pci_device::map_extra(uint64_t memory_window_start, uint64_t memory_window_end, uint64_t memory_offset, address_space *memory_space,
+ uint64_t io_window_start, uint64_t io_window_end, uint64_t io_offset, address_space *io_space)
+{
+ vision964_pci_device::map_extra(
+ memory_window_start, memory_window_end, memory_offset, memory_space,
+ io_window_start, io_window_end, io_offset, io_space
+ );
+ // TODO: new MMIO goes here
+}
diff --git a/src/devices/bus/pci/vision.h b/src/devices/bus/pci/vision.h
new file mode 100644
index 00000000000..f1e9439ddb6
--- /dev/null
+++ b/src/devices/bus/pci/vision.h
@@ -0,0 +1,76 @@
+// license:BSD-3-Clause
+// copyright-holders: Angelo Salese
+
+#ifndef MAME_BUS_PCI_S3VISION_PCI_H
+#define MAME_BUS_PCI_S3VISION_PCI_H
+
+#pragma once
+
+#include "pci_slot.h"
+
+#include "video/pc_vga_s3.h"
+
+class vision864_pci_device : public pci_card_device
+{
+public:
+ vision864_pci_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ static constexpr feature_type imperfect_features() { return feature::GRAPHICS; }
+
+ void legacy_io_map(address_map &map);
+
+protected:
+ vision864_pci_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+ virtual void map_extra(uint64_t memory_window_start, uint64_t memory_window_end, uint64_t memory_offset, address_space *memory_space,
+ uint64_t io_window_start, uint64_t io_window_end, uint64_t io_offset, address_space *io_space) override;
+
+ required_device<s3vision864_vga_device> m_vga;
+ required_memory_region m_bios;
+private:
+ u8 vram_r(offs_t offset);
+ void vram_w(offs_t offset, uint8_t data);
+};
+
+class vision964_pci_device : public vision864_pci_device
+{
+public:
+ vision964_pci_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ vision964_pci_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void device_add_mconfig(machine_config &config) override;
+
+ virtual const tiny_rom_entry *device_rom_region() const override;
+};
+
+class vision968_pci_device : public vision964_pci_device
+{
+public:
+ vision968_pci_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override;
+
+ virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ virtual void map_extra(uint64_t memory_window_start, uint64_t memory_window_end, uint64_t memory_offset, address_space *memory_space,
+ uint64_t io_window_start, uint64_t io_window_end, uint64_t io_offset, address_space *io_space) override;
+
+ void lfb_map(address_map &map);
+};
+
+DECLARE_DEVICE_TYPE(VISION864_PCI, vision864_pci_device)
+DECLARE_DEVICE_TYPE(VISION964_PCI, vision964_pci_device)
+DECLARE_DEVICE_TYPE(VISION968_PCI, vision968_pci_device)
+
+#endif // MAME_BUS_PCI_S3VISION_PCI_H
diff --git a/src/devices/bus/pci/vt6306.cpp b/src/devices/bus/pci/vt6306.cpp
new file mode 100644
index 00000000000..4af9cd01c48
--- /dev/null
+++ b/src/devices/bus/pci/vt6306.cpp
@@ -0,0 +1,97 @@
+// license:BSD-3-Clause
+// copyright-holders:
+/**************************************************************************************************
+
+VIA VT6306 generic FireWire IEEE 1394a card
+
+- paired with USB 2.0 controller on a Sunix UFC3212V 4x USB 3x Firewire card
+ (as multifunction, at .3 while USB takes .0/.1/.2)
+- midway/midzeus.cpp crusnexo/thegrid uses regular IEEE 1394 ports.
+- skeleton/pegasos2.cpp uses an on-board version of this.
+- PHY has default vendor ID=0x004063, device ID=306000, Compliance Level=1
+
+**************************************************************************************************/
+
+#include "emu.h"
+#include "vt6306.h"
+
+#define LOG_WARN (1U << 1)
+
+#define VERBOSE (LOG_GENERAL | LOG_WARN)
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+#define LOGWARN(...) LOGMASKED(LOG_WARN, __VA_ARGS__)
+
+
+DEFINE_DEVICE_TYPE(VT6306_PCI, vt6306_device, "vt6306", "VT6306 VIA Fire II IEEE-1394a OHCI Link Layer Controller")
+
+
+
+vt6306_device::vt6306_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : pci_card_device(mconfig, type, tag, owner, clock)
+{
+ set_ids(0x11063044, 0x00, 0x0c0010, 0x11063044);
+ // Sunix UFC3212V has these values
+// set_ids(0x11063044, 0x46, 0x0c0010, 0x1106e8c1);
+}
+
+vt6306_device::vt6306_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : vt6306_device(mconfig, VT6306_PCI, tag, owner, clock)
+{
+}
+
+void vt6306_device::device_add_mconfig(machine_config &config)
+{
+
+}
+
+void vt6306_device::device_start()
+{
+ pci_card_device::device_start();
+
+ add_map(2048, M_MEM, FUNC(vt6306_device::ohci_mmio_map));
+ add_map( 128, M_IO, FUNC(vt6306_device::vio_map));
+// add_map( 256, M_MEM, FUNC(vt6306_device::cardbus_map));
+
+ // INTA#
+ intr_pin = 1;
+
+ // TODO: min_gnt = 0x00, max_lat = 0x20
+}
+
+void vt6306_device::device_reset()
+{
+ pci_card_device::device_reset();
+
+ command = 0x0000;
+ // doc claims not having an I/O space but real HW pci.exe proved otherwise
+ command_mask = 7;
+ // Fast Back-to-Back, medium DEVSEL#
+ status = 0x0280;
+
+ remap_cb();
+}
+
+u8 vt6306_device::capptr_r()
+{
+ return 0x50;
+}
+
+void vt6306_device::config_map(address_map &map)
+{
+ pci_card_device::config_map(map);
+// map(0x40, 0x43) PCI HCI Control (?)
+ // ACPI
+ map(0x50, 0x50).lr8(NAME([] () { return 0x01; }));
+ map(0x51, 0x51).lr8(NAME([] () { return 0x00; })); // NULL pointer
+// map(0x52, 0x57) PCI Power Management v1.1
+}
+
+void vt6306_device::ohci_mmio_map(address_map &map)
+{
+}
+
+void vt6306_device::vio_map(address_map &map)
+{
+}
diff --git a/src/devices/bus/pci/vt6306.h b/src/devices/bus/pci/vt6306.h
new file mode 100644
index 00000000000..a11c355b58c
--- /dev/null
+++ b/src/devices/bus/pci/vt6306.h
@@ -0,0 +1,38 @@
+// license:BSD-3-Clause
+// copyright-holders:
+
+#ifndef MAME_BUS_PCI_VT6306_H
+#define MAME_BUS_PCI_VT6306_H
+
+#pragma once
+
+#include "pci_slot.h"
+
+class vt6306_device : public pci_card_device
+{
+public:
+ vt6306_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ vt6306_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+
+// virtual void map_extra(uint64_t memory_window_start, uint64_t memory_window_end, uint64_t memory_offset, address_space *memory_space,
+// uint64_t io_window_start, uint64_t io_window_end, uint64_t io_offset, address_space *io_space) override;
+
+ virtual void config_map(address_map &map) override;
+
+private:
+ void ohci_mmio_map(address_map &map);
+ void vio_map(address_map &map);
+
+ virtual u8 capptr_r() override;
+
+};
+
+DECLARE_DEVICE_TYPE(VT6306_PCI, vt6306_device)
+
+#endif // MAME_BUS_PCI_VT6306_H
diff --git a/src/devices/bus/pci/wd9710_pci.cpp b/src/devices/bus/pci/wd9710_pci.cpp
new file mode 100644
index 00000000000..4e4ec013bb5
--- /dev/null
+++ b/src/devices/bus/pci/wd9710_pci.cpp
@@ -0,0 +1,132 @@
+// license:BSD-3-Clause
+// copyright-holders: Angelo Salese
+/**************************************************************************************************
+
+WD9710 PCI cards
+
+Essentially a WD90C33 upgraded to PCI.
+
+TODO:
+- Any mode beyond 4bpp is bound to fail;
+
+**************************************************************************************************/
+
+#include "emu.h"
+#include "wd9710_pci.h"
+
+#define LOG_WARN (1U << 1)
+
+#define VERBOSE (LOG_GENERAL | LOG_WARN)
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+#define LOGWARN(...) LOGMASKED(LOG_WARN, __VA_ARGS__)
+
+
+DEFINE_DEVICE_TYPE(WD9710_PCI, wd9710_pci_device, "wd9710_pci", "Western Digital WD9710-MZ")
+//DEFINE_DEVICE_TYPE(WD9712_PCI, wd9712_pci_device, "wd9712_pci", "Western Digital WD9712-??")
+
+
+wd9710_pci_device::wd9710_pci_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : pci_card_device(mconfig, type, tag, owner, clock)
+ , m_svga(*this, "svga")
+ , m_vga_rom(*this, "vga_rom")
+{
+ set_ids(0x101c9710, 0x00, 0x030000, 0x101c9710);
+}
+
+wd9710_pci_device::wd9710_pci_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : wd9710_pci_device(mconfig, WD9710_PCI, tag, owner, clock)
+{
+}
+
+ROM_START( wd9710mz )
+ ROM_REGION32_LE( 0x8000, "vga_rom", ROMREGION_ERASEFF )
+ // Philips Paradise Pipeline 64
+ ROM_SYSTEM_BIOS( 0, "paradise", "Paradise WD9710 v1.01.00 12/06/95")
+ ROMX_LOAD( "bios.bin", 0x0000, 0x8000, CRC(98338249) SHA1(b5dbb28d60adf53c711ec16bc45eab102e40b6a2), ROM_BIOS(0) )
+ ROM_IGNORE( 0x8000 )
+ROM_END
+
+const tiny_rom_entry *wd9710_pci_device::device_rom_region() const
+{
+ return ROM_NAME(wd9710mz);
+}
+
+void wd9710_pci_device::device_add_mconfig(machine_config &config)
+{
+ screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
+ screen.set_raw(25.175_MHz_XTAL, 800, 0, 640, 524, 0, 480);
+ screen.set_screen_update("svga", FUNC(wd90c33_vga_device::screen_update));
+
+ // TODO: bump to specific WD9710 VGA core
+ WD90C33(config, m_svga, 0);
+ m_svga->set_screen("screen");
+ // 2MB, 4MB
+ m_svga->set_vram_size(4*1024*1024);
+}
+
+void wd9710_pci_device::device_start()
+{
+ pci_card_device::device_start();
+
+ add_map(4*1024*1024, M_MEM, FUNC(wd9710_pci_device::vram_aperture_map));
+
+ add_rom((u8 *)m_vga_rom->base(), 0x8000);
+ expansion_rom_base = 0xc0000;
+
+ // INTA#
+ intr_pin = 1;
+}
+
+void wd9710_pci_device::device_reset()
+{
+ pci_card_device::device_reset();
+
+ command = 0x0000;
+ command_mask = 0x23;
+ // TODO: configurable thru config bit 20
+ status = 0x0200;
+
+ remap_cb();
+}
+
+void wd9710_pci_device::config_map(address_map &map)
+{
+ pci_card_device::config_map(map);
+}
+
+void wd9710_pci_device::vram_aperture_map(address_map &map)
+{
+ map(0x000000, 0x3fffff).rw(m_svga, FUNC(wd90c33_vga_device::mem_linear_r), FUNC(wd90c33_vga_device::mem_linear_w));
+}
+
+void wd9710_pci_device::legacy_io_map(address_map &map)
+{
+ map(0, 0x02f).m(m_svga, FUNC(wd90c33_vga_device::io_map));
+}
+
+uint8_t wd9710_pci_device::vram_r(offs_t offset)
+{
+ return downcast<wd90c33_vga_device *>(m_svga.target())->mem_r(offset);
+}
+
+void wd9710_pci_device::vram_w(offs_t offset, uint8_t data)
+{
+ downcast<wd90c33_vga_device *>(m_svga.target())->mem_w(offset, data);
+}
+
+void wd9710_pci_device::map_extra(uint64_t memory_window_start, uint64_t memory_window_end, uint64_t memory_offset, address_space *memory_space,
+ uint64_t io_window_start, uint64_t io_window_end, uint64_t io_offset, address_space *io_space)
+{
+ if (BIT(command, 1))
+ {
+ memory_space->install_readwrite_handler(0xa0000, 0xbffff, read8sm_delegate(*this, FUNC(wd9710_pci_device::vram_r)), write8sm_delegate(*this, FUNC(wd9710_pci_device::vram_w)));
+ }
+
+ if (BIT(command, 0))
+ {
+ io_space->install_device(0x03b0, 0x03df, *this, &wd9710_pci_device::legacy_io_map);
+ // TODO: PnP ports (shouldn't have any other BAR space)
+ }
+}
diff --git a/src/devices/bus/pci/wd9710_pci.h b/src/devices/bus/pci/wd9710_pci.h
new file mode 100644
index 00000000000..52dfcb4a207
--- /dev/null
+++ b/src/devices/bus/pci/wd9710_pci.h
@@ -0,0 +1,49 @@
+// license:BSD-3-Clause
+// copyright-holders: Angelo Salese
+
+#ifndef MAME_BUS_PCI_WD9710_PCI_H
+#define MAME_BUS_PCI_WD9710_PCI_H
+
+#pragma once
+
+#include "pci_slot.h"
+
+#include "video/pc_vga_paradise.h"
+
+
+class wd9710_pci_device : public pci_card_device
+{
+public:
+ wd9710_pci_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ static constexpr feature_type unemulated_features() { return feature::GRAPHICS; }
+
+ void legacy_io_map(address_map &map);
+
+protected:
+ wd9710_pci_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+ virtual void map_extra(uint64_t memory_window_start, uint64_t memory_window_end, uint64_t memory_offset, address_space *memory_space,
+ uint64_t io_window_start, uint64_t io_window_end, uint64_t io_offset, address_space *io_space) override;
+
+ virtual void config_map(address_map &map) override;
+
+private:
+ required_device<wd90c33_vga_device> m_svga;
+ required_memory_region m_vga_rom;
+
+ void vram_aperture_map(address_map &map);
+
+ u8 vram_r(offs_t offset);
+ void vram_w(offs_t offset, uint8_t data);
+};
+
+DECLARE_DEVICE_TYPE(WD9710_PCI, wd9710_pci_device)
+
+#endif // MAME_BUS_PCI_WD9710_PCI_H
diff --git a/src/devices/bus/pci/ymp21.cpp b/src/devices/bus/pci/ymp21.cpp
new file mode 100644
index 00000000000..8819230d88f
--- /dev/null
+++ b/src/devices/bus/pci/ymp21.cpp
@@ -0,0 +1,219 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+
+// Banks (with size)
+// 0:0240 = bcr1MEL
+// 1:0240 = deqc1
+// 2:0240 = deqm1
+// 3:0240 = dspc1
+// 4:0120 = dspa1
+// 5:0240 = dspm1
+// 6:0240 = ?
+// 7:0040 = n1mod0
+// 8:0006 = n1creg0
+// 9:0020 = n1fgtim0
+// a:0040 = n1fguram0
+
+// Registers (with address)
+// 1:00e0 = dsp run (0x40000000)
+// 7:0040 = n1mod0KeyOnOff (0/0xffff)
+// f:c100 = TRWF
+// f:c101 = TRWFO
+
+// CLDW/CCK/CDO0 is the three pins of the ym3437c
+
+
+#include "emu.h"
+#include "ymp21.h"
+
+ymp21_device::ymp21_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : pci_card_device(mconfig, type, tag, owner, clock),
+ m_tx_cb(*this),
+ m_dsp3_buffer(*this, "dsp3", 0x80 * 5, ENDIANNESS_LITTLE)
+{
+}
+
+void ymp21_device::device_start()
+{
+ pci_card_device::device_start();
+
+ add_map(0x40000, M_MEM, FUNC(ymp21_device::map));
+ intr_pin = 0x01;
+
+ save_item(NAME(m_dsp3_ctrl1));
+ save_item(NAME(m_dsp3_glob1));
+ save_item(NAME(m_dsp3_glob2));
+ save_item(NAME(m_dsp3_glob3));
+
+ m_rx_timer[0] = timer_alloc(FUNC(ymp21_device::uart_rx), this);
+ m_rx_timer[1] = timer_alloc(FUNC(ymp21_device::uart_rx), this);
+ m_tx_timer[0] = timer_alloc(FUNC(ymp21_device::uart_tx), this);
+ m_tx_timer[1] = timer_alloc(FUNC(ymp21_device::uart_tx), this);
+}
+
+void ymp21_device::device_reset()
+{
+ pci_card_device::device_reset();
+
+ std::fill(m_dsp3_ctrl1.begin(), m_dsp3_ctrl1.end(), 0);
+ std::fill(m_dsp3_glob1.begin(), m_dsp3_glob1.end(), 0);
+ std::fill(m_dsp3_glob2.begin(), m_dsp3_glob2.end(), 0);
+ std::fill(m_dsp3_glob3.begin(), m_dsp3_glob3.end(), 0);
+}
+
+void ymp21_device::map(address_map &map)
+{
+ map(0x3e000, 0x3e000).rw(FUNC(ymp21_device::uart_status_r), FUNC(ymp21_device::uart_ctrl_w)).select(2);
+ map(0x3e001, 0x3e001).rw(FUNC(ymp21_device::uart_data_r), FUNC(ymp21_device::uart_data_w)).select(2);
+
+ map(0x3f000, 0x3f07f).w(FUNC(ymp21_device::dsp3_buffer_w)).select(0x00700);
+ map(0x3f080, 0x3f083).rw(FUNC(ymp21_device::dsp3_status_r), FUNC(ymp21_device::dsp3_ctrl1_w)).select(0x00700);
+ map(0x3f084, 0x3f087).w(FUNC(ymp21_device::dsp3_ctrl2_w)).select(0x00700);
+ map(0x3f088, 0x3f08b).w(FUNC(ymp21_device::dsp3_glob1_w)).select(0x00700);
+ map(0x3f08c, 0x3f08f).w(FUNC(ymp21_device::dsp3_glob2_w)).select(0x00700);
+ map(0x3f090, 0x3f093).w(FUNC(ymp21_device::dsp3_glob3_w)).select(0x00700);
+
+ map(0x3ff00, 0x3ff03).rw(FUNC(ymp21_device::port0_r), FUNC(ymp21_device::port0_w));
+ map(0x3ff04, 0x3ff07).rw(FUNC(ymp21_device::status_r), FUNC(ymp21_device::irq_w));
+ map(0x3ff10, 0x3ff13).w(FUNC(ymp21_device::port1_w));
+}
+
+void ymp21_device::uart_data_w(offs_t offset, u8 data)
+{
+ logerror("uart_data_w %d, %02x\n", offset, data);
+}
+
+u8 ymp21_device::uart_data_r(offs_t offset)
+{
+ logerror("uart_data_r %d\n", offset);
+ return 0;
+}
+
+void ymp21_device::uart_ctrl_w(offs_t offset, u8 data)
+{
+ logerror("uart_ctrl_w %d, %02x\n", offset, data);
+}
+
+u8 ymp21_device::uart_status_r(offs_t offset)
+{
+ logerror("uart_status_r %d\n", offset);
+ return 0;
+}
+
+void ymp21_device::port0_w(u32 data)
+{
+ logerror("port0_w %08x\n", data);
+}
+
+u32 ymp21_device::port0_r()
+{
+ logerror("port0_r\n");
+ return 0;
+}
+
+void ymp21_device::port1_w(u32 data)
+{
+ logerror("port1_w %08x -%s%s%s%s%s%s%s\n", data,
+ ((data & 0x00030000) == 0x00000000) ? " 48000" : ((data & 0x00030000) == 0x00010000) ? " 44100" : ((data & 0x00030000) == 0x00000000) ? " 32000": "",
+ data & 0x00800000 ? "" : " reset0",
+ data & 0x02000000 ? " mute" : "",
+ data & 0x08000000 ? " CDO0" : "",
+ data & 0x10000000 ? " CLDW" : "",
+ data & 0x20000000 ? " CCK" : "",
+ (data & 0xc0000000) == 0xc0000000 ? " running" : ""
+ );
+}
+
+void ymp21_device::irq_w(u32 data)
+{
+ logerror("irq_w %08x\n", data);
+ irq_pin_w(0, data & 0x04000000);
+}
+
+u32 ymp21_device::status_r()
+{
+ machine().debug_break();
+ logerror("status_r\n");
+ return 0;
+}
+
+void ymp21_device::dsp3_buffer_w(offs_t offset, u32 data, u32 mem_mask)
+{
+ offs_t slot = offset >> 6;
+ if(slot >= 5)
+ return;
+
+ COMBINE_DATA(&m_dsp3_buffer[(slot << 5) | offset]);
+}
+
+u32 ymp21_device::dsp3_status_r(offs_t offset)
+{
+ offs_t slot = offset >> 6;
+ if(slot >= 5)
+ return 0;
+
+ // bit 31 = busy
+
+ return 0;
+}
+
+void ymp21_device::dsp3_ctrl1_w(offs_t offset, u32 data)
+{
+ offs_t slot = offset >> 6;
+ if(slot >= 5)
+ return;
+
+ m_dsp3_ctrl1[slot] = data;
+}
+
+void ymp21_device::dsp3_ctrl2_w(offs_t offset, u32 data)
+{
+ offs_t slot = offset >> 6;
+ if(slot >= 5)
+ return;
+
+ logerror("dsp3 upload %d %x:%08x %02x\n", slot, (data >> 8) & 0xff, (m_dsp3_ctrl1[slot] << 16) | (data >> 16), m_dsp3_ctrl1[slot] >> 16);
+}
+
+void ymp21_device::dsp3_glob1_w(offs_t offset, u32 data)
+{
+ offs_t slot = offset >> 6;
+ if(slot >= 5)
+ return;
+
+ m_dsp3_glob1[slot] = data;
+}
+
+void ymp21_device::dsp3_glob2_w(offs_t offset, u32 data)
+{
+ offs_t slot = offset >> 6;
+ if(slot >= 5)
+ return;
+
+ m_dsp3_glob2[slot] = data;
+}
+
+void ymp21_device::dsp3_glob3_w(offs_t offset, u32 data)
+{
+ offs_t slot = offset >> 6;
+ if(slot >= 5)
+ return;
+
+ m_dsp3_glob3[slot] = data;
+
+ logerror("dsp3 %d globals: %04x %04x %08x %04x\n",
+ slot,
+ m_dsp3_glob1[slot] >> 16,
+ m_dsp3_glob1[slot] & 0xffff,
+ m_dsp3_glob2[slot],
+ m_dsp3_glob3[slot] >> 16);
+}
+
+TIMER_CALLBACK_MEMBER(ymp21_device::uart_rx)
+{
+}
+
+TIMER_CALLBACK_MEMBER(ymp21_device::uart_tx)
+{
+}
+
diff --git a/src/devices/bus/pci/ymp21.h b/src/devices/bus/pci/ymp21.h
new file mode 100644
index 00000000000..21f22a3e09a
--- /dev/null
+++ b/src/devices/bus/pci/ymp21.h
@@ -0,0 +1,58 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+
+// PCI interfacing gate array common to the sw1000xg and the ds2416
+
+#ifndef MAME_BUS_PCI_YMP21_H
+#define MAME_BUS_PCI_YMP21_H
+
+#pragma once
+
+#include "pci_slot.h"
+
+#include <array>
+
+
+class ymp21_device : public pci_card_device {
+protected:
+ devcb_write_line::array<2> m_tx_cb;
+
+ ymp21_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock = 0);
+
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+private:
+ memory_share_creator<u32> m_dsp3_buffer;
+ std::array<u32, 5> m_dsp3_ctrl1;
+ std::array<u32, 5> m_dsp3_glob1, m_dsp3_glob2, m_dsp3_glob3;
+
+ emu_timer *m_rx_timer[2], *m_tx_timer[2];
+
+ void map(address_map &map);
+
+ TIMER_CALLBACK_MEMBER(uart_rx);
+ TIMER_CALLBACK_MEMBER(uart_tx);
+
+ void uart_data_w(offs_t offset, u8 data);
+ u8 uart_data_r(offs_t offset);
+ void uart_ctrl_w(offs_t offset, u8 data);
+ u8 uart_status_r(offs_t offset);
+
+ void port0_w(u32 data);
+ u32 port0_r();
+ void port1_w(u32 data);
+ void irq_w(u32 data);
+ u32 status_r();
+
+ void dsp3_buffer_w(offs_t offset, u32 data, u32 mem_mask);
+ void dsp3_ctrl1_w(offs_t offset, u32 data);
+ void dsp3_ctrl2_w(offs_t offset, u32 data);
+ u32 dsp3_status_r(offs_t offset);
+
+ void dsp3_glob1_w(offs_t offset, u32 data);
+ void dsp3_glob2_w(offs_t offset, u32 data);
+ void dsp3_glob3_w(offs_t offset, u32 data);
+};
+
+#endif
diff --git a/src/devices/bus/pci/zr36057.cpp b/src/devices/bus/pci/zr36057.cpp
new file mode 100644
index 00000000000..a2064613546
--- /dev/null
+++ b/src/devices/bus/pci/zr36057.cpp
@@ -0,0 +1,87 @@
+// license:BSD-3-Clause
+// copyright-holders:
+/**************************************************************************************************
+
+Zoran ZR36057 / ZR36067 PCI-based chipsets
+
+PCI glue logic for multimedia MJPEG, MPEG1 & DVD.
+Paired with every single TV standard for video capture in the fairly decent number of subvendor
+iterations.
+- https://www.kernel.org/doc/html/v4.14/media/v4l-drivers/zoran.html
+- misc/sliver.cpp uses ZR36050
+- misc/magictg.cpp uses ZR36016
+
+**************************************************************************************************/
+
+#include "emu.h"
+#include "zr36057.h"
+
+#define LOG_WARN (1U << 1)
+
+#define VERBOSE (LOG_GENERAL | LOG_WARN)
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+#define LOGWARN(...) LOGMASKED(LOG_WARN, __VA_ARGS__)
+
+
+DEFINE_DEVICE_TYPE(ZR36057_PCI, zr36057_device, "zr36057", "Zoran ZR36057-based Enhanced Multimedia Controller")
+//DEFINE_DEVICE_TYPE(ZR36067_PCI, zr36067_device, "zr36067", "Zoran ZR36067-based AV Controller")
+
+
+zr36057_device::zr36057_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : pci_card_device(mconfig, type, tag, owner, clock)
+{
+ // ZR36057PQC Video cutting chipset
+ // device ID reportedly same for ZR36057 and ZR36067, revision 0x02 for latter.
+ // Four known subvendors:
+ // - 0x10317efe: Pinnacle/Miro DC10+
+ // - 0x1031fc00: Pinnacle/Miro DC50, Motion JPEG Capture/CODEC Board
+ // - 0x12f88a02: Electronic Design GmbH Tekram Video Kit
+ // - 0x13ca4231: Iomega JPEG/TV Card
+ // NOTE: subvendor is omitted in '36057 design (missing?), driven at PCIRST time to 32 pins in
+ // '36067 thru pull-up or pull-down resistors (subvendor responsibility?)
+ set_ids(0x11de6057, 0x01, 0x040000, 0x10317efe);
+}
+
+zr36057_device::zr36057_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : zr36057_device(mconfig, ZR36057_PCI, tag, owner, clock)
+{
+}
+
+void zr36057_device::device_add_mconfig(machine_config &config)
+{
+
+}
+
+void zr36057_device::device_start()
+{
+ pci_card_device::device_start();
+
+ add_map(4096, M_MEM, FUNC(zr36057_device::map));
+
+ // INTA#
+ intr_pin = 1;
+}
+
+void zr36057_device::device_reset()
+{
+ pci_card_device::device_reset();
+
+ // fast DEVSEL#
+ command = 0x0000;
+ status = 0x0000;
+ intr_line = 0x0a;
+ // TODO: PCI regs 0x3e/0x3f max_lat = 0x10 (4 usec), min_gnt = 0x02 (0.5 usec)
+
+ remap_cb();
+}
+
+void zr36057_device::config_map(address_map &map)
+{
+ pci_card_device::config_map(map);
+}
+
+void zr36057_device::map(address_map &map)
+{
+}
diff --git a/src/devices/bus/pci/zr36057.h b/src/devices/bus/pci/zr36057.h
new file mode 100644
index 00000000000..6a249a24217
--- /dev/null
+++ b/src/devices/bus/pci/zr36057.h
@@ -0,0 +1,39 @@
+// license:BSD-3-Clause
+// copyright-holders:
+
+#ifndef MAME_BUS_PCI_ZR36057_H
+#define MAME_BUS_PCI_ZR36057_H
+
+#pragma once
+
+#include "pci_slot.h"
+
+
+class zr36057_device : public pci_card_device
+{
+public:
+ zr36057_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ static constexpr feature_type unemulated_features() { return feature::CAPTURE; }
+
+protected:
+ zr36057_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+
+// virtual const tiny_rom_entry *device_rom_region() const override;
+
+// virtual void map_extra(uint64_t memory_window_start, uint64_t memory_window_end, uint64_t memory_offset, address_space *memory_space,
+// uint64_t io_window_start, uint64_t io_window_end, uint64_t io_offset, address_space *io_space) override;
+
+ virtual void config_map(address_map &map) override;
+
+private:
+ void map(address_map &map);
+};
+
+DECLARE_DEVICE_TYPE(ZR36057_PCI, zr36057_device)
+
+#endif // MAME_BUS_PCI_ZR36057_H
diff --git a/src/devices/bus/pet/2joysnd.cpp b/src/devices/bus/pet/2joysnd.cpp
index 6d65b70542a..89e9ac6f31d 100644
--- a/src/devices/bus/pet/2joysnd.cpp
+++ b/src/devices/bus/pet/2joysnd.cpp
@@ -152,7 +152,7 @@ void pet_userport_joystick_and_sound_device::update_port2()
}
-DECLARE_WRITE_LINE_MEMBER( pet_userport_joystick_and_sound_device::input_m )
+void pet_userport_joystick_and_sound_device::input_m(int state)
{
m_dac->write(state);
}
diff --git a/src/devices/bus/pet/2joysnd.h b/src/devices/bus/pet/2joysnd.h
index 644d64fc564..22694f7d439 100644
--- a/src/devices/bus/pet/2joysnd.h
+++ b/src/devices/bus/pet/2joysnd.h
@@ -28,15 +28,15 @@ public:
// construction/destruction
pet_userport_joystick_and_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual DECLARE_WRITE_LINE_MEMBER( input_m ) override;
+ virtual void input_m(int state) override;
// device_pet_user_port_interface overrides
- WRITE_LINE_MEMBER( write_up1 ) { m_up1 = state; update_port1(); }
- WRITE_LINE_MEMBER( write_down1 ) { m_down1 = state; update_port1(); }
- WRITE_LINE_MEMBER( write_fire1 ) { m_fire1 = state; update_port1(); }
- WRITE_LINE_MEMBER( write_up2 ) { m_up2 = state; update_port2(); }
- WRITE_LINE_MEMBER( write_down2 ) { m_down2 = state; update_port2(); }
- WRITE_LINE_MEMBER( write_fire2 ) { m_fire2 = state; update_port2(); }
+ void write_up1(int state) { m_up1 = state; update_port1(); }
+ void write_down1(int state) { m_down1 = state; update_port1(); }
+ void write_fire1(int state) { m_fire1 = state; update_port1(); }
+ void write_up2(int state) { m_up2 = state; update_port2(); }
+ void write_down2(int state) { m_down2 = state; update_port2(); }
+ void write_fire2(int state) { m_fire2 = state; update_port2(); }
protected:
// device-level overrides
diff --git a/src/devices/bus/pet/c2n.cpp b/src/devices/bus/pet/c2n.cpp
index 94f0dc4dca3..4365f15671d 100644
--- a/src/devices/bus/pet/c2n.cpp
+++ b/src/devices/bus/pet/c2n.cpp
@@ -9,6 +9,8 @@
#include "emu.h"
#include "c2n.h"
+#include "formats/cbm_tap.h"
+
//**************************************************************************
diff --git a/src/devices/bus/pet/c2n.h b/src/devices/bus/pet/c2n.h
index 86d8e5df288..d8c741c6b4f 100644
--- a/src/devices/bus/pet/c2n.h
+++ b/src/devices/bus/pet/c2n.h
@@ -12,7 +12,6 @@
#pragma once
#include "cass.h"
-#include "formats/cbm_tap.h"
#include "imagedev/cassette.h"
diff --git a/src/devices/bus/pet/cass.cpp b/src/devices/bus/pet/cass.cpp
index 301633e6d73..332d0140312 100644
--- a/src/devices/bus/pet/cass.cpp
+++ b/src/devices/bus/pet/cass.cpp
@@ -76,18 +76,15 @@ pet_datassette_port_device::~pet_datassette_port_device()
void pet_datassette_port_device::device_start()
{
m_cart = get_card_device();
-
- // resolve callbacks
- m_read_handler.resolve_safe();
}
-READ_LINE_MEMBER( pet_datassette_port_device::read ) { int state = 1; if (m_cart != nullptr) state = m_cart->datassette_read(); return state; }
-WRITE_LINE_MEMBER( pet_datassette_port_device::write ) { if (m_cart != nullptr) m_cart->datassette_write(state); }
-READ_LINE_MEMBER( pet_datassette_port_device::sense_r ) { int state = 1; if (m_cart != nullptr) state = m_cart->datassette_sense(); return state; }
-WRITE_LINE_MEMBER( pet_datassette_port_device::motor_w ) { if (m_cart != nullptr) m_cart->datassette_motor(state); }
+int pet_datassette_port_device::read() { int state = 1; if (m_cart != nullptr) state = m_cart->datassette_read(); return state; }
+void pet_datassette_port_device::write(int state) { if (m_cart != nullptr) m_cart->datassette_write(state); }
+int pet_datassette_port_device::sense_r() { int state = 1; if (m_cart != nullptr) state = m_cart->datassette_sense(); return state; }
+void pet_datassette_port_device::motor_w(int state) { if (m_cart != nullptr) m_cart->datassette_motor(state); }
-WRITE_LINE_MEMBER( pet_datassette_port_device::read_w ) { m_read_handler(state); }
+void pet_datassette_port_device::read_w(int state) { m_read_handler(state); }
// slot devices
diff --git a/src/devices/bus/pet/cass.h b/src/devices/bus/pet/cass.h
index a6a6eac11f9..51c2e5dfa42 100644
--- a/src/devices/bus/pet/cass.h
+++ b/src/devices/bus/pet/cass.h
@@ -59,13 +59,13 @@ public:
auto read_handler() { return m_read_handler.bind(); }
// computer interface
- DECLARE_READ_LINE_MEMBER( read );
- DECLARE_WRITE_LINE_MEMBER( write );
- DECLARE_READ_LINE_MEMBER( sense_r );
- DECLARE_WRITE_LINE_MEMBER( motor_w );
+ int read();
+ void write(int state);
+ int sense_r();
+ void motor_w(int state);
// device interface
- DECLARE_WRITE_LINE_MEMBER( read_w );
+ void read_w(int state);
protected:
// device-level overrides
diff --git a/src/devices/bus/pet/cb2snd.cpp b/src/devices/bus/pet/cb2snd.cpp
index b80d2efcce8..17dfc72b30b 100644
--- a/src/devices/bus/pet/cb2snd.cpp
+++ b/src/devices/bus/pet/cb2snd.cpp
@@ -55,7 +55,7 @@ void pet_userport_cb2_sound_device::device_start()
{
}
-DECLARE_WRITE_LINE_MEMBER( pet_userport_cb2_sound_device::input_m )
+void pet_userport_cb2_sound_device::input_m(int state)
{
m_dac->write(state);
}
diff --git a/src/devices/bus/pet/cb2snd.h b/src/devices/bus/pet/cb2snd.h
index cd39cc5bbb8..719e0db7c9f 100644
--- a/src/devices/bus/pet/cb2snd.h
+++ b/src/devices/bus/pet/cb2snd.h
@@ -25,7 +25,7 @@ public:
// construction/destruction
pet_userport_cb2_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual DECLARE_WRITE_LINE_MEMBER( input_m ) override;
+ virtual void input_m(int state) override;
protected:
// device-level overrides
diff --git a/src/devices/bus/pet/diag.h b/src/devices/bus/pet/diag.h
index 8bcf1bfd415..400c3df6a1c 100644
--- a/src/devices/bus/pet/diag.h
+++ b/src/devices/bus/pet/diag.h
@@ -28,19 +28,19 @@ public:
pet_userport_diagnostic_connector_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// device_pet_user_port_interface overrides
- virtual DECLARE_WRITE_LINE_MEMBER( input_2 ) override { output_b(state); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_3 ) override { output_c(state); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_4 ) override { output_d(state); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_6 ) override { output_7(state); output_8(state); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_7 ) override { output_6(state); output_8(state); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_8 ) override { output_6(state); output_7(state); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_9 ) override { output_k(state); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_10 ) override { output_l(state); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_b ) override { output_2(state); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_c ) override { output_3(state); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_d ) override { output_4(state); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_k ) override { output_9(state); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_l ) override { output_10(state); }
+ virtual void input_2(int state) override { output_b(state); }
+ virtual void input_3(int state) override { output_c(state); }
+ virtual void input_4(int state) override { output_d(state); }
+ virtual void input_6(int state) override { output_7(state); output_8(state); }
+ virtual void input_7(int state) override { output_6(state); output_8(state); }
+ virtual void input_8(int state) override { output_6(state); output_7(state); }
+ virtual void input_9(int state) override { output_k(state); }
+ virtual void input_10(int state) override { output_l(state); }
+ virtual void input_b(int state) override { output_2(state); }
+ virtual void input_c(int state) override { output_3(state); }
+ virtual void input_d(int state) override { output_4(state); }
+ virtual void input_k(int state) override { output_9(state); }
+ virtual void input_l(int state) override { output_10(state); }
protected:
// device-level overrides
diff --git a/src/devices/bus/pet/exp.cpp b/src/devices/bus/pet/exp.cpp
index aef8c5dfbf4..ee22ba3fc5d 100644
--- a/src/devices/bus/pet/exp.cpp
+++ b/src/devices/bus/pet/exp.cpp
@@ -39,7 +39,7 @@ pet_expansion_slot_device::pet_expansion_slot_device(const machine_config &mconf
device_t(mconfig, PET_EXPANSION_SLOT, tag, owner, clock),
device_single_card_slot_interface<device_pet_expansion_card_interface>(mconfig, *this),
m_card(nullptr),
- m_read_dma(*this),
+ m_read_dma(*this, 0),
m_write_dma(*this)
{
}
@@ -81,10 +81,6 @@ device_pet_expansion_card_interface::~device_pet_expansion_card_interface()
void pet_expansion_slot_device::device_start()
{
m_card = get_card_device();
-
- // resolve callbacks
- m_read_dma.resolve_safe(0);
- m_write_dma.resolve_safe();
}
@@ -128,7 +124,7 @@ void pet_expansion_slot_device::write(offs_t offset, uint8_t data, int &sel)
// diag_r - DIAG read
//-------------------------------------------------
-READ_LINE_MEMBER( pet_expansion_slot_device::diag_r )
+int pet_expansion_slot_device::diag_r()
{
return m_card ? m_card->pet_diag_r() : 1;
}
@@ -138,7 +134,7 @@ READ_LINE_MEMBER( pet_expansion_slot_device::diag_r )
// irq_w - IRQ write
//-------------------------------------------------
-WRITE_LINE_MEMBER( pet_expansion_slot_device::irq_w )
+void pet_expansion_slot_device::irq_w(int state)
{
if (m_card) m_card->pet_irq_w(state);
}
diff --git a/src/devices/bus/pet/exp.h b/src/devices/bus/pet/exp.h
index e8018bdd732..b8b53701a79 100644
--- a/src/devices/bus/pet/exp.h
+++ b/src/devices/bus/pet/exp.h
@@ -48,8 +48,8 @@ public:
int norom_r(offs_t offset, int sel);
uint8_t read(offs_t offset, uint8_t data, int &sel);
void write(offs_t offset, uint8_t data, int &sel);
- DECLARE_READ_LINE_MEMBER( diag_r );
- DECLARE_WRITE_LINE_MEMBER( irq_w );
+ int diag_r();
+ void irq_w(int state);
// cartridge interface
uint8_t dma_bd_r(offs_t offset);
diff --git a/src/devices/bus/pet/petuja.h b/src/devices/bus/pet/petuja.h
index b268c0d1519..9d5c9693743 100644
--- a/src/devices/bus/pet/petuja.h
+++ b/src/devices/bus/pet/petuja.h
@@ -33,12 +33,12 @@ public:
virtual ioport_constructor device_input_ports() const override;
// device_pet_user_port_interface overrides
- WRITE_LINE_MEMBER( write_up1 ) { m_up1 = state; update_port1(); }
- WRITE_LINE_MEMBER( write_down1 ) { m_down1 = state; update_port1(); }
- WRITE_LINE_MEMBER( write_fire1 ) { m_fire1 = state; update_port1(); }
- WRITE_LINE_MEMBER( write_up2 ) { m_up2 = state; update_port2(); }
- WRITE_LINE_MEMBER( write_down2 ) { m_down2 = state; update_port2(); }
- WRITE_LINE_MEMBER( write_fire2 ) { m_fire2 = state; update_port2(); }
+ void write_up1(int state) { m_up1 = state; update_port1(); }
+ void write_down1(int state) { m_down1 = state; update_port1(); }
+ void write_fire1(int state) { m_fire1 = state; update_port1(); }
+ void write_up2(int state) { m_up2 = state; update_port2(); }
+ void write_down2(int state) { m_down2 = state; update_port2(); }
+ void write_fire2(int state) { m_fire2 = state; update_port2(); }
protected:
// device-level overrides
diff --git a/src/devices/bus/pet/superpet.cpp b/src/devices/bus/pet/superpet.cpp
index df5c0071600..1b6bb9e80df 100644
--- a/src/devices/bus/pet/superpet.cpp
+++ b/src/devices/bus/pet/superpet.cpp
@@ -417,7 +417,7 @@ void superpet_device::write(offs_t offset, uint8_t data)
// acia_irq_w -
//-------------------------------------------------
-WRITE_LINE_MEMBER( superpet_device::acia_irq_w )
+void superpet_device::acia_irq_w(int state)
{
m_acia_irq = state;
diff --git a/src/devices/bus/pet/superpet.h b/src/devices/bus/pet/superpet.h
index 56c07df525f..8dff4cd00b6 100644
--- a/src/devices/bus/pet/superpet.h
+++ b/src/devices/bus/pet/superpet.h
@@ -48,7 +48,7 @@ protected:
virtual void pet_irq_w(int state) override;
private:
- DECLARE_WRITE_LINE_MEMBER( acia_irq_w );
+ void acia_irq_w(int state);
uint8_t read(offs_t offset);
void write(offs_t offset, uint8_t data);
diff --git a/src/devices/bus/pet/user.cpp b/src/devices/bus/pet/user.cpp
index 574c6c9afe9..87da4269628 100644
--- a/src/devices/bus/pet/user.cpp
+++ b/src/devices/bus/pet/user.cpp
@@ -46,26 +46,6 @@ void pet_user_port_device::device_config_complete()
void pet_user_port_device::device_start()
{
- m_2_handler.resolve_safe();
- m_3_handler.resolve_safe();
- m_4_handler.resolve_safe();
- m_5_handler.resolve_safe();
- m_6_handler.resolve_safe();
- m_7_handler.resolve_safe();
- m_8_handler.resolve_safe();
- m_9_handler.resolve_safe();
- m_10_handler.resolve_safe();
- m_b_handler.resolve_safe();
- m_c_handler.resolve_safe();
- m_d_handler.resolve_safe();
- m_e_handler.resolve_safe();
- m_f_handler.resolve_safe();
- m_h_handler.resolve_safe();
- m_j_handler.resolve_safe();
- m_k_handler.resolve_safe();
- m_l_handler.resolve_safe();
- m_m_handler.resolve_safe();
-
// pull up
m_3_handler(1);
m_4_handler(1);
@@ -86,25 +66,25 @@ void pet_user_port_device::device_start()
m_m_handler(1);
}
-WRITE_LINE_MEMBER( pet_user_port_device::write_2 ) { if (m_card != nullptr) m_card->input_2(state); }
-WRITE_LINE_MEMBER( pet_user_port_device::write_3 ) { if (m_card != nullptr) m_card->input_3(state); }
-WRITE_LINE_MEMBER( pet_user_port_device::write_4 ) { if (m_card != nullptr) m_card->input_4(state); }
-WRITE_LINE_MEMBER( pet_user_port_device::write_5 ) { if (m_card != nullptr) m_card->input_5(state); }
-WRITE_LINE_MEMBER( pet_user_port_device::write_6 ) { if (m_card != nullptr) m_card->input_6(state); }
-WRITE_LINE_MEMBER( pet_user_port_device::write_7 ) { if (m_card != nullptr) m_card->input_7(state); }
-WRITE_LINE_MEMBER( pet_user_port_device::write_8 ) { if (m_card != nullptr) m_card->input_8(state); }
-WRITE_LINE_MEMBER( pet_user_port_device::write_9 ) { if (m_card != nullptr) m_card->input_9(state); }
-WRITE_LINE_MEMBER( pet_user_port_device::write_10 ) { if (m_card != nullptr) m_card->input_10(state); }
-WRITE_LINE_MEMBER( pet_user_port_device::write_b ) { if (m_card != nullptr) m_card->input_b(state); }
-WRITE_LINE_MEMBER( pet_user_port_device::write_c ) { if (m_card != nullptr) m_card->input_c(state); }
-WRITE_LINE_MEMBER( pet_user_port_device::write_d ) { if (m_card != nullptr) m_card->input_d(state); }
-WRITE_LINE_MEMBER( pet_user_port_device::write_e ) { if (m_card != nullptr) m_card->input_e(state); }
-WRITE_LINE_MEMBER( pet_user_port_device::write_f ) { if (m_card != nullptr) m_card->input_f(state); }
-WRITE_LINE_MEMBER( pet_user_port_device::write_h ) { if (m_card != nullptr) m_card->input_h(state); }
-WRITE_LINE_MEMBER( pet_user_port_device::write_j ) { if (m_card != nullptr) m_card->input_j(state); }
-WRITE_LINE_MEMBER( pet_user_port_device::write_k ) { if (m_card != nullptr) m_card->input_k(state); }
-WRITE_LINE_MEMBER( pet_user_port_device::write_l ) { if (m_card != nullptr) m_card->input_l(state); }
-WRITE_LINE_MEMBER( pet_user_port_device::write_m ) { if (m_card != nullptr) m_card->input_m(state); }
+void pet_user_port_device::write_2(int state) { if (m_card != nullptr) m_card->input_2(state); }
+void pet_user_port_device::write_3(int state) { if (m_card != nullptr) m_card->input_3(state); }
+void pet_user_port_device::write_4(int state) { if (m_card != nullptr) m_card->input_4(state); }
+void pet_user_port_device::write_5(int state) { if (m_card != nullptr) m_card->input_5(state); }
+void pet_user_port_device::write_6(int state) { if (m_card != nullptr) m_card->input_6(state); }
+void pet_user_port_device::write_7(int state) { if (m_card != nullptr) m_card->input_7(state); }
+void pet_user_port_device::write_8(int state) { if (m_card != nullptr) m_card->input_8(state); }
+void pet_user_port_device::write_9(int state) { if (m_card != nullptr) m_card->input_9(state); }
+void pet_user_port_device::write_10(int state) { if (m_card != nullptr) m_card->input_10(state); }
+void pet_user_port_device::write_b(int state) { if (m_card != nullptr) m_card->input_b(state); }
+void pet_user_port_device::write_c(int state) { if (m_card != nullptr) m_card->input_c(state); }
+void pet_user_port_device::write_d(int state) { if (m_card != nullptr) m_card->input_d(state); }
+void pet_user_port_device::write_e(int state) { if (m_card != nullptr) m_card->input_e(state); }
+void pet_user_port_device::write_f(int state) { if (m_card != nullptr) m_card->input_f(state); }
+void pet_user_port_device::write_h(int state) { if (m_card != nullptr) m_card->input_h(state); }
+void pet_user_port_device::write_j(int state) { if (m_card != nullptr) m_card->input_j(state); }
+void pet_user_port_device::write_k(int state) { if (m_card != nullptr) m_card->input_k(state); }
+void pet_user_port_device::write_l(int state) { if (m_card != nullptr) m_card->input_l(state); }
+void pet_user_port_device::write_m(int state) { if (m_card != nullptr) m_card->input_m(state); }
// class device_pet_user_port_interface
diff --git a/src/devices/bus/pet/user.h b/src/devices/bus/pet/user.h
index 4a6a64c3081..52e334d40d0 100644
--- a/src/devices/bus/pet/user.h
+++ b/src/devices/bus/pet/user.h
@@ -67,25 +67,25 @@ public:
auto pl_handler() { return m_l_handler.bind(); }
auto pm_handler() { return m_m_handler.bind(); }
- DECLARE_WRITE_LINE_MEMBER( write_2 );
- DECLARE_WRITE_LINE_MEMBER( write_3 );
- DECLARE_WRITE_LINE_MEMBER( write_4 );
- DECLARE_WRITE_LINE_MEMBER( write_5 );
- DECLARE_WRITE_LINE_MEMBER( write_6 );
- DECLARE_WRITE_LINE_MEMBER( write_7 );
- DECLARE_WRITE_LINE_MEMBER( write_8 );
- DECLARE_WRITE_LINE_MEMBER( write_9 );
- DECLARE_WRITE_LINE_MEMBER( write_10 );
- DECLARE_WRITE_LINE_MEMBER( write_b );
- DECLARE_WRITE_LINE_MEMBER( write_c );
- DECLARE_WRITE_LINE_MEMBER( write_d );
- DECLARE_WRITE_LINE_MEMBER( write_e );
- DECLARE_WRITE_LINE_MEMBER( write_f );
- DECLARE_WRITE_LINE_MEMBER( write_h );
- DECLARE_WRITE_LINE_MEMBER( write_j );
- DECLARE_WRITE_LINE_MEMBER( write_k );
- DECLARE_WRITE_LINE_MEMBER( write_l );
- DECLARE_WRITE_LINE_MEMBER( write_m );
+ void write_2(int state);
+ void write_3(int state);
+ void write_4(int state);
+ void write_5(int state);
+ void write_6(int state);
+ void write_7(int state);
+ void write_8(int state);
+ void write_9(int state);
+ void write_10(int state);
+ void write_b(int state);
+ void write_c(int state);
+ void write_d(int state);
+ void write_e(int state);
+ void write_f(int state);
+ void write_h(int state);
+ void write_j(int state);
+ void write_k(int state);
+ void write_l(int state);
+ void write_m(int state);
protected:
// device-level overrides
@@ -124,48 +124,48 @@ class device_pet_user_port_interface : public device_interface
public:
virtual ~device_pet_user_port_interface();
- DECLARE_WRITE_LINE_MEMBER( output_2 ) { m_slot->m_2_handler(state); }
- DECLARE_WRITE_LINE_MEMBER( output_3 ) { m_slot->m_3_handler(state); }
- DECLARE_WRITE_LINE_MEMBER( output_4 ) { m_slot->m_4_handler(state); }
- DECLARE_WRITE_LINE_MEMBER( output_5 ) { m_slot->m_5_handler(state); }
- DECLARE_WRITE_LINE_MEMBER( output_6 ) { m_slot->m_6_handler(state); }
- DECLARE_WRITE_LINE_MEMBER( output_7 ) { m_slot->m_7_handler(state); }
- DECLARE_WRITE_LINE_MEMBER( output_8 ) { m_slot->m_8_handler(state); }
- DECLARE_WRITE_LINE_MEMBER( output_9 ) { m_slot->m_9_handler(state); }
- DECLARE_WRITE_LINE_MEMBER( output_10 ) { m_slot->m_10_handler(state); }
- DECLARE_WRITE_LINE_MEMBER( output_b ) { m_slot->m_b_handler(state); }
- DECLARE_WRITE_LINE_MEMBER( output_c ) { m_slot->m_c_handler(state); }
- DECLARE_WRITE_LINE_MEMBER( output_d ) { m_slot->m_d_handler(state); }
- DECLARE_WRITE_LINE_MEMBER( output_e ) { m_slot->m_e_handler(state); }
- DECLARE_WRITE_LINE_MEMBER( output_f ) { m_slot->m_f_handler(state); }
- DECLARE_WRITE_LINE_MEMBER( output_h ) { m_slot->m_h_handler(state); }
- DECLARE_WRITE_LINE_MEMBER( output_j ) { m_slot->m_j_handler(state); }
- DECLARE_WRITE_LINE_MEMBER( output_k ) { m_slot->m_k_handler(state); }
- DECLARE_WRITE_LINE_MEMBER( output_l ) { m_slot->m_l_handler(state); }
- DECLARE_WRITE_LINE_MEMBER( output_m ) { m_slot->m_m_handler(state); }
+ void output_2(int state) { m_slot->m_2_handler(state); }
+ void output_3(int state) { m_slot->m_3_handler(state); }
+ void output_4(int state) { m_slot->m_4_handler(state); }
+ void output_5(int state) { m_slot->m_5_handler(state); }
+ void output_6(int state) { m_slot->m_6_handler(state); }
+ void output_7(int state) { m_slot->m_7_handler(state); }
+ void output_8(int state) { m_slot->m_8_handler(state); }
+ void output_9(int state) { m_slot->m_9_handler(state); }
+ void output_10(int state) { m_slot->m_10_handler(state); }
+ void output_b(int state) { m_slot->m_b_handler(state); }
+ void output_c(int state) { m_slot->m_c_handler(state); }
+ void output_d(int state) { m_slot->m_d_handler(state); }
+ void output_e(int state) { m_slot->m_e_handler(state); }
+ void output_f(int state) { m_slot->m_f_handler(state); }
+ void output_h(int state) { m_slot->m_h_handler(state); }
+ void output_j(int state) { m_slot->m_j_handler(state); }
+ void output_k(int state) { m_slot->m_k_handler(state); }
+ void output_l(int state) { m_slot->m_l_handler(state); }
+ void output_m(int state) { m_slot->m_m_handler(state); }
protected:
device_pet_user_port_interface(const machine_config &mconfig, device_t &device);
- virtual DECLARE_WRITE_LINE_MEMBER( input_2 ) {}
- virtual DECLARE_WRITE_LINE_MEMBER( input_3 ) {}
- virtual DECLARE_WRITE_LINE_MEMBER( input_4 ) {}
- virtual DECLARE_WRITE_LINE_MEMBER( input_5 ) {}
- virtual DECLARE_WRITE_LINE_MEMBER( input_6 ) {}
- virtual DECLARE_WRITE_LINE_MEMBER( input_7 ) {}
- virtual DECLARE_WRITE_LINE_MEMBER( input_8 ) {}
- virtual DECLARE_WRITE_LINE_MEMBER( input_9 ) {}
- virtual DECLARE_WRITE_LINE_MEMBER( input_10 ) {}
- virtual DECLARE_WRITE_LINE_MEMBER( input_b ) {}
- virtual DECLARE_WRITE_LINE_MEMBER( input_c ) {}
- virtual DECLARE_WRITE_LINE_MEMBER( input_d ) {}
- virtual DECLARE_WRITE_LINE_MEMBER( input_e ) {}
- virtual DECLARE_WRITE_LINE_MEMBER( input_f ) {}
- virtual DECLARE_WRITE_LINE_MEMBER( input_h ) {}
- virtual DECLARE_WRITE_LINE_MEMBER( input_j ) {}
- virtual DECLARE_WRITE_LINE_MEMBER( input_k ) {}
- virtual DECLARE_WRITE_LINE_MEMBER( input_l ) {}
- virtual DECLARE_WRITE_LINE_MEMBER( input_m ) {}
+ virtual void input_2(int state) {}
+ virtual void input_3(int state) {}
+ virtual void input_4(int state) {}
+ virtual void input_5(int state) {}
+ virtual void input_6(int state) {}
+ virtual void input_7(int state) {}
+ virtual void input_8(int state) {}
+ virtual void input_9(int state) {}
+ virtual void input_10(int state) {}
+ virtual void input_b(int state) {}
+ virtual void input_c(int state) {}
+ virtual void input_d(int state) {}
+ virtual void input_e(int state) {}
+ virtual void input_f(int state) {}
+ virtual void input_h(int state) {}
+ virtual void input_j(int state) {}
+ virtual void input_k(int state) {}
+ virtual void input_l(int state) {}
+ virtual void input_m(int state) {}
pet_user_port_device *m_slot;
};
diff --git a/src/devices/bus/plg1x0/plg100-vl.cpp b/src/devices/bus/plg1x0/plg100-vl.cpp
new file mode 100644
index 00000000000..177813052df
--- /dev/null
+++ b/src/devices/bus/plg1x0/plg100-vl.cpp
@@ -0,0 +1,96 @@
+// license:BSD-3-Clause
+// copyright-holders: Olivier Galibert
+
+// Yamaha PLG100-VL
+
+// Virtual Acoustic Synthesis, physical-modelling synthesis, VL70-m on a plugin board
+
+// Build around a h8 for the control and a dsp-v for the synthesis
+
+#include "emu.h"
+#include "plg100-vl.h"
+
+#include "cpu/h8/h83002.h"
+#include "sound/dspv.h"
+
+namespace {
+
+class plg100_vl_device : public device_t, public device_plg1x0_interface
+{
+public:
+ plg100_vl_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
+ virtual ~plg100_vl_device();
+
+ virtual void midi_rx(int state) override;
+
+protected:
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override;
+
+private:
+ required_device<h83002_device> m_cpu;
+ required_device<dspv_device> m_dspv;
+
+ void map(address_map &map);
+};
+
+plg100_vl_device::plg100_vl_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, PLG100_VL, tag, owner, clock),
+ device_plg1x0_interface(mconfig, *this),
+ m_cpu(*this, "cpu"),
+ m_dspv(*this, "dspv")
+{
+}
+
+plg100_vl_device::~plg100_vl_device()
+{
+}
+
+void plg100_vl_device::midi_rx(int state)
+{
+ m_cpu->sci_rx_w<1>(state);
+}
+
+void plg100_vl_device::map(address_map &map)
+{
+ map(0x000000, 0x0fffff).rom().region("cpu", 0);
+ map(0x400000, 0x40007f).m(m_dspv, FUNC(dspv_device::map));
+ map(0x200000, 0x20ffff).ram();
+}
+
+void plg100_vl_device::device_add_mconfig(machine_config &config)
+{
+ H83002(config, m_cpu, 10_MHz_XTAL);
+ m_cpu->set_addrmap(AS_PROGRAM, &plg100_vl_device::map);
+ m_cpu->write_sci_tx<1>().set([this] (int state) { m_connector->do_midi_tx(state); });
+
+ DSPV(config, m_dspv, 22.5792_MHz_XTAL);
+ m_dspv->add_route(0, DEVICE_SELF_OWNER, 1.0, AUTO_ALLOC_INPUT, 0);
+ m_dspv->add_route(1, DEVICE_SELF_OWNER, 1.0, AUTO_ALLOC_INPUT, 1);
+}
+
+ROM_START( plg100_vl )
+ ROM_REGION( 0x100000, "cpu", 0 )
+ ROM_LOAD16_WORD_SWAP( "xt47810.ic03", 0x000000, 0x100000, CRC(ef472e45) SHA1(13d54c33a4708c77de2dc1e02210da107add6ce6) )
+ROM_END
+
+void plg100_vl_device::device_start()
+{
+}
+
+void plg100_vl_device::device_reset()
+{
+ // Active-low, wired to gnd
+ m_cpu->set_input_line(0, ASSERT_LINE);
+}
+
+const tiny_rom_entry *plg100_vl_device::device_rom_region() const
+{
+ return ROM_NAME(plg100_vl);
+}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(PLG100_VL, device_plg1x0_interface, plg100_vl_device, "plg100_vl", "Yamaha PLG100-VL")
diff --git a/src/devices/bus/plg1x0/plg100-vl.h b/src/devices/bus/plg1x0/plg100-vl.h
new file mode 100644
index 00000000000..6ff3cd48a8f
--- /dev/null
+++ b/src/devices/bus/plg1x0/plg100-vl.h
@@ -0,0 +1,15 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+
+#ifndef MAME_BUS_PLG1X0_PLG100VL_H
+#define MAME_BUS_PLG1X0_PLG100VL_H
+
+// Yamaha PLG100-VL
+
+#pragma once
+
+#include "plg1x0.h"
+
+DECLARE_DEVICE_TYPE(PLG100_VL, device_plg1x0_interface)
+
+#endif // MAME_BUS_PLG1X0_PLG100_VL_H
diff --git a/src/devices/bus/plg1x0/plg150-ap.cpp b/src/devices/bus/plg1x0/plg150-ap.cpp
new file mode 100644
index 00000000000..7b92cf37666
--- /dev/null
+++ b/src/devices/bus/plg1x0/plg150-ap.cpp
@@ -0,0 +1,92 @@
+// license:BSD-3-Clause
+// copyright-holders: Olivier Galibert
+
+// Yamaha PLG150-AP
+
+// Acoustic Piano, a plugin dedicated to a high-quality piano sound
+
+// Dual SWX00
+
+#include "emu.h"
+#include "plg150-ap.h"
+
+#include "cpu/h8/swx00.h"
+
+namespace {
+
+class plg150_ap_device : public device_t, public device_plg1x0_interface
+{
+public:
+ plg150_ap_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
+ virtual ~plg150_ap_device();
+
+ virtual void midi_rx(int state) override;
+
+protected:
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override;
+
+private:
+ required_device<swx00_device> m_cpu;
+
+ void map(address_map &map);
+};
+
+plg150_ap_device::plg150_ap_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, PLG150_AP, tag, owner, clock),
+ device_plg1x0_interface(mconfig, *this),
+ m_cpu(*this, "cpu")
+{
+}
+
+plg150_ap_device::~plg150_ap_device()
+{
+}
+
+void plg150_ap_device::midi_rx(int state)
+{
+ m_cpu->sci_rx_w<1>(state);
+}
+
+void plg150_ap_device::map(address_map &map)
+{
+ map(0x000000, 0x07ffff).rom().region("cpu", 0);
+ map(0x200000, 0x207fff).ram();
+}
+
+void plg150_ap_device::device_add_mconfig(machine_config &config)
+{
+ SWX00(config, m_cpu, 8.4672_MHz_XTAL*2, 1);
+ m_cpu->set_addrmap(AS_PROGRAM, &plg150_ap_device::map);
+ m_cpu->write_sci_tx<1>().set([this] (int state) { m_connector->do_midi_tx(state); });
+ m_cpu->sci_set_external_clock_period(0, attotime::from_hz(500000));
+ m_cpu->sci_set_external_clock_period(1, attotime::from_hz(500000));
+}
+
+ROM_START( plg150_ap )
+ ROM_REGION( 0x80000, "cpu", 0 )
+ ROM_LOAD16_WORD_SWAP( "x5757b0.ic03", 0x00000, 0x80000, CRC(5383b363) SHA1(b8e8e0673439c80dc9aecd6638f1c20454c82080) )
+
+ ROM_REGION( 0x1000000, "swx00", 0 )
+ ROM_LOAD( "x575810.ic09", 0x000000, 0x800000, CRC(273b4574) SHA1(b33d67f7fe3a020c19133cc52bd6a228227941c5) )
+ ROM_LOAD( "x575910.ic11", 0x800000, 0x800000, CRC(32a37ef3) SHA1(c0b5dfb1fbb5a3ddd33e6303039fbc197478abd2) )
+ROM_END
+
+void plg150_ap_device::device_start()
+{
+}
+
+void plg150_ap_device::device_reset()
+{
+}
+
+const tiny_rom_entry *plg150_ap_device::device_rom_region() const
+{
+ return ROM_NAME(plg150_ap);
+}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(PLG150_AP, device_plg1x0_interface, plg150_ap_device, "plg150_ap", "Yamaha PLG150-AP")
diff --git a/src/devices/bus/plg1x0/plg150-ap.h b/src/devices/bus/plg1x0/plg150-ap.h
new file mode 100644
index 00000000000..8e56ed6061c
--- /dev/null
+++ b/src/devices/bus/plg1x0/plg150-ap.h
@@ -0,0 +1,15 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+
+#ifndef MAME_BUS_PLG1X0_PLG150AP_H
+#define MAME_BUS_PLG1X0_PLG150AP_H
+
+// Yamaha PLG150-AP
+
+#pragma once
+
+#include "plg1x0.h"
+
+DECLARE_DEVICE_TYPE(PLG150_AP, device_plg1x0_interface)
+
+#endif // MAME_BUS_PLG1X0_PLG150_AP_H
diff --git a/src/devices/bus/plg1x0/plg1x0.cpp b/src/devices/bus/plg1x0/plg1x0.cpp
new file mode 100644
index 00000000000..6abd5100209
--- /dev/null
+++ b/src/devices/bus/plg1x0/plg1x0.cpp
@@ -0,0 +1,51 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+
+#include "emu.h"
+#include "plg1x0.h"
+
+#include "plg100-vl.h"
+#include "plg150-ap.h"
+
+DEFINE_DEVICE_TYPE(PLG1X0_CONNECTOR, plg1x0_connector, "plg1x0_connector", "PLG1x0 extension connector")
+
+plg1x0_connector::plg1x0_connector(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, PLG1X0_CONNECTOR, tag, owner, clock),
+ device_single_card_slot_interface<device_plg1x0_interface>(mconfig, *this),
+ device_mixer_interface(mconfig, *this, 2),
+ m_midi_tx(*this)
+{
+}
+
+void plg1x0_connector::device_start()
+{
+ save_item(NAME(m_state_system_is_annoying));
+}
+
+void plg1x0_connector::midi_rx(int state)
+{
+ auto card = get_card_device();
+ if(card)
+ card->midi_rx(state);
+}
+
+void plg1x0_intf(device_slot_interface &device)
+{
+ device.option_add("plg100vl", PLG100_VL);
+ device.option_add("plg150ap", PLG150_AP);
+}
+
+device_plg1x0_interface::device_plg1x0_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "plg1x0"),
+ m_connector(nullptr)
+{
+}
+
+device_plg1x0_interface::~device_plg1x0_interface()
+{
+}
+
+void device_plg1x0_interface::interface_pre_start()
+{
+ m_connector = downcast<plg1x0_connector *>(device().owner());
+}
diff --git a/src/devices/bus/plg1x0/plg1x0.h b/src/devices/bus/plg1x0/plg1x0.h
new file mode 100644
index 00000000000..8c049c215d5
--- /dev/null
+++ b/src/devices/bus/plg1x0/plg1x0.h
@@ -0,0 +1,82 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+
+// The PLG100 series is a bunch of proprietary plugins for the Yamaha
+// MU series of expanders. It mostly provides two midi-rate (and midi
+// protocol) serial lines (in and out) and two stereo serial sample
+// streams (in and out too).
+//
+// The PLG150 series, the successor, seems essentially compatible.
+// The main difference is (in some cases) nvram to save settings.
+
+// Known existing cards:
+// PLG100-DX: DX7 as a plugin
+// PLG100-SG: Singing speech synthesis, e.g. a Vocaloid before the Vocaloid existed
+// PLG100-VH: Voice Harmonizer, harmony effects on the A/D inputs
+// PLG100-VL: Virtual Acoustic Synthesis, physical-modelling synthesis, a VL70-m on a plugin card
+// PLG100-XG: MU50 as a plugin
+//
+// PLG150-AN: Analog Physical Modeling
+// PLG150-AP: Acoustic Piano
+// PLG150-DR: Drums
+// PLG150-DX: DX7 as a plugin
+// PLG150-PC: Latin drums
+// PLG150-PF: Piano
+// PLG150-VL: Virtual Acoustic Synthesis
+
+
+#ifndef MAME_BUS_PLG1X0_PLG1X0_H
+#define MAME_BUS_PLG1X0_PLG1X0_H
+
+#pragma once
+
+class device_plg1x0_interface;
+
+class plg1x0_connector: public device_t, public device_single_card_slot_interface<device_plg1x0_interface>, public device_mixer_interface
+{
+public:
+ template <typename T>
+ plg1x0_connector(const machine_config &mconfig, const char *tag, device_t *owner, T &&opts, const char *dflt)
+ : plg1x0_connector(mconfig, tag, owner, (uint32_t)0)
+ {
+ option_reset();
+ opts(*this);
+ set_default_option(dflt);
+ set_fixed(false);
+ }
+
+ plg1x0_connector(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ void midi_rx(int state);
+ auto midi_tx() { return m_midi_tx.bind(); }
+
+ void do_midi_tx(int state) { m_midi_tx(state); }
+
+protected:
+ bool m_state_system_is_annoying = true;
+ devcb_write_line m_midi_tx;
+
+ virtual void device_start() override;
+};
+
+class device_plg1x0_interface: public device_interface
+{
+public:
+ virtual ~device_plg1x0_interface();
+
+ virtual void midi_rx(int state) = 0;
+
+protected:
+ plg1x0_connector *m_connector;
+
+ device_plg1x0_interface(const machine_config &mconfig, device_t &device);
+
+ virtual void interface_pre_start() override;
+};
+
+DECLARE_DEVICE_TYPE(PLG1X0_CONNECTOR, plg1x0_connector)
+
+void plg1x0_intf(device_slot_interface &device);
+
+#endif // MAME_BUS_PLG1X0_PLG1X0_H
+
diff --git a/src/devices/bus/plus4/c1551.cpp b/src/devices/bus/plus4/c1551.cpp
index 42bca7daa57..999faed9108 100644
--- a/src/devices/bus/plus4/c1551.cpp
+++ b/src/devices/bus/plus4/c1551.cpp
@@ -9,6 +9,9 @@
#include "emu.h"
#include "c1551.h"
+#include "formats/d64_dsk.h"
+#include "formats/g64_dsk.h"
+
//**************************************************************************
@@ -340,7 +343,6 @@ void c1551_device::device_add_mconfig(machine_config &config)
m_maincpu->set_addrmap(AS_PROGRAM, &c1551_device::c1551_mem);
m_maincpu->read_callback().set(FUNC(c1551_device::port_r));
m_maincpu->write_callback().set(FUNC(c1551_device::port_w));
- //config.set_perfect_quantum(m_maincpu); FIXME: not safe in a slot device - add barriers
PLS100(config, m_pla);
diff --git a/src/devices/bus/plus4/diag264_lb_user.h b/src/devices/bus/plus4/diag264_lb_user.h
index dd45e469106..932868f81a3 100644
--- a/src/devices/bus/plus4/diag264_lb_user.h
+++ b/src/devices/bus/plus4/diag264_lb_user.h
@@ -32,23 +32,23 @@ protected:
virtual void device_start() override;
// device_pet_user_port_interface overrides
- virtual DECLARE_WRITE_LINE_MEMBER(input_b) override { output_6(state); }
- virtual DECLARE_WRITE_LINE_MEMBER(input_k) override { output_7(state); }
- virtual DECLARE_WRITE_LINE_MEMBER(input_4) override { output_j(state); }
- virtual DECLARE_WRITE_LINE_MEMBER(input_5) override { output_f(state); }
-
- virtual DECLARE_WRITE_LINE_MEMBER(input_6) override { output_b(state); }
- virtual DECLARE_WRITE_LINE_MEMBER(input_7) override { output_k(state); }
- virtual DECLARE_WRITE_LINE_MEMBER(input_j) override { output_4(state); }
- virtual DECLARE_WRITE_LINE_MEMBER(input_f) override { output_5(state); }
-
- virtual DECLARE_WRITE_LINE_MEMBER(input_c) override { output_m(state); }
- virtual DECLARE_WRITE_LINE_MEMBER(input_d) override { output_l(state); }
- virtual DECLARE_WRITE_LINE_MEMBER(input_e) override { output_h(state); }
-
- virtual DECLARE_WRITE_LINE_MEMBER(input_m) override { output_c(state); }
- virtual DECLARE_WRITE_LINE_MEMBER(input_l) override { output_d(state); }
- virtual DECLARE_WRITE_LINE_MEMBER(input_h) override { output_e(state); }
+ virtual void input_b(int state) override { output_6(state); }
+ virtual void input_k(int state) override { output_7(state); }
+ virtual void input_4(int state) override { output_j(state); }
+ virtual void input_5(int state) override { output_f(state); }
+
+ virtual void input_6(int state) override { output_b(state); }
+ virtual void input_7(int state) override { output_k(state); }
+ virtual void input_j(int state) override { output_4(state); }
+ virtual void input_f(int state) override { output_5(state); }
+
+ virtual void input_c(int state) override { output_m(state); }
+ virtual void input_d(int state) override { output_l(state); }
+ virtual void input_e(int state) override { output_h(state); }
+
+ virtual void input_m(int state) override { output_c(state); }
+ virtual void input_l(int state) override { output_d(state); }
+ virtual void input_h(int state) override { output_e(state); }
};
// device type definition
diff --git a/src/devices/bus/plus4/exp.cpp b/src/devices/bus/plus4/exp.cpp
index 1086683c02a..b475875145c 100644
--- a/src/devices/bus/plus4/exp.cpp
+++ b/src/devices/bus/plus4/exp.cpp
@@ -69,7 +69,7 @@ plus4_expansion_slot_device::plus4_expansion_slot_device(const machine_config &m
device_single_card_slot_interface<device_plus4_expansion_card_interface>(mconfig, *this),
device_cartrom_image_interface(mconfig, *this),
m_write_irq(*this),
- m_read_dma_cd(*this),
+ m_read_dma_cd(*this, 0xff),
m_write_dma_cd(*this),
m_write_aec(*this),
m_card(nullptr)
@@ -84,12 +84,6 @@ plus4_expansion_slot_device::plus4_expansion_slot_device(const machine_config &m
void plus4_expansion_slot_device::device_start()
{
m_card = get_card_device();
-
- // resolve callbacks
- m_write_irq.resolve_safe();
- m_read_dma_cd.resolve_safe(0xff);
- m_write_dma_cd.resolve_safe();
- m_write_aec.resolve_safe();
}
@@ -97,13 +91,14 @@ void plus4_expansion_slot_device::device_start()
// call_load -
//-------------------------------------------------
-image_init_result plus4_expansion_slot_device::call_load()
+std::pair<std::error_condition, std::string> plus4_expansion_slot_device::call_load()
{
if (m_card)
{
if (!loaded_through_softlist())
{
// TODO
+ return std::make_pair(image_error::UNSUPPORTED, "Plus/4 Expansion software must be loaded from the software list");
}
else
{
@@ -117,14 +112,11 @@ image_init_result plus4_expansion_slot_device::call_load()
m_card->m_c2h_size = get_software_region_length("c2h");
if ((m_card->m_c1l_size & (m_card->m_c1l_size - 1)) || (m_card->m_c1h_size & (m_card->m_c1h_size - 1)) || (m_card->m_c2l_size & (m_card->m_c2l_size - 1)) || (m_card->m_c2h_size & (m_card->m_c2h_size - 1)))
- {
- seterror(image_error::INVALIDIMAGE, "ROM size must be power of 2");
- return image_init_result::FAIL;
- }
+ return std::make_pair(image_error::INVALIDLENGTH, "All ROM sizes must be powers of 2");
}
}
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
diff --git a/src/devices/bus/plus4/exp.h b/src/devices/bus/plus4/exp.h
index bac19750c2d..8dbd43106cf 100644
--- a/src/devices/bus/plus4/exp.h
+++ b/src/devices/bus/plus4/exp.h
@@ -79,22 +79,22 @@ public:
// cartridge interface
uint8_t dma_cd_r(offs_t offset) { return m_read_dma_cd(offset); }
void dma_cd_w(offs_t offset, uint8_t data) { m_write_dma_cd(offset, data); }
- DECLARE_WRITE_LINE_MEMBER( irq_w ) { m_write_irq(state); }
- DECLARE_WRITE_LINE_MEMBER( aec_w ) { m_write_aec(state); }
+ void irq_w(int state) { m_write_irq(state); }
+ void aec_w(int state) { m_write_aec(state); }
int phi2() { return clock(); }
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
- // image-level overrides
- virtual image_init_result call_load() override;
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
virtual bool is_reset_on_load() const noexcept override { return true; }
virtual const char *image_interface() const noexcept override { return "plus4_cart"; }
virtual const char *file_extensions() const noexcept override { return "rom,bin"; }
- // slot interface overrides
+ // device_slot_interface implementation
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
devcb_write_line m_write_irq;
diff --git a/src/devices/bus/pofo/ccm.cpp b/src/devices/bus/pofo/ccm.cpp
index d491af7266f..d2b60021f1d 100644
--- a/src/devices/bus/pofo/ccm.cpp
+++ b/src/devices/bus/pofo/ccm.cpp
@@ -11,6 +11,8 @@
#include "softlist_dev.h"
+#include <tuple>
+
//**************************************************************************
@@ -68,17 +70,27 @@ void portfolio_memory_card_slot_device::device_start()
// call_load -
//-------------------------------------------------
-image_init_result portfolio_memory_card_slot_device::call_load()
+std::pair<std::error_condition, std::string> portfolio_memory_card_slot_device::call_load()
{
+ std::error_condition err;
+
if (m_card)
{
if (!loaded_through_softlist())
- fread(m_card->m_rom, length());
+ {
+ size_t const size = length();
+ size_t actual;
+ std::tie(err, m_card->m_rom, actual) = read(image_core_file(), size);
+ if (!err && (actual != size))
+ err = std::errc::io_error;
+ }
else
+ {
load_software_region("rom", m_card->m_rom);
+ }
}
- return image_init_result::PASS;
+ return std::make_pair(err, std::string());
}
diff --git a/src/devices/bus/pofo/ccm.h b/src/devices/bus/pofo/ccm.h
index 53e3c7a65ea..317884c8ce2 100644
--- a/src/devices/bus/pofo/ccm.h
+++ b/src/devices/bus/pofo/ccm.h
@@ -115,18 +115,18 @@ public:
void nwri_w(offs_t offset, uint8_t data) { if (m_card != nullptr) m_card->nwri_w(offset, data); }
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
- // image-level overrides
- virtual image_init_result call_load() override;
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
virtual const software_list_loader &get_software_list_loader() const override;
virtual bool is_reset_on_load() const noexcept override { return true; }
virtual const char *image_interface() const noexcept override { return "pofo_card"; }
virtual const char *file_extensions() const noexcept override { return "rom,bin"; }
- // slot interface overrides
+ // device_slot_interface implementation
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
device_portfolio_memory_card_slot_interface *m_card;
diff --git a/src/devices/bus/pofo/exp.cpp b/src/devices/bus/pofo/exp.cpp
index 8dc14ecfd03..d97b229624a 100644
--- a/src/devices/bus/pofo/exp.cpp
+++ b/src/devices/bus/pofo/exp.cpp
@@ -33,9 +33,9 @@ device_portfolio_expansion_slot_interface::device_portfolio_expansion_slot_inter
m_slot = dynamic_cast<portfolio_expansion_slot_device *>(device.owner());
}
-WRITE_LINE_MEMBER( device_portfolio_expansion_slot_interface::eint_w ) { m_slot->eint_w(state); }
-WRITE_LINE_MEMBER( device_portfolio_expansion_slot_interface::nmio_w ) { m_slot->nmio_w(state); }
-WRITE_LINE_MEMBER( device_portfolio_expansion_slot_interface::wake_w ) { m_slot->wake_w(state); }
+void device_portfolio_expansion_slot_interface::eint_w(int state) { m_slot->eint_w(state); }
+void device_portfolio_expansion_slot_interface::nmio_w(int state) { m_slot->nmio_w(state); }
+void device_portfolio_expansion_slot_interface::wake_w(int state) { m_slot->wake_w(state); }
@@ -65,11 +65,6 @@ portfolio_expansion_slot_device::portfolio_expansion_slot_device(const machine_c
void portfolio_expansion_slot_device::device_start()
{
m_card = get_card_device();
-
- // resolve callbacks
- m_write_eint.resolve_safe();
- m_write_nmio.resolve_safe();
- m_write_wake.resolve_safe();
}
diff --git a/src/devices/bus/pofo/exp.h b/src/devices/bus/pofo/exp.h
index 0790aa04123..9f37bcf444c 100644
--- a/src/devices/bus/pofo/exp.h
+++ b/src/devices/bus/pofo/exp.h
@@ -68,11 +68,11 @@ public:
virtual uint8_t nrdi_r(offs_t offset, uint8_t data, bool iom, bool bcom, bool ncc1) { return data; }
virtual void nwri_w(offs_t offset, uint8_t data, bool iom, bool bcom, bool ncc1) { }
- virtual WRITE_LINE_MEMBER( iint_w ) { }
+ virtual void iint_w(int state) { }
- DECLARE_WRITE_LINE_MEMBER( eint_w );
- DECLARE_WRITE_LINE_MEMBER( nmio_w );
- DECLARE_WRITE_LINE_MEMBER( wake_w );
+ void eint_w(int state);
+ void nmio_w(int state);
+ void wake_w(int state);
protected:
// construction/destruction
@@ -115,12 +115,12 @@ public:
uint8_t nrdi_r(offs_t offset, uint8_t data, bool iom, bool bcom, bool ncc1) { return (m_card != nullptr) ? m_card->nrdi_r(offset, data, iom, bcom, ncc1) : data; }
void nwri_w(offs_t offset, uint8_t data, bool iom, bool bcom, bool ncc1) { if (m_card != nullptr) m_card->nwri_w(offset, data, iom, bcom, ncc1); }
- WRITE_LINE_MEMBER( iint_w ) { if (m_card != nullptr) m_card->iint_w(state); }
+ void iint_w(int state) { if (m_card != nullptr) m_card->iint_w(state); }
// peripheral interface
- WRITE_LINE_MEMBER( eint_w ) { m_write_eint(state); }
- WRITE_LINE_MEMBER( nmio_w ) { m_write_nmio(state); }
- WRITE_LINE_MEMBER( wake_w ) { m_write_wake(state); }
+ void eint_w(int state) { m_write_eint(state); }
+ void nmio_w(int state) { m_write_nmio(state); }
+ void wake_w(int state) { m_write_wake(state); }
protected:
// device-level overrides
diff --git a/src/devices/bus/pofo/hpc104.cpp b/src/devices/bus/pofo/hpc104.cpp
index 0d8953b20c6..01dd6beb7c2 100644
--- a/src/devices/bus/pofo/hpc104.cpp
+++ b/src/devices/bus/pofo/hpc104.cpp
@@ -141,6 +141,25 @@ void pofo_hpc104_device::device_reset()
}
+void pofo_hpc104_device::nvram_default()
+{
+}
+
+
+bool pofo_hpc104_device::nvram_read(util::read_stream &file)
+{
+ auto const [err, actual] = read(file, m_nvram, 0x40000);
+ return !err && (actual == 0x40000);
+}
+
+
+bool pofo_hpc104_device::nvram_write(util::write_stream &file)
+{
+ auto const [err, actual] = write(file, m_nvram, 0x40000);
+ return !err;
+}
+
+
//-------------------------------------------------
// nrdi_r - read
//-------------------------------------------------
diff --git a/src/devices/bus/pofo/hpc104.h b/src/devices/bus/pofo/hpc104.h
index d5d1c36c3d3..d8802d869f1 100644
--- a/src/devices/bus/pofo/hpc104.h
+++ b/src/devices/bus/pofo/hpc104.h
@@ -33,26 +33,24 @@ public:
protected:
pofo_hpc104_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
-
- // optional information overrides
+ // device_t implementation
virtual void device_add_mconfig(machine_config &config) override;
virtual ioport_constructor device_input_ports() const override;
+ virtual void device_start() override;
+ virtual void device_reset() override;
- // device_nvram_interface overrides
- virtual void nvram_default() override { }
- virtual bool nvram_read(util::read_stream &file) override { size_t actual; return !file.read(m_nvram, 0x40000, actual) && actual == 0x40000; }
- virtual bool nvram_write(util::write_stream &file) override { size_t actual; return !file.write(m_nvram, 0x40000, actual) && actual == 0x40000; }
+ // device_nvram_interface implementation
+ virtual void nvram_default() override;
+ virtual bool nvram_read(util::read_stream &file) override;
+ virtual bool nvram_write(util::write_stream &file) override;
- // device_portfolio_expansion_slot_interface overrides
+ // device_portfolio_expansion_slot_interface implementation
virtual bool nmd1() override { return m_ccm->cdet_r(); }
virtual uint8_t nrdi_r(offs_t offset, uint8_t data, bool iom, bool bcom, bool ncc1) override;
virtual void nwri_w(offs_t offset, uint8_t data, bool iom, bool bcom, bool ncc1) override;
- virtual WRITE_LINE_MEMBER( iint_w ) override { m_exp->iint_w(state); }
+ virtual void iint_w(int state) override { m_exp->iint_w(state); }
private:
required_device<portfolio_memory_card_slot_device> m_ccm;
diff --git a/src/devices/bus/pofo/ram.cpp b/src/devices/bus/pofo/ram.cpp
index 7f1298b8b95..253b30d228b 100644
--- a/src/devices/bus/pofo/ram.cpp
+++ b/src/devices/bus/pofo/ram.cpp
@@ -44,6 +44,25 @@ void portfolio_ram_card_device::device_start()
}
+void portfolio_ram_card_device::nvram_default()
+{
+}
+
+
+bool portfolio_ram_card_device::nvram_read(util::read_stream &file)
+{
+ auto const [err, actual] = read(file, m_nvram, m_nvram.bytes());
+ return !err && (actual == m_nvram.bytes());
+}
+
+
+bool portfolio_ram_card_device::nvram_write(util::write_stream &file)
+{
+ auto const [err, actual] = write(file, m_nvram, m_nvram.bytes());
+ return !err;
+}
+
+
//-------------------------------------------------
// nrdi_r - read
//-------------------------------------------------
diff --git a/src/devices/bus/pofo/ram.h b/src/devices/bus/pofo/ram.h
index 7217299a989..0332d201fb9 100644
--- a/src/devices/bus/pofo/ram.h
+++ b/src/devices/bus/pofo/ram.h
@@ -30,15 +30,15 @@ public:
portfolio_ram_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
- // device_nvram_interface overrides
- virtual void nvram_default() override { }
- virtual bool nvram_read(util::read_stream &file) override { size_t actual; return !file.read(m_nvram, m_nvram.bytes(), actual) && actual == m_nvram.bytes(); }
- virtual bool nvram_write(util::write_stream &file) override { size_t actual; return !file.write(m_nvram, m_nvram.bytes(), actual) && actual == m_nvram.bytes(); }
+ // device_nvram_interface implementation
+ virtual void nvram_default() override;
+ virtual bool nvram_read(util::read_stream &file) override;
+ virtual bool nvram_write(util::write_stream &file) override;
- // device_portfolio_memory_card_slot_interface overrides
+ // device_portfolio_memory_card_slot_interface implementation
virtual bool cdet() override { return 0; }
virtual uint8_t nrdi_r(offs_t offset) override;
diff --git a/src/devices/bus/psi_kbd/psi_kbd.cpp b/src/devices/bus/psi_kbd/psi_kbd.cpp
index 1ba3a0e2620..08c072d2d68 100644
--- a/src/devices/bus/psi_kbd/psi_kbd.cpp
+++ b/src/devices/bus/psi_kbd/psi_kbd.cpp
@@ -53,10 +53,6 @@ void psi_keyboard_bus_device::device_start()
{
// get connected keyboard
m_kbd = get_card_device();
-
- // resolve callbacks
- m_rx_handler.resolve_safe();
- m_key_strobe_handler.resolve_safe();
}
//-------------------------------------------------
@@ -72,7 +68,7 @@ void psi_keyboard_bus_device::device_reset()
// host to module interface
//-------------------------------------------------
-WRITE_LINE_MEMBER( psi_keyboard_bus_device::tx_w )
+void psi_keyboard_bus_device::tx_w(int state)
{
if (m_kbd)
m_kbd->tx_w(state);
diff --git a/src/devices/bus/psi_kbd/psi_kbd.h b/src/devices/bus/psi_kbd/psi_kbd.h
index 364ef98586a..37e9f1f327e 100644
--- a/src/devices/bus/psi_kbd/psi_kbd.h
+++ b/src/devices/bus/psi_kbd/psi_kbd.h
@@ -61,12 +61,12 @@ public:
auto key_strobe() { return m_key_strobe_handler.bind(); }
// called from keyboard
- DECLARE_WRITE_LINE_MEMBER( rx_w ) { m_rx_handler(state); }
- DECLARE_WRITE_LINE_MEMBER( key_strobe_w ) { m_key_strobe_handler(state); }
+ void rx_w(int state) { m_rx_handler(state); }
+ void key_strobe_w(int state) { m_key_strobe_handler(state); }
void key_data_w(uint8_t data) { m_key_data = data; }
// called from host
- DECLARE_WRITE_LINE_MEMBER( tx_w );
+ void tx_w(int state);
uint8_t key_data_r() { return m_key_data; }
protected:
diff --git a/src/devices/bus/psion/honda/slot.cpp b/src/devices/bus/psion/honda/slot.cpp
new file mode 100644
index 00000000000..268fa9aadaf
--- /dev/null
+++ b/src/devices/bus/psion/honda/slot.cpp
@@ -0,0 +1,124 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Psion Honda Expansion slot emulation
+
+ This port is on Series 3c/3mx/Siena machines only.
+
+ TODO:
+ - add RS232 interface handlers
+
+**********************************************************************/
+
+#include "emu.h"
+#include "slot.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(PSION_HONDA_SLOT, psion_honda_slot_device, "psion_honda_slot", "Psion Honda Expansion slot")
+
+
+//**************************************************************************
+// DEVICE PSION_EXP PORT INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// device_psion_honda_interface - constructor
+//-------------------------------------------------
+
+device_psion_honda_interface::device_psion_honda_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "psionhonda")
+{
+ m_slot = dynamic_cast<psion_honda_slot_device *>(device.owner());
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// psion_honda_slot_device - constructor
+//-------------------------------------------------
+
+psion_honda_slot_device::psion_honda_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, PSION_HONDA_SLOT, tag, owner, clock)
+ , device_single_card_slot_interface<device_psion_honda_interface>(mconfig, *this)
+ , m_rxd_handler(*this)
+ , m_dcd_handler(*this)
+ , m_dsr_handler(*this)
+ , m_cts_handler(*this)
+ , m_sdoe_handler(*this)
+ , m_card(nullptr)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void psion_honda_slot_device::device_start()
+{
+ m_card = get_card_device();
+}
+
+
+//-------------------------------------------------
+// read
+//-------------------------------------------------
+
+uint8_t psion_honda_slot_device::data_r()
+{
+ return m_card ? m_card->data_r() : 0x00;
+}
+
+
+//-------------------------------------------------
+// write
+//-------------------------------------------------
+
+void psion_honda_slot_device::data_w(uint16_t data)
+{
+ if (m_card)
+ m_card->data_w(data);
+}
+
+void psion_honda_slot_device::write_txd(int state)
+{
+ if (m_card)
+ m_card->write_txd(state);
+}
+
+void psion_honda_slot_device::write_dtr(int state)
+{
+ if (m_card)
+ m_card->write_dtr(state);
+}
+
+void psion_honda_slot_device::write_rts(int state)
+{
+ if (m_card)
+ m_card->write_rts(state);
+}
+
+
+//-------------------------------------------------
+// SLOT_INTERFACE( psion_honda_devices )
+//-------------------------------------------------
+
+// slot devices
+//#include "parallel.h"
+//#include "pclink.h"
+#include "ssd.h"
+
+void psion_honda_devices(device_slot_interface &device)
+{
+ //device.option_add("parallel", PSION_PARALLEL); // Psion Parallel Printer Link cable
+ //device.option_add("pclink", PSION_PCLINK); // Psion PC Link cable
+ device.option_add("ssd", PSION_SIENA_SSD); // Psion Siena SSD Drive
+}
diff --git a/src/devices/bus/psion/honda/slot.h b/src/devices/bus/psion/honda/slot.h
new file mode 100644
index 00000000000..30ef50e1a3f
--- /dev/null
+++ b/src/devices/bus/psion/honda/slot.h
@@ -0,0 +1,119 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Psion Honda Expansion slot emulation
+
+**********************************************************************
+
+ Pin Name Comments
+
+ 1 VEXT
+ 2 RTS - RS232
+ 3 DTR - RS232
+ 4 TXD - RS232
+ 5 DSR - RS232
+ 6 DCD - RS232
+ 7 CTS - RS232
+ 8 RXD - RS232
+ 9 SDOE - SIBO data direction control
+ 10 EXTSTAT - active low SIBO peripheral detect line
+ 11 EXON - SIBO external turn-on
+ 12 INT - SIBO peripheral interrupt
+ 13 SD - SIBO serial data
+ 14 SCK - SIBO data clock
+ 15 GND - Signal and Power ground
+
+**********************************************************************/
+
+#ifndef MAME_BUS_PSION_HONDA_SLOT_H
+#define MAME_BUS_PSION_HONDA_SLOT_H
+
+#pragma once
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> psion_honda_slot_device
+
+class device_psion_honda_interface;
+
+class psion_honda_slot_device : public device_t, public device_single_card_slot_interface<device_psion_honda_interface>
+{
+public:
+ // construction/destruction
+ template <typename T>
+ psion_honda_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&slot_options, const char *default_option)
+ : psion_honda_slot_device(mconfig, tag, owner)
+ {
+ option_reset();
+ slot_options(*this);
+ set_default_option(default_option);
+ set_fixed(false);
+ }
+
+ psion_honda_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
+
+ // callbacks
+ auto rxd_handler() { return m_rxd_handler.bind(); }
+ auto dcd_handler() { return m_dcd_handler.bind(); }
+ auto dsr_handler() { return m_dsr_handler.bind(); }
+ auto cts_handler() { return m_cts_handler.bind(); }
+ auto sdoe_handler() { return m_sdoe_handler.bind(); }
+
+ uint8_t data_r();
+ void data_w(uint16_t data);
+
+ void write_txd(int state);
+ void write_dtr(int state);
+ void write_rts(int state);
+
+ void write_rxd(int state) { m_rxd_handler(state); }
+ void write_dcd(int state) { m_dcd_handler(state); }
+ void write_dsr(int state) { m_dsr_handler(state); }
+ void write_cts(int state) { m_cts_handler(state); }
+ void write_sdoe(int state) { m_sdoe_handler(state); }
+
+protected:
+ // device_t overrides
+ virtual void device_start() override;
+
+private:
+ devcb_write_line m_rxd_handler;
+ devcb_write_line m_dcd_handler;
+ devcb_write_line m_dsr_handler;
+ devcb_write_line m_cts_handler;
+ devcb_write_line m_sdoe_handler;
+
+ device_psion_honda_interface *m_card;
+};
+
+
+// ======================> device_psion_honda_interface
+
+class device_psion_honda_interface : public device_interface
+{
+public:
+ virtual void write_txd(int state) { }
+ virtual void write_dtr(int state) { }
+ virtual void write_rts(int state) { }
+
+ virtual uint8_t data_r() { return 0x00; }
+ virtual void data_w(uint16_t data) { }
+
+protected:
+ device_psion_honda_interface(const machine_config &mconfig, device_t &device);
+
+ psion_honda_slot_device *m_slot;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(PSION_HONDA_SLOT, psion_honda_slot_device)
+
+void psion_honda_devices(device_slot_interface &device);
+
+
+#endif // MAME_BUS_PSION_HONDA_SLOT_H
diff --git a/src/devices/bus/psion/honda/ssd.cpp b/src/devices/bus/psion/honda/ssd.cpp
new file mode 100644
index 00000000000..4fe09fa8843
--- /dev/null
+++ b/src/devices/bus/psion/honda/ssd.cpp
@@ -0,0 +1,56 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Psion Siena SSD Drive
+
+**********************************************************************/
+
+#include "emu.h"
+#include "ssd.h"
+#include "bus/rs232/rs232.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(PSION_SIENA_SSD, psion_siena_ssd_device, "psion_siena_ssd", "Psion Siena SSD Drive")
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void psion_siena_ssd_device::device_add_mconfig(machine_config &config)
+{
+ PSION_SSD(config, m_ssd);
+ m_ssd->door_cb().set(DEVICE_SELF_OWNER, FUNC(psion_honda_slot_device::write_sdoe));
+
+ RS232_PORT(config, "rs232", default_rs232_devices, nullptr);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// psion_siena_ssd_device - constructor
+//-------------------------------------------------
+
+psion_siena_ssd_device::psion_siena_ssd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, PSION_SIENA_SSD, tag, owner, clock)
+ , device_psion_honda_interface(mconfig, *this)
+ , m_ssd(*this, "ssd")
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void psion_siena_ssd_device::device_start()
+{
+}
diff --git a/src/devices/bus/psion/honda/ssd.h b/src/devices/bus/psion/honda/ssd.h
new file mode 100644
index 00000000000..171b0549110
--- /dev/null
+++ b/src/devices/bus/psion/honda/ssd.h
@@ -0,0 +1,51 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Psion Siena SSD Drive
+
+**********************************************************************/
+
+#ifndef MAME_BUS_PSION_HONDA_SSD_H
+#define MAME_BUS_PSION_HONDA_SSD_H
+
+#include "slot.h"
+#include "machine/psion_ssd.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> psion_siena_ssd_device
+
+class psion_siena_ssd_device :
+ public device_t,
+ public device_psion_honda_interface
+{
+public:
+ // construction/destruction
+ psion_siena_ssd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ static constexpr feature_type unemulated_features() { return feature::COMMS; }
+
+protected:
+ // device_t overrides
+ virtual void device_start() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+
+ virtual uint8_t data_r() override { return m_ssd->data_r(); }
+ virtual void data_w(uint16_t data) override { m_ssd->data_w(data); }
+
+private:
+ required_device<psion_ssd_device> m_ssd;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(PSION_SIENA_SSD, psion_siena_ssd_device)
+
+
+#endif // MAME_BUS_PSION_HONDA_SSD_H
diff --git a/src/devices/bus/psion/module/slot.cpp b/src/devices/bus/psion/module/slot.cpp
new file mode 100644
index 00000000000..55107f8f3ac
--- /dev/null
+++ b/src/devices/bus/psion/module/slot.cpp
@@ -0,0 +1,113 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Psion Extended Internal Expansion slot emulation
+
+ This port is on Series MC/HC machines only.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "slot.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(PSION_MODULE_SLOT, psion_module_slot_device, "psion_module_slot", "Psion Extended Internal Expansion slot")
+
+
+//**************************************************************************
+// DEVICE PSION_EXP PORT INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// device_psion_module_interface - constructor
+//-------------------------------------------------
+
+device_psion_module_interface::device_psion_module_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "psionmodule")
+{
+ m_slot = dynamic_cast<psion_module_slot_device *>(device.owner());
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// psion_module_slot_device - constructor
+//-------------------------------------------------
+
+psion_module_slot_device::psion_module_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, PSION_MODULE_SLOT, tag, owner, clock)
+ , device_single_card_slot_interface<device_psion_module_interface>(mconfig, *this)
+ , m_card(nullptr)
+ , m_intr_cb(*this)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void psion_module_slot_device::device_start()
+{
+ m_card = get_card_device();
+}
+
+
+//-------------------------------------------------
+// read
+//-------------------------------------------------
+
+uint8_t psion_module_slot_device::data_r()
+{
+ return m_card ? m_card->data_r() : 0x00;
+}
+
+uint8_t psion_module_slot_device::io_r(offs_t offset)
+{
+ if (m_card)
+ return m_card->io_r(offset);
+ else
+ return 0x00;
+}
+
+
+//-------------------------------------------------
+// write
+//-------------------------------------------------
+
+void psion_module_slot_device::data_w(uint16_t data)
+{
+ if (m_card)
+ m_card->data_w(data);
+}
+
+void psion_module_slot_device::io_w(offs_t offset, uint8_t data)
+{
+ if (m_card)
+ m_card->io_w(offset, data);
+}
+
+
+//-------------------------------------------------
+// SLOT_INTERFACE( psion_module_devices )
+//-------------------------------------------------
+
+// slot devices
+//#include "rs232parallel"
+//#include "rs232ttl"
+
+void psion_hcmodule_devices(device_slot_interface &device)
+{
+}
+
+void psion_mcmodule_devices(device_slot_interface &device)
+{
+}
diff --git a/src/devices/bus/psion/module/slot.h b/src/devices/bus/psion/module/slot.h
new file mode 100644
index 00000000000..8919277627b
--- /dev/null
+++ b/src/devices/bus/psion/module/slot.h
@@ -0,0 +1,116 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Psion Extended Internal Expansion slot emulation
+
+**********************************************************************
+
+ Pin Name Comments
+
+ 1 GND Should mate first when device inserted
+ 2 GND Should mate first when device inserted
+ 3 AD0 8 bit multiplexed address and data bus pulled low
+ 4 AD1
+ 5 AD2
+ 6 AD3
+ 7 AD4
+ 8 AD5
+ 9 AD6
+ 10 AD7
+ 11 ALE Address latch enable - high when valid address on AD0-AD7
+ 12 IOWR I/O write strobe - active high, data valid on falling edge
+ 13 IORD I/O read strobe - high when device can place valid data on AD0-AD7
+ 14 EES External Expansion Select - high during I/O cycles to expansion device
+ 15 SCLX 512 KHz SCL signal for SLD bus - usually Hi-Z and pulled low
+ 16 DNC For future expansion - do not use
+ 17 THERM Connected to thermistor
+ 18 VB1 Connected to internal NiCd battery
+ 19 Vsup Unregulated battery voltage - present all the time
+ 20 INTR Active high interrupt input
+ 21 _EXON Active low input pulled up to Vcc1 - pull low to switch machine on
+ 22 SD SIBO serial protocol data line - pulled low
+ 23 SCLK SIBO serial protocol clock line - Hi-Z in standby needs a pull down
+ 24 GND 0v
+ 25 Vcc2 +5 volt supply, switched off in standby
+
+**********************************************************************/
+
+#ifndef MAME_BUS_PSION_MODULE_SLOT_H
+#define MAME_BUS_PSION_MODULE_SLOT_H
+
+#pragma once
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> psion_module_slot_device
+
+class device_psion_module_interface;
+
+class psion_module_slot_device : public device_t, public device_single_card_slot_interface<device_psion_module_interface>
+{
+public:
+ // construction/destruction
+ template <typename T>
+ psion_module_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&slot_options, const char *default_option)
+ : psion_module_slot_device(mconfig, tag, owner)
+ {
+ option_reset();
+ slot_options(*this);
+ set_default_option(default_option);
+ set_fixed(false);
+ }
+
+ psion_module_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
+
+ // callbacks
+ auto intr_cb() { return m_intr_cb.bind(); }
+
+ uint8_t io_r(offs_t offset);
+ void io_w(offs_t offset, uint8_t data);
+
+ uint8_t data_r();
+ void data_w(uint16_t data);
+
+ void intr_w(int state) { m_intr_cb(state); }
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+
+ device_psion_module_interface *m_card;
+
+private:
+ devcb_write_line m_intr_cb;
+};
+
+
+// ======================> device_psion_module_interface
+
+class device_psion_module_interface : public device_interface
+{
+public:
+ virtual uint8_t io_r(offs_t offset) { return 0x00; }
+ virtual void io_w(offs_t offset, uint8_t data) { }
+
+ virtual uint8_t data_r() { return 0x00; }
+ virtual void data_w(uint16_t data) { }
+
+protected:
+ device_psion_module_interface(const machine_config &mconfig, device_t &device);
+
+ psion_module_slot_device *m_slot;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(PSION_MODULE_SLOT, psion_module_slot_device)
+
+void psion_hcmodule_devices(device_slot_interface &device);
+void psion_mcmodule_devices(device_slot_interface &device);
+
+
+#endif // MAME_BUS_PSION_MODULE_SLOT_H
diff --git a/src/devices/bus/gamegear/smsctrladp.cpp b/src/devices/bus/psion/sibo/3fax.cpp
index d066f815697..9a5119c3d8d 100644
--- a/src/devices/bus/gamegear/smsctrladp.cpp
+++ b/src/devices/bus/psion/sibo/3fax.cpp
@@ -1,84 +1,84 @@
// license:BSD-3-Clause
-// copyright-holders:Fabio Priuli
+// copyright-holders:Nigel Barnes
/**********************************************************************
- Sega Game Gear "SMS Controller Adaptor" emulation
- Also known as "Master Link" cable.
+ Psion 3-Fax Modem
+
+ TODO: add other devices
+ - 32K RAM (KM62256)
+ - R6653-21
+ - Flash N28F010-150
**********************************************************************/
#include "emu.h"
-#include "smsctrladp.h"
-
+#include "3fax.h"
//**************************************************************************
// DEVICE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(SMS_CTRL_ADAPTOR, sms_ctrl_adaptor_device, "sms_ctrl_adaptor", "SMS Controller Adaptor")
-
+DEFINE_DEVICE_TYPE(PSION_3FAX_MODEM, psion_3fax_modem_device, "psion_3fax", "Psion 3-Fax Modem")
-//**************************************************************************
-// LIVE DEVICE
-//**************************************************************************
//-------------------------------------------------
-// sms_ctrl_adaptor_device - constructor
+// ROM( 3fax )
//-------------------------------------------------
-sms_ctrl_adaptor_device::sms_ctrl_adaptor_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, SMS_CTRL_ADAPTOR, tag, owner, clock),
- device_gg_ext_port_interface(mconfig, *this),
- m_subctrl_port(*this, "ctrl")
-{
-}
-
+ROM_START(3fax)
+ ROM_REGION(0x100000, "rom", 0)
+ ROM_LOAD("3fax_v2.01.rom", 0x0000, 0x100000, CRC(55c7c95b) SHA1(85d6f7e3cd316be5f49e7dd25755673144fce3d7))
+ROM_END
//-------------------------------------------------
-// device_start - device-specific startup
+// rom_region - device-specific ROM region
//-------------------------------------------------
-void sms_ctrl_adaptor_device::device_start()
+const tiny_rom_entry *psion_3fax_modem_device::device_rom_region() const
{
+ return ROM_NAME(3fax);
}
-//-------------------------------------------------
-// sms_peripheral_r - sms_ctrl_adaptor read
-//-------------------------------------------------
-
-uint8_t sms_ctrl_adaptor_device::peripheral_r()
+void psion_3fax_modem_device::asic4_map(address_map &map)
{
- return m_subctrl_port->port_r();
+ map(0x400000, 0x4fffff).rom().region("rom", 0);
}
//-------------------------------------------------
-// sms_peripheral_w - sms_ctrl_adaptor write
+// device_add_mconfig - add device configuration
//-------------------------------------------------
-void sms_ctrl_adaptor_device::peripheral_w(uint8_t data)
+void psion_3fax_modem_device::device_add_mconfig(machine_config &config)
{
- m_subctrl_port->port_w(data);
+ PSION_ASIC4(config, m_asic4);
+ m_asic4->set_ext_info_byte(0xac6);
+ m_asic4->set_addrmap(0, &psion_3fax_modem_device::asic4_map);
}
-WRITE_LINE_MEMBER( sms_ctrl_adaptor_device::th_pin_w )
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// psion_3fax_modem_device - constructor
+//-------------------------------------------------
+
+psion_3fax_modem_device::psion_3fax_modem_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, PSION_3FAX_MODEM, tag, owner, clock)
+ , device_psion_sibo_interface(mconfig, *this)
+ , m_asic4(*this, "asic4")
{
- m_port->th_pin_w(state);
}
//-------------------------------------------------
-// device_add_mconfig - add device configuration
+// device_start - device-specific startup
//-------------------------------------------------
-void sms_ctrl_adaptor_device::device_add_mconfig(machine_config &config)
+void psion_3fax_modem_device::device_start()
{
- SMS_CONTROL_PORT(config, m_subctrl_port, sms_control_port_devices, "joypad");
- if (m_port != nullptr)
- m_subctrl_port->set_screen_tag(m_port->m_screen);
- m_subctrl_port->th_input_handler().set(FUNC(sms_ctrl_adaptor_device::th_pin_w));
}
-
diff --git a/src/devices/bus/psion/sibo/3fax.h b/src/devices/bus/psion/sibo/3fax.h
new file mode 100644
index 00000000000..744e1cf0c6b
--- /dev/null
+++ b/src/devices/bus/psion/sibo/3fax.h
@@ -0,0 +1,54 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Psion 3-Fax Modem
+
+**********************************************************************/
+
+#ifndef MAME_BUS_PSION_SIBO_3FAX_H
+#define MAME_BUS_PSION_SIBO_3FAX_H
+
+#include "slot.h"
+#include "machine/psion_asic4.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> psion_3fax_modem_device
+
+class psion_3fax_modem_device :
+ public device_t,
+ public device_psion_sibo_interface
+{
+public:
+ // construction/destruction
+ psion_3fax_modem_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ static constexpr feature_type unemulated_features() { return feature::COMMS; }
+
+protected:
+ // device_t overrides
+ virtual void device_start() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+ virtual uint8_t data_r() override { return m_asic4->data_r(); }
+ virtual void data_w(uint16_t data) override { m_asic4->data_w(data); }
+
+private:
+ required_device<psion_asic4_device> m_asic4;
+
+ void asic4_map(address_map &map);
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(PSION_3FAX_MODEM, psion_3fax_modem_device)
+
+
+#endif // MAME_BUS_PSION_SIBO_3FAX_H
diff --git a/src/devices/bus/psion/sibo/3link.cpp b/src/devices/bus/psion/sibo/3link.cpp
new file mode 100644
index 00000000000..08d0af0aa0e
--- /dev/null
+++ b/src/devices/bus/psion/sibo/3link.cpp
@@ -0,0 +1,151 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Psion 3-Link RS232 Serial Interface / Parallel Printer Interface
+
+ Note:
+ The Acorn A-Link RS232 Serial Interface has a slightly different wiring
+ to the 3-Link. The A-Link will work fine with PC software, and plugged
+ into a PC, but the 3-Link will not work with the Acorn software.
+
+ The 3-Link and A-Link have been confirmed to have the same ROM.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "3link.h"
+#include "bus/centronics/ctronics.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(PSION_3LINK_SERIAL, psion_3link_serial_device, "psion_3link_ser", "Psion 3-Link RS232 Serial Interface")
+DEFINE_DEVICE_TYPE(PSION_3LINK_PARALLEL, psion_3link_parallel_device, "psion_3link_par", "Psion 3-Link Parallel Printer Interface")
+
+
+//-------------------------------------------------
+// ROM( 3link_serial )
+//-------------------------------------------------
+
+ROM_START(3link_serial)
+ ROM_REGION(0x20000, "rom", 0)
+ ROM_LOAD("3link_v1.21f.rom", 0x0000, 0x20000, CRC(211f6218) SHA1(11cab06779ea19f109970dfa641b89f0121bfd95))
+ROM_END
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+const tiny_rom_entry *psion_3link_serial_device::device_rom_region() const
+{
+ return ROM_NAME(3link_serial);
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void psion_3link_serial_device::device_add_mconfig(machine_config &config)
+{
+ PSION_ASIC5(config, m_asic5, 1'536'000).set_mode(psion_asic5_device::PERIPHERAL_MODE); // TODO: clock derived from host
+ m_asic5->set_info_byte(0x05); // ROM + RS232
+ m_asic5->readpa_handler().set([this]() { return m_rom[m_addr_latch & 0x1ffff]; });
+ m_asic5->writepb_handler().set([this](uint8_t data) { m_addr_latch = (m_addr_latch & 0xffff00) | (data << 0); });
+ m_asic5->writepd_handler().set([this](uint8_t data) { m_addr_latch = (m_addr_latch & 0xff00ff) | (data << 8); });
+ m_asic5->writecs_handler().set([this](uint8_t data) { m_addr_latch = (m_addr_latch & 0x00ffff) | (BIT(~data, 1) << 16); });
+ m_asic5->txd_handler().set(m_rs232, FUNC(rs232_port_device::write_txd));
+ m_asic5->rts_handler().set(m_rs232, FUNC(rs232_port_device::write_rts));
+ m_asic5->dtr_handler().set(m_rs232, FUNC(rs232_port_device::write_dtr));
+ m_asic5->int_handler().set(DEVICE_SELF_OWNER, FUNC(psion_sibo_slot_device::int_w));
+
+ RS232_PORT(config, m_rs232, default_rs232_devices, nullptr);
+ m_rs232->rxd_handler().set(m_asic5, FUNC(psion_asic5_device::write_rxd));
+ m_rs232->dcd_handler().set(m_asic5, FUNC(psion_asic5_device::write_dcd));
+ m_rs232->dsr_handler().set(m_asic5, FUNC(psion_asic5_device::write_dsr));
+ m_rs232->cts_handler().set(m_asic5, FUNC(psion_asic5_device::write_cts));
+}
+
+void psion_3link_parallel_device::device_add_mconfig(machine_config &config)
+{
+ PSION_ASIC5(config, m_asic5, 1'536'000).set_mode(psion_asic5_device::PERIPHERAL_MODE); // TODO: clock derived from host
+ m_asic5->set_info_byte(0x02); // Parallel
+ m_asic5->readpa_handler().set("cent_status_in", FUNC(input_buffer_device::read));
+ m_asic5->writepb_handler().set("cent_data_out", FUNC(output_latch_device::write));
+ m_asic5->writepc_handler().set("cent_ctrl_out", FUNC(output_latch_device::write));
+
+ centronics_device &centronics(CENTRONICS(config, "centronics", centronics_devices, "printer"));
+ centronics.busy_handler().set("cent_status_in", FUNC(input_buffer_device::write_bit4));
+ centronics.ack_handler().set("cent_status_in", FUNC(input_buffer_device::write_bit5));
+ centronics.fault_handler().set("cent_status_in", FUNC(input_buffer_device::write_bit6));
+ centronics.perror_handler().set("cent_status_in", FUNC(input_buffer_device::write_bit7));
+
+ output_latch_device &cent_data_out(OUTPUT_LATCH(config, "cent_data_out"));
+ centronics.set_output_latch(cent_data_out);
+
+ output_latch_device &cent_ctrl_out(OUTPUT_LATCH(config, "cent_ctrl_out"));
+ cent_ctrl_out.bit_handler<4>().set("centronics", FUNC(centronics_device::write_strobe));
+ cent_ctrl_out.bit_handler<5>().set("centronics", FUNC(centronics_device::write_init));
+ cent_ctrl_out.bit_handler<6>().set("centronics", FUNC(centronics_device::write_autofd));
+ cent_ctrl_out.bit_handler<7>().set("centronics", FUNC(centronics_device::write_select_in));
+
+ INPUT_BUFFER(config, "cent_status_in");
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// psion_3link_device - constructor
+//-------------------------------------------------
+
+psion_3link_serial_device::psion_3link_serial_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, PSION_3LINK_SERIAL, tag, owner, clock)
+ , device_psion_sibo_interface(mconfig, *this)
+ , m_rom(*this, "rom")
+ , m_asic5(*this, "asic5")
+ , m_rs232(*this, "rs232")
+{
+}
+
+psion_3link_parallel_device::psion_3link_parallel_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, PSION_3LINK_PARALLEL, tag, owner, clock)
+ , device_psion_sibo_interface(mconfig, *this)
+ , m_asic5(*this, "asic5")
+ , m_cent_ctrl_out(*this, "cent_ctrl_out")
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void psion_3link_serial_device::device_start()
+{
+ save_item(NAME(m_addr_latch));
+}
+
+void psion_3link_parallel_device::device_start()
+{
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void psion_3link_serial_device::device_reset()
+{
+ m_addr_latch = 0x00;
+}
+
+void psion_3link_parallel_device::device_reset()
+{
+ m_cent_ctrl_out->write(0xff); // pullups
+}
diff --git a/src/devices/bus/psion/sibo/3link.h b/src/devices/bus/psion/sibo/3link.h
new file mode 100644
index 00000000000..fba517b98b8
--- /dev/null
+++ b/src/devices/bus/psion/sibo/3link.h
@@ -0,0 +1,83 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Psion 3-Link RS232 Serial Interface / Parallel Printer Interface
+
+**********************************************************************/
+
+#ifndef MAME_BUS_PSION_SIBO_3LINK_H
+#define MAME_BUS_PSION_SIBO_3LINK_H
+
+#include "slot.h"
+#include "machine/output_latch.h"
+#include "machine/psion_asic5.h"
+#include "bus/rs232/rs232.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> psion_3link_serial_device
+
+class psion_3link_serial_device : public device_t, public device_psion_sibo_interface
+{
+public:
+ // construction/destruction
+ psion_3link_serial_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ static constexpr feature_type imperfect_features() { return feature::COMMS; }
+
+protected:
+ // device_t overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+ virtual uint8_t data_r() override { return m_asic5->data_r(); }
+ virtual void data_w(uint16_t data) override { m_asic5->data_w(data); }
+
+private:
+ required_region_ptr<uint8_t> m_rom;
+ required_device<psion_asic5_device> m_asic5;
+ required_device<rs232_port_device> m_rs232;
+
+ uint32_t m_addr_latch;
+};
+
+
+// ======================> psion_3link_parallel_device
+
+class psion_3link_parallel_device : public device_t, public device_psion_sibo_interface
+{
+public:
+ // construction/destruction
+ psion_3link_parallel_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device_t overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+
+ virtual uint8_t data_r() override { return m_asic5->data_r(); }
+ virtual void data_w(uint16_t data) override { m_asic5->data_w(data); }
+
+private:
+ required_device<psion_asic5_device> m_asic5;
+ required_device<output_latch_device> m_cent_ctrl_out;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(PSION_3LINK_SERIAL, psion_3link_serial_device)
+DECLARE_DEVICE_TYPE(PSION_3LINK_PARALLEL, psion_3link_parallel_device)
+
+
+#endif // MAME_BUS_PSION_SIBO_3LINK_H
diff --git a/src/devices/bus/psion/sibo/slot.cpp b/src/devices/bus/psion/sibo/slot.cpp
new file mode 100644
index 00000000000..bc45988e2c4
--- /dev/null
+++ b/src/devices/bus/psion/sibo/slot.cpp
@@ -0,0 +1,98 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Psion Reduced External Expansion slot emulation
+
+ This port is on Series 3/3a machines only.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "slot.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(PSION_SIBO_SLOT, psion_sibo_slot_device, "psion_sibo_slot", "Psion Reduced External Expansion slot")
+
+
+//**************************************************************************
+// DEVICE PSION_EXP PORT INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// device_psion_sibo_interface - constructor
+//-------------------------------------------------
+
+device_psion_sibo_interface::device_psion_sibo_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "psionsibo")
+{
+ m_slot = dynamic_cast<psion_sibo_slot_device *>(device.owner());
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// psion_sibo_slot_device - constructor
+//-------------------------------------------------
+
+psion_sibo_slot_device::psion_sibo_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, PSION_SIBO_SLOT, tag, owner, clock)
+ , device_single_card_slot_interface<device_psion_sibo_interface>(mconfig, *this)
+ , m_int_cb(*this)
+ , m_card(nullptr)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void psion_sibo_slot_device::device_start()
+{
+ m_card = get_card_device();
+}
+
+
+//-------------------------------------------------
+// read
+//-------------------------------------------------
+
+uint8_t psion_sibo_slot_device::data_r()
+{
+ return m_card ? m_card->data_r() : 0x00;
+}
+
+
+//-------------------------------------------------
+// write
+//-------------------------------------------------
+
+void psion_sibo_slot_device::data_w(uint16_t data)
+{
+ if (m_card)
+ m_card->data_w(data);
+}
+
+
+//-------------------------------------------------
+// SLOT_INTERFACE( psion_sibo_devices )
+//-------------------------------------------------
+
+// slot devices
+#include "3fax.h"
+#include "3link.h"
+
+void psion_sibo_devices(device_slot_interface &device)
+{
+ device.option_add("fax", PSION_3FAX_MODEM); // Psion 3-Fax Modem
+ device.option_add("parallel", PSION_3LINK_PARALLEL); // Psion 3-Link Parallel Printer Interface
+ device.option_add("serial", PSION_3LINK_SERIAL); // Psion 3-Link RS232 Serial Interface
+}
diff --git a/src/devices/bus/psion/sibo/slot.h b/src/devices/bus/psion/sibo/slot.h
new file mode 100644
index 00000000000..c4f9a9f0429
--- /dev/null
+++ b/src/devices/bus/psion/sibo/slot.h
@@ -0,0 +1,90 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Psion Reduced External Expansion slot emulation
+
+**********************************************************************
+
+ Pin Name Comments
+
+ 1 MSD Master SIBO serial protocol data line - pulled low
+ 2 MCLK Master SIBO serial protocol clock line - low in standby
+ 3 Vcc +5 volt supply, switched off in standby
+ 4 GND Signal ground, this signal should mate first when connector inserted
+ 5 SSD/INT Slave SIBO serial data line or active high interrupt input
+ 6 SCK/EXON Slave SIBO serial clock line or active high switch on input
+
+**********************************************************************/
+
+#ifndef MAME_BUS_PSION_SIBO_SLOT_H
+#define MAME_BUS_PSION_SIBO_SLOT_H
+
+#pragma once
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> psion_sibo_slot_device
+
+class device_psion_sibo_interface;
+
+class psion_sibo_slot_device : public device_t, public device_single_card_slot_interface<device_psion_sibo_interface>
+{
+public:
+ // construction/destruction
+ template <typename T>
+ psion_sibo_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&slot_options, const char *default_option)
+ : psion_sibo_slot_device(mconfig, tag, owner)
+ {
+ option_reset();
+ slot_options(*this);
+ set_default_option(default_option);
+ set_fixed(false);
+ }
+
+ psion_sibo_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
+
+ // callbacks
+ auto int_cb() { return m_int_cb.bind(); }
+
+ uint8_t data_r();
+ void data_w(uint16_t data);
+
+ void int_w(int state) { m_int_cb(state); }
+
+protected:
+ // device_t overrides
+ virtual void device_start() override;
+
+private:
+ devcb_write_line m_int_cb;
+
+ device_psion_sibo_interface *m_card;
+};
+
+
+// ======================> device_psion_sibo_interface
+
+class device_psion_sibo_interface : public device_interface
+{
+public:
+ virtual uint8_t data_r() { return 0x00; }
+ virtual void data_w(uint16_t data) { }
+
+protected:
+ device_psion_sibo_interface(const machine_config &mconfig, device_t &device);
+
+ psion_sibo_slot_device *m_slot;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(PSION_SIBO_SLOT, psion_sibo_slot_device)
+
+void psion_sibo_devices(device_slot_interface &device);
+
+
+#endif // MAME_BUS_PSION_SIBO_SLOT_H
diff --git a/src/devices/bus/psx/ctlrport.cpp b/src/devices/bus/psx/ctlrport.cpp
index 1e6158ff614..bd445add41e 100644
--- a/src/devices/bus/psx/ctlrport.cpp
+++ b/src/devices/bus/psx/ctlrport.cpp
@@ -4,9 +4,11 @@
#include "emu.h"
#include "ctlrport.h"
+
#include "analogue.h"
#include "multitap.h"
+
DEFINE_DEVICE_TYPE(PSX_CONTROLLER_PORT, psx_controller_port_device, "psx_controller_port", "Playstation Controller Port")
DEFINE_DEVICE_TYPE(PSXCONTROLLERPORTS, psxcontrollerports_device, "psxcontrollerports", "Playstation Controller Bus")
DEFINE_DEVICE_TYPE(PSX_STANDARD_CONTROLLER, psx_standard_controller_device, "psx_standard_controller", "Playstation Standard Controller")
@@ -14,6 +16,7 @@ DEFINE_DEVICE_TYPE(PSX_STANDARD_CONTROLLER, psx_standard_controller_device, "psx
psx_controller_port_device::psx_controller_port_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, PSX_CONTROLLER_PORT, tag, owner, clock),
device_single_card_slot_interface<device_psx_controller_interface>(mconfig, *this),
+ m_ack_cb(*this),
m_tx(false),
m_dev(nullptr),
m_card(*this, "card")
@@ -49,11 +52,8 @@ psxcontrollerports_device::psxcontrollerports_device(const machine_config &mconf
void psxcontrollerports_device::device_start()
{
- m_dsr_handler.resolve_safe();
- m_rxd_handler.resolve_safe();
-
- m_port0->setup_ack_cb(psx_controller_port_device::void_cb(&psxcontrollerports_device::ack, this));
- m_port1->setup_ack_cb(psx_controller_port_device::void_cb(&psxcontrollerports_device::ack, this));
+ m_port0->set_ack_cb(*this, FUNC(psxcontrollerports_device::ack));
+ m_port1->set_ack_cb(*this, FUNC(psxcontrollerports_device::ack));
}
// add controllers to define so they can be connected to the multitap
@@ -73,20 +73,20 @@ void psx_controllers_nomulti(device_slot_interface &device)
PSX_CONTROLLERS
}
-WRITE_LINE_MEMBER(psxcontrollerports_device::write_dtr)
+void psxcontrollerports_device::write_dtr(int state)
{
m_port0->sel_w(!state);
m_port1->sel_w(state);
}
-WRITE_LINE_MEMBER(psxcontrollerports_device::write_sck)
+void psxcontrollerports_device::write_sck(int state)
{
m_port0->clock_w(state);
m_port1->clock_w(state);
m_rxd_handler(m_port0->rx_r() && m_port1->rx_r());
}
-WRITE_LINE_MEMBER(psxcontrollerports_device::write_txd)
+void psxcontrollerports_device::write_txd(int state)
{
m_port0->tx_w(state);
m_port1->tx_w(state);
diff --git a/src/devices/bus/psx/ctlrport.h b/src/devices/bus/psx/ctlrport.h
index 5c8fc82dd22..0fc7fba52d7 100644
--- a/src/devices/bus/psx/ctlrport.h
+++ b/src/devices/bus/psx/ctlrport.h
@@ -89,9 +89,9 @@ public:
auto dsr() { return m_dsr_handler.bind(); }
auto rxd() { return m_rxd_handler.bind(); }
- DECLARE_WRITE_LINE_MEMBER(write_sck);
- DECLARE_WRITE_LINE_MEMBER(write_dtr);
- DECLARE_WRITE_LINE_MEMBER(write_txd);
+ void write_sck(int state);
+ void write_dtr(int state);
+ void write_txd(int state);
protected:
virtual void device_start() override;
@@ -108,6 +108,8 @@ class psx_controller_port_device : public device_t,
public device_single_card_slot_interface<device_psx_controller_interface>
{
public:
+ typedef device_delegate<void ()> void_cb;
+
template <typename T>
psx_controller_port_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts, char const *dflt)
: psx_controller_port_device(mconfig, tag, owner, (uint32_t)0)
@@ -119,29 +121,30 @@ public:
}
psx_controller_port_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- typedef delegate<void ()> void_cb;
- void ack() { if(!ack_cb.isnull()) ack_cb(); }
- void setup_ack_cb(void_cb cb) { ack_cb = cb; }
+ template <typename... T>
+ void set_ack_cb(T &&... args) { m_ack_cb.set(std::forward<T>(args)...); }
+
+ void ack() { m_ack_cb(); }
- DECLARE_WRITE_LINE_MEMBER(tx_w) { m_tx = state; }
- DECLARE_WRITE_LINE_MEMBER(sel_w) { if(m_dev) m_dev->sel_w(state); m_card->sel_w(state); }
- DECLARE_WRITE_LINE_MEMBER(clock_w) { if(m_dev) m_dev->clock_w(state); m_card->clock_w(state); }
+ void tx_w(int state) { m_tx = state; }
+ void sel_w(int state) { if(m_dev) m_dev->sel_w(state); m_card->sel_w(state); }
+ void clock_w(int state) { if(m_dev) m_dev->clock_w(state); m_card->clock_w(state); }
- DECLARE_READ_LINE_MEMBER(rx_r) { return (m_dev?m_dev->rx_r():true) && m_card->rx_r(); }
- DECLARE_READ_LINE_MEMBER(ack_r) { return (m_dev?m_dev->ack_r():true) && m_card->ack_r(); }
- DECLARE_READ_LINE_MEMBER(tx_r) { return m_tx; }
+ int rx_r() { return (m_dev?m_dev->rx_r():true) && m_card->rx_r(); }
+ int ack_r() { return (m_dev?m_dev->ack_r():true) && m_card->ack_r(); }
+ int tx_r() { return m_tx; }
void disable_card(bool status);
protected:
- virtual void device_start() override {}
+ virtual void device_start() override { m_ack_cb.resolve_safe(); }
virtual void device_reset() override { m_tx = true; }
virtual void device_config_complete() override;
virtual void device_add_mconfig(machine_config &config) override;
private:
- void_cb ack_cb;
+ void_cb m_ack_cb;
bool m_tx;
device_psx_controller_interface *m_dev;
diff --git a/src/devices/bus/psx/gamebooster.cpp b/src/devices/bus/psx/gamebooster.cpp
index 87dee3d9530..1c414ca41a2 100644
--- a/src/devices/bus/psx/gamebooster.cpp
+++ b/src/devices/bus/psx/gamebooster.cpp
@@ -11,8 +11,17 @@
#include "emu.h"
#include "gamebooster.h"
+#include "bus/gameboy/carts.h"
+#include "bus/gameboy/gbslot.h"
+
#include "softlist_dev.h"
+#include <utility>
+
+//#define VERBOSE 1
+#include "logmacro.h"
+
+
//**************************************************************************
// DEVICE DEFINITIONS
//**************************************************************************
@@ -24,18 +33,10 @@ DEFINE_DEVICE_TYPE(PSX_GAMEBOOSTER, psx_gamebooster_device, "psxgboost", "Datel
//-------------------------------------------------
ROM_START( psxgboost )
- ROM_REGION(0x40000, "rom", 0)
+ ROM_REGION16_LE(0x40000, "rom", 0)
ROM_LOAD("game booster.rom", 0x0000, 0x40000, CRC(c8e459b8) SHA1(c20ab073f61242f37665f12199b95cfa3a83e9fc) )
ROM_END
-//-------------------------------------------------
-// rom_region - device-specific ROM region
-//-------------------------------------------------
-
-const tiny_rom_entry *psx_gamebooster_device::device_rom_region() const
-{
- return ROM_NAME( psxgboost );
-}
//**************************************************************************
// LIVE DEVICE
@@ -48,53 +49,77 @@ const tiny_rom_entry *psx_gamebooster_device::device_rom_region() const
psx_gamebooster_device::psx_gamebooster_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, PSX_GAMEBOOSTER, tag, owner, clock)
, psx_parallel_interface(mconfig, *this)
+ , device_memory_interface(mconfig, *this)
, m_rom(*this, "rom")
- , m_cartslot(*this, "gbslot")
+ , m_cart_config("cart", ENDIANNESS_LITTLE, 8, 16, 0)
{
}
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-void psx_gamebooster_device::device_start()
+//**************************************************************************
+// DEVICE_T IMPLEMENTATION
+//**************************************************************************
+
+const tiny_rom_entry *psx_gamebooster_device::device_rom_region() const
{
+ return ROM_NAME( psxgboost );
}
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
+void psx_gamebooster_device::device_add_mconfig(machine_config &config)
+{
+ GB_CART_SLOT(config, "gbslot", gameboy_cartridges, nullptr).set_space(DEVICE_SELF, 0);
+
+ SOFTWARE_LIST(config, "cart_list").set_original("gameboy");
+ SOFTWARE_LIST(config, "gbc_list").set_compatible("gbcolor");
+}
+
+void psx_gamebooster_device::device_start()
+{
+ space(0).specific(m_cart_space);
+}
void psx_gamebooster_device::device_reset()
{
}
+
//**************************************************************************
-// IMPLEMENTATION
+// DEVICE_MEMORY_INTERFACE IMPLEMENTATION
+//**************************************************************************
+
+device_memory_interface::space_config_vector psx_gamebooster_device::memory_space_config() const
+{
+ return space_config_vector{ std::make_pair(0, &m_cart_config) };
+}
+
+
+//**************************************************************************
+// PSX_PARALLEL_INTERFACE IMPLEMENTATION
//**************************************************************************
uint16_t psx_gamebooster_device::exp_r(offs_t offset, uint16_t mem_mask)
{
if (offset < 0x20000)
{
- return m_rom->base()[(offset * 2) & 0x3ffff] | (m_rom->base()[((offset * 2) + 1) & 0x3ffff] << 8);
+ return m_rom[offset & 0x1ffff];
}
else if (offset < 0x24000)
{
offset -= 0x20000;
uint16_t retval = 0;
- if (mem_mask & 0xff00) retval |= (m_cartslot->read_rom((offset*2)+1))<<8;
- if (mem_mask & 0x00ff) retval |= m_cartslot->read_rom((offset*2)+0);
+
+ if (mem_mask & 0xff00) retval |= uint16_t(m_cart_space.read_byte((offset << 1) + 1)) << 8;
+ if (mem_mask & 0x00ff) retval |= uint16_t(m_cart_space.read_byte((offset << 1) + 0)) << 0;
return retval;
}
else
{
- logerror("%s: psx_gamebooster_device::exp_r %04x\n", machine().describe_context(), offset*2);
- }
+ logerror("%s: psx_gamebooster_device::exp_r %04x\n", machine().describe_context(), offset << 1);
- return 0x0000;
+ return 0x0000;
+ }
}
void psx_gamebooster_device::exp_w(offs_t offset, uint16_t data, uint16_t mem_mask)
@@ -102,61 +127,18 @@ void psx_gamebooster_device::exp_w(offs_t offset, uint16_t data, uint16_t mem_ma
if (offset < 0x20000)
{
- logerror("%s: psx_gamebooster_device::exp_w %04x %04x\n", machine().describe_context(), offset*2, data);
+ logerror("%s: psx_gamebooster_device::exp_w %04x %04x\n", machine().describe_context(), offset << 1, data);
}
else if (offset < 0x24000)
{
offset -= 0x20000;
- logerror("%s: psx_gamebooster_device::exp_w %04x %04x\n", machine().describe_context(), offset*2, data);
-
- if (mem_mask & 0xff00) m_cartslot->write_bank((offset*2)+1, data>>8);
- if (mem_mask & 0x00ff) m_cartslot->write_bank((offset*2)+0, data); // send this 2nd or it erases the bank with the above
+ LOG("%s: psx_gamebooster_device::exp_w %04x %04x\n", machine().describe_context(), offset << 1, data);
+ if (mem_mask & 0xff00) m_cart_space.write_byte((offset << 1) + 1, data >> 8);
+ if (mem_mask & 0x00ff) m_cart_space.write_byte((offset << 1) + 0, data >> 0); // send this 2nd or it erases the bank with the above
}
else
{
- logerror("%s: psx_gamebooster_device::exp_w %04x %04x\n", machine().describe_context(), offset*2, data);
+ logerror("%s: psx_gamebooster_device::exp_w %04x %04x\n", machine().describe_context(), offset << 1, data);
}
}
-
-static void gb_cart(device_slot_interface &device)
-{
- device.option_add_internal("rom", GB_STD_ROM);
- device.option_add_internal("rom_mbc1", GB_ROM_MBC1);
- device.option_add_internal("rom_mbc1col", GB_ROM_MBC1);
- device.option_add_internal("rom_mbc2", GB_ROM_MBC2);
- device.option_add_internal("rom_mbc3", GB_ROM_MBC3);
- device.option_add_internal("rom_huc1", GB_ROM_MBC3);
- device.option_add_internal("rom_huc3", GB_ROM_MBC3);
- device.option_add_internal("rom_mbc5", GB_ROM_MBC5);
- device.option_add_internal("rom_mbc6", GB_ROM_MBC6);
- device.option_add_internal("rom_mbc7", GB_ROM_MBC7);
- device.option_add_internal("rom_tama5", GB_ROM_TAMA5);
- device.option_add_internal("rom_mmm01", GB_ROM_MMM01);
- device.option_add_internal("rom_m161", GB_ROM_M161);
- device.option_add_internal("rom_sachen1", GB_ROM_SACHEN1);
- device.option_add_internal("rom_sachen2", GB_ROM_SACHEN2);
- device.option_add_internal("rom_wisdom", GB_ROM_WISDOM);
- device.option_add_internal("rom_yong", GB_ROM_YONG);
- device.option_add_internal("rom_lasama", GB_ROM_LASAMA);
- device.option_add_internal("rom_atvrac", GB_ROM_ATVRAC);
- device.option_add_internal("rom_camera", GB_STD_ROM);
- device.option_add_internal("rom_188in1", GB_ROM_188IN1);
- device.option_add_internal("rom_sintax", GB_ROM_SINTAX);
- device.option_add_internal("rom_chong", GB_ROM_CHONGWU);
- device.option_add_internal("rom_licheng", GB_ROM_LICHENG);
- device.option_add_internal("rom_digimon", GB_ROM_DIGIMON);
- device.option_add_internal("rom_rock8", GB_ROM_ROCKMAN8);
- device.option_add_internal("rom_sm3sp", GB_ROM_SM3SP);
-// device.option_add_internal("rom_dkong5", GB_ROM_DKONG5);
-// device.option_add_internal("rom_unk01", GB_ROM_UNK01);
-}
-
-void psx_gamebooster_device::device_add_mconfig(machine_config &config)
-{
- /* cartslot */
- GB_CART_SLOT(config, m_cartslot, gb_cart, nullptr);
-
- SOFTWARE_LIST(config, "cart_list").set_original("gameboy");
- SOFTWARE_LIST(config, "gbc_list").set_compatible("gbcolor");
-}
diff --git a/src/devices/bus/psx/gamebooster.h b/src/devices/bus/psx/gamebooster.h
index 808f05061f0..9e990f726d5 100644
--- a/src/devices/bus/psx/gamebooster.h
+++ b/src/devices/bus/psx/gamebooster.h
@@ -6,10 +6,8 @@
#pragma once
-
#include "parallel.h"
-#include "bus/gameboy/rom.h"
-#include "bus/gameboy/mbc.h"
+
//**************************************************************************
// TYPE DEFINITIONS
@@ -19,31 +17,36 @@
class psx_gamebooster_device :
public device_t,
- public psx_parallel_interface
+ public psx_parallel_interface,
+ public device_memory_interface
{
public:
// construction/destruction
psx_gamebooster_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ // psx_parallel_interface implementation
+ virtual uint16_t exp_r(offs_t offset, uint16_t mem_mask = ~0) override;
+ virtual void exp_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) override;
- // optional information overrides
+protected:
+ // device_t implementation
virtual const tiny_rom_entry *device_rom_region() const override;
virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_start() override;
+ virtual void device_reset() override;
- virtual uint16_t exp_r(offs_t offset, uint16_t mem_mask = ~0) override;
- virtual void exp_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) override;
+ // device_memory_interface implementation
+ virtual space_config_vector memory_space_config() const override;
private:
- required_memory_region m_rom;
- required_device<gb_cart_slot_device> m_cartslot;
+ required_region_ptr<u16> m_rom;
+
+ const address_space_config m_cart_config;
+ memory_access<16, 0, 0, ENDIANNESS_LITTLE>::specific m_cart_space;
};
-// device type definition
+// device type declaration
DECLARE_DEVICE_TYPE(PSX_GAMEBOOSTER, psx_gamebooster_device)
#endif // MAME_BUS_PSX_GAMEBOOSTER_H
diff --git a/src/devices/bus/psx/memcard.cpp b/src/devices/bus/psx/memcard.cpp
index 682439ff76e..927f52688d4 100644
--- a/src/devices/bus/psx/memcard.cpp
+++ b/src/devices/bus/psx/memcard.cpp
@@ -295,38 +295,34 @@ unsigned char psxcard_device::checksum_data(const unsigned char *buf, const unsi
return chk;
}
-image_init_result psxcard_device::call_load()
+std::pair<std::error_condition, std::string> psxcard_device::call_load()
{
if(m_disabled)
- {
- logerror("psxcard: port disabled\n");
- return image_init_result::FAIL;
- }
+ return std::make_pair(image_error::UNSUPPORTED, "Memory card port is disabled");
if(length() != card_size)
- return image_init_result::FAIL;
- return image_init_result::PASS;
+ {
+ return std::make_pair(
+ image_error::INVALIDLENGTH,
+ util::string_format("Unsupported memory card size (must be %u bytes)", card_size));
+ }
+ return std::make_pair(std::error_condition(), std::string());
}
-image_init_result psxcard_device::call_create(int format_type, util::option_resolution *format_options)
+std::pair<std::error_condition, std::string> psxcard_device::call_create(int format_type, util::option_resolution *format_options)
{
- uint8_t block[block_size];
- int i, ret;
-
if(m_disabled)
- {
- logerror("psxcard: port disabled\n");
- return image_init_result::FAIL;
- }
+ return std::make_pair(image_error::UNSUPPORTED, "Memory card port is disabled");
+ uint8_t block[block_size];
memset(block, '\0', block_size);
- for(i = 0; i < (card_size/block_size); i++)
+ for(int i = 0; i < (card_size/block_size); i++)
{
- ret = fwrite(block, block_size);
+ auto const ret = fwrite(block, block_size);
if(ret != block_size)
- return image_init_result::FAIL;
+ return std::make_pair(image_error::UNSPECIFIED, std::string());
}
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
void psxcard_device::do_card()
diff --git a/src/devices/bus/psx/memcard.h b/src/devices/bus/psx/memcard.h
index a558f07164c..557800cb4d8 100644
--- a/src/devices/bus/psx/memcard.h
+++ b/src/devices/bus/psx/memcard.h
@@ -20,8 +20,8 @@ public:
virtual bool is_reset_on_load() const noexcept override { return false; }
virtual const char *file_extensions() const noexcept override { return "mc"; }
- virtual image_init_result call_load() override;
- virtual image_init_result call_create(int format_type, util::option_resolution *format_options) override;
+ virtual std::pair<std::error_condition, std::string> call_load() override;
+ virtual std::pair<std::error_condition, std::string> call_create(int format_type, util::option_resolution *format_options) override;
void disable(bool state) { m_disabled = state; if(state) unload(); }
diff --git a/src/devices/bus/psx/multitap.cpp b/src/devices/bus/psx/multitap.cpp
index 5de09102287..4cbeba57c96 100644
--- a/src/devices/bus/psx/multitap.cpp
+++ b/src/devices/bus/psx/multitap.cpp
@@ -31,10 +31,10 @@ void psx_multitap_device::device_add_mconfig(machine_config &config)
void psx_multitap_device::device_start()
{
- m_porta->setup_ack_cb(psx_controller_port_device::void_cb(&psx_multitap_device::ack, this));
- m_portb->setup_ack_cb(psx_controller_port_device::void_cb(&psx_multitap_device::ack, this));
- m_portc->setup_ack_cb(psx_controller_port_device::void_cb(&psx_multitap_device::ack, this));
- m_portd->setup_ack_cb(psx_controller_port_device::void_cb(&psx_multitap_device::ack, this));
+ m_porta->set_ack_cb(*this, FUNC(psx_multitap_device::ack));
+ m_portb->set_ack_cb(*this, FUNC(psx_multitap_device::ack));
+ m_portc->set_ack_cb(*this, FUNC(psx_multitap_device::ack));
+ m_portd->set_ack_cb(*this, FUNC(psx_multitap_device::ack));
m_nextmode = false;
save_item(NAME(m_activeport));
diff --git a/src/devices/bus/qbus/dvk_mx.cpp b/src/devices/bus/qbus/dvk_mx.cpp
new file mode 100644
index 00000000000..757262481ec
--- /dev/null
+++ b/src/devices/bus/qbus/dvk_mx.cpp
@@ -0,0 +1,770 @@
+// license:BSD-3-Clause
+// copyright-holders:Sergey Svishchev
+/***************************************************************************
+
+ DVK "MX" floppy controller (decimal ID 3.057.122)
+
+ Supports four 5.25" drives (single- or double-sided, 40- or 80-track).
+
+ Uses FM encoding and software-defined track format;
+ usually 11 sectors of 256 bytes, with simple additive checksum.
+
+ RT-11 driver name: MX.SYS
+
+ References:
+ https://emuverse.ru/downloads/computers/DVK/docs/KMD/kngmd_MX_2.djvu
+ https://torlus.com/floppy/forum/viewtopic.php?t=1384
+ http://hobot.pdp-11.ru/ukdwk_archive/dwkwebcomplekt/DWKFiles/mx/README.mx1
+
+***************************************************************************/
+
+#include "emu.h"
+#include "dvk_mx.h"
+
+#include "formats/dvk_mx_dsk.h"
+
+#define LOG_WARN (1U << 1) // Show warnings
+#define LOG_SHIFT (1U << 2) // Shows shift register contents
+#define LOG_REGS (1U << 3) // Digital input/output register and data rate select
+#define LOG_STATE (1U << 4) // State machine
+#define LOG_LIVE (1U << 5) // Live states
+
+#define VERBOSE (LOG_GENERAL | LOG_REGS | LOG_LIVE | LOG_STATE)
+#include "logmacro.h"
+
+#define LOGWARN(...) LOGMASKED(LOG_WARN, __VA_ARGS__)
+#define LOGSHIFT(...) LOGMASKED(LOG_SHIFT, __VA_ARGS__)
+#define LOGREGS(...) LOGMASKED(LOG_REGS, __VA_ARGS__)
+#define LOGLIVE(...) LOGMASKED(LOG_LIVE, __VA_ARGS__)
+#define LOGSTATE(...) LOGMASKED(LOG_STATE, __VA_ARGS__)
+
+
+//**************************************************************************
+// MACROS / CONSTANTS
+//**************************************************************************
+
+#define MXCSR_GETDRIVE(x) (((x) >> MXCSR_V_DRIVE) & MXCSR_M_DRIVE)
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(DVK_MX, dvk_mx_device, "dvk_mx", "DVK MX floppy controller")
+
+
+
+inline dvk_mx_device::floppy_info::floppy_info()
+ : tm(nullptr)
+ , dev(nullptr)
+ , id(0)
+ , main_state(0)
+ , sub_state(0)
+ , dir(0)
+ , counter(0)
+ , live(false)
+ , index(false)
+{
+}
+
+
+inline dvk_mx_device::live_info::live_info()
+ : tm(attotime::never)
+ , state(IDLE)
+ , next_state(-1)
+ , fi(nullptr)
+ , shift_reg(0)
+ , bit_counter(0)
+ , byte_counter(0)
+ , data_separator_phase(false)
+ , data_reg(0)
+ , cksum(0)
+ , pll()
+{
+}
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// dvk_mx_device - constructor
+//-------------------------------------------------
+
+dvk_mx_device::dvk_mx_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, DVK_MX, tag, owner, clock)
+ , device_qbus_card_interface(mconfig, *this)
+ , m_connectors(*this, "%u", 0U)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void dvk_mx_device::device_start()
+{
+ for (int i = 0; i != 4; i++)
+ {
+ flopi[i].tm = timer_alloc(FUNC(dvk_mx_device::update_floppy), this);
+ flopi[i].id = i;
+ if (m_connectors[i])
+ {
+ flopi[i].dev = m_connectors[i]->get_device();
+ if (flopi[i].dev != nullptr)
+ flopi[i].dev->setup_index_pulse_cb(floppy_image_device::index_pulse_cb(&dvk_mx_device::index_callback, this));
+ }
+ else
+ flopi[i].dev = nullptr;
+
+ flopi[i].main_state = IDLE;
+ flopi[i].sub_state = IDLE;
+ flopi[i].live = false;
+ }
+
+ // save state
+ save_item(NAME(m_mxcs));
+ save_item(NAME(m_rbuf));
+ save_item(NAME(m_wbuf));
+ save_item(NAME(selected_drive));
+
+ m_timer_2khz = timer_alloc(FUNC(dvk_mx_device::twokhz_tick), this);
+
+ m_bus->install_device(0177130, 0177133, read16sm_delegate(*this, FUNC(dvk_mx_device::read)),
+ write16sm_delegate(*this, FUNC(dvk_mx_device::write)));
+
+ m_mxcs = 0;
+ selected_drive = -1;
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void dvk_mx_device::device_reset()
+{
+ m_rbuf = m_wbuf = 0;
+
+ m_mxcs &= ~MXCSR_ERR;
+
+ m_timer_2khz->adjust(attotime::never, 0, attotime::never);
+
+ live_abort();
+ set_ds(-1);
+}
+
+void dvk_mx_device::floppy_formats(format_registration &fr)
+{
+ fr.add_mfm_containers();
+ fr.add(FLOPPY_DVK_MX_FORMAT);
+}
+
+static void mx_floppies(device_slot_interface &device)
+{
+ device.option_add("525qd", FLOPPY_525_QD);
+ device.option_add("525dd", FLOPPY_525_DD);
+}
+
+void dvk_mx_device::device_add_mconfig(machine_config &config)
+{
+ FLOPPY_CONNECTOR(config, "0", mx_floppies, "525qd", dvk_mx_device::floppy_formats);
+ FLOPPY_CONNECTOR(config, "1", mx_floppies, "525qd", dvk_mx_device::floppy_formats);
+ FLOPPY_CONNECTOR(config, "2", mx_floppies, "525dd", dvk_mx_device::floppy_formats);
+ FLOPPY_CONNECTOR(config, "3", mx_floppies, "525dd", dvk_mx_device::floppy_formats);
+}
+
+uint16_t dvk_mx_device::read(offs_t offset)
+{
+ uint16_t data = 0;
+
+ switch (offset)
+ {
+ case 0:
+ data = m_mxcs & MXCSR_RD;
+ if (selected_drive != -1)
+ {
+ floppy_info &fi = flopi[selected_drive];
+ if (!fi.dev->trk00_r()) data |= MXCSR_TRK0;
+ if (fi.dev->wpt_r()) data |= MXCSR_WP;
+ if (fi.index) data |= MXCSR_INDEX;
+ }
+ if (!machine().side_effects_disabled())
+ m_mxcs &= ~MXCSR_TIMER;
+ break;
+
+ case 1:
+ data = m_rbuf;
+ if (!machine().side_effects_disabled())
+ m_mxcs &= ~MXCSR_TR;
+ break;
+ }
+
+ return data;
+}
+
+void dvk_mx_device::write(offs_t offset, uint16_t data)
+{
+ switch (offset)
+ {
+ case 0:
+ if (!BIT(data, 1))
+ set_ds(MXCSR_GETDRIVE(data));
+ else
+ set_ds(-1);
+ if (selected_drive != -1)
+ {
+ floppy_info &fi = flopi[selected_drive];
+ fi.dev->mon_w(!BIT(data, 6));
+ fi.dev->ss_w(BIT(data, 12));
+ if (BIT(data, 4))
+ {
+ LOG("COMMAND STEP %s\n", BIT(data, 5) ? "+1" : "-1");
+ execute_command(2);
+ }
+ if (data & MXCSR_GO)
+ {
+ LOG("COMMAND %s drive %d c:h %d:%d\n", BIT(data, 13)?"WRITE":"READ", selected_drive, fi.dev->get_cyl(), BIT(data, 12));
+ m_mxcs &= ~MXCSR_TR;
+ execute_command(BIT(data, 13));
+ }
+ }
+
+ if (BIT(data, 7))
+ {
+ m_timer_2khz->adjust(attotime::from_hz(2000), 0, attotime::from_hz(2000));
+ }
+ else
+ {
+ m_timer_2khz->adjust(attotime::never, 0, attotime::never);
+ }
+ UPDATE_16BIT(&m_mxcs, data, MXCSR_WR);
+ break;
+
+ case 1:
+ m_wbuf = data;
+ m_mxcs &= ~MXCSR_TR;
+ }
+}
+
+void dvk_mx_device::execute_command(int command)
+{
+ m_mxcs &= ~MXCSR_ERR;
+ live_abort();
+
+ switch (command)
+ {
+ case 0:
+ read_data_start(flopi[selected_drive]);
+ break;
+
+ case 1:
+ write_data_start(flopi[selected_drive]);
+ break;
+
+ case 2:
+ seek_start(flopi[selected_drive]);
+ break;
+ }
+}
+
+TIMER_CALLBACK_MEMBER(dvk_mx_device::twokhz_tick)
+{
+ m_mxcs |= MXCSR_TIMER;
+}
+
+std::string dvk_mx_device::ttsn() const
+{
+ return machine().time().to_string();
+}
+
+//-------------------------------------------------
+// update_tick - pump the device life cycle
+//-------------------------------------------------
+
+TIMER_CALLBACK_MEMBER(dvk_mx_device::update_floppy)
+{
+ live_sync();
+
+ floppy_info &fi = flopi[param];
+ switch (fi.sub_state)
+ {
+ case SEEK_WAIT_STEP_SIGNAL_TIME:
+ fi.sub_state = SEEK_WAIT_STEP_SIGNAL_TIME_DONE;
+ break;
+ case SEEK_WAIT_STEP_TIME:
+ fi.sub_state = SEEK_WAIT_STEP_TIME_DONE;
+ break;
+ }
+
+ general_continue(fi);
+}
+
+void dvk_mx_device::live_start(floppy_info &fi, int state)
+{
+ cur_live.tm = machine().time();
+ cur_live.state = state;
+ cur_live.next_state = -1;
+ cur_live.fi = &fi;
+ cur_live.shift_reg = 0;
+ cur_live.bit_counter = 0;
+ cur_live.data_separator_phase = false;
+ cur_live.data_reg = 0;
+ cur_live.pll.reset(cur_live.tm);
+ cur_live.pll.set_clock(attotime::from_hz(250000));
+ checkpoint_live = cur_live;
+ fi.live = true;
+
+ LOGLIVE("%s: Called live_start (%d)\n", cur_live.tm.to_string(), state);
+ live_run();
+}
+
+void dvk_mx_device::checkpoint()
+{
+ if (cur_live.fi)
+ cur_live.pll.commit(cur_live.fi->dev, cur_live.tm);
+ checkpoint_live = cur_live;
+}
+
+void dvk_mx_device::rollback()
+{
+ cur_live = checkpoint_live;
+}
+
+void dvk_mx_device::live_delay(int state)
+{
+ cur_live.next_state = state;
+ if (cur_live.tm != machine().time())
+ cur_live.fi->tm->adjust(cur_live.tm - machine().time(), cur_live.fi->id);
+ else
+ live_sync();
+}
+
+void dvk_mx_device::live_sync()
+{
+ if (!cur_live.tm.is_never())
+ {
+ if (cur_live.tm > machine().time())
+ {
+ rollback();
+ live_run(machine().time());
+ cur_live.pll.commit(cur_live.fi->dev, cur_live.tm);
+ }
+ else
+ {
+ cur_live.pll.commit(cur_live.fi->dev, cur_live.tm);
+ if (cur_live.next_state != -1)
+ {
+ cur_live.state = cur_live.next_state;
+ cur_live.next_state = -1;
+ }
+ if (cur_live.state == IDLE)
+ {
+ cur_live.pll.stop_writing(cur_live.fi->dev, cur_live.tm);
+ cur_live.tm = attotime::never;
+ cur_live.fi->live = false;
+ cur_live.fi = nullptr;
+ }
+ }
+ cur_live.next_state = -1;
+ checkpoint();
+ }
+}
+
+void dvk_mx_device::live_abort()
+{
+ if (!cur_live.tm.is_never() && cur_live.tm > machine().time())
+ {
+ rollback();
+ live_run(machine().time());
+ }
+
+ if (cur_live.fi)
+ {
+ cur_live.pll.stop_writing(cur_live.fi->dev, cur_live.tm);
+ cur_live.fi->live = false;
+ cur_live.fi = nullptr;
+ }
+
+ cur_live.tm = attotime::never;
+ cur_live.state = IDLE;
+ cur_live.next_state = -1;
+}
+
+void dvk_mx_device::live_run(attotime limit)
+{
+ if (cur_live.state == IDLE || cur_live.next_state != -1)
+ return;
+
+ if (limit == attotime::never)
+ {
+ if (cur_live.fi->dev)
+ limit = cur_live.fi->dev->time_next_index();
+ if (limit == attotime::never)
+ {
+ // Happens when there's no disk or if the fdc is not
+ // connected to a drive, hence no index pulse. Force a
+ // sync from time to time in that case, so that the main
+ // cpu timeout isn't too painful. Avoids looping into
+ // infinity looking for data too.
+
+ limit = machine().time() + attotime::from_msec(1);
+ cur_live.fi->tm->adjust(attotime::from_msec(1), cur_live.fi->id);
+ }
+ }
+
+ for (;;)
+ {
+ switch (cur_live.state)
+ {
+ case SEARCH_ID:
+ if (read_one_bit(limit))
+ return;
+
+ if (!(cur_live.bit_counter & 255))
+ {
+ LOGSHIFT("%s (%s): shift = %04x data=%02x c=%d\n", cur_live.tm.to_string(), limit.to_string(), cur_live.shift_reg,
+ bitswap<8>(cur_live.shift_reg, 14, 12, 10, 8, 6, 4, 2, 0), cur_live.bit_counter);
+ }
+
+ if (cur_live.shift_reg == 0xaaaaffaf)
+ {
+ LOGLIVE("%s: Found SYNC\n", cur_live.tm.to_string());
+ cur_live.data_separator_phase = false;
+ cur_live.bit_counter = 0;
+ cur_live.state = READ_TRACK_DATA_BYTE;
+ cur_live.data_reg = 0363; // 0xf3
+ checkpoint();
+ }
+ break;
+
+ case READ_TRACK_DATA:
+ if (read_one_bit(limit))
+ return;
+ if (cur_live.bit_counter & 31)
+ break;
+ live_delay(READ_TRACK_DATA_BYTE);
+ return;
+
+ case READ_TRACK_DATA_BYTE:
+ m_rbuf = cur_live.data_reg;
+ m_mxcs |= MXCSR_TR;
+ cur_live.state = READ_TRACK_DATA;
+ checkpoint();
+ break;
+
+ case WRITE_TRACK_DATA:
+ live_write_fm(m_wbuf);
+ cur_live.state = WRITE_TRACK_DATA_BYTE;
+ cur_live.bit_counter = 32;
+ checkpoint();
+ break;
+
+ case WRITE_TRACK_DATA_BYTE:
+ if (write_one_bit(limit))
+ return;
+ if (cur_live.bit_counter == 0)
+ {
+ LOGLIVE("%s: Write next %s\n", cur_live.tm.to_string(), (m_mxcs & MXCSR_TR)?"TR":"");
+ if (m_mxcs & MXCSR_TR)
+ {
+ m_mxcs |= MXCSR_ERR;
+ cur_live.pll.stop_writing(cur_live.fi->dev, cur_live.tm);
+ cur_live.state = IDLE;
+ }
+ else
+ {
+ m_mxcs |= MXCSR_TR;
+ live_delay(WRITE_TRACK_DATA);
+ }
+ return;
+ }
+ break;
+
+ default:
+ LOGWARN("%s: Unknown live state %d\n", cur_live.tm.to_string(), cur_live.state);
+ return;
+ }
+ }
+}
+
+void dvk_mx_device::seek_start(floppy_info &fi)
+{
+ fi.main_state = SEEK;
+ fi.sub_state = SEEK_WAIT_STEP_SIGNAL_TIME;
+ fi.dir = !BIT(m_mxcs, 5);
+ seek_continue(fi);
+}
+
+void dvk_mx_device::seek_continue(floppy_info &fi)
+{
+ for (;;)
+ {
+ switch (fi.sub_state)
+ {
+ case SEEK_MOVE:
+ LOGSTATE("sub SEEK_MOVE\n");
+ if (fi.dev)
+ {
+ fi.dev->dir_w(fi.dir);
+ fi.dev->stp_w(0);
+ fi.dev->stp_w(1);
+ }
+ fi.main_state = fi.sub_state = IDLE;
+ m_mxcs &= ~MXCSR_STEP;
+ return;
+
+ case SEEK_WAIT_STEP_SIGNAL_TIME:
+ LOGSTATE("sub SEEK_WAIT_STEP_SIGNAL_TIME\n");
+ fi.tm->adjust(attotime::from_msec(2), fi.id); // FIXME
+ return;
+
+ case SEEK_WAIT_STEP_SIGNAL_TIME_DONE:
+ LOGSTATE("sub SEEK_WAIT_STEP_SIGNAL_TIME_DONE\n");
+ fi.sub_state = SEEK_MOVE;
+ break;
+ }
+ }
+}
+
+
+void dvk_mx_device::read_data_start(floppy_info &fi)
+{
+ fi.main_state = READ_DATA;
+ fi.sub_state = WAIT_INDEX;
+ read_data_continue(fi);
+}
+
+void dvk_mx_device::read_data_continue(floppy_info &fi)
+{
+ for (;;)
+ {
+ switch (fi.sub_state)
+ {
+ case WAIT_INDEX:
+ LOGSTATE("sub WAIT_INDEX\n");
+ return;
+
+ case WAIT_INDEX_DONE:
+ LOGSTATE("sub WAIT_INDEX_DONE\n");
+ fi.counter = 0;
+ fi.sub_state = SCAN_ID;
+ LOGSTATE("live SEARCH_ID\n");
+ live_start(fi, SEARCH_ID);
+ return;
+
+ case SCAN_ID:
+ LOGSTATE("sub SCAN_ID\n");
+ fi.sub_state = TRACK_READ;
+ LOGSTATE("live READ_TRACK_DATA_BYTE\n");
+ live_start(fi, READ_TRACK_DATA_BYTE);
+ return;
+
+ case SCAN_ID_FAILED:
+ LOGSTATE("sub SCAN_ID_FAILED\n");
+ fi.sub_state = COMMAND_DONE;
+ break;
+
+ case TRACK_READ:
+ LOGSTATE("sub TRACK_READ\n");
+ fi.sub_state = COMMAND_DONE;
+ break;
+
+ case COMMAND_DONE:
+ LOGSTATE("sub COMMAND_DONE\n");
+ fi.main_state = fi.sub_state = IDLE;
+ return;
+
+ default:
+ LOGWARN("%s: read sector unknown sub-state %d\n", ttsn(), fi.sub_state);
+ return;
+ }
+ }
+}
+
+void dvk_mx_device::write_data_start(floppy_info &fi)
+{
+ fi.main_state = WRITE_DATA;
+ fi.sub_state = WAIT_INDEX;
+ write_data_continue(fi);
+}
+
+void dvk_mx_device::write_data_continue(floppy_info &fi)
+{
+ for (;;)
+ {
+ switch (fi.sub_state)
+ {
+ case WAIT_INDEX:
+ LOGSTATE("sub WAIT_INDEX\n");
+ return;
+
+ case WAIT_INDEX_DONE:
+ LOGSTATE("sub WAIT_INDEX_DONE\n");
+ fi.sub_state = TRACK_WRITTEN;
+ LOGSTATE("live WRITE_TRACK_DATA\n");
+ live_start(fi, WRITE_TRACK_DATA);
+ return;
+
+ case TRACK_WRITTEN:
+ LOGSTATE("sub TRACK_WRITTEN\n");
+ fi.sub_state = COMMAND_DONE;
+ break;
+
+ case COMMAND_DONE:
+ LOGSTATE("sub COMMAND_DONE\n");
+ fi.main_state = fi.sub_state = IDLE;
+ return;
+
+ default:
+ LOGWARN("%s: write sector unknown sub-state %d\n", ttsn(), fi.sub_state);
+ return;
+ }
+ }
+}
+
+
+void dvk_mx_device::index_callback(floppy_image_device *floppy, int state)
+{
+ for (floppy_info &fi : flopi)
+ {
+ if (fi.dev != floppy)
+ continue;
+
+ fi.index = state;
+
+ if (!state)
+ {
+ general_continue(fi);
+ continue;
+ }
+
+ switch (fi.sub_state)
+ {
+ case IDLE:
+ case SEEK_MOVE:
+ case SEEK_WAIT_STEP_SIGNAL_TIME:
+ case SEEK_WAIT_STEP_SIGNAL_TIME_DONE:
+ case SEEK_WAIT_STEP_TIME:
+ case SEEK_WAIT_STEP_TIME_DONE:
+ case SCAN_ID_FAILED:
+ break;
+
+ case TRACK_READ:
+ fi.sub_state = IDLE;
+ break;
+
+ case WAIT_INDEX:
+ fi.sub_state = WAIT_INDEX_DONE;
+ live_abort();
+ break;
+
+ case SCAN_ID:
+ fi.counter++;
+ if (fi.counter == 2)
+ {
+ fi.sub_state = SCAN_ID_FAILED;
+ live_abort();
+ }
+ break;
+
+ default:
+ LOGWARN("%s: Index pulse on unknown sub-state %d\n", ttsn(), fi.sub_state);
+ break;
+ }
+
+ general_continue(fi);
+ }
+}
+
+void dvk_mx_device::general_continue(floppy_info &fi)
+{
+ if (fi.live && cur_live.state != IDLE)
+ {
+ live_run();
+ if (cur_live.state != IDLE)
+ return;
+ }
+
+ switch (fi.main_state)
+ {
+ case IDLE:
+ break;
+
+ case SEEK:
+ seek_continue(fi);
+ break;
+
+ case READ_DATA:
+ read_data_continue(fi);
+ break;
+
+ case WRITE_DATA:
+ write_data_continue(fi);
+ break;
+
+ default:
+ LOGWARN("%s: general_continue on unknown main-state %d\n", ttsn(), fi.main_state);
+ break;
+ }
+}
+
+
+bool dvk_mx_device::read_one_bit(const attotime &limit)
+{
+ int bit = cur_live.pll.get_next_bit(cur_live.tm, cur_live.fi->dev, limit);
+ if (bit < 0)
+ return true;
+ cur_live.shift_reg = (cur_live.shift_reg << 1) | bit;
+ cur_live.bit_counter++;
+ if (cur_live.data_separator_phase)
+ {
+ cur_live.data_reg = (cur_live.data_reg << 1) | bit;
+ }
+ cur_live.data_separator_phase = !cur_live.data_separator_phase;
+ return false;
+}
+
+bool dvk_mx_device::write_one_bit(const attotime &limit)
+{
+ bool bit = cur_live.shift_reg & 0x80000000;
+ if (cur_live.pll.write_next_bit(bit, cur_live.tm, cur_live.fi->dev, limit))
+ return true;
+ cur_live.shift_reg = cur_live.shift_reg << 1;
+ cur_live.bit_counter--;
+ return false;
+}
+
+void dvk_mx_device::live_write_fm(uint16_t fm)
+{
+ uint32_t raw = 0xaaaaaaaa;
+ for (int i = 0; i < 16; i++)
+ if (fm & (0x8000 >> i))
+ raw |= 0x40000000 >> (2*i);
+ cur_live.data_reg = fm;
+ cur_live.shift_reg = raw;
+ LOGLIVE("%s: Write %04x (%06o) FM %08x\n", cur_live.tm.to_string(), fm, fm, raw);
+}
+
+
+//-------------------------------------------------
+// set_floppy -
+//-------------------------------------------------
+
+void dvk_mx_device::set_ds(int fid)
+{
+ if (selected_drive == fid)
+ return;
+
+ live_abort();
+
+ // pass drive select to connected drives
+ for (floppy_info &fi : flopi)
+ if (fi.dev)
+ fi.dev->ds_w(fid);
+
+ // record selected drive
+ selected_drive = fid;
+}
diff --git a/src/devices/bus/qbus/dvk_mx.h b/src/devices/bus/qbus/dvk_mx.h
new file mode 100644
index 00000000000..f65b4ec1b27
--- /dev/null
+++ b/src/devices/bus/qbus/dvk_mx.h
@@ -0,0 +1,176 @@
+// license:BSD-3-Clause
+// copyright-holders:Sergey Svishchev
+/***************************************************************************
+
+ DVK "MX" floppy controller (decimal ID 3.057.122)
+
+***************************************************************************/
+
+#ifndef MAME_BUS_QBUS_DVK_MX_H
+#define MAME_BUS_QBUS_DVK_MX_H
+
+#pragma once
+
+#include "qbus.h"
+
+#include "imagedev/floppy.h"
+#include "machine/fdc_pll.h"
+#include "machine/pdp11.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> dvk_mx_device
+
+class dvk_mx_device : public device_t, public device_qbus_card_interface
+{
+public:
+ dvk_mx_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ uint16_t read(offs_t offset);
+ void write(offs_t offset, uint16_t data);
+
+protected:
+ // device_t implementation
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+
+ TIMER_CALLBACK_MEMBER(update_floppy);
+ TIMER_CALLBACK_MEMBER(twokhz_tick);
+
+private:
+ enum {
+ IDLE,
+
+ // Main states
+ SEEK,
+ READ_DATA,
+ WRITE_DATA,
+
+ // Sub-states
+ COMMAND_DONE,
+
+ SEEK_MOVE,
+ SEEK_WAIT_STEP_SIGNAL_TIME,
+ SEEK_WAIT_STEP_SIGNAL_TIME_DONE,
+ SEEK_WAIT_STEP_TIME,
+ SEEK_WAIT_STEP_TIME_DONE,
+ SEEK_WAIT_DONE,
+ SEEK_DONE,
+
+ WAIT_INDEX,
+ WAIT_INDEX_DONE,
+
+ SCAN_ID,
+ SCAN_ID_FAILED,
+
+ TRACK_READ,
+ TRACK_WRITTEN,
+
+ // Live states
+ SEARCH_ID,
+ READ_TRACK_DATA,
+ READ_TRACK_DATA_BYTE,
+
+ WRITE_TRACK_DATA,
+ WRITE_TRACK_DATA_BYTE,
+ };
+
+ enum {
+ MXCSR_DRVSE_L = 0000002,
+ MXCSR_STEP = 0000020,
+ MXCSR_DIR = 0000040,
+ MXCSR_MON = 0000100,
+ MXCSR_TIMER = 0000200,
+ MXCSR_ERR = 0000400,
+ MXCSR_INDEX = 0001000,
+ MXCSR_WP = 0002000,
+ MXCSR_TRK0 = 0004000,
+ MXCSR_TOPHEAD = 0010000,
+ MXCSR_WRITE = 0020000,
+ MXCSR_GO = 0040000,
+ MXCSR_TR = 0100000,
+ MXCSR_V_DRIVE = 2,
+ MXCSR_M_DRIVE = 3,
+ MXCSR_DRIVE = (MXCSR_M_DRIVE << MXCSR_V_DRIVE),
+ MXCSR_RD = (MXCSR_TR|MXCSR_GO|MXCSR_WRITE|MXCSR_TOPHEAD|MXCSR_TRK0|MXCSR_WP|MXCSR_INDEX|MXCSR_ERR|MXCSR_TIMER|MXCSR_MON|MXCSR_DIR|MXCSR_STEP|MXCSR_DRIVE|MXCSR_DRVSE_L),
+ MXCSR_WR = (MXCSR_WRITE|MXCSR_TOPHEAD|MXCSR_TIMER|MXCSR_MON|MXCSR_DIR|MXCSR_STEP|MXCSR_DRIVE|MXCSR_DRVSE_L)
+ };
+
+ struct floppy_info {
+ floppy_info();
+
+ emu_timer *tm;
+ floppy_image_device *dev;
+ int id;
+ int main_state, sub_state;
+ int dir, counter;
+ bool live, index;
+ };
+
+ struct live_info {
+ live_info();
+
+ attotime tm;
+ int state, next_state;
+ floppy_info *fi;
+ uint32_t shift_reg;
+ int bit_counter, byte_counter;
+ bool data_separator_phase;
+ uint16_t data_reg, cksum;
+ fdc_pll_t pll;
+ };
+
+ required_device_array<floppy_connector, 4> m_connectors;
+
+ uint16_t m_mxcs;
+ uint16_t m_rbuf;
+ uint16_t m_wbuf;
+
+ int selected_drive;
+
+ emu_timer *m_timer_2khz;
+
+ floppy_info flopi[4];
+ live_info cur_live, checkpoint_live;
+
+ static void floppy_formats(format_registration &fr);
+
+ std::string ttsn() const;
+
+ void execute_command(int command);
+ void set_ds(int fid);
+
+ void seek_start(floppy_info &fi);
+ void seek_continue(floppy_info &fi);
+
+ void read_data_start(floppy_info &fi);
+ void read_data_continue(floppy_info &fi);
+
+ void write_data_start(floppy_info &fi);
+ void write_data_continue(floppy_info &fi);
+
+ void general_continue(floppy_info &fi);
+ void index_callback(floppy_image_device *floppy, int state);
+
+ void live_start(floppy_info &fi, int live_state);
+ void live_abort();
+ void checkpoint();
+ void rollback();
+ void live_delay(int state);
+ void live_sync();
+ void live_run(attotime limit = attotime::never);
+ void live_write_fm(uint16_t fm);
+
+ bool read_one_bit(const attotime &limit);
+ bool write_one_bit(const attotime &limit);
+};
+
+
+// device type declaration
+DECLARE_DEVICE_TYPE(DVK_MX, dvk_mx_device)
+
+#endif // MAME_BUS_QBUS_DVK_MX_H
diff --git a/src/devices/bus/qbus/pc11.cpp b/src/devices/bus/qbus/pc11.cpp
index 2fc73ada4df..c27e240cc08 100644
--- a/src/devices/bus/qbus/pc11.cpp
+++ b/src/devices/bus/qbus/pc11.cpp
@@ -12,8 +12,7 @@
#include "pc11.h"
-//#define LOG_GENERAL (1U << 0)
-#define LOG_DBG (1U << 2)
+#define LOG_DBG (1U << 1)
//#define VERBOSE (LOG_GENERAL | LOG_DBG)
//#define LOG_OUTPUT_FUNC osd_printf_info
@@ -136,7 +135,7 @@ void pc11_device::z80daisy_irq_reti()
}
-image_init_result pc11_device::call_load()
+std::pair<std::error_condition, std::string> pc11_device::call_load()
{
/* reader unit */
m_fd = this;
@@ -144,7 +143,7 @@ image_init_result pc11_device::call_load()
LOG("call_load filename %s is_open %d\n", m_fd->filename(), m_fd->is_open());
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
void pc11_device::call_unload()
diff --git a/src/devices/bus/qbus/pc11.h b/src/devices/bus/qbus/pc11.h
index cbc0d134f47..2247fb54f72 100644
--- a/src/devices/bus/qbus/pc11.h
+++ b/src/devices/bus/qbus/pc11.h
@@ -36,22 +36,22 @@ public:
// construction/destruction
pc11_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- // image-level overrides
+ // device_image_interface implementation
virtual const char *image_interface() const noexcept override { return "pdp11_ptap"; }
virtual const char *file_extensions() const noexcept override { return "bin,bim,lda"; }
- virtual image_init_result call_load() override;
+ virtual std::pair<std::error_condition, std::string> call_load() override;
virtual void call_unload() override;
uint16_t read(offs_t offset);
void write(offs_t offset, uint16_t data);
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
virtual void device_reset() override;
- // device_z80daisy_interface overrides
+ // device_z80daisy_interface implementation
virtual int z80daisy_irq_state() override;
virtual int z80daisy_irq_ack() override;
virtual void z80daisy_irq_reti() override;
@@ -81,4 +81,4 @@ private:
// device type definition
DECLARE_DEVICE_TYPE(DEC_PC11, pc11_device)
-#endif
+#endif // MAME_BUS_QBUS_PC11_H
diff --git a/src/devices/bus/qbus/qbus.cpp b/src/devices/bus/qbus/qbus.cpp
index c159bb976ff..565bab97e92 100644
--- a/src/devices/bus/qbus/qbus.cpp
+++ b/src/devices/bus/qbus/qbus.cpp
@@ -12,9 +12,12 @@
// Peripheral boards
#include "dsd4432.h"
+#include "dvk_kgd.h"
+#include "dvk_mx.h"
#include "pc11.h"
+#include "qg640.h"
#include "qtx.h"
-#include "dvk_kgd.h"
+#include "uknc_kmd.h"
void qbus_cards(device_slot_interface &device)
@@ -23,6 +26,9 @@ void qbus_cards(device_slot_interface &device)
device.option_add("qts1", TTI_QTS1);
device.option_add("dsd4432", DSD4432);
device.option_add("kgd", DVK_KGD);
+ device.option_add("mx", DVK_MX);
+ device.option_add("mz", UKNC_KMD);
+ device.option_add("qg640", MATROX_QG640);
}
@@ -44,8 +50,7 @@ DEFINE_DEVICE_TYPE(QBUS_SLOT, qbus_slot_device, "qbus_slot", "DEC Qbus slot")
device_qbus_card_interface::device_qbus_card_interface(const machine_config &mconfig, device_t &device) :
device_interface(device, "qbus"),
- m_bus(nullptr),
- m_next(nullptr)
+ m_bus(nullptr)
{
}
@@ -74,13 +79,8 @@ qbus_slot_device::qbus_slot_device(const machine_config &mconfig, const char *ta
void qbus_slot_device::device_start()
{
device_qbus_card_interface *dev = dynamic_cast<device_qbus_card_interface *>(get_card_device());
- if (dev) m_bus->add_card(dev);
-
- m_write_birq4.resolve_safe();
- m_write_birq5.resolve_safe();
- m_write_birq6.resolve_safe();
- m_write_birq7.resolve_safe();
- m_write_bdmr.resolve_safe();
+ if (dev)
+ m_bus->add_card(*dev);
}
@@ -102,6 +102,17 @@ qbus_device::qbus_device(const machine_config &mconfig, const char *tag, device_
{
}
+qbus_device::~qbus_device()
+{
+}
+
+device_memory_interface::space_config_vector qbus_device::memory_space_config() const
+{
+ return space_config_vector {
+ std::make_pair(AS_PROGRAM, &m_program_config)
+ };
+}
+
//-------------------------------------------------
// device_start - device-specific startup
@@ -109,12 +120,6 @@ qbus_device::qbus_device(const machine_config &mconfig, const char *tag, device_
void qbus_device::device_start()
{
- // resolve callbacks
- m_out_birq4_cb.resolve_safe();
- m_out_birq5_cb.resolve_safe();
- m_out_birq6_cb.resolve_safe();
- m_out_birq7_cb.resolve_safe();
- m_out_bdmr_cb.resolve_safe();
}
@@ -131,10 +136,10 @@ void qbus_device::device_reset()
// add_card - add card
//-------------------------------------------------
-void qbus_device::add_card(device_qbus_card_interface *card)
+void qbus_device::add_card(device_qbus_card_interface &card)
{
- card->m_bus = this;
- m_device_list.append(*card);
+ card.m_bus = this;
+ m_device_list.emplace_back(card);
}
void qbus_device::install_device(offs_t start, offs_t end, read16sm_delegate rhandler, write16sm_delegate whandler, uint32_t mask)
@@ -150,14 +155,12 @@ void qbus_device::install_device(offs_t start, offs_t end, read16sm_delegate rha
int qbus_device::z80daisy_irq_state()
{
int data = 0;
- device_qbus_card_interface *entry = m_device_list.first();
- while (entry)
+ for (device_qbus_card_interface &entry : m_device_list)
{
- data = entry->z80daisy_irq_state();
+ data = entry.z80daisy_irq_state();
if (data)
return data;
- entry = entry->next();
}
return data;
@@ -166,14 +169,12 @@ int qbus_device::z80daisy_irq_state()
int qbus_device::z80daisy_irq_ack()
{
int vec = -1;
- device_qbus_card_interface *entry = m_device_list.first();
- while (entry)
+ for (device_qbus_card_interface &entry : m_device_list)
{
- vec = entry->z80daisy_irq_ack();
+ vec = entry.z80daisy_irq_ack();
if (vec > 0)
return vec;
- entry = entry->next();
}
return vec;
diff --git a/src/devices/bus/qbus/qbus.h b/src/devices/bus/qbus/qbus.h
index 3b5ca881292..ae6248c6a40 100644
--- a/src/devices/bus/qbus/qbus.h
+++ b/src/devices/bus/qbus/qbus.h
@@ -13,6 +13,9 @@
#include "machine/z80daisy.h"
+#include <functional>
+#include <vector>
+
//**************************************************************************
// TYPE DEFINITIONS
@@ -25,12 +28,9 @@ class qbus_device;
class device_qbus_card_interface : public device_interface
{
friend class qbus_device;
- template <class ElementType> friend class simple_list;
public:
- device_qbus_card_interface *next() const { return m_next; }
-
- // device_qbus_card_interface overrides
+ // Q-Bus interface
virtual void biaki_w(int state) { }
virtual void bdmgi_w(int state) { }
@@ -42,10 +42,7 @@ protected:
virtual int z80daisy_irq_ack() { return -1; }
virtual void z80daisy_irq_reti() { }
- qbus_device *m_bus;
-
-private:
- device_qbus_card_interface *m_next;
+ qbus_device *m_bus;
};
@@ -67,41 +64,36 @@ public:
qbus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- ~qbus_device() { m_device_list.detach_all(); }
+ ~qbus_device();
// inline configuration
template <typename T> void set_space(T &&tag, int spacenum) { m_space.set_tag(std::forward<T>(tag), spacenum); }
- virtual space_config_vector memory_space_config() const override
- {
- return space_config_vector {
- std::make_pair(AS_PROGRAM, &m_program_config)
- };
- }
+ virtual space_config_vector memory_space_config() const override;
auto birq4() { return m_out_birq4_cb.bind(); }
auto birq5() { return m_out_birq6_cb.bind(); }
auto birq6() { return m_out_birq6_cb.bind(); }
auto birq7() { return m_out_birq7_cb.bind(); }
- void add_card(device_qbus_card_interface *card);
+ void add_card(device_qbus_card_interface &card);
void install_device(offs_t start, offs_t end, read16sm_delegate rhandler, write16sm_delegate whandler, uint32_t mask=0xffffffff);
- DECLARE_WRITE_LINE_MEMBER(birq4_w) { m_out_birq4_cb(state); }
- DECLARE_WRITE_LINE_MEMBER(birq5_w) { m_out_birq5_cb(state); }
- DECLARE_WRITE_LINE_MEMBER(birq6_w) { m_out_birq6_cb(state); }
- DECLARE_WRITE_LINE_MEMBER(birq7_w) { m_out_birq7_cb(state); }
+ void birq4_w(int state) { m_out_birq4_cb(state); }
+ void birq5_w(int state) { m_out_birq5_cb(state); }
+ void birq6_w(int state) { m_out_birq6_cb(state); }
+ void birq7_w(int state) { m_out_birq7_cb(state); }
- DECLARE_WRITE_LINE_MEMBER(bdmr_w) { m_out_bdmr_cb(state); }
+ void bdmr_w(int state) { m_out_bdmr_cb(state); }
const address_space_config m_program_config;
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
virtual void device_reset() override;
- // device_z80daisy_interface overrides
+ // device_z80daisy_interface implementation
virtual int z80daisy_irq_state() override;
virtual int z80daisy_irq_ack() override;
virtual void z80daisy_irq_reti() override;
@@ -110,13 +102,15 @@ protected:
required_address_space m_space;
private:
+ using card_vector = std::vector<std::reference_wrapper<device_qbus_card_interface> >;
+
devcb_write_line m_out_birq4_cb;
devcb_write_line m_out_birq5_cb;
devcb_write_line m_out_birq6_cb;
devcb_write_line m_out_birq7_cb;
devcb_write_line m_out_bdmr_cb;
- simple_list<device_qbus_card_interface> m_device_list;
+ card_vector m_device_list;
};
@@ -138,11 +132,11 @@ public:
qbus_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// computer interface
- DECLARE_WRITE_LINE_MEMBER( biaki_w ) { if (m_card) m_card->biaki_w(state); }
- DECLARE_WRITE_LINE_MEMBER( bdmgi_w ) { if (m_card) m_card->bdmgi_w(state); }
+ void biaki_w(int state) { if (m_card) m_card->biaki_w(state); }
+ void bdmgi_w(int state) { if (m_card) m_card->bdmgi_w(state); }
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
virtual void device_reset() override { if (m_card) get_card_device()->reset(); }
diff --git a/src/devices/bus/qbus/qg640.cpp b/src/devices/bus/qbus/qg640.cpp
new file mode 100644
index 00000000000..785f4b4ebe2
--- /dev/null
+++ b/src/devices/bus/qbus/qg640.cpp
@@ -0,0 +1,106 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/**********************************************************************
+
+ Matrox QG-640 640×480×8 graphics card (skeleton)
+
+**********************************************************************/
+
+#include "emu.h"
+#include "qg640.h"
+
+#include "cpu/ns32000/ns32000.h"
+#include "screen.h"
+
+// device type definition
+DEFINE_DEVICE_TYPE(MATROX_QG640, qg640_device, "qg640", "Matrox QG-640 Color Display Processor Card")
+
+qg640_device::qg640_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MATROX_QG640, tag, owner, clock)
+ , device_qbus_card_interface(mconfig, *this)
+ , m_qgcpu(*this, "qgcpu")
+ , m_fifo(*this, "fifo")
+ , m_acrtc(*this, "acrtc")
+ , m_clut(*this, "clut%u", 1U)
+{
+}
+
+void qg640_device::device_start()
+{
+}
+
+u32 qg640_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
+{
+ return 0;
+}
+
+u8 qg640_device::status_r()
+{
+ return 0;
+}
+
+void qg640_device::unknown_w(u8 data)
+{
+ logerror("%s: unknown_w 0x%02X\n", machine().describe_context(), data);
+}
+
+void qg640_device::clut_w(offs_t offset, u8 data)
+{
+ m_clut[BIT(offset, 18)]->write(BIT(offset, 16, 2), data);
+}
+
+u16 qg640_device::acrtc_r(offs_t offset)
+{
+ return m_acrtc->read16(!BIT(offset, 17));
+}
+
+void qg640_device::acrtc_w(offs_t offset, u16 data)
+{
+ m_acrtc->write16(!BIT(offset, 17), data);
+}
+
+void qg640_device::mem_map(address_map &map)
+{
+ map(0x000000, 0x01ffff).rom().region("firmware", 0);
+ map(0x400000, 0x400000).r(FUNC(qg640_device::status_r));
+ map(0x500000, 0x500000).w(FUNC(qg640_device::unknown_w));
+ map(0x600000, 0x600000).select(0x70000).w(FUNC(qg640_device::clut_w));
+ map(0x780000, 0x780001).select(0x40000).rw(FUNC(qg640_device::acrtc_r), FUNC(qg640_device::acrtc_w));
+ map(0xc00000, 0xc1ffff).ram(); // 4x OKI M41464-12
+}
+
+void qg640_device::videoram_map(address_map &map)
+{
+ map(0x00000, 0x7ffff).ram(); // 10x HM53461P-12
+}
+
+void qg640_device::device_add_mconfig(machine_config &config)
+{
+ NS32016(config, m_qgcpu, 18.432_MHz_XTAL / 2); // NS32016N-10 + NS32C201D-10C
+ m_qgcpu->set_addrmap(AS_PROGRAM, &qg640_device::mem_map);
+
+ IDT7201(config, m_fifo);
+
+ screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
+ screen.set_raw(50_MHz_XTAL / 2, 816, 0, 640, 510, 0, 480); // 25 MHz pixel clock, 30.63 kHz horizontal, 60.07 Hz vertical
+ screen.set_screen_update(FUNC(qg640_device::screen_update));
+
+ HD63484(config, m_acrtc, 50_MHz_XTAL / 8); // SCC63484C8N64; divider unknown
+ m_acrtc->set_screen("screen");
+ m_acrtc->set_addrmap(0, &qg640_device::videoram_map);
+
+ BT471(config, m_clut[0], 0); // IMSG170P-35
+ BT471(config, m_clut[1], 0); // IMSG170P-35
+}
+
+ROM_START(qg640)
+ ROM_REGION16_LE(0x20000, "firmware", 0)
+ // "COPYRIGHT (C) 1985 Matrox Electronics, Ltd." (agrees with board copyright date; EPROMs and most other ICs have 1989 date codes, however)
+ ROM_LOAD16_BYTE("504-8.bin", 0x00000, 0x10000, CRC(213c5804) SHA1(6ab86aeda47d148dd85a548ef716c98b61c53a1a)) // TMS27C512JL
+ ROM_LOAD16_BYTE("505-8.bin", 0x00001, 0x10000, CRC(73610833) SHA1(815b195c37ca1053e5cddfa1efd4764c4550f4b5)) // TMS27C512JL
+ROM_END
+
+const tiny_rom_entry *qg640_device::device_rom_region() const
+{
+ return ROM_NAME(qg640);
+}
diff --git a/src/devices/bus/qbus/qg640.h b/src/devices/bus/qbus/qg640.h
new file mode 100644
index 00000000000..30cd93ca0ce
--- /dev/null
+++ b/src/devices/bus/qbus/qg640.h
@@ -0,0 +1,54 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+
+#ifndef MAME_BUS_QBUS_QG640_H
+#define MAME_BUS_QBUS_QG640_H
+
+#pragma once
+
+#include "qbus.h"
+#include "machine/7200fifo.h"
+#include "video/bt47x.h"
+#include "video/hd63484.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> qg640_device
+
+class qg640_device : public device_t, public device_qbus_card_interface
+{
+public:
+ // device type constructor
+ qg640_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+private:
+ u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
+
+ u8 status_r();
+ void unknown_w(u8 data);
+ void clut_w(offs_t offset, u8 data);
+ u16 acrtc_r(offs_t offset);
+ void acrtc_w(offs_t offset, u16 data);
+
+ void mem_map(address_map &map);
+ void videoram_map(address_map &map);
+
+ required_device<cpu_device> m_qgcpu;
+ required_device<idt7201_device> m_fifo;
+ required_device<hd63484_device> m_acrtc;
+ required_device_array<bt47x_device_base, 2> m_clut;
+};
+
+// device type declaration
+DECLARE_DEVICE_TYPE(MATROX_QG640, qg640_device)
+
+#endif // MAME_BUS_QBUS_QG640_H
diff --git a/src/devices/bus/qbus/qtx.cpp b/src/devices/bus/qbus/qtx.cpp
index e07023c06c6..b4e684577d1 100644
--- a/src/devices/bus/qbus/qtx.cpp
+++ b/src/devices/bus/qbus/qtx.cpp
@@ -20,7 +20,7 @@ Other: LED, 20MHz crystal. Next to the MC68901P is another chip just as large (4
#include "bus/nscsi/devices.h"
#include "bus/rs232/rs232.h"
-#include "cpu/m68000/m68000.h"
+#include "cpu/m68000/m68008.h"
#include "machine/74259.h"
#include "machine/eepromser.h"
diff --git a/src/devices/bus/qbus/qtx.h b/src/devices/bus/qbus/qtx.h
index 99c38f9f3ec..2357c0342e3 100644
--- a/src/devices/bus/qbus/qtx.h
+++ b/src/devices/bus/qbus/qtx.h
@@ -8,7 +8,7 @@
#include "qbus.h"
#include "machine/mc68901.h"
-#include "machine/ncr5390.h"
+#include "machine/ncr53c90.h"
//**************************************************************************
diff --git a/src/devices/bus/qbus/uknc_kmd.cpp b/src/devices/bus/qbus/uknc_kmd.cpp
new file mode 100644
index 00000000000..ddef50aee2f
--- /dev/null
+++ b/src/devices/bus/qbus/uknc_kmd.cpp
@@ -0,0 +1,87 @@
+// license:BSD-3-Clause
+// copyright-holders:Sergey Svishchev
+/***************************************************************************
+
+ UKNC floppy controller (device driver MZ.SYS)
+
+***************************************************************************/
+
+#include "emu.h"
+#include "uknc_kmd.h"
+
+#include "machine/pdp11.h"
+
+#include "formats/bk0010_dsk.h"
+
+
+namespace {
+
+void uknc_floppies(device_slot_interface &device)
+{
+ device.option_add("525qd", FLOPPY_525_QD);
+}
+
+void uknc_floppy_formats(format_registration &fr)
+{
+ fr.add_mfm_containers();
+ fr.add(FLOPPY_BK0010_FORMAT);
+}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(UKNC_KMD, uknc_kmd_device, "uknc_kmd", "UKNC floppy")
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// uknc_kmd_device - constructor
+//-------------------------------------------------
+
+uknc_kmd_device::uknc_kmd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, UKNC_KMD, tag, owner, clock)
+ , device_qbus_card_interface(mconfig, *this)
+ , m_fdc(*this, "fdc")
+{
+}
+
+void uknc_kmd_device::device_add_mconfig(machine_config &config)
+{
+ K1801VP128(config, m_fdc, XTAL(4'000'000));
+ m_fdc->ds_in_callback().set(
+ [] (uint16_t data) -> uint16_t
+ {
+ switch (data & 02003)
+ {
+ case 02000: return 3;
+ case 02001: return 2;
+ case 02002: return 1;
+ case 02003: return 0;
+ default: return -1;
+ }
+ });
+ FLOPPY_CONNECTOR(config, "fdc:0", uknc_floppies, "525qd", uknc_floppy_formats);
+ FLOPPY_CONNECTOR(config, "fdc:1", uknc_floppies, "525qd", uknc_floppy_formats);
+ FLOPPY_CONNECTOR(config, "fdc:2", uknc_floppies, "525qd", uknc_floppy_formats);
+ FLOPPY_CONNECTOR(config, "fdc:3", uknc_floppies, "525qd", uknc_floppy_formats);
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void uknc_kmd_device::device_start()
+{
+ m_bus->install_device(0177130, 0177133,
+ emu::rw_delegate(m_fdc, FUNC(k1801vp128_device::read)),
+ emu::rw_delegate(m_fdc, FUNC(k1801vp128_device::write)));
+}
+
diff --git a/src/devices/bus/qbus/uknc_kmd.h b/src/devices/bus/qbus/uknc_kmd.h
new file mode 100644
index 00000000000..fc7b8ece7b9
--- /dev/null
+++ b/src/devices/bus/qbus/uknc_kmd.h
@@ -0,0 +1,43 @@
+// license:BSD-3-Clause
+// copyright-holders:Sergey Svishchev
+/***************************************************************************
+
+ UKNC floppy controller (device driver MZ.SYS)
+
+***************************************************************************/
+
+#ifndef MAME_BUS_QBUS_UKNC_KMD_H
+#define MAME_BUS_QBUS_UKNC_KMD_H
+
+#pragma once
+
+#include "qbus.h"
+
+#include "machine/1801vp128.h"
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+// ======================> uknc_kmd_device
+
+class uknc_kmd_device : public device_t, public device_qbus_card_interface
+{
+public:
+ // construction/destruction
+ uknc_kmd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device_t implementation
+ virtual void device_start() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+
+ required_device<k1801vp128_device> m_fdc;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(UKNC_KMD, uknc_kmd_device)
+
+#endif // MAME_BUS_QBUS_UKNC_KMD_H
diff --git a/src/devices/bus/ql/cst_q_plus4.cpp b/src/devices/bus/ql/cst_q_plus4.cpp
index 96269dc6ef5..147aa9b3f62 100644
--- a/src/devices/bus/ql/cst_q_plus4.cpp
+++ b/src/devices/bus/ql/cst_q_plus4.cpp
@@ -52,7 +52,7 @@ const tiny_rom_entry *cst_q_plus4_device::device_rom_region() const
void cst_q_plus4_device::device_add_mconfig(machine_config &config)
{
- PIA6821(config, MC6821_TAG, 0);
+ PIA6821(config, MC6821_TAG);
QL_EXPANSION_SLOT(config, m_exp1, DERIVED_CLOCK(1, 1), ql_expansion_cards, nullptr);
m_exp1->extintl_wr_callback().set(FUNC(cst_q_plus4_device::exp1_extintl_w));
diff --git a/src/devices/bus/ql/cst_q_plus4.h b/src/devices/bus/ql/cst_q_plus4.h
index 4c8ea616f51..799829bce99 100644
--- a/src/devices/bus/ql/cst_q_plus4.h
+++ b/src/devices/bus/ql/cst_q_plus4.h
@@ -41,10 +41,10 @@ protected:
virtual void write(offs_t offset, uint8_t data) override;
private:
- DECLARE_WRITE_LINE_MEMBER( exp1_extintl_w ) { m_exp1_extinl = state; update_extintl(); }
- DECLARE_WRITE_LINE_MEMBER( exp2_extintl_w ) { m_exp2_extinl = state; update_extintl(); }
- DECLARE_WRITE_LINE_MEMBER( exp3_extintl_w ) { m_exp3_extinl = state; update_extintl(); }
- DECLARE_WRITE_LINE_MEMBER( exp4_extintl_w ) { m_exp4_extinl = state; update_extintl(); }
+ void exp1_extintl_w(int state) { m_exp1_extinl = state; update_extintl(); }
+ void exp2_extintl_w(int state) { m_exp2_extinl = state; update_extintl(); }
+ void exp3_extintl_w(int state) { m_exp3_extinl = state; update_extintl(); }
+ void exp4_extintl_w(int state) { m_exp4_extinl = state; update_extintl(); }
void update_extintl() { m_slot->extintl_w(m_exp1_extinl || m_exp2_extinl || m_exp3_extinl || m_exp4_extinl); }
diff --git a/src/devices/bus/ql/exp.cpp b/src/devices/bus/ql/exp.cpp
index aadb3905b86..ab2bb007d80 100644
--- a/src/devices/bus/ql/exp.cpp
+++ b/src/devices/bus/ql/exp.cpp
@@ -68,12 +68,6 @@ ql_expansion_slot_device::ql_expansion_slot_device(const machine_config &mconfig
void ql_expansion_slot_device::device_resolve_objects()
{
- // resolve callbacks
- m_write_ipl0l.resolve_safe();
- m_write_ipl1l.resolve_safe();
- m_write_berrl.resolve_safe();
- m_write_extintl.resolve_safe();
-
m_card = get_card_device();
}
diff --git a/src/devices/bus/ql/exp.h b/src/devices/bus/ql/exp.h
index 31948566bfd..767f98cf4ef 100644
--- a/src/devices/bus/ql/exp.h
+++ b/src/devices/bus/ql/exp.h
@@ -102,13 +102,13 @@ public:
// computer interface
uint8_t read(offs_t offset, uint8_t data) { if (m_card) data = m_card->read(offset, data); return data; }
void write(offs_t offset, uint8_t data) { if (m_card) m_card->write(offset, data); }
- DECLARE_WRITE_LINE_MEMBER( romoeh_w ) { if (m_card) m_card->romoeh_w(state); }
+ void romoeh_w(int state) { if (m_card) m_card->romoeh_w(state); }
// card interface
- DECLARE_WRITE_LINE_MEMBER( ipl0l_w ) { m_write_ipl0l(state); }
- DECLARE_WRITE_LINE_MEMBER( ipl1l_w ) { m_write_ipl1l(state); }
- DECLARE_WRITE_LINE_MEMBER( berrl_w ) { m_write_berrl(state); }
- DECLARE_WRITE_LINE_MEMBER( extintl_w ) { m_write_extintl(state); }
+ void ipl0l_w(int state) { m_write_ipl0l(state); }
+ void ipl1l_w(int state) { m_write_ipl1l(state); }
+ void berrl_w(int state) { m_write_berrl(state); }
+ void extintl_w(int state) { m_write_extintl(state); }
protected:
// device-level overrides
diff --git a/src/devices/bus/ql/rom.cpp b/src/devices/bus/ql/rom.cpp
index a3186b9a5b8..ab0e3c1e765 100644
--- a/src/devices/bus/ql/rom.cpp
+++ b/src/devices/bus/ql/rom.cpp
@@ -9,6 +9,8 @@
#include "emu.h"
#include "rom.h"
+#include <tuple>
+
//**************************************************************************
@@ -85,13 +87,19 @@ void ql_rom_cartridge_slot_device::device_start()
// call_load -
//-------------------------------------------------
-image_init_result ql_rom_cartridge_slot_device::call_load()
+std::pair<std::error_condition, std::string> ql_rom_cartridge_slot_device::call_load()
{
+ std::error_condition err;
+
if (m_card)
{
if (!loaded_through_softlist())
{
- fread(m_card->m_rom, length());
+ size_t const size = length();
+ size_t actual;
+ std::tie(err, m_card->m_rom, actual) = util::read(image_core_file(), size);
+ if (!err && (actual != size))
+ err = std::errc::io_error;
}
else
{
@@ -99,7 +107,7 @@ image_init_result ql_rom_cartridge_slot_device::call_load()
}
}
- return image_init_result::PASS;
+ return std::make_pair(err, std::string());
}
diff --git a/src/devices/bus/ql/rom.h b/src/devices/bus/ql/rom.h
index 690b3c231bc..fe32cdcf828 100644
--- a/src/devices/bus/ql/rom.h
+++ b/src/devices/bus/ql/rom.h
@@ -88,21 +88,21 @@ public:
// computer interface
uint8_t read(offs_t offset, uint8_t data) { if (m_card) data = m_card->read(offset, data); return data; }
void write(offs_t offset, uint8_t data) { if (m_card) m_card->write(offset, data); }
- DECLARE_WRITE_LINE_MEMBER( romoeh_w ) { if (m_card) m_card->romoeh_w(state); }
+ void romoeh_w(int state) { if (m_card) m_card->romoeh_w(state); }
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_resolve_objects() override;
virtual void device_start() override;
- // image-level overrides
- virtual image_init_result call_load() override;
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
virtual bool is_reset_on_load() const noexcept override { return true; }
virtual const char *image_interface() const noexcept override { return "ql_cart"; }
virtual const char *file_extensions() const noexcept override { return "rom,bin"; }
- // slot interface overrides
+ // device_slot_interface implementation
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
device_ql_rom_cartridge_card_interface *m_card;
diff --git a/src/devices/bus/ql/sandy_superdisk.cpp b/src/devices/bus/ql/sandy_superdisk.cpp
index 45b0f3035a4..9a704ec6493 100644
--- a/src/devices/bus/ql/sandy_superdisk.cpp
+++ b/src/devices/bus/ql/sandy_superdisk.cpp
@@ -9,6 +9,8 @@
#include "emu.h"
#include "sandy_superdisk.h"
+#include "formats/ql_dsk.h"
+
//**************************************************************************
@@ -73,7 +75,7 @@ void sandy_super_disk_device::floppy_formats(format_registration &fr)
// centronics
//-------------------------------------------------
-WRITE_LINE_MEMBER( sandy_super_disk_device::busy_w )
+void sandy_super_disk_device::busy_w(int state)
{
m_busy = state;
check_interrupt();
@@ -87,8 +89,8 @@ WRITE_LINE_MEMBER( sandy_super_disk_device::busy_w )
void sandy_super_disk_device::device_add_mconfig(machine_config &config)
{
WD1772(config, m_fdc, 8000000);
- FLOPPY_CONNECTOR(config, m_floppy0, sandy_super_disk_floppies, "35dd", sandy_super_disk_device::floppy_formats);
- FLOPPY_CONNECTOR(config, m_floppy1, sandy_super_disk_floppies, nullptr, sandy_super_disk_device::floppy_formats);
+ FLOPPY_CONNECTOR(config, m_floppy[0], sandy_super_disk_floppies, "35dd", sandy_super_disk_device::floppy_formats);
+ FLOPPY_CONNECTOR(config, m_floppy[1], sandy_super_disk_floppies, nullptr, sandy_super_disk_device::floppy_formats);
CENTRONICS(config, m_centronics, centronics_devices, "printer");
m_centronics->ack_handler().set(FUNC(sandy_super_disk_device::busy_w));
@@ -110,8 +112,7 @@ sandy_super_disk_device::sandy_super_disk_device(const machine_config &mconfig,
device_t(mconfig, SANDY_SUPER_DISK, tag, owner, clock),
device_ql_expansion_card_interface(mconfig, *this),
m_fdc(*this, WD1772_TAG),
- m_floppy0(*this, WD1772_TAG":0"),
- m_floppy1(*this, WD1772_TAG":1"),
+ m_floppy(*this, WD1772_TAG":%u", 0U),
m_centronics(*this, CENTRONICS_TAG),
m_latch(*this, TTL74273_TAG),
m_rom(*this, "rom"),
@@ -230,11 +231,11 @@ void sandy_super_disk_device::write(offs_t offset, uint8_t data)
if (BIT(data, 1))
{
- floppy = m_floppy0->get_device();
+ floppy = m_floppy[0]->get_device();
}
else if (BIT(data, 2))
{
- floppy = m_floppy1->get_device();
+ floppy = m_floppy[1]->get_device();
}
m_fdc->set_floppy(floppy);
diff --git a/src/devices/bus/ql/sandy_superdisk.h b/src/devices/bus/ql/sandy_superdisk.h
index 8f821e953ad..ec7f7cc9ef2 100644
--- a/src/devices/bus/ql/sandy_superdisk.h
+++ b/src/devices/bus/ql/sandy_superdisk.h
@@ -13,7 +13,6 @@
#include "exp.h"
#include "bus/centronics/ctronics.h"
-#include "formats/ql_dsk.h"
#include "imagedev/floppy.h"
#include "machine/wd_fdc.h"
@@ -45,15 +44,14 @@ protected:
virtual void write(offs_t offset, uint8_t data) override;
private:
- WRITE_LINE_MEMBER( busy_w );
+ void busy_w(int state);
static void floppy_formats(format_registration &fr);
void check_interrupt();
required_device<wd1772_device> m_fdc;
- required_device<floppy_connector> m_floppy0;
- required_device<floppy_connector> m_floppy1;
+ required_device_array<floppy_connector, 2> m_floppy;
required_device<centronics_device> m_centronics;
required_device<output_latch_device> m_latch;
required_memory_region m_rom;
diff --git a/src/devices/bus/ql/sandy_superqboard.cpp b/src/devices/bus/ql/sandy_superqboard.cpp
index ad1ce340524..109fc273a39 100644
--- a/src/devices/bus/ql/sandy_superqboard.cpp
+++ b/src/devices/bus/ql/sandy_superqboard.cpp
@@ -9,6 +9,8 @@
#include "emu.h"
#include "sandy_superqboard.h"
+#include "formats/ql_dsk.h"
+
//**************************************************************************
@@ -86,7 +88,7 @@ void sandy_superqboard_device::floppy_formats(format_registration &fr)
// centronics
//-------------------------------------------------
-WRITE_LINE_MEMBER( sandy_superqboard_device::busy_w )
+void sandy_superqboard_device::busy_w(int state)
{
if (state)
{
@@ -108,8 +110,8 @@ WRITE_LINE_MEMBER( sandy_superqboard_device::busy_w )
void sandy_superqboard_device::device_add_mconfig(machine_config &config)
{
WD1772(config, m_fdc, XTAL(16'000'000)/2);
- FLOPPY_CONNECTOR(config, m_floppy0, sandy_superqboard_floppies, "35hd", sandy_superqboard_device::floppy_formats);
- FLOPPY_CONNECTOR(config, m_floppy1, sandy_superqboard_floppies, nullptr, sandy_superqboard_device::floppy_formats);
+ FLOPPY_CONNECTOR(config, m_floppy[0], sandy_superqboard_floppies, "35hd", sandy_superqboard_device::floppy_formats);
+ FLOPPY_CONNECTOR(config, m_floppy[1], sandy_superqboard_floppies, nullptr, sandy_superqboard_device::floppy_formats);
CENTRONICS(config, m_centronics, centronics_devices, "printer");
m_centronics->ack_handler().set(FUNC(sandy_superqboard_device::busy_w));
@@ -216,8 +218,7 @@ sandy_superqboard_device::sandy_superqboard_device(const machine_config &mconfig
device_t(mconfig, type, tag, owner, clock),
device_ql_expansion_card_interface(mconfig, *this),
m_fdc(*this, WD1772_TAG),
- m_floppy0(*this, WD1772_TAG":0"),
- m_floppy1(*this, WD1772_TAG":1"),
+ m_floppy(*this, WD1772_TAG":%u", 0U),
m_centronics(*this, CENTRONICS_TAG),
m_latch(*this, TTL74273_TAG),
m_rom(*this, "rom"),
@@ -377,11 +378,11 @@ void sandy_superqboard_device::write(offs_t offset, uint8_t data)
if (BIT(data, 1))
{
- floppy = m_floppy0->get_device();
+ floppy = m_floppy[0]->get_device();
}
else if (BIT(data, 2))
{
- floppy = m_floppy1->get_device();
+ floppy = m_floppy[1]->get_device();
}
m_fdc->set_floppy(floppy);
diff --git a/src/devices/bus/ql/sandy_superqboard.h b/src/devices/bus/ql/sandy_superqboard.h
index 244d0e8a54f..bc64d9c6c97 100644
--- a/src/devices/bus/ql/sandy_superqboard.h
+++ b/src/devices/bus/ql/sandy_superqboard.h
@@ -13,7 +13,6 @@
#include "exp.h"
#include "bus/centronics/ctronics.h"
-#include "formats/ql_dsk.h"
#include "imagedev/floppy.h"
#include "machine/wd_fdc.h"
@@ -50,7 +49,7 @@ protected:
virtual void write(offs_t offset, uint8_t data) override;
private:
- WRITE_LINE_MEMBER( busy_w );
+ void busy_w(int state);
static void floppy_formats(format_registration &fr);
@@ -69,8 +68,7 @@ private:
void check_interrupt();
required_device<wd1772_device> m_fdc;
- required_device<floppy_connector> m_floppy0;
- required_device<floppy_connector> m_floppy1;
+ required_device_array<floppy_connector, 2> m_floppy;
required_device<centronics_device> m_centronics;
required_device<output_latch_device> m_latch;
required_memory_region m_rom;
diff --git a/src/devices/bus/ql/trumpcard.cpp b/src/devices/bus/ql/trumpcard.cpp
index 7c51ad3c220..b77a33de985 100644
--- a/src/devices/bus/ql/trumpcard.cpp
+++ b/src/devices/bus/ql/trumpcard.cpp
@@ -9,6 +9,7 @@
#include "emu.h"
#include "trumpcard.h"
+#include "formats/ql_dsk.h"
//**************************************************************************
@@ -91,8 +92,8 @@ void ql_trump_card_device::floppy_formats(format_registration &fr)
void ql_trump_card_device::device_add_mconfig(machine_config &config)
{
WD1772(config, m_fdc, 8000000);
- FLOPPY_CONNECTOR(config, m_floppy0, ql_trump_card_floppies, "35dd", ql_trump_card_device::floppy_formats);
- FLOPPY_CONNECTOR(config, m_floppy1, ql_trump_card_floppies, nullptr, ql_trump_card_device::floppy_formats);
+ FLOPPY_CONNECTOR(config, m_floppy[0], ql_trump_card_floppies, "35dd", ql_trump_card_device::floppy_formats);
+ FLOPPY_CONNECTOR(config, m_floppy[1], ql_trump_card_floppies, nullptr, ql_trump_card_device::floppy_formats);
}
@@ -113,8 +114,7 @@ ql_trump_card_device::ql_trump_card_device(const machine_config &mconfig, device
device_t(mconfig, type, tag, owner, clock),
device_ql_expansion_card_interface(mconfig, *this),
m_fdc(*this, WD1772_TAG),
- m_floppy0(*this, WD1772_TAG":0"),
- m_floppy1(*this, WD1772_TAG":1"),
+ m_floppy(*this, WD1772_TAG":%u", 0U),
m_rom(*this, "rom"),
m_ram(*this, "ram", ram_size, ENDIANNESS_BIG),
m_ram_size(ram_size),
@@ -247,11 +247,11 @@ void ql_trump_card_device::write(offs_t offset, uint8_t data)
if (BIT(data, 1))
{
- floppy = m_floppy0->get_device();
+ floppy = m_floppy[0]->get_device();
}
else if (BIT(data, 0))
{
- floppy = m_floppy1->get_device();
+ floppy = m_floppy[1]->get_device();
}
m_fdc->set_floppy(floppy);
diff --git a/src/devices/bus/ql/trumpcard.h b/src/devices/bus/ql/trumpcard.h
index 42fad0633e1..a3833f1c1d8 100644
--- a/src/devices/bus/ql/trumpcard.h
+++ b/src/devices/bus/ql/trumpcard.h
@@ -14,7 +14,6 @@
#include "exp.h"
#include "imagedev/floppy.h"
#include "machine/wd_fdc.h"
-#include "formats/ql_dsk.h"
@@ -50,8 +49,7 @@ private:
static void floppy_formats(format_registration &fr);
required_device<wd1772_device> m_fdc;
- required_device<floppy_connector> m_floppy0;
- required_device<floppy_connector> m_floppy1;
+ required_device_array<floppy_connector, 2> m_floppy;
required_memory_region m_rom;
memory_share_creator<uint8_t> m_ram;
diff --git a/src/devices/bus/rc2014/cf.cpp b/src/devices/bus/rc2014/cf.cpp
index 9640853da86..3ba614f2cdb 100644
--- a/src/devices/bus/rc2014/cf.cpp
+++ b/src/devices/bus/rc2014/cf.cpp
@@ -29,7 +29,7 @@ protected:
virtual void device_reset() override;
virtual void device_add_mconfig(machine_config &config) override;
- DECLARE_WRITE_LINE_MEMBER( tx_w ) { m_bus->tx_w(state); }
+ void tx_w(int state) { m_bus->tx_w(state); }
uint8_t ide_cs0_r(offs_t offset) { return m_ata->cs0_r(offset); }
void ide_cs0_w(offs_t offset, uint8_t data) { m_ata->cs0_w(offset, data); }
diff --git a/src/devices/bus/rc2014/clock.cpp b/src/devices/bus/rc2014/clock.cpp
index bb73143edc2..00a5e88d358 100644
--- a/src/devices/bus/rc2014/clock.cpp
+++ b/src/devices/bus/rc2014/clock.cpp
@@ -28,7 +28,7 @@ protected:
virtual void device_start() override;
virtual void device_add_mconfig(machine_config &config) override;
- DECLARE_WRITE_LINE_MEMBER( clk_w ) { m_bus->clk_w(state); }
+ void clk_w(int state) { m_bus->clk_w(state); }
};
single_clock_device::single_clock_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
@@ -69,8 +69,8 @@ protected:
virtual void device_add_mconfig(machine_config &config) override;
virtual ioport_constructor device_input_ports() const override;
- virtual DECLARE_WRITE_LINE_MEMBER( clk_w ) = 0;
- virtual DECLARE_WRITE_LINE_MEMBER( clk2_w ) = 0;
+ virtual void clk_w(int state) = 0;
+ virtual void clk2_w(int state) = 0;
// base-class members
required_device<clock_device> m_clock_1;
@@ -173,8 +173,8 @@ protected:
virtual void device_reset() override;
// base-class overrides
- DECLARE_WRITE_LINE_MEMBER( clk_w ) override { m_bus->clk_w(state); }
- DECLARE_WRITE_LINE_MEMBER( clk2_w ) override { m_bus->clk2_w(state); }
+ void clk_w(int state) override { m_bus->clk_w(state); }
+ void clk2_w(int state) override { m_bus->clk2_w(state); }
};
dual_clock_device::dual_clock_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
@@ -204,8 +204,8 @@ protected:
virtual void device_reset() override;
// base-class overrides
- DECLARE_WRITE_LINE_MEMBER( clk_w ) override { m_bus->clk_w(state); }
- DECLARE_WRITE_LINE_MEMBER( clk2_w ) override { }
+ void clk_w(int state) override { m_bus->clk_w(state); }
+ void clk2_w(int state) override { }
};
dual_clock_device_40pin::dual_clock_device_40pin(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
diff --git a/src/devices/bus/rc2014/fdc.cpp b/src/devices/bus/rc2014/fdc.cpp
index ba8ce96d7ab..b650e96f7ad 100644
--- a/src/devices/bus/rc2014/fdc.cpp
+++ b/src/devices/bus/rc2014/fdc.cpp
@@ -11,8 +11,6 @@
#include "machine/upd765.h"
#include "imagedev/floppy.h"
-#include "formats/imd_dsk.h"
-#include "formats/pc_dsk.h"
namespace {
@@ -91,21 +89,14 @@ static void rc2014_floppies(device_slot_interface &device)
device.option_add("35hd", FLOPPY_35_HD);
}
-static void rc2014_floppy_formats(format_registration &fr)
-{
- fr.add_mfm_containers();
- fr.add(FLOPPY_IMD_FORMAT);
- fr.add(FLOPPY_PC_FORMAT);
-}
-
void rc2014_fdc9266_device::device_add_mconfig(machine_config &config)
{
// FDC9266
UPD765A(config, m_fdc, XTAL(8'000'000), true, true);
// floppy drives
- FLOPPY_CONNECTOR(config, m_floppy[0], rc2014_floppies, "35hd", rc2014_floppy_formats);
- FLOPPY_CONNECTOR(config, m_floppy[1], rc2014_floppies, "35hd", rc2014_floppy_formats);
+ FLOPPY_CONNECTOR(config, m_floppy[0], rc2014_floppies, "35hd", floppy_image_device::default_pc_floppy_formats);
+ FLOPPY_CONNECTOR(config, m_floppy[1], rc2014_floppies, "35hd", floppy_image_device::default_pc_floppy_formats);
}
static INPUT_PORTS_START( rc2014_fdc9266_jumpers )
@@ -202,8 +193,8 @@ void rc2014_wd37c65_device::device_add_mconfig(machine_config &config)
WD37C65C(config, m_fdc, 16_MHz_XTAL);
// floppy drives
- FLOPPY_CONNECTOR(config, m_floppy[0], rc2014_floppies, "35hd", rc2014_floppy_formats);
- FLOPPY_CONNECTOR(config, m_floppy[1], rc2014_floppies, "35hd", rc2014_floppy_formats);
+ FLOPPY_CONNECTOR(config, m_floppy[0], rc2014_floppies, "35hd", floppy_image_device::default_pc_floppy_formats);
+ FLOPPY_CONNECTOR(config, m_floppy[1], rc2014_floppies, "35hd", floppy_image_device::default_pc_floppy_formats);
}
static INPUT_PORTS_START( rc2014_wd37c65_jumpers )
diff --git a/src/devices/bus/rc2014/micro.cpp b/src/devices/bus/rc2014/micro.cpp
index f818dcd8c7f..80f89ce56b0 100644
--- a/src/devices/bus/rc2014/micro.cpp
+++ b/src/devices/bus/rc2014/micro.cpp
@@ -8,13 +8,15 @@
#include "emu.h"
#include "micro.h"
+
#include "modules.h"
+#include "bus/ata/ataintf.h"
+#include "bus/rs232/rs232.h"
#include "cpu/z80/z80.h"
#include "machine/6850acia.h"
#include "machine/clock.h"
-#include "bus/ata/ataintf.h"
-#include "bus/rs232/rs232.h"
+
namespace {
@@ -30,7 +32,7 @@ public:
rc2014_micro(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
private:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
virtual void device_reset() override;
virtual void device_resolve_objects() override;
@@ -38,8 +40,11 @@ private:
virtual ioport_constructor device_input_ports() const override;
virtual const tiny_rom_entry *device_rom_region() const override;
- DECLARE_WRITE_LINE_MEMBER( clk_w ) { m_bus->clk_w(state); }
- DECLARE_WRITE_LINE_MEMBER( tx_w ) { m_bus->tx_w(state); }
+ virtual void card_int_w(int state) override { m_maincpu->set_input_line(INPUT_LINE_IRQ0, state); }
+ virtual void card_rx_w(int state) override { m_acia->write_rxd(state); }
+
+ void clk_w(int state) { m_bus->clk_w(state); }
+ void tx_w(int state) { m_bus->tx_w(state); }
void addrmap_mem(address_map &map) { map.unmap_value_high(); }
void addrmap_io(address_map &map) { map.unmap_value_high(); }
@@ -96,10 +101,6 @@ void rc2014_micro::device_resolve_objects()
// Setup CPU
m_bus->assign_installer(AS_PROGRAM, &m_maincpu->space(AS_PROGRAM));
m_bus->assign_installer(AS_IO, &m_maincpu->space(AS_IO));
- m_bus->int_callback().append_inputline(m_maincpu, INPUT_LINE_IRQ0);
-
- // Setup ACIA
- m_bus->rx_callback().append(m_acia, FUNC(acia6850_device::write_rxd));
}
static DEVICE_INPUT_DEFAULTS_START( terminal )
@@ -178,7 +179,7 @@ public:
rc2014_mini_cpm(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
virtual void device_reset() override;
virtual void device_post_load() override { update_banks(); }
@@ -186,7 +187,7 @@ protected:
virtual ioport_constructor device_input_ports() const override;
virtual const tiny_rom_entry *device_rom_region() const override;
- DECLARE_WRITE_LINE_MEMBER( tx_w ) { m_bus->tx_w(state); }
+ void tx_w(int state) { m_bus->tx_w(state); }
uint8_t ide_cs0_r(offs_t offset) { return m_ata->cs0_r(offset); }
void ide_cs0_w(offs_t offset, uint8_t data) { m_ata->cs0_w(offset, data); }
@@ -291,7 +292,9 @@ const tiny_rom_entry *rc2014_mini_cpm::device_rom_region() const
return ROM_NAME( rc2014_mini_cpm );
}
-}
+} // anonymous namespace
+
+
//**************************************************************************
// DEVICE DEFINITIONS
//**************************************************************************
diff --git a/src/devices/bus/rc2014/ram.cpp b/src/devices/bus/rc2014/ram.cpp
index dc7c89ae170..588e606a12f 100644
--- a/src/devices/bus/rc2014/ram.cpp
+++ b/src/devices/bus/rc2014/ram.cpp
@@ -23,7 +23,7 @@ public:
ram_32k_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
private:
@@ -61,14 +61,14 @@ protected:
// construction/destruction
ram_64k_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
virtual void device_reset() override;
virtual void device_post_load() override { update_banks(); }
virtual ioport_constructor device_input_ports() const override;
- DECLARE_WRITE_LINE_MEMBER( page_w ) { m_bank = state; update_banks(); }
+ void page_w(int state) { m_bank = state; update_banks(); }
virtual void update_banks() = 0;
@@ -131,12 +131,13 @@ public:
ram_64k_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_reset() override;
- virtual void device_resolve_objects() override;
// base-class overrides
void update_banks() override;
+
+ virtual void card_page_w(int state) override { page_w(state); }
};
ram_64k_device::ram_64k_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
@@ -154,11 +155,6 @@ void ram_64k_device::device_reset()
m_bus->installer(AS_PROGRAM)->install_ram(m_start_addr->read() * 0x1000, 0xffff, m_ram.get() + m_start_addr->read() * 0x1000);
}
-void ram_64k_device::device_resolve_objects()
-{
- m_bus->page_callback().append(*this, FUNC(ram_64k_device::page_w));
-}
-
void ram_64k_device::update_banks()
{
if (m_paged->read() == 0) return; // If not paged skip
@@ -180,7 +176,7 @@ public:
ram_64k_device_40pin(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_reset() override;
// base-class overrides
@@ -208,7 +204,9 @@ void ram_64k_device_40pin::device_reset()
}
}
-}
+} // anonymous namespace
+
+
//**************************************************************************
// DEVICE DEFINITIONS
//**************************************************************************
diff --git a/src/devices/bus/rc2014/rc2014.cpp b/src/devices/bus/rc2014/rc2014.cpp
index afe6ba6172a..baee04e8e37 100644
--- a/src/devices/bus/rc2014/rc2014.cpp
+++ b/src/devices/bus/rc2014/rc2014.cpp
@@ -20,14 +20,6 @@
rc2014_bus_device::rc2014_bus_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, type, tag, owner, clock)
, m_installer{}
- , m_clk(*this)
- , m_int(*this)
- , m_tx(*this)
- , m_rx(*this)
- , m_user1(*this)
- , m_user2(*this)
- , m_user3(*this)
- , m_user4(*this)
, m_daisy_chain{}
{
}
@@ -46,15 +38,6 @@ rc2014_bus_device::~rc2014_bus_device()
void rc2014_bus_device::device_start()
{
- // resolve callbacks
- m_clk.resolve_safe();
- m_int.resolve_safe();
- m_tx.resolve_safe();
- m_rx.resolve_safe();
- m_user1.resolve_safe();
- m_user2.resolve_safe();
- m_user3.resolve_safe();
- m_user4.resolve_safe();
}
void rc2014_bus_device::device_reset()
@@ -63,6 +46,12 @@ void rc2014_bus_device::device_reset()
installer(AS_IO)->unmap_readwrite(0, (1 << installer(AS_IO)->space_config().addr_width()) - 1);
}
+void rc2014_bus_device::add_card(device_rc2014_card_interface &card)
+{
+ card.m_bus = this;
+ m_device_list.emplace_back(card);
+}
+
void rc2014_bus_device::set_bus_clock(u32 clock)
{
set_clock(clock);
@@ -96,6 +85,54 @@ const z80_daisy_config* rc2014_bus_device::get_daisy_chain()
return (const z80_daisy_config*)m_daisy_chain;
}
+void rc2014_bus_device::clk_w(int state)
+{
+ for (device_rc2014_card_interface &entry : m_device_list)
+ entry.card_clk_w(state);
+}
+
+void rc2014_bus_device::int_w(int state)
+{
+ for (device_rc2014_card_interface &entry : m_device_list)
+ entry.card_int_w(state);
+}
+
+void rc2014_bus_device::tx_w(int state)
+{
+ for (device_rc2014_card_interface &entry : m_device_list)
+ entry.card_tx_w(state);
+}
+
+void rc2014_bus_device::rx_w(int state)
+{
+ for (device_rc2014_card_interface &entry : m_device_list)
+ entry.card_rx_w(state);
+}
+
+void rc2014_bus_device::user1_w(int state)
+{
+ for (device_rc2014_card_interface &entry : m_device_list)
+ entry.card_user1_w(state);
+}
+
+void rc2014_bus_device::user2_w(int state)
+{
+ for (device_rc2014_card_interface &entry : m_device_list)
+ entry.card_user2_w(state);
+}
+
+void rc2014_bus_device::user3_w(int state)
+{
+ for (device_rc2014_card_interface &entry : m_device_list)
+ entry.card_user3_w(state);
+}
+
+void rc2014_bus_device::user4_w(int state)
+{
+ for (device_rc2014_card_interface &entry : m_device_list)
+ entry.card_user4_w(state);
+}
+
//-------------------------------------------------
// device_rc2014_card_interface
//-------------------------------------------------
@@ -106,11 +143,6 @@ device_rc2014_card_interface::device_rc2014_card_interface(const machine_config
{
}
-void device_rc2014_card_interface::set_bus_device(rc2014_bus_device *bus_device)
-{
- m_bus = bus_device;
-}
-
//-------------------------------------------------
// rc2014_slot_device
//-------------------------------------------------
@@ -136,7 +168,7 @@ void rc2014_slot_device::device_resolve_objects()
device_rc2014_card_interface *const card(dynamic_cast<device_rc2014_card_interface *>(get_card_device()));
if (card)
- card->set_bus_device(m_bus);
+ m_bus->add_card(*card);
}
//**************************************************************************
@@ -154,30 +186,13 @@ rc2014_ext_bus_device::rc2014_ext_bus_device(const machine_config &mconfig, cons
rc2014_ext_bus_device::rc2014_ext_bus_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
: rc2014_bus_device(mconfig, type, tag, owner, clock)
- , m_clk2(*this)
- , m_page(*this)
- , m_nmi(*this)
- , m_tx2(*this)
- , m_rx2(*this)
- , m_user5(*this)
- , m_user6(*this)
- , m_user7(*this)
- , m_user8(*this)
{
}
-void rc2014_ext_bus_device::device_start()
+void rc2014_ext_bus_device::add_card(device_rc2014_ext_card_interface &card)
{
- rc2014_bus_device::device_start();
- m_clk2.resolve_safe();
- m_page.resolve_safe();
- m_nmi.resolve_safe();
- m_tx2.resolve_safe();
- m_rx2.resolve_safe();
- m_user5.resolve_safe();
- m_user6.resolve_safe();
- m_user7.resolve_safe();
- m_user8.resolve_safe();
+ card.m_bus = this;
+ m_device_list.emplace_back(card);
}
//-------------------------------------------------
@@ -189,12 +204,6 @@ device_rc2014_ext_card_interface::device_rc2014_ext_card_interface(const machine
, m_bus(nullptr)
{
}
-
-void device_rc2014_ext_card_interface::set_bus_device(rc2014_ext_bus_device *bus_device)
-{
- m_bus = bus_device;
-}
-
//-------------------------------------------------
// rc2014_ext_slot_device
//-------------------------------------------------
@@ -213,13 +222,67 @@ void rc2014_ext_slot_device::device_start()
{
}
+void rc2014_ext_bus_device::clk2_w(int state)
+{
+ for (device_rc2014_ext_card_interface &entry : m_device_list)
+ entry.card_clk2_w(state);
+}
+
+void rc2014_ext_bus_device::page_w(int state)
+{
+ for (device_rc2014_ext_card_interface &entry : m_device_list)
+ entry.card_page_w(state);
+}
+
+void rc2014_ext_bus_device::nmi_w(int state)
+{
+ for (device_rc2014_ext_card_interface &entry : m_device_list)
+ entry.card_nmi_w(state);
+}
+
+void rc2014_ext_bus_device::tx2_w(int state)
+{
+ for (device_rc2014_ext_card_interface &entry : m_device_list)
+ entry.card_tx2_w(state);
+}
+
+void rc2014_ext_bus_device::rx2_w(int state)
+{
+ for (device_rc2014_ext_card_interface &entry : m_device_list)
+ entry.card_rx2_w(state);
+}
+
+void rc2014_ext_bus_device::user5_w(int state)
+{
+ for (device_rc2014_ext_card_interface &entry : m_device_list)
+ entry.card_user5_w(state);
+}
+
+void rc2014_ext_bus_device::user6_w(int state)
+{
+ for (device_rc2014_ext_card_interface &entry : m_device_list)
+ entry.card_user6_w(state);
+}
+
+void rc2014_ext_bus_device::user7_w(int state)
+{
+ for (device_rc2014_ext_card_interface &entry : m_device_list)
+ entry.card_user7_w(state);
+}
+
+void rc2014_ext_bus_device::user8_w(int state)
+{
+ for (device_rc2014_ext_card_interface &entry : m_device_list)
+ entry.card_user8_w(state);
+}
+
void rc2014_ext_slot_device::device_resolve_objects()
{
rc2014_slot_device::device_resolve_objects();
device_rc2014_ext_card_interface *const card(dynamic_cast<device_rc2014_ext_card_interface *>(get_card_device()));
if (card)
- card->set_bus_device(dynamic_cast<rc2014_ext_bus_device *>(m_bus.target()));
+ ((rc2014_ext_bus_device*)m_bus.lookup())->add_card(*card);
}
//**************************************************************************
@@ -246,6 +309,12 @@ void rc2014_rc80_bus_device::device_start()
rc2014_ext_bus_device::device_start();
}
+void rc2014_rc80_bus_device::add_card(device_rc2014_rc80_card_interface &card)
+{
+ card.m_bus = this;
+ m_device_list.emplace_back(card);
+}
+
//-------------------------------------------------
// device_rc2014_rc80_card_interface
//-------------------------------------------------
@@ -256,11 +325,6 @@ device_rc2014_rc80_card_interface::device_rc2014_rc80_card_interface(const machi
{
}
-void device_rc2014_rc80_card_interface::set_bus_device(rc2014_rc80_bus_device *bus_device)
-{
- m_bus = bus_device;
-}
-
//-------------------------------------------------
// rc2014_rc80_slot_device
//-------------------------------------------------
@@ -280,7 +344,7 @@ void rc2014_rc80_slot_device::device_resolve_objects()
device_rc2014_rc80_card_interface *const card(dynamic_cast<device_rc2014_rc80_card_interface *>(get_card_device()));
if (card)
- card->set_bus_device(dynamic_cast<rc2014_rc80_bus_device *>(m_bus.target()));
+ ((rc2014_rc80_bus_device*)m_bus.lookup())->add_card(*card);
}
//**************************************************************************
diff --git a/src/devices/bus/rc2014/rc2014.h b/src/devices/bus/rc2014/rc2014.h
index a40355af389..225ea087ea5 100644
--- a/src/devices/bus/rc2014/rc2014.h
+++ b/src/devices/bus/rc2014/rc2014.h
@@ -60,6 +60,10 @@
#include "machine/z80daisy.h"
+#include <functional>
+#include <vector>
+
+
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
@@ -69,6 +73,7 @@
//**************************************************************************
// ======================> rc2014_bus_device
+class device_rc2014_card_interface;
class rc2014_bus_device : public device_t
{
@@ -77,23 +82,14 @@ public:
rc2014_bus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual ~rc2014_bus_device();
- auto clk_callback() { return m_clk.bind(); }
- auto int_callback() { return m_int.bind(); }
- auto tx_callback() { return m_tx.bind(); }
- auto rx_callback() { return m_rx.bind(); }
- auto user1_callback() { return m_user1.bind(); }
- auto user2_callback() { return m_user2.bind(); }
- auto user3_callback() { return m_user3.bind(); }
- auto user4_callback() { return m_user4.bind(); }
-
- DECLARE_WRITE_LINE_MEMBER( clk_w ) { m_clk(state); }
- DECLARE_WRITE_LINE_MEMBER( int_w ) { m_int(state); }
- DECLARE_WRITE_LINE_MEMBER( tx_w ) { m_tx(state); }
- DECLARE_WRITE_LINE_MEMBER( rx_w ) { m_rx(state); }
- DECLARE_WRITE_LINE_MEMBER( user1_w ) { m_user1(state); }
- DECLARE_WRITE_LINE_MEMBER( user2_w ) { m_user2(state); }
- DECLARE_WRITE_LINE_MEMBER( user3_w ) { m_user3(state); }
- DECLARE_WRITE_LINE_MEMBER( user4_w ) { m_user4(state); }
+ void clk_w(int state);
+ void int_w(int state);
+ void tx_w(int state);
+ void rx_w(int state);
+ void user1_w(int state);
+ void user2_w(int state);
+ void user3_w(int state);
+ void user4_w(int state);
void set_bus_clock(u32 clock);
void set_bus_clock(const XTAL &xtal) { set_bus_clock(xtal.value()); }
@@ -102,24 +98,21 @@ public:
void add_to_daisy_chain(std::string tag) { m_daisy.push_back(tag); }
const z80_daisy_config* get_daisy_chain();
+ void add_card(device_rc2014_card_interface &card);
protected:
rc2014_bus_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
- // device-level overrides
+
+ // device_t implementation
virtual void device_start() override;
virtual void device_reset() override;
private:
+ using card_vector = std::vector<std::reference_wrapper<device_rc2014_card_interface> >;
+
address_space_installer *m_installer[4];
- devcb_write_line m_clk;
- devcb_write_line m_int;
- devcb_write_line m_tx;
- devcb_write_line m_rx;
- devcb_write_line m_user1;
- devcb_write_line m_user2;
- devcb_write_line m_user3;
- devcb_write_line m_user4;
std::vector<std::string> m_daisy;
char **m_daisy_chain;
+ card_vector m_device_list;
};
// ======================> device_rc2014_card_interface
@@ -129,13 +122,22 @@ class rc2014_slot_device;
class device_rc2014_card_interface : public device_interface
{
friend class rc2014_slot_device;
+ friend class rc2014_bus_device;
public:
// construction/destruction
device_rc2014_card_interface(const machine_config &mconfig, device_t &device);
-protected:
- void set_bus_device(rc2014_bus_device *bus_device);
+ virtual void card_clk_w(int state) { }
+ virtual void card_int_w(int state) { }
+ virtual void card_tx_w(int state) { }
+ virtual void card_rx_w(int state) { }
+ virtual void card_user1_w(int state) { }
+ virtual void card_user2_w(int state) { }
+ virtual void card_user3_w(int state) { }
+ virtual void card_user4_w(int state) { }
+
+protected:
rc2014_bus_device *m_bus;
};
@@ -159,7 +161,8 @@ public:
protected:
rc2014_slot_device(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock);
- // device-level overrides
+
+ // device_t implementation
virtual void device_start() override;
virtual void device_resolve_objects() override;
@@ -171,6 +174,7 @@ protected:
//**************************************************************************
// ======================> rc2014_ext_bus_device
+class device_rc2014_ext_card_interface;
class rc2014_ext_bus_device : public rc2014_bus_device
{
@@ -178,57 +182,48 @@ public:
// construction/destruction
rc2014_ext_bus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- auto clk2_callback() { return m_clk2.bind(); }
- auto page_callback() { return m_page.bind(); }
- auto nmi_callback() { return m_nmi.bind(); }
- auto tx2_callback() { return m_tx2.bind(); }
- auto rx2_callback() { return m_rx2.bind(); }
- auto user5_callback() { return m_user5.bind(); }
- auto user6_callback() { return m_user6.bind(); }
- auto user7_callback() { return m_user7.bind(); }
- auto user8_callback() { return m_user8.bind(); }
-
- DECLARE_WRITE_LINE_MEMBER( clk2_w ) { m_clk2(state); }
- DECLARE_WRITE_LINE_MEMBER( page_w ) { m_page(state); }
- DECLARE_WRITE_LINE_MEMBER( nmi_w ) { m_nmi(state); }
- DECLARE_WRITE_LINE_MEMBER( tx2_w ) { m_tx2(state); }
- DECLARE_WRITE_LINE_MEMBER( rx2_w ) { m_rx2(state); }
- DECLARE_WRITE_LINE_MEMBER( user5_w ) { m_user5(state); }
- DECLARE_WRITE_LINE_MEMBER( user6_w ) { m_user6(state); }
- DECLARE_WRITE_LINE_MEMBER( user7_w ) { m_user7(state); }
- DECLARE_WRITE_LINE_MEMBER( user8_w ) { m_user8(state); }
+ void clk2_w(int state);
+ void page_w(int state);
+ void nmi_w(int state);
+ void tx2_w(int state);
+ void rx2_w(int state);
+ void user5_w(int state);
+ void user6_w(int state);
+ void user7_w(int state);
+ void user8_w(int state);
+
+ void add_card(device_rc2014_ext_card_interface &card);
protected:
rc2014_ext_bus_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
- // device-level overrides
- virtual void device_start() override;
private:
- devcb_write_line m_clk2;
- devcb_write_line m_page;
- devcb_write_line m_nmi;
- devcb_write_line m_tx2;
- devcb_write_line m_rx2;
- devcb_write_line m_user5;
- devcb_write_line m_user6;
- devcb_write_line m_user7;
- devcb_write_line m_user8;
+ using card_vector = std::vector<std::reference_wrapper<device_rc2014_ext_card_interface> >;
+ card_vector m_device_list;
};
// ======================> device_rc2014_ext_card_interface
-class rc2014_ext_slot_device;
-
class device_rc2014_ext_card_interface : public device_rc2014_card_interface
{
- friend class rc2014_ext_slot_device;
+ friend class rc2014_ext_bus_device;
protected:
// construction/destruction
device_rc2014_ext_card_interface(const machine_config &mconfig, device_t &device);
- void set_bus_device(rc2014_ext_bus_device *bus_device);
+public:
+ virtual void card_clk2_w(int state) { }
+ virtual void card_page_w(int state) { }
+ virtual void card_nmi_w(int state) { }
+ virtual void card_tx2_w(int state) { }
+ virtual void card_rx2_w(int state) { }
+ virtual void card_user5_w(int state) { }
+ virtual void card_user6_w(int state) { }
+ virtual void card_user7_w(int state) { }
+ virtual void card_user8_w(int state) { }
+protected:
rc2014_ext_bus_device *m_bus;
};
@@ -252,7 +247,8 @@ public:
protected:
rc2014_ext_slot_device(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock);
- // device-level overrides
+
+ // device_t implementation
virtual void device_start() override;
virtual void device_resolve_objects() override;
};
@@ -262,6 +258,7 @@ protected:
//**************************************************************************
// ======================> rc2014_rc80_bus_device
+class device_rc2014_rc80_card_interface;
class rc2014_rc80_bus_device : public rc2014_ext_bus_device
{
@@ -269,26 +266,29 @@ public:
// construction/destruction
rc2014_rc80_bus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ void add_card(device_rc2014_rc80_card_interface &card);
+
protected:
rc2014_rc80_bus_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
- // device-level overrides
+
+ // device_t implementation
virtual void device_start() override;
+
+private:
+ using card_vector = std::vector<std::reference_wrapper<device_rc2014_rc80_card_interface> >;
+ card_vector m_device_list;
};
// ======================> device_rc2014_rc80_card_interface
-class rc2014_rc80_slot_device;
-
class device_rc2014_rc80_card_interface : public device_rc2014_ext_card_interface
{
- friend class rc2014_rc80_slot_device;
+ friend class rc2014_rc80_bus_device;
protected:
// construction/destruction
device_rc2014_rc80_card_interface(const machine_config &mconfig, device_t &device);
- void set_bus_device(rc2014_rc80_bus_device *bus_device);
-
rc2014_rc80_bus_device *m_bus;
};
@@ -311,12 +311,13 @@ public:
}
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
virtual void device_resolve_objects() override;
};
-// device type definition
+
+// device type declarations
DECLARE_DEVICE_TYPE(RC2014_BUS, rc2014_bus_device)
DECLARE_DEVICE_TYPE(RC2014_SLOT, rc2014_slot_device)
diff --git a/src/devices/bus/rc2014/serial.cpp b/src/devices/bus/rc2014/serial.cpp
index 9453055f2ce..f62841666fe 100644
--- a/src/devices/bus/rc2014/serial.cpp
+++ b/src/devices/bus/rc2014/serial.cpp
@@ -8,9 +8,11 @@
#include "emu.h"
#include "serial.h"
+
+#include "bus/rs232/rs232.h"
#include "machine/6850acia.h"
#include "machine/z80sio.h"
-#include "bus/rs232/rs232.h"
+
namespace {
@@ -26,14 +28,17 @@ public:
serial_io_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
virtual void device_reset() override;
- virtual void device_resolve_objects() override;
virtual void device_add_mconfig(machine_config &config) override;
- DECLARE_WRITE_LINE_MEMBER( irq_w ) { m_bus->int_w(state); }
- DECLARE_WRITE_LINE_MEMBER( tx_w ) { m_bus->tx_w(state); }
+ void irq_w(int state) { m_bus->int_w(state); }
+ void tx_w(int state) { m_bus->tx_w(state); }
+
+ virtual void card_clk_w(int state) override { m_acia->write_txc(state); m_acia->write_rxc(state); }
+ virtual void card_rx_w(int state) override { m_acia->write_rxd(state); }
+
private:
required_device<acia6850_device> m_acia;
};
@@ -55,13 +60,6 @@ void serial_io_device::device_reset()
m_bus->installer(AS_IO)->install_readwrite_handler(0x80, 0x81, 0, 0xff3e, 0, read8sm_delegate(*m_acia, FUNC(acia6850_device::read)), write8sm_delegate(*m_acia, FUNC(acia6850_device::write)));
}
-void serial_io_device::device_resolve_objects()
-{
- m_bus->clk_callback().append(m_acia, FUNC(acia6850_device::write_txc));
- m_bus->clk_callback().append(m_acia, FUNC(acia6850_device::write_rxc));
-
- m_bus->rx_callback().append(m_acia, FUNC(acia6850_device::write_rxd));
-}
// JP1 is used to enable power from USB-to-Serial cable
@@ -108,11 +106,11 @@ protected:
virtual void device_add_mconfig(machine_config &config) override;
virtual ioport_constructor device_input_ports() const override;
- virtual DECLARE_WRITE_LINE_MEMBER( irq_w ) = 0;
- virtual DECLARE_WRITE_LINE_MEMBER( tx_w ) = 0;
- virtual DECLARE_WRITE_LINE_MEMBER( tx2_w ) = 0;
- DECLARE_WRITE_LINE_MEMBER( clk1_w ) { if (m_clk_portb == 1) { m_sio->txcb_w(state); m_sio->rxcb_w(state); } }
- DECLARE_WRITE_LINE_MEMBER( clk2_w ) { if (m_clk_portb == 0) { m_sio->txcb_w(state); m_sio->rxcb_w(state); } }
+ virtual void irq_w(int state) = 0;
+ virtual void tx_w(int state) = 0;
+ virtual void tx2_w(int state) = 0;
+ void clk1_w(int state) { if (m_clk_portb == 1) { m_sio->txcb_w(state); m_sio->rxcb_w(state); } }
+ void clk2_w(int state) { if (m_clk_portb == 0) { m_sio->txcb_w(state); m_sio->rxcb_w(state); } }
// base-class members
u8 m_clk_portb;
@@ -188,9 +186,14 @@ protected:
virtual void device_resolve_objects() override;
// base-class overrides
- DECLARE_WRITE_LINE_MEMBER( irq_w ) override { m_bus->int_w(state); }
- DECLARE_WRITE_LINE_MEMBER( tx_w ) override { m_bus->tx_w(state); }
- DECLARE_WRITE_LINE_MEMBER( tx2_w ) override { m_bus->tx2_w(state); }
+ void irq_w(int state) override { m_bus->int_w(state); }
+ void tx_w(int state) override { m_bus->tx_w(state); }
+ void tx2_w(int state) override { m_bus->tx2_w(state); }
+
+ virtual void card_clk_w(int state) override { m_sio->txca_w(state); m_sio->rxca_w(state); clk1_w(state); }
+ virtual void card_clk2_w(int state) override { clk2_w(state); }
+ virtual void card_rx_w(int state) override { m_sio->rxa_w(state); }
+ virtual void card_rx2_w(int state) override { m_sio->rxb_w(state); }
};
dual_serial_device::dual_serial_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
@@ -211,14 +214,6 @@ void dual_serial_device::device_reset()
void dual_serial_device::device_resolve_objects()
{
- m_bus->clk_callback().append(m_sio, FUNC(z80sio_device::txca_w));
- m_bus->clk_callback().append(m_sio, FUNC(z80sio_device::rxca_w));
- m_bus->clk_callback().append(*this, FUNC(dual_serial_device::clk1_w));
- m_bus->clk2_callback().append(*this, FUNC(dual_serial_device::clk2_w));
-
- m_bus->rx_callback().append(m_sio, FUNC(z80sio_device::rxa_w));
- m_bus->rx2_callback().append(m_sio, FUNC(z80sio_device::rxb_w));
-
m_bus->add_to_daisy_chain(m_sio->tag());
}
@@ -238,9 +233,12 @@ protected:
virtual void device_resolve_objects() override;
// base-class overrides
- DECLARE_WRITE_LINE_MEMBER( irq_w ) override { m_bus->int_w(state); }
- DECLARE_WRITE_LINE_MEMBER( tx_w ) override { m_bus->tx_w(state); }
- DECLARE_WRITE_LINE_MEMBER( tx2_w ) override { }
+ void irq_w(int state) override { m_bus->int_w(state); }
+ void tx_w(int state) override { m_bus->tx_w(state); }
+ void tx2_w(int state) override { }
+
+ virtual void card_clk_w(int state) override { m_sio->txca_w(state); m_sio->rxca_w(state); clk1_w(state); }
+ virtual void card_rx_w(int state) override { m_sio->rxa_w(state); }
};
dual_serial_device_40pin::dual_serial_device_40pin(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
@@ -261,16 +259,12 @@ void dual_serial_device_40pin::device_reset()
void dual_serial_device_40pin::device_resolve_objects()
{
- m_bus->clk_callback().append(m_sio, FUNC(z80sio_device::txca_w));
- m_bus->clk_callback().append(m_sio, FUNC(z80sio_device::rxca_w));
- m_bus->clk_callback().append(*this, FUNC(dual_serial_device_40pin::clk1_w));
-
- m_bus->rx_callback().append(m_sio, FUNC(z80sio_device::rxa_w));
-
m_bus->add_to_daisy_chain(m_sio->tag());
}
-}
+} // anonymous namespace
+
+
//**************************************************************************
// DEVICE DEFINITIONS
//**************************************************************************
diff --git a/src/devices/bus/rc2014/z180cpu.cpp b/src/devices/bus/rc2014/z180cpu.cpp
index c715970b299..53128c585ba 100644
--- a/src/devices/bus/rc2014/z180cpu.cpp
+++ b/src/devices/bus/rc2014/z180cpu.cpp
@@ -9,9 +9,10 @@
#include "emu.h"
#include "z180cpu.h"
+#include "bus/rs232/rs232.h"
#include "cpu/z180/z180.h"
#include "machine/clock.h"
-#include "bus/rs232/rs232.h"
+
namespace {
@@ -25,7 +26,7 @@ protected:
// construction/destruction
z180cpu_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
virtual void device_resolve_objects() override;
virtual void device_add_mconfig(machine_config &config) override;
@@ -33,9 +34,13 @@ protected:
void addrmap_mem(address_map &map) { map.unmap_value_high(); }
void addrmap_io(address_map &map) { map.unmap_value_high(); }
- DECLARE_WRITE_LINE_MEMBER( clk_w ) { m_bus->clk_w(state); }
- DECLARE_WRITE_LINE_MEMBER( tx_w ) { m_bus->tx_w(state); }
- DECLARE_WRITE_LINE_MEMBER( tx2_w ) { m_bus->tx2_w(state); }
+ void clk_w(int state) { m_bus->clk_w(state); }
+ void tx_w(int state) { m_bus->tx_w(state); }
+ void tx2_w(int state) { m_bus->tx2_w(state); }
+
+ virtual void card_int_w(int state) override { m_maincpu->set_input_line(INPUT_LINE_IRQ0, state); }
+ virtual void card_rx_w(int state) override { m_maincpu->rxa0_w(state); }
+ virtual void card_rx2_w(int state) override { m_maincpu->rxa1_w(state); }
// object finders
required_device<z180_device> m_maincpu;
@@ -60,11 +65,6 @@ void z180cpu_base::device_resolve_objects()
{
m_bus->assign_installer(AS_PROGRAM, &m_maincpu->space(AS_PROGRAM));
m_bus->assign_installer(AS_IO, &m_maincpu->space(AS_IO));
-
- m_bus->int_callback().append_inputline(m_maincpu, INPUT_LINE_IRQ0);
-
- m_bus->rx_callback().append(m_maincpu, FUNC(z180_device::rxa0_w));
- m_bus->rx2_callback().append(m_maincpu, FUNC(z180_device::rxa1_w));
}
// This is here only to configure our terminal for interactive use
@@ -112,7 +112,7 @@ public:
sc111_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
};
@@ -125,7 +125,9 @@ void sc111_device::device_start()
{
}
-}
+} // anonymous namespace
+
+
//**************************************************************************
// DEVICE DEFINITIONS
//**************************************************************************
diff --git a/src/devices/bus/rc2014/z80cpu.cpp b/src/devices/bus/rc2014/z80cpu.cpp
index 9723c947e2e..b14f0342229 100644
--- a/src/devices/bus/rc2014/z80cpu.cpp
+++ b/src/devices/bus/rc2014/z80cpu.cpp
@@ -23,7 +23,7 @@ protected:
// construction/destruction
z80cpu_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
virtual void device_add_mconfig(machine_config &config) override;
@@ -63,9 +63,11 @@ public:
z80cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
virtual void device_resolve_objects() override;
+
+ virtual void card_int_w(int state) override { m_maincpu->set_input_line(INPUT_LINE_IRQ0, state); }
};
z80cpu_device::z80cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
@@ -83,8 +85,6 @@ void z80cpu_device::device_resolve_objects()
{
m_bus->assign_installer(AS_PROGRAM, &m_maincpu->space(AS_PROGRAM));
m_bus->assign_installer(AS_IO, &m_maincpu->space(AS_IO));
-
- m_bus->int_callback().append_inputline(m_maincpu, INPUT_LINE_IRQ0);
}
//**************************************************************************
@@ -97,10 +97,14 @@ class z80cpu21_device : public z80cpu_base, public device_rc2014_ext_card_interf
public:
// construction/destruction
z80cpu21_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
virtual void device_resolve_objects() override;
+
+ virtual void card_int_w(int state) override { m_maincpu->set_input_line(INPUT_LINE_IRQ0, state); }
+ virtual void card_nmi_w(int state) override { m_maincpu->set_input_line(INPUT_LINE_NMI, state); }
};
z80cpu21_device::z80cpu21_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
@@ -118,12 +122,11 @@ void z80cpu21_device::device_resolve_objects()
{
m_bus->assign_installer(AS_PROGRAM, &m_maincpu->space(AS_PROGRAM));
m_bus->assign_installer(AS_IO, &m_maincpu->space(AS_IO));
-
- m_bus->int_callback().append_inputline(m_maincpu, INPUT_LINE_IRQ0);
- m_bus->nmi_callback().append_inputline(m_maincpu, INPUT_LINE_NMI);
}
-}
+} // anonymous namespace
+
+
//**************************************************************************
// DEVICE DEFINITIONS
//**************************************************************************
diff --git a/src/devices/bus/rs232/exorterm.cpp b/src/devices/bus/rs232/exorterm.cpp
index a4980d53538..130173ce569 100644
--- a/src/devices/bus/rs232/exorterm.cpp
+++ b/src/devices/bus/rs232/exorterm.cpp
@@ -34,19 +34,19 @@ ioport_constructor exorterm155_terminal_device::device_input_ports() const
return INPUT_PORTS_NAME(exorterm155_terminal);
}
-WRITE_LINE_MEMBER(exorterm155_terminal_device::input_txd)
+void exorterm155_terminal_device::input_txd(int state)
{
m_exorterm155->rs232_conn_rxd_w(state);
}
-WRITE_LINE_MEMBER(exorterm155_terminal_device::route_term_rts)
+void exorterm155_terminal_device::route_term_rts(int state)
{
// Loop the terminal RTS output to the terminal CTS input.
m_exorterm155->rs232_conn_cts_w(state);
}
// This terminal uses DTR for hardware flow control.
-WRITE_LINE_MEMBER(exorterm155_terminal_device::route_term_dtr)
+void exorterm155_terminal_device::route_term_dtr(int state)
{
if (m_flow_control->read())
{
diff --git a/src/devices/bus/rs232/exorterm.h b/src/devices/bus/rs232/exorterm.h
index c8ae8298b13..c658b4bbe8e 100644
--- a/src/devices/bus/rs232/exorterm.h
+++ b/src/devices/bus/rs232/exorterm.h
@@ -15,7 +15,7 @@ class exorterm155_terminal_device : public device_t, public device_rs232_port_in
public:
exorterm155_terminal_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual DECLARE_WRITE_LINE_MEMBER(input_txd) override;
+ virtual void input_txd(int state) override;
DECLARE_INPUT_CHANGED_MEMBER(flow_control);
@@ -29,8 +29,8 @@ private:
required_device<exorterm155_device> m_exorterm155;
required_ioport m_flow_control;
- DECLARE_WRITE_LINE_MEMBER(route_term_rts);
- DECLARE_WRITE_LINE_MEMBER(route_term_dtr);
+ void route_term_rts(int state);
+ void route_term_dtr(int state);
int m_dtr;
};
diff --git a/src/devices/bus/rs232/hlemouse.cpp b/src/devices/bus/rs232/hlemouse.cpp
index 7b25b1e327b..02577316448 100644
--- a/src/devices/bus/rs232/hlemouse.cpp
+++ b/src/devices/bus/rs232/hlemouse.cpp
@@ -53,7 +53,7 @@
10000lmr xxxxxxxx yyyyyyyy xxxxxxxx yyyyyyyy
- The Mouse systems rotatable protcol allows the host to infer
+ The Mouse systems rotatable protocol allows the host to infer
rotation around the third axis at the cost of halving the maximum
sustained movement speed. The M-1 mouse has two sensors spaced 100
counts apart horizontally. If DIP switch 2 is on, the X and Y delta
@@ -239,13 +239,13 @@ void hle_msmouse_device_base::device_start()
machine().scheduler().synchronize(timer_expired_delegate(FUNC(hle_msmouse_device_base::start_mouse), this));
}
-WRITE_LINE_MEMBER(hle_msmouse_device_base::input_dtr)
+void hle_msmouse_device_base::input_dtr(int state)
{
m_dtr = state ? 1U : 0U;
check_enable();
}
-WRITE_LINE_MEMBER(hle_msmouse_device_base::input_rts)
+void hle_msmouse_device_base::input_rts(int state)
{
m_rts = state ? 1U : 0U;
check_enable();
diff --git a/src/devices/bus/rs232/hlemouse.h b/src/devices/bus/rs232/hlemouse.h
index d2fae5bd4d1..183822c9dc5 100644
--- a/src/devices/bus/rs232/hlemouse.h
+++ b/src/devices/bus/rs232/hlemouse.h
@@ -33,8 +33,8 @@ protected:
virtual void device_resolve_objects() override;
virtual void device_start() override;
- virtual DECLARE_WRITE_LINE_MEMBER(input_dtr) override;
- virtual DECLARE_WRITE_LINE_MEMBER(input_rts) override;
+ virtual void input_dtr(int state) override;
+ virtual void input_rts(int state) override;
virtual void tra_complete() override;
diff --git a/src/devices/bus/rs232/ie15.cpp b/src/devices/bus/rs232/ie15.cpp
index 904d65f246c..7f11557fa10 100644
--- a/src/devices/bus/rs232/ie15.cpp
+++ b/src/devices/bus/rs232/ie15.cpp
@@ -18,7 +18,7 @@ public:
{
}
- virtual DECLARE_WRITE_LINE_MEMBER( input_txd ) override { m_ie15->rs232_conn_rxd_w(state); }
+ virtual void input_txd(int state) override { m_ie15->rs232_conn_rxd_w(state); }
protected:
virtual void device_start() override { }
diff --git a/src/devices/bus/rs232/keyboard.cpp b/src/devices/bus/rs232/keyboard.cpp
index 64beb75d6f2..50ea6a1a95f 100644
--- a/src/devices/bus/rs232/keyboard.cpp
+++ b/src/devices/bus/rs232/keyboard.cpp
@@ -35,12 +35,12 @@ ioport_constructor serial_keyboard_device::device_input_ports() const
return INPUT_PORTS_NAME(serial_keyboard);
}
-WRITE_LINE_MEMBER( serial_keyboard_device::input_txd )
+void serial_keyboard_device::input_txd(int state)
{
device_buffered_serial_interface::rx_w(state);
}
-WRITE_LINE_MEMBER( serial_keyboard_device::update_serial )
+void serial_keyboard_device::update_serial(int state)
{
reset();
}
diff --git a/src/devices/bus/rs232/keyboard.h b/src/devices/bus/rs232/keyboard.h
index 190a33a49e4..04552216079 100644
--- a/src/devices/bus/rs232/keyboard.h
+++ b/src/devices/bus/rs232/keyboard.h
@@ -18,9 +18,9 @@ public:
virtual ioport_constructor device_input_ports() const override;
- virtual DECLARE_WRITE_LINE_MEMBER( input_txd ) override;
+ virtual void input_txd(int state) override;
- DECLARE_WRITE_LINE_MEMBER(update_serial);
+ void update_serial(int state);
protected:
serial_keyboard_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
diff --git a/src/devices/bus/rs232/loopback.cpp b/src/devices/bus/rs232/loopback.cpp
index de1f07f3cd7..36006472154 100644
--- a/src/devices/bus/rs232/loopback.cpp
+++ b/src/devices/bus/rs232/loopback.cpp
@@ -4,7 +4,7 @@
#include "emu.h"
#include "loopback.h"
-DEFINE_DEVICE_TYPE(RS232_LOOPBACK, rs232_loopback_device, "rs232_loopback", "RS232 Loopback")
+DEFINE_DEVICE_TYPE(RS232_LOOPBACK, rs232_loopback_device, "rs232_loopback", "RS-232 Loopback")
rs232_loopback_device::rs232_loopback_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, RS232_LOOPBACK, tag, owner, clock)
@@ -16,7 +16,7 @@ void rs232_loopback_device::device_start()
{
}
-WRITE_LINE_MEMBER( rs232_loopback_device::input_txd )
+void rs232_loopback_device::input_txd(int state)
{
if (started())
{
@@ -24,7 +24,7 @@ WRITE_LINE_MEMBER( rs232_loopback_device::input_txd )
}
}
-WRITE_LINE_MEMBER( rs232_loopback_device::input_rts )
+void rs232_loopback_device::input_rts(int state)
{
if (started())
{
@@ -34,7 +34,7 @@ WRITE_LINE_MEMBER( rs232_loopback_device::input_rts )
}
}
-WRITE_LINE_MEMBER( rs232_loopback_device::input_dtr )
+void rs232_loopback_device::input_dtr(int state)
{
if (started())
{
@@ -43,7 +43,7 @@ WRITE_LINE_MEMBER( rs232_loopback_device::input_dtr )
}
}
-DEFINE_DEVICE_TYPE(DEC_RS232_LOOPBACK, dec_rs232_loopback_device, "dec_rs232_loopback", "RS232 Loopback (DEC 12-15336-00)")
+DEFINE_DEVICE_TYPE(DEC_RS232_LOOPBACK, dec_rs232_loopback_device, "dec_rs232_loopback", "RS-232 Loopback (DEC 12-15336-00)")
dec_rs232_loopback_device::dec_rs232_loopback_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, DEC_RS232_LOOPBACK, tag, owner, clock)
@@ -55,7 +55,7 @@ void dec_rs232_loopback_device::device_start()
{
}
-WRITE_LINE_MEMBER( dec_rs232_loopback_device::input_txd )
+void dec_rs232_loopback_device::input_txd(int state)
{
// Pin 2 (Transmitted Data) connected to Pin 3 (Received Data) and Pin 15 (Transmission Clock)
if (started())
@@ -65,7 +65,7 @@ WRITE_LINE_MEMBER( dec_rs232_loopback_device::input_txd )
}
}
-WRITE_LINE_MEMBER( dec_rs232_loopback_device::input_rts )
+void dec_rs232_loopback_device::input_rts(int state)
{
// Pin 4 (Request to Send) connected to Pin 5 (Clear to Send) and Pin 8 (Carrier Detect)
if (started())
@@ -75,7 +75,7 @@ WRITE_LINE_MEMBER( dec_rs232_loopback_device::input_rts )
}
}
-WRITE_LINE_MEMBER( dec_rs232_loopback_device::input_dtr )
+void dec_rs232_loopback_device::input_dtr(int state)
{
// Pin 20 (Data Terminal Ready) connected to Pin 6 (Data Set Ready) and 22 (Ring Indicator)
if (started())
@@ -85,7 +85,7 @@ WRITE_LINE_MEMBER( dec_rs232_loopback_device::input_dtr )
}
}
-WRITE_LINE_MEMBER( dec_rs232_loopback_device::input_spds )
+void dec_rs232_loopback_device::input_spds(int state)
{
// Pin 19 (Speed Select) connected to Pin 12 (Speed Indicator) and 17 (Receive Clock)
if (started())
diff --git a/src/devices/bus/rs232/loopback.h b/src/devices/bus/rs232/loopback.h
index b7f499d08d0..bfd167e451d 100644
--- a/src/devices/bus/rs232/loopback.h
+++ b/src/devices/bus/rs232/loopback.h
@@ -13,9 +13,9 @@ class rs232_loopback_device : public device_t, public device_rs232_port_interfac
public:
rs232_loopback_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual WRITE_LINE_MEMBER( input_txd ) override;
- virtual WRITE_LINE_MEMBER( input_rts ) override;
- virtual WRITE_LINE_MEMBER( input_dtr ) override;
+ virtual void input_txd(int state) override;
+ virtual void input_rts(int state) override;
+ virtual void input_dtr(int state) override;
protected:
virtual void device_start() override;
@@ -26,10 +26,10 @@ class dec_rs232_loopback_device : public device_t, public device_rs232_port_inte
public:
dec_rs232_loopback_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual WRITE_LINE_MEMBER( input_txd ) override;
- virtual WRITE_LINE_MEMBER( input_rts ) override;
- virtual WRITE_LINE_MEMBER( input_dtr ) override;
- virtual WRITE_LINE_MEMBER( input_spds ) override;
+ virtual void input_txd(int state) override;
+ virtual void input_rts(int state) override;
+ virtual void input_dtr(int state) override;
+ virtual void input_spds(int state) override;
protected:
virtual void device_start() override;
diff --git a/src/devices/bus/rs232/mboardd.cpp b/src/devices/bus/rs232/mboardd.cpp
index b2b44a6db70..05649283a89 100644
--- a/src/devices/bus/rs232/mboardd.cpp
+++ b/src/devices/bus/rs232/mboardd.cpp
@@ -36,7 +36,7 @@ class mockingboard_d_device : public device_t, public device_rs232_port_interfac
public:
mockingboard_d_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual DECLARE_WRITE_LINE_MEMBER( input_txd ) override;
+ virtual void input_txd(int state) override;
required_device<m6803_cpu_device> m_cpu;
required_device<ay8913_device> m_ay1;
@@ -110,7 +110,7 @@ void mockingboard_d_device::m6803_mem(address_map &map)
map(0xf800, 0xffff).rom().region("mbcpu", 0);
}
-WRITE_LINE_MEMBER(mockingboard_d_device::input_txd)
+void mockingboard_d_device::input_txd(int state)
{
m_rx_state = (state & 1);
}
diff --git a/src/devices/bus/rs232/nss_tvinterface.cpp b/src/devices/bus/rs232/nss_tvinterface.cpp
new file mode 100644
index 00000000000..2456ff26161
--- /dev/null
+++ b/src/devices/bus/rs232/nss_tvinterface.cpp
@@ -0,0 +1,249 @@
+// license:BSD-3-Clause
+// copyright-holders:hap
+// thanks-to:Achim
+/*******************************************************************************
+
+Novag Super System Peripheral: TV Interface
+
+It's a box that connects to a CRT TV, for showing an in-progress chess game.
+
+It's meant to be connected either like: PC -> Distributor -> TV Interface, or
+like: chesscomputer -> Distributor -> TV Interface. But the distributor is only
+for converting to/from RS-232/TTL voltage, so MAME can ignore it.
+
+It expects a baud rate of 9600, 8 data bits, 1 stop bit, no parity.
+
+Hardware notes:
+- PCB label: 100122 REV C
+- Hitachi HD63A03RP @ 4.9152MHz
+- 8KB ROM (27C64A), 4KB RAM (2*UM6116-3)
+- TMT TM6310 CGA chip, 14.318MHz XTAL, 8KB CG ROM (27C64A, only 2KB used)
+
+TODO:
+- dump/add English version
+- Currently, MAME only has CGA emulation on ISA cards, but this thing is not an
+ ISA card, nor compatible with IBM CGA standard. So if MAME ever adds a more
+ generic CGA device, use that.
+
+*******************************************************************************/
+
+#include "emu.h"
+#include "nss_tvinterface.h"
+
+#include "cpu/m6800/m6801.h"
+#include "video/cgapal.h"
+#include "video/mc6845.h"
+
+#include "emupal.h"
+#include "screen.h"
+
+namespace {
+
+//-------------------------------------------------
+// initialization
+//-------------------------------------------------
+
+class nss_tvinterface_device : public device_t, public device_rs232_port_interface
+{
+public:
+ nss_tvinterface_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual void device_start() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+
+ virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual ioport_constructor device_input_ports() const override;
+
+ virtual void input_txd(int state) override { m_rx_state = state ? 1 : 0; }
+
+private:
+ required_device<hd6303r_cpu_device> m_maincpu;
+ required_device<mc6845_device> m_crtc;
+ required_device<palette_device> m_palette;
+ required_device<screen_device> m_screen;
+ required_shared_ptr<u8> m_vram;
+ required_region_ptr<u8> m_cg_rom;
+
+ u8 m_rx_state = 0;
+
+ void palette(palette_device &palette) const;
+ MC6845_UPDATE_ROW(crtc_update_row);
+
+ u8 cga_sync_r();
+ void cga_mode_control_w(u8 data);
+ void cga_color_select_w(u8 data);
+ void unknown_w(u8 data);
+
+ void main_map(address_map &map);
+
+ u8 p2_r();
+ void p2_w(u8 data);
+};
+
+nss_tvinterface_device::nss_tvinterface_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ device_t(mconfig, NSS_TVINTERFACE, tag, owner, clock),
+ device_rs232_port_interface(mconfig, *this),
+ m_maincpu(*this, "maincpu"),
+ m_crtc(*this, "crtc"),
+ m_palette(*this, "palette"),
+ m_screen(*this, "screen"),
+ m_vram(*this, "vram"),
+ m_cg_rom(*this, "cg_rom")
+{ }
+
+void nss_tvinterface_device::device_start()
+{
+ save_item(NAME(m_rx_state));
+}
+
+
+//-------------------------------------------------
+// CGA video
+//-------------------------------------------------
+
+void nss_tvinterface_device::palette(palette_device &palette) const
+{
+ for (int i = 0; i < 16; i++)
+ palette.set_pen_color(i, cga_palette[i][0], cga_palette[i][1], cga_palette[i][2]);
+}
+
+MC6845_UPDATE_ROW(nss_tvinterface_device::crtc_update_row)
+{
+ const pen_t *pen = m_palette->pens();
+
+ for (int x = 0; x < x_count; x++)
+ {
+ u16 offset = (ma + x) << 1 & 0x7ff;
+
+ u8 chr = m_vram[offset];
+ u8 data = m_cg_rom[((ra << 8 | chr) & 0x7ff) | 0x1000];
+
+ u8 attr = m_vram[offset | 1];
+ u8 fg = attr & 0xf;
+ u8 bg = attr >> 4 & 0xf;
+
+ for (int xi = 0; xi < 8; xi++)
+ bitmap.pix(y, x << 3 | xi) = BIT(data, xi ^ 7) ? pen[fg] : pen[bg];
+ }
+}
+
+u8 nss_tvinterface_device::cga_sync_r()
+{
+ return (m_crtc->vsync_r() * 9) | m_crtc->hsync_r();
+}
+
+void nss_tvinterface_device::cga_mode_control_w(u8 data)
+{
+ // only uses textmode
+}
+
+void nss_tvinterface_device::cga_color_select_w(u8 data)
+{
+ // does not use 2bpp palette
+}
+
+
+//-------------------------------------------------
+// internal i/o
+//-------------------------------------------------
+
+void nss_tvinterface_device::unknown_w(u8 data)
+{
+}
+
+u8 nss_tvinterface_device::p2_r()
+{
+ // P23: serial in
+ return m_rx_state << 3;
+}
+
+void nss_tvinterface_device::p2_w(u8 data)
+{
+ // P24: serial out
+ output_rxd(BIT(~data, 4));
+}
+
+void nss_tvinterface_device::main_map(address_map &map)
+{
+ map(0x8000, 0x87ff).ram().share(m_vram);
+
+ map(0xa3bd, 0xa3bd).portr("IN.0");
+ map(0xa3be, 0xa3be).w(FUNC(nss_tvinterface_device::unknown_w));
+
+ map(0xa3d0, 0xa3d0).mirror(0x0006).w(m_crtc, FUNC(mc6845_device::address_w));
+ map(0xa3d1, 0xa3d1).mirror(0x0006).rw(m_crtc, FUNC(mc6845_device::register_r), FUNC(mc6845_device::register_w));
+ map(0xa3d8, 0xa3d8).w(FUNC(nss_tvinterface_device::cga_mode_control_w));
+ map(0xa3d9, 0xa3d9).w(FUNC(nss_tvinterface_device::cga_color_select_w));
+ map(0xa3da, 0xa3da).r(FUNC(nss_tvinterface_device::cga_sync_r));
+
+ map(0xc000, 0xc7ff).ram();
+ map(0xe000, 0xffff).rom();
+}
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+static INPUT_PORTS_START( nss_tvinterface )
+ PORT_START("IN.0")
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_NAME("Select")
+ PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_BUTTON2) PORT_NAME("Change")
+INPUT_PORTS_END
+
+ioport_constructor nss_tvinterface_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(nss_tvinterface);
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void nss_tvinterface_device::device_add_mconfig(machine_config &config)
+{
+ // basic machine hardware
+ HD6303R(config, m_maincpu, 4.9152_MHz_XTAL);
+ m_maincpu->set_addrmap(AS_PROGRAM, &nss_tvinterface_device::main_map);
+ m_maincpu->in_p2_cb().set(FUNC(nss_tvinterface_device::p2_r));
+ m_maincpu->out_p2_cb().set(FUNC(nss_tvinterface_device::p2_w));
+
+ // video hardware
+ SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
+ m_screen->set_raw(14.318181_MHz_XTAL/2, 472, 0, 320, 260, 0, 200);
+ m_screen->set_screen_update(m_crtc, FUNC(mc6845_device::screen_update));
+
+ MC6845(config, m_crtc, 14.318181_MHz_XTAL/16);
+ m_crtc->set_screen(m_screen);
+ m_crtc->set_show_border_area(false);
+ m_crtc->set_char_width(8);
+ m_crtc->set_update_row_callback(FUNC(nss_tvinterface_device::crtc_update_row));
+
+ PALETTE(config, m_palette, FUNC(nss_tvinterface_device::palette), 16);
+}
+
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+ROM_START(nss_tvinterface)
+ ROM_REGION( 0x10000, "maincpu", 0 )
+ ROM_LOAD("tvgr_011091", 0xe000, 0x2000, CRC(0ff64cec) SHA1(d35881111cdf8e85a843e3b085447d07244d8d70) )
+
+ ROM_REGION( 0x2000, "cg_rom", 0 )
+ ROM_LOAD("cg_930", 0x0000, 0x2000, CRC(98287b9d) SHA1(b20d7856e4739bafcd66434adf9881824f8a611b) )
+ROM_END
+
+const tiny_rom_entry *nss_tvinterface_device::device_rom_region() const
+{
+ return ROM_NAME(nss_tvinterface);
+}
+
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(NSS_TVINTERFACE, device_rs232_port_interface, nss_tvinterface_device, "nss_tvinterface", "Novag Super System TV Interface")
diff --git a/src/devices/bus/rs232/nss_tvinterface.h b/src/devices/bus/rs232/nss_tvinterface.h
new file mode 100644
index 00000000000..470bd693a5c
--- /dev/null
+++ b/src/devices/bus/rs232/nss_tvinterface.h
@@ -0,0 +1,18 @@
+// license:BSD-3-Clause
+// copyright-holders:hap
+/*******************************************************************************
+
+ Novag Super System Peripheral: TV Interface
+
+*******************************************************************************/
+
+#ifndef MAME_BUS_RS232_NSS_TVINTERFACE_H
+#define MAME_BUS_RS232_NSS_TVINTERFACE_H
+
+#pragma once
+
+#include "rs232.h"
+
+DECLARE_DEVICE_TYPE(NSS_TVINTERFACE, device_rs232_port_interface)
+
+#endif // MAME_BUS_RS232_NSS_TVINTERFACE_H
diff --git a/src/devices/bus/rs232/null_modem.cpp b/src/devices/bus/rs232/null_modem.cpp
index 5b19f1d8e29..083fcb0d516 100644
--- a/src/devices/bus/rs232/null_modem.cpp
+++ b/src/devices/bus/rs232/null_modem.cpp
@@ -37,10 +37,10 @@ static INPUT_PORTS_START(null_modem)
PORT_START("FLOW_CONTROL")
PORT_CONFNAME(0x07, 0x00, "Flow Control")
- PORT_CONFSETTING(0x00, "Off")
- PORT_CONFSETTING(0x01, "RTS")
- PORT_CONFSETTING(0x02, "DTR")
- PORT_CONFSETTING(0x04, "XON/XOFF")
+ PORT_CONFSETTING( 0x00, DEF_STR(Off))
+ PORT_CONFSETTING( 0x01, "RTS")
+ PORT_CONFSETTING( 0x02, "DTR")
+ PORT_CONFSETTING( 0x04, "XON/XOFF")
INPUT_PORTS_END
ioport_constructor null_modem_device::device_input_ports() const
@@ -53,7 +53,7 @@ void null_modem_device::device_start()
m_timer_poll = timer_alloc(FUNC(null_modem_device::update_queue), this);
}
-WRITE_LINE_MEMBER(null_modem_device::update_serial)
+void null_modem_device::update_serial(int state)
{
int startbits = 1;
int databits = convert_databits(m_rs232_databits->read());
@@ -96,7 +96,7 @@ TIMER_CALLBACK_MEMBER(null_modem_device::update_queue)
if (m_input_count != 0)
{
- uint8_t fc = m_flow->read();
+ uint8_t const fc = m_flow->read();
if (fc == 0 || (fc == 1 && m_rts == 0) || (fc == 2 && m_dtr == 0) || (fc == 4 && m_xoff == 0))
{
@@ -106,7 +106,7 @@ TIMER_CALLBACK_MEMBER(null_modem_device::update_queue)
}
}
- int txbaud = convert_baud(m_rs232_txbaud->read());
+ int const txbaud = convert_baud(m_rs232_txbaud->read());
m_timer_poll->adjust(attotime::from_hz(txbaud));
}
}
@@ -123,11 +123,9 @@ void null_modem_device::tra_complete()
void null_modem_device::rcv_complete()
{
- u8 data;
-
receive_register_extract();
- data = get_received_char();
+ uint8_t const data = get_received_char();
if (m_flow->read() != 4)
{
m_stream->output(data);
@@ -151,4 +149,4 @@ void null_modem_device::rcv_complete()
}
}
-DEFINE_DEVICE_TYPE(NULL_MODEM, null_modem_device, "null_modem", "RS232 Null Modem")
+DEFINE_DEVICE_TYPE(NULL_MODEM, null_modem_device, "null_modem", "RS-232 Null Modem")
diff --git a/src/devices/bus/rs232/null_modem.h b/src/devices/bus/rs232/null_modem.h
index bd9b2520fc4..c59973dc39b 100644
--- a/src/devices/bus/rs232/null_modem.h
+++ b/src/devices/bus/rs232/null_modem.h
@@ -16,11 +16,11 @@ class null_modem_device : public device_t,
public:
null_modem_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual WRITE_LINE_MEMBER( input_txd ) override { device_serial_interface::rx_w(state); }
- virtual WRITE_LINE_MEMBER( input_rts ) override { m_rts = state; }
- virtual WRITE_LINE_MEMBER( input_dtr ) override { m_dtr = state; }
+ virtual void input_txd(int state) override { device_serial_interface::rx_w(state); }
+ virtual void input_rts(int state) override { m_rts = state; }
+ virtual void input_dtr(int state) override { m_dtr = state; }
- DECLARE_WRITE_LINE_MEMBER(update_serial);
+ void update_serial(int state);
protected:
virtual ioport_constructor device_input_ports() const override;
diff --git a/src/devices/bus/rs232/patchbox.cpp b/src/devices/bus/rs232/patchbox.cpp
index ccd16f2867e..8d6ed0c9153 100644
--- a/src/devices/bus/rs232/patchbox.cpp
+++ b/src/devices/bus/rs232/patchbox.cpp
@@ -127,15 +127,15 @@ protected:
m_dce_port->write_spds(m_signals[m_sources[SPDS]] ^ m_invert[SPDS]);
}
- virtual DECLARE_WRITE_LINE_MEMBER( input_txd ) override { signal_in<TXD>(state); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_dtr ) override { signal_in<DTR>(state); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_rts ) override { signal_in<RTS>(state); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_etc ) override { signal_in<ETC>(state); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_spds ) override { signal_in<SPDS>(state); }
+ virtual void input_txd(int state) override { signal_in<TXD>(state); }
+ virtual void input_dtr(int state) override { signal_in<DTR>(state); }
+ virtual void input_rts(int state) override { signal_in<RTS>(state); }
+ virtual void input_etc(int state) override { signal_in<ETC>(state); }
+ virtual void input_spds(int state) override { signal_in<SPDS>(state); }
private:
template <ioport_value Signal>
- DECLARE_WRITE_LINE_MEMBER( signal_in )
+ void signal_in(int state)
{
state = state ? 1 : 0;
if (m_signals[Signal] != state)
diff --git a/src/devices/bus/rs232/printer.cpp b/src/devices/bus/rs232/printer.cpp
index 19347b84002..0112edc8715 100644
--- a/src/devices/bus/rs232/printer.cpp
+++ b/src/devices/bus/rs232/printer.cpp
@@ -55,7 +55,7 @@ void serial_printer_device::device_start()
{
}
-WRITE_LINE_MEMBER(serial_printer_device::update_serial)
+void serial_printer_device::update_serial(int state)
{
int startbits = 1;
int databits = convert_databits(m_rs232_databits->read());
@@ -79,7 +79,7 @@ void serial_printer_device::device_reset()
update_serial(0);
}
-WRITE_LINE_MEMBER(serial_printer_device::printer_online)
+void serial_printer_device::printer_online(int state)
{
/// TODO: ?
}
diff --git a/src/devices/bus/rs232/printer.h b/src/devices/bus/rs232/printer.h
index cdc0fbbbbf7..795c1128896 100644
--- a/src/devices/bus/rs232/printer.h
+++ b/src/devices/bus/rs232/printer.h
@@ -16,9 +16,9 @@ class serial_printer_device : public device_t,
public:
serial_printer_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual DECLARE_WRITE_LINE_MEMBER( input_txd ) override { device_serial_interface::rx_w(state); }
+ virtual void input_txd(int state) override { device_serial_interface::rx_w(state); }
- DECLARE_WRITE_LINE_MEMBER(update_serial);
+ void update_serial(int state);
protected:
serial_printer_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
@@ -31,7 +31,7 @@ protected:
int m_initial_rx_state;
private:
- DECLARE_WRITE_LINE_MEMBER(printer_online);
+ void printer_online(int state);
required_device<printer_image_device> m_printer;
diff --git a/src/devices/bus/rs232/pty.cpp b/src/devices/bus/rs232/pty.cpp
index 3cef298dc6c..f633f72bdec 100644
--- a/src/devices/bus/rs232/pty.cpp
+++ b/src/devices/bus/rs232/pty.cpp
@@ -7,8 +7,6 @@
#include <cstdio>
-static constexpr int TIMER_POLL = 1;
-
pseudo_terminal_device::pseudo_terminal_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, PSEUDO_TERMINAL, tag, owner, clock),
device_serial_interface(mconfig, *this),
@@ -19,13 +17,17 @@ pseudo_terminal_device::pseudo_terminal_device(const machine_config &mconfig, co
m_rs232_databits(*this, "RS232_DATABITS"),
m_rs232_parity(*this, "RS232_PARITY"),
m_rs232_stopbits(*this, "RS232_STOPBITS"),
+ m_flow(*this, "FLOW_CONTROL"),
m_input_count(0),
m_input_index(0),
- m_timer_poll(nullptr)
+ m_timer_poll(nullptr),
+ m_rts(0),
+ m_dtr(0),
+ m_xoff(0)
{
}
-WRITE_LINE_MEMBER(pseudo_terminal_device::update_serial)
+void pseudo_terminal_device::update_serial(int state)
{
int startbits = 1;
int databits = convert_databits(m_rs232_databits->read());
@@ -46,6 +48,8 @@ WRITE_LINE_MEMBER(pseudo_terminal_device::update_serial)
output_dcd(0);
output_dsr(0);
output_cts(0);
+
+ m_xoff = 0;
}
static INPUT_PORTS_START(pseudo_terminal)
@@ -54,6 +58,13 @@ static INPUT_PORTS_START(pseudo_terminal)
PORT_RS232_DATABITS("RS232_DATABITS", RS232_DATABITS_8, "Data Bits", pseudo_terminal_device, update_serial)
PORT_RS232_PARITY("RS232_PARITY", RS232_PARITY_NONE, "Parity", pseudo_terminal_device, update_serial)
PORT_RS232_STOPBITS("RS232_STOPBITS", RS232_STOPBITS_1, "Stop Bits", pseudo_terminal_device, update_serial)
+
+ PORT_START("FLOW_CONTROL")
+ PORT_CONFNAME(0x07, 0x00, "Flow Control")
+ PORT_CONFSETTING( 0x00, DEF_STR(Off))
+ PORT_CONFSETTING( 0x01, "RTS")
+ PORT_CONFSETTING( 0x02, "DTR")
+ PORT_CONFSETTING( 0x04, "XON/XOFF")
INPUT_PORTS_END
ioport_constructor pseudo_terminal_device::device_input_ports() const
@@ -92,7 +103,29 @@ void pseudo_terminal_device::tra_complete()
void pseudo_terminal_device::rcv_complete()
{
receive_register_extract();
- write(get_received_char());
+
+ uint8_t const data = get_received_char();
+ if (m_flow->read() != 4)
+ {
+ write(data);
+ }
+ else
+ {
+ switch (data)
+ {
+ case 0x13: // XOFF
+ m_xoff = 1;
+ return;
+
+ case 0x11: // XON
+ m_xoff = 0;
+ return;
+
+ default:
+ break;
+ }
+ write(data);
+ }
}
TIMER_CALLBACK_MEMBER(pseudo_terminal_device::update_queue)
@@ -102,26 +135,28 @@ TIMER_CALLBACK_MEMBER(pseudo_terminal_device::update_queue)
if (m_input_index == m_input_count)
{
m_input_index = 0;
- int tmp = read(m_input_buffer , sizeof(m_input_buffer));
- if (tmp > 0) {
+ int const tmp = read(m_input_buffer, sizeof(m_input_buffer));
+ if (tmp > 0)
m_input_count = tmp;
- } else {
+ else
m_input_count = 0;
- }
}
if (m_input_count != 0)
{
- transmit_register_setup(m_input_buffer[ m_input_index++ ]);
+ uint8_t const fc = m_flow->read();
- m_timer_poll->adjust(attotime::never);
- }
- else
- {
- int txbaud = convert_baud(m_rs232_txbaud->read());
- m_timer_poll->adjust(attotime::from_hz(txbaud));
+ if (fc == 0 || (fc == 1 && m_rts == 0) || (fc == 2 && m_dtr == 0) || (fc == 4 && m_xoff == 0))
+ {
+ transmit_register_setup(m_input_buffer[m_input_index++]);
+ m_timer_poll->adjust(attotime::never);
+ return;
+ }
}
+
+ int const txbaud = convert_baud(m_rs232_txbaud->read());
+ m_timer_poll->adjust(attotime::from_hz(txbaud));
}
}
-DEFINE_DEVICE_TYPE(PSEUDO_TERMINAL, pseudo_terminal_device, "pseudo_terminal", "Pseudo terminal")
+DEFINE_DEVICE_TYPE(PSEUDO_TERMINAL, pseudo_terminal_device, "pseudo_terminal", "Pseudo Terminal")
diff --git a/src/devices/bus/rs232/pty.h b/src/devices/bus/rs232/pty.h
index f9fefec5e72..0f7ae08aa2a 100644
--- a/src/devices/bus/rs232/pty.h
+++ b/src/devices/bus/rs232/pty.h
@@ -17,9 +17,9 @@ class pseudo_terminal_device : public device_t,
public:
pseudo_terminal_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual DECLARE_WRITE_LINE_MEMBER( input_txd ) override { device_serial_interface::rx_w(state); }
+ virtual void input_txd(int state) override { device_serial_interface::rx_w(state); }
- DECLARE_WRITE_LINE_MEMBER(update_serial);
+ void update_serial(int state);
protected:
virtual ioport_constructor device_input_ports() const override;
@@ -39,11 +39,15 @@ private:
required_ioport m_rs232_databits;
required_ioport m_rs232_parity;
required_ioport m_rs232_stopbits;
+ required_ioport m_flow;
- uint8_t m_input_buffer[ 1024 ];
+ uint8_t m_input_buffer[1024];
uint32_t m_input_count;
uint32_t m_input_index;
emu_timer *m_timer_poll;
+ int m_rts;
+ int m_dtr;
+ int m_xoff;
};
DECLARE_DEVICE_TYPE(PSEUDO_TERMINAL, pseudo_terminal_device)
diff --git a/src/devices/bus/rs232/rs232.cpp b/src/devices/bus/rs232/rs232.cpp
index 805d295c4de..11a81a54471 100644
--- a/src/devices/bus/rs232/rs232.cpp
+++ b/src/devices/bus/rs232/rs232.cpp
@@ -83,15 +83,6 @@ void rs232_port_device::device_config_complete()
void rs232_port_device::device_resolve_objects()
{
- m_rxd_handler.resolve_safe();
- m_dcd_handler.resolve_safe();
- m_dsr_handler.resolve_safe();
- m_ri_handler.resolve_safe();
- m_si_handler.resolve_safe();
- m_cts_handler.resolve_safe();
- m_rxc_handler.resolve_safe();
- m_txc_handler.resolve_safe();
-
m_rxd = 1;
m_dcd = 1;
m_dsr = 1;
@@ -122,31 +113,31 @@ void rs232_port_device::device_start()
save_item(NAME(m_dce_txc));
}
-WRITE_LINE_MEMBER( rs232_port_device::write_txd )
+void rs232_port_device::write_txd(int state)
{
if (m_dev)
m_dev->input_txd(state);
}
-WRITE_LINE_MEMBER( rs232_port_device::write_dtr )
+void rs232_port_device::write_dtr(int state)
{
if (m_dev)
m_dev->input_dtr(state);
}
-WRITE_LINE_MEMBER( rs232_port_device::write_rts )
+void rs232_port_device::write_rts(int state)
{
if (m_dev)
m_dev->input_rts(state);
}
-WRITE_LINE_MEMBER( rs232_port_device::write_etc )
+void rs232_port_device::write_etc(int state)
{
if (m_dev)
m_dev->input_etc(state);
}
-WRITE_LINE_MEMBER( rs232_port_device::write_spds )
+void rs232_port_device::write_spds(int state)
{
if (m_dev)
m_dev->input_spds(state);
@@ -167,11 +158,13 @@ device_rs232_port_interface::~device_rs232_port_interface()
#include "keyboard.h"
#include "loopback.h"
#include "mboardd.h"
+#include "nss_tvinterface.h"
#include "null_modem.h"
#include "patchbox.h"
#include "printer.h"
#include "pty.h"
#include "rs232_sync_io.h"
+#include "scorpion.h"
#include "sun_kbd.h"
#include "swtpc8212.h"
#include "terminal.h"
@@ -186,12 +179,14 @@ void default_rs232_devices(device_slot_interface &device)
device.option_add("keyboard", SERIAL_KEYBOARD);
device.option_add("loopback", RS232_LOOPBACK);
device.option_add("mockingboard", SERIAL_MOCKINGBOARD_D);
+ device.option_add("nss_tvi", NSS_TVINTERFACE);
device.option_add("null_modem", NULL_MODEM);
device.option_add("patch", RS232_PATCH_BOX);
device.option_add("printer", SERIAL_PRINTER);
device.option_add("pty", PSEUDO_TERMINAL);
device.option_add("rs232_sync_io", RS232_SYNC_IO);
device.option_add("rs_printer", RADIO_SHACK_SERIAL_PRINTER);
+ device.option_add("scorpion", SCORPION_IC);
device.option_add("sunkbd", SUN_KBD_ADAPTOR);
device.option_add("swtpc8212", SERIAL_TERMINAL_SWTPC8212);
device.option_add("terminal", SERIAL_TERMINAL);
diff --git a/src/devices/bus/rs232/rs232.h b/src/devices/bus/rs232/rs232.h
index 576b0797dc4..cfbd9206265 100644
--- a/src/devices/bus/rs232/rs232.h
+++ b/src/devices/bus/rs232/rs232.h
@@ -31,6 +31,7 @@
#define RS232_BAUD_2000 (0x13)
#define RS232_BAUD_3600 (0x14)
#define RS232_BAUD_7200 (0x15)
+#define RS232_BAUD_111900 (0x16)
#define PORT_RS232_BAUD(_tag, _default_baud, _description, _class, _write_line) \
PORT_START(_tag) \
@@ -56,6 +57,7 @@
PORT_CONFSETTING( RS232_BAUD_28800, "28800") \
PORT_CONFSETTING( RS232_BAUD_38400, "38400") \
PORT_CONFSETTING( RS232_BAUD_57600, "57600") \
+ PORT_CONFSETTING( RS232_BAUD_111900, "111900") \
PORT_CONFSETTING( RS232_BAUD_115200, "115200")
#define RS232_DATABITS_5 (0x00)
@@ -128,20 +130,20 @@ public:
auto rxc_handler() { return m_rxc_handler.bind(); }
auto txc_handler() { return m_txc_handler.bind(); }
- DECLARE_WRITE_LINE_MEMBER( write_txd ); // DB25 pin 2 V.24 circuit 103 Transmitted data
- DECLARE_WRITE_LINE_MEMBER( write_dtr ); // DB25 pin 20 V.24 circuit 108/2 Data terminal ready
- DECLARE_WRITE_LINE_MEMBER( write_rts ); // DB25 pin 4 V.24 circuit 105 Request to send
- DECLARE_WRITE_LINE_MEMBER( write_etc ); // DB25 pin 24 V.24 circuit 113 Transmitter signal element timing (DTE)
- DECLARE_WRITE_LINE_MEMBER( write_spds ); // DB25 pin 23 V.24 circuit 111 Data signal rate selector (DTE)
-
- DECLARE_READ_LINE_MEMBER( rxd_r ) { return m_rxd; } // DB25 pin 3 V.24 circuit 104 Received data
- DECLARE_READ_LINE_MEMBER( dcd_r ) { return m_dcd; } // DB25 pin 8 V.24 circuit 109 Data channel received line signal detector
- DECLARE_READ_LINE_MEMBER( dsr_r ) { return m_dsr; } // DB25 pin 6 V.24 circuit 107 Data set ready
- DECLARE_READ_LINE_MEMBER( ri_r ) { return m_ri; } // DB25 pin 22 V.24 circuit 125 Calling indicator
- DECLARE_READ_LINE_MEMBER( si_r ) { return m_si; } // V.24 circuit 112 Data signal rate selector (DCE)
- DECLARE_READ_LINE_MEMBER( cts_r ) { return m_cts; } // DB25 pin 5 V.24 circuit 106 Ready for sending
- DECLARE_READ_LINE_MEMBER( rxc_r ) { return m_dce_rxc; } // DB25 pin 17 V.24 circuit 115 Receiver signal element timing (DCE)
- DECLARE_READ_LINE_MEMBER( txc_r ) { return m_dce_txc; } // DB25 pin 15 V.24 circuit 114 Transmitter signal element timing (DCE)
+ void write_txd(int state); // DB25 pin 2 V.24 circuit 103 Transmitted data
+ void write_dtr(int state); // DB25 pin 20 V.24 circuit 108/2 Data terminal ready
+ void write_rts(int state); // DB25 pin 4 V.24 circuit 105 Request to send
+ void write_etc(int state); // DB25 pin 24 V.24 circuit 113 Transmitter signal element timing (DTE)
+ void write_spds(int state); // DB25 pin 23 V.24 circuit 111 Data signal rate selector (DTE)
+
+ int rxd_r() { return m_rxd; } // DB25 pin 3 V.24 circuit 104 Received data
+ int dcd_r() { return m_dcd; } // DB25 pin 8 V.24 circuit 109 Data channel received line signal detector
+ int dsr_r() { return m_dsr; } // DB25 pin 6 V.24 circuit 107 Data set ready
+ int ri_r() { return m_ri; } // DB25 pin 22 V.24 circuit 125 Calling indicator
+ int si_r() { return m_si; } // V.24 circuit 112 Data signal rate selector (DCE)
+ int cts_r() { return m_cts; } // DB25 pin 5 V.24 circuit 106 Ready for sending
+ int rxc_r() { return m_dce_rxc; } // DB25 pin 17 V.24 circuit 115 Receiver signal element timing (DCE)
+ int txc_r() { return m_dce_txc; } // DB25 pin 15 V.24 circuit 114 Transmitter signal element timing (DCE)
protected:
rs232_port_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
@@ -180,20 +182,20 @@ class device_rs232_port_interface : public device_interface
public:
virtual ~device_rs232_port_interface();
- virtual DECLARE_WRITE_LINE_MEMBER( input_txd ) { }
- virtual DECLARE_WRITE_LINE_MEMBER( input_dtr ) { }
- virtual DECLARE_WRITE_LINE_MEMBER( input_rts ) { }
- virtual DECLARE_WRITE_LINE_MEMBER( input_etc ) { }
- virtual DECLARE_WRITE_LINE_MEMBER( input_spds ) { }
-
- DECLARE_WRITE_LINE_MEMBER( output_rxd ) { m_port->m_rxd = state; m_port->m_rxd_handler(state); }
- DECLARE_WRITE_LINE_MEMBER( output_dcd ) { m_port->m_dcd = state; m_port->m_dcd_handler(state); }
- DECLARE_WRITE_LINE_MEMBER( output_dsr ) { m_port->m_dsr = state; m_port->m_dsr_handler(state); }
- DECLARE_WRITE_LINE_MEMBER( output_ri ) { m_port->m_ri = state; m_port->m_ri_handler(state); }
- DECLARE_WRITE_LINE_MEMBER( output_si ) { m_port->m_si = state; m_port->m_si_handler(state); }
- DECLARE_WRITE_LINE_MEMBER( output_cts ) { m_port->m_cts = state; m_port->m_cts_handler(state); }
- DECLARE_WRITE_LINE_MEMBER( output_rxc ) { m_port->m_dce_rxc = state; m_port->m_rxc_handler(state); }
- DECLARE_WRITE_LINE_MEMBER( output_txc ) { m_port->m_dce_txc = state; m_port->m_txc_handler(state); }
+ virtual void input_txd(int state) { }
+ virtual void input_dtr(int state) { }
+ virtual void input_rts(int state) { }
+ virtual void input_etc(int state) { }
+ virtual void input_spds(int state) { }
+
+ void output_rxd(int state) { m_port->m_rxd = state; m_port->m_rxd_handler(state); }
+ void output_dcd(int state) { m_port->m_dcd = state; m_port->m_dcd_handler(state); }
+ void output_dsr(int state) { m_port->m_dsr = state; m_port->m_dsr_handler(state); }
+ void output_ri(int state) { m_port->m_ri = state; m_port->m_ri_handler(state); }
+ void output_si(int state) { m_port->m_si = state; m_port->m_si_handler(state); }
+ void output_cts(int state) { m_port->m_cts = state; m_port->m_cts_handler(state); }
+ void output_rxc(int state) { m_port->m_dce_rxc = state; m_port->m_rxc_handler(state); }
+ void output_txc(int state) { m_port->m_dce_txc = state; m_port->m_txc_handler(state); }
protected:
device_rs232_port_interface(const machine_config &mconfig, device_t &device);
@@ -226,7 +228,8 @@ protected:
1800,
2000,
3600,
- 7200
+ 7200,
+ 111900
};
return values[baud];
@@ -277,7 +280,7 @@ template <uint32_t FIFO_LENGTH>
class buffered_rs232_device : public device_t, public device_buffered_serial_interface<FIFO_LENGTH>, public device_rs232_port_interface
{
public:
- virtual DECLARE_WRITE_LINE_MEMBER( input_txd ) override
+ virtual void input_txd(int state) override
{
device_buffered_serial_interface<FIFO_LENGTH>::rx_w(state);
}
diff --git a/src/devices/bus/rs232/rs232_sync_io.cpp b/src/devices/bus/rs232/rs232_sync_io.cpp
index 8403c41e2cf..9812087b363 100644
--- a/src/devices/bus/rs232/rs232_sync_io.cpp
+++ b/src/devices/bus/rs232/rs232_sync_io.cpp
@@ -70,13 +70,13 @@ rs232_sync_io_device:: ~rs232_sync_io_device()
{
}
-WRITE_LINE_MEMBER(rs232_sync_io_device::input_txd)
+void rs232_sync_io_device::input_txd(int state)
{
m_txd = state;
LOG("TxD %d %u\n" , state , m_tx_counter);
}
-WRITE_LINE_MEMBER(rs232_sync_io_device::input_rts)
+void rs232_sync_io_device::input_rts(int state)
{
m_rts = state;
}
@@ -191,11 +191,11 @@ TIMER_CALLBACK_MEMBER(rs232_sync_io_device::clock_tick)
}
}
-WRITE_LINE_MEMBER(rs232_sync_io_device::update_serial)
+void rs232_sync_io_device::update_serial(int state)
{
auto baud_rate = convert_baud(m_rs232_baud->read());
auto period = attotime::from_hz(baud_rate * 2);
m_clk_timer->adjust(period , 0 , period);
}
-DEFINE_DEVICE_TYPE(RS232_SYNC_IO, rs232_sync_io_device, "rs232_sync_io", "RS232 Synchronous I/O")
+DEFINE_DEVICE_TYPE(RS232_SYNC_IO, rs232_sync_io_device, "rs232_sync_io", "RS-232 Synchronous I/O")
diff --git a/src/devices/bus/rs232/rs232_sync_io.h b/src/devices/bus/rs232/rs232_sync_io.h
index a5b6818de48..3b821b31a18 100644
--- a/src/devices/bus/rs232/rs232_sync_io.h
+++ b/src/devices/bus/rs232/rs232_sync_io.h
@@ -23,10 +23,10 @@ public:
rs232_sync_io_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual ~rs232_sync_io_device();
- virtual DECLARE_WRITE_LINE_MEMBER(input_txd) override;
- virtual DECLARE_WRITE_LINE_MEMBER(input_rts) override;
+ virtual void input_txd(int state) override;
+ virtual void input_rts(int state) override;
- DECLARE_WRITE_LINE_MEMBER(update_serial);
+ void update_serial(int state);
protected:
// device-level overrides
diff --git a/src/devices/bus/rs232/scorpion.cpp b/src/devices/bus/rs232/scorpion.cpp
new file mode 100644
index 00000000000..e32f0a2b12c
--- /dev/null
+++ b/src/devices/bus/rs232/scorpion.cpp
@@ -0,0 +1,199 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/******************************************************************************
+
+ Micro-Robotics Scorpion Intelligent Controller
+
+ Specification:
+ - 6303 CMOS micro-processor, 1.23 MHz operation
+ - 24K RAM with battery backup
+ - 32K system ROM
+ - clock calendar
+
+ Programming requirements:
+ A computer with a serial port capable of running at 9600 baud, supporting a
+ terminal emulator preferably conforming to VT52 or VT100 standards.
+
+ Note: Use with BBC Micro with Scorpion Terminal Emulator ROM.
+
+ TODO:
+ - verify serial handshaking
+ - LCD display
+ - 20 key keypad
+
+******************************************************************************/
+
+#include "emu.h"
+#include "scorpion.h"
+
+#include "cpu/m6800/m6801.h"
+#include "machine/nvram.h"
+#include "machine/pcf8573.h"
+
+
+#define LOG_PORT2 (1U << 1)
+#define LOG_PORT5 (1U << 2)
+#define LOG_PORT6 (1U << 3)
+#define LOG_PORT7 (1U << 4)
+
+#define VERBOSE (0)
+#include "logmacro.h"
+
+
+namespace {
+
+class scorpion_ic_device : public device_t, public device_rs232_port_interface
+{
+public:
+ scorpion_ic_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, SCORPION_IC, tag, owner, clock)
+ , device_rs232_port_interface(mconfig, *this)
+ , m_maincpu(*this, "maincpu")
+ , m_rombank(*this, "rombank")
+ , m_rtc(*this, "rtc")
+ , m_txd(0)
+ , m_rts(0)
+ {
+ }
+
+ virtual void input_txd(int state) override { m_txd = state; }
+ virtual void input_rts(int state) override { m_rts = state; }
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+private:
+ required_device<hd6301x_cpu_device> m_maincpu;
+ required_memory_bank m_rombank;
+ required_device<pcf8573_device> m_rtc;
+
+ void scorpion_map(address_map &map);
+
+ uint8_t port2_r();
+ uint8_t port5_r();
+ uint8_t port6_r();
+ void port6_w(uint8_t data);
+ void port7_w(uint8_t data);
+
+ int m_txd;
+ int m_rts;
+};
+
+
+void scorpion_ic_device::device_start()
+{
+ m_rombank->configure_entries(0, 2, memregion("sys_rom")->base(), 0x4000);
+}
+
+void scorpion_ic_device::device_reset()
+{
+ m_rombank->set_entry(0);
+
+ output_cts(0);
+}
+
+
+ROM_START( scorpion )
+ ROM_REGION(0x8000, "sys_rom", 0)
+ ROM_SYSTEM_BIOS(0, "61203", "Version 61203 (3rd Dec 1986)")
+ ROMX_LOAD("scorpion_61203.bin", 0x0000, 0x8000, CRC(4ff495d1) SHA1(91c273c94cd0dbca655e192dd01ac6dc3a4f60a8), ROM_BIOS(0))
+
+ ROM_REGION(0x4000, "exp_rom", ROMREGION_ERASE00)
+ROM_END
+
+const tiny_rom_entry *scorpion_ic_device::device_rom_region() const
+{
+ return ROM_NAME( scorpion );
+}
+
+
+void scorpion_ic_device::scorpion_map(address_map &map)
+{
+ map(0x07f0, 0x07f0).nopr(); // ??
+ map(0x0bf0, 0x0bf0).nopr(); // ??
+ map(0x0ef0, 0x0ef0).nopr(); // ??
+ map(0x0fb0, 0x0fb0).nopr(); // ??
+ map(0x0fe0, 0x0fe0).nopr(); // ??
+ map(0x2000, 0x7fff).ram().share("nvram");
+ map(0x8000, 0xbfff).rom().region("exp_rom", 0);
+ map(0xc000, 0xffff).bankr("rombank").nopw();
+}
+
+
+void scorpion_ic_device::device_add_mconfig(machine_config &config)
+{
+ HD6303X(config, m_maincpu, 4.9152_MHz_XTAL); // TODO: verify clock
+ m_maincpu->set_addrmap(AS_PROGRAM, &scorpion_ic_device::scorpion_map);
+ m_maincpu->in_p2_cb().set(FUNC(scorpion_ic_device::port2_r));
+ //m_maincpu->out_p2_cb().set([this](uint8_t data) { logerror("%s port2_w: %02x\n", machine().describe_context(), data); } );
+ m_maincpu->in_p5_cb().set(FUNC(scorpion_ic_device::port5_r));
+ m_maincpu->in_p6_cb().set(FUNC(scorpion_ic_device::port6_r));
+ m_maincpu->out_p6_cb().set(FUNC(scorpion_ic_device::port6_w));
+ m_maincpu->out_p7_cb().set(FUNC(scorpion_ic_device::port7_w));
+ m_maincpu->out_ser_tx_cb().set(FUNC(scorpion_ic_device::output_rxd));
+
+ NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0);
+
+ PCF8573(config, m_rtc, 32.768_kHz_XTAL);
+}
+
+
+uint8_t scorpion_ic_device::port2_r()
+{
+ uint8_t data = 0xf7;
+
+ data |= m_txd << 3;
+
+ if (!machine().side_effects_disabled())
+ LOGMASKED(LOG_PORT2, "%s port2_r: %02x\n", machine().describe_context(), data);
+
+ return data;
+}
+
+uint8_t scorpion_ic_device::port5_r()
+{
+ uint8_t data = 0xef;
+
+ data |= m_rts << 4;
+
+ if (!machine().side_effects_disabled())
+ LOGMASKED(LOG_PORT5, "%s port5_r: %02x\n", machine().describe_context(), data);
+
+ return data;
+}
+
+uint8_t scorpion_ic_device::port6_r()
+{
+ uint8_t data = 0x00;
+
+ data |= m_rtc->sda_r() << 3;
+
+ if (!machine().side_effects_disabled())
+ LOGMASKED(LOG_PORT6, "%s port6_r: %02x\n", machine().describe_context(), data);
+
+ return data;
+}
+
+void scorpion_ic_device::port6_w(uint8_t data)
+{
+ LOGMASKED(LOG_PORT6, "%s port6_w: %02x\n", machine().describe_context(), data);
+
+ m_rtc->sda_w(BIT(data, 3));
+ m_rtc->scl_w(BIT(data, 4));
+
+ m_rombank->set_entry(BIT(data, 6));
+}
+
+void scorpion_ic_device::port7_w(uint8_t data)
+{
+ LOGMASKED(LOG_PORT7, "%s port7_w: %02x\n", machine().describe_context(), data);
+}
+
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(SCORPION_IC, device_rs232_port_interface, scorpion_ic_device, "scorpion_ic", "Micro-Robotics Scorpion Intelligent Controller")
diff --git a/src/devices/bus/rs232/scorpion.h b/src/devices/bus/rs232/scorpion.h
new file mode 100644
index 00000000000..81f02159458
--- /dev/null
+++ b/src/devices/bus/rs232/scorpion.h
@@ -0,0 +1,13 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+#ifndef MAME_BUS_RS232_SCORPION_H
+#define MAME_BUS_RS232_SCORPION_H
+
+#pragma once
+
+#include "rs232.h"
+
+
+DECLARE_DEVICE_TYPE(SCORPION_IC, device_rs232_port_interface)
+
+#endif // MAME_BUS_RS232_SCORPION_H
diff --git a/src/devices/bus/rs232/sun_kbd.cpp b/src/devices/bus/rs232/sun_kbd.cpp
index 32ed5d42c80..316a2012b82 100644
--- a/src/devices/bus/rs232/sun_kbd.cpp
+++ b/src/devices/bus/rs232/sun_kbd.cpp
@@ -20,7 +20,7 @@ public:
{
}
- virtual DECLARE_WRITE_LINE_MEMBER( input_txd ) override { m_keyboard_port->write_txd(state); }
+ virtual void input_txd(int state) override { m_keyboard_port->write_txd(state); }
protected:
virtual void device_add_mconfig(machine_config &config) override
diff --git a/src/devices/bus/rs232/swtpc8212.cpp b/src/devices/bus/rs232/swtpc8212.cpp
index b7265aea5d5..aa331c66a93 100644
--- a/src/devices/bus/rs232/swtpc8212.cpp
+++ b/src/devices/bus/rs232/swtpc8212.cpp
@@ -34,19 +34,19 @@ ioport_constructor swtpc8212_terminal_device::device_input_ports() const
return INPUT_PORTS_NAME(swtpc8212_terminal);
}
-WRITE_LINE_MEMBER(swtpc8212_terminal_device::input_txd)
+void swtpc8212_terminal_device::input_txd(int state)
{
m_swtpc8212->rs232_conn_rxd_w(state);
}
-WRITE_LINE_MEMBER(swtpc8212_terminal_device::route_term_rts)
+void swtpc8212_terminal_device::route_term_rts(int state)
{
// Loop the terminal RTS output to the terminal CTS input.
m_swtpc8212->rs232_conn_cts_w(state);
}
// This terminal uses DTR for hardware flow control.
-WRITE_LINE_MEMBER(swtpc8212_terminal_device::route_term_dtr)
+void swtpc8212_terminal_device::route_term_dtr(int state)
{
if (m_flow_control->read())
{
diff --git a/src/devices/bus/rs232/swtpc8212.h b/src/devices/bus/rs232/swtpc8212.h
index 2af82fa3215..6105faa7058 100644
--- a/src/devices/bus/rs232/swtpc8212.h
+++ b/src/devices/bus/rs232/swtpc8212.h
@@ -15,7 +15,7 @@ class swtpc8212_terminal_device : public device_t, public device_rs232_port_inte
public:
swtpc8212_terminal_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual DECLARE_WRITE_LINE_MEMBER(input_txd) override;
+ virtual void input_txd(int state) override;
DECLARE_INPUT_CHANGED_MEMBER(flow_control);
@@ -29,8 +29,8 @@ private:
required_device<swtpc8212_device> m_swtpc8212;
required_ioport m_flow_control;
- DECLARE_WRITE_LINE_MEMBER(route_term_rts);
- DECLARE_WRITE_LINE_MEMBER(route_term_dtr);
+ void route_term_rts(int state);
+ void route_term_dtr(int state);
int m_dtr;
};
diff --git a/src/devices/bus/rs232/terminal.cpp b/src/devices/bus/rs232/terminal.cpp
index 24c37f5a0e2..a1ae0612694 100644
--- a/src/devices/bus/rs232/terminal.cpp
+++ b/src/devices/bus/rs232/terminal.cpp
@@ -15,9 +15,9 @@ class serial_terminal_device : public generic_terminal_device,
public:
serial_terminal_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual DECLARE_WRITE_LINE_MEMBER( input_txd ) override { device_buffered_serial_interface::rx_w(state); }
+ virtual void input_txd(int state) override { device_buffered_serial_interface::rx_w(state); }
- DECLARE_WRITE_LINE_MEMBER(update_serial);
+ void update_serial(int state);
protected:
virtual ioport_constructor device_input_ports() const override;
@@ -63,7 +63,7 @@ ioport_constructor serial_terminal_device::device_input_ports() const
return INPUT_PORTS_NAME(serial_terminal);
}
-WRITE_LINE_MEMBER(serial_terminal_device::update_serial)
+void serial_terminal_device::update_serial(int state)
{
clear_fifo();
diff --git a/src/devices/bus/rs232/xvd701.cpp b/src/devices/bus/rs232/xvd701.cpp
index a04365f2239..3b1c3843f96 100644
--- a/src/devices/bus/rs232/xvd701.cpp
+++ b/src/devices/bus/rs232/xvd701.cpp
@@ -4,7 +4,7 @@
#include "emu.h"
#include "xvd701.h"
-#define LOG_COMMAND (1 << 1)
+#define LOG_COMMAND (1U << 1)
// #define VERBOSE (LOG_COMMAND)
// #define LOG_OUTPUT_STREAM std::cout
diff --git a/src/devices/bus/rs232/xvd701.h b/src/devices/bus/rs232/xvd701.h
index 8e85e377f76..2d1419d307f 100644
--- a/src/devices/bus/rs232/xvd701.h
+++ b/src/devices/bus/rs232/xvd701.h
@@ -13,7 +13,7 @@ class jvc_xvd701_device : public device_t,
public:
jvc_xvd701_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual WRITE_LINE_MEMBER( input_txd ) override { device_serial_interface::rx_w(state); }
+ virtual void input_txd(int state) override { device_serial_interface::rx_w(state); }
protected:
virtual ioport_constructor device_input_ports() const override;
virtual void device_start() override;
diff --git a/src/devices/bus/rtpc/kbd.cpp b/src/devices/bus/rtpc/kbd.cpp
index 13cc1759a2d..f403114b8f7 100644
--- a/src/devices/bus/rtpc/kbd.cpp
+++ b/src/devices/bus/rtpc/kbd.cpp
@@ -15,7 +15,7 @@
* set and scan codes are very similar to a PC keyboard (scan code "set 3").
*
* Sources:
- * - http://bitsavers.org/pdf/ibm/pc/rt/6489893_RT_PC_Technical_Reference_Volume_1_Nov85.pdf
+ * - IBM RT PC Hardware Technical Reference Volume I, 75X0232, March 1987
*
* Key switches are addressed using an 8 bit code as follows:
*
@@ -49,13 +49,12 @@
#include "sound/spkrdev.h"
#include "speaker.h"
-#define LOG_GENERAL (1U << 0)
#define LOG_PORTS (1U << 1)
//#define VERBOSE (LOG_GENERAL)
#include "logmacro.h"
-DEFINE_DEVICE_TYPE(RTPC_KBD, rtpc_kbd_device, "rtpc_kbd", "IBM PC RT Keyboard")
+DEFINE_DEVICE_TYPE(RTPC_KBD, rtpc_kbd_device, "rtpc_kbd", "IBM RT PC Keyboard")
rtpc_kbd_device::rtpc_kbd_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
: device_t(mconfig, RTPC_KBD, tag, owner, clock)
diff --git a/src/devices/bus/rtpc/kbd_con.cpp b/src/devices/bus/rtpc/kbd_con.cpp
index f8617fe3ef5..3e689485594 100644
--- a/src/devices/bus/rtpc/kbd_con.cpp
+++ b/src/devices/bus/rtpc/kbd_con.cpp
@@ -10,8 +10,6 @@
#include "emu.h"
#include "kbd_con.h"
-#define LOG_GENERAL (1U << 0)
-
//#define VERBOSE (LOG_GENERAL)
#include "logmacro.h"
@@ -37,12 +35,6 @@ void rtpc_kbd_con_device::device_config_complete()
m_keyboard = get_card_device();
}
-void rtpc_kbd_con_device::device_resolve_objects()
-{
- m_out_clock_cb.resolve_safe();
- m_out_data_cb.resolve_safe();
-}
-
void rtpc_kbd_con_device::device_start()
{
save_item(NAME(m_clock_state));
diff --git a/src/devices/bus/rtpc/kbd_con.h b/src/devices/bus/rtpc/kbd_con.h
index b066fc56137..1c38bbc09e7 100644
--- a/src/devices/bus/rtpc/kbd_con.h
+++ b/src/devices/bus/rtpc/kbd_con.h
@@ -36,7 +36,6 @@ public:
void data_write_from_kb(int state);
protected:
- virtual void device_resolve_objects() override;
virtual void device_config_complete() override;
virtual void device_start() override;
diff --git a/src/devices/bus/s100/ascsasi.cpp b/src/devices/bus/s100/ascsasi.cpp
index 73cacf9680a..1733b2caf3e 100644
--- a/src/devices/bus/s100/ascsasi.cpp
+++ b/src/devices/bus/s100/ascsasi.cpp
@@ -46,8 +46,8 @@ protected:
virtual void s100_sout_w(offs_t offset, u8 data) override;
private:
- DECLARE_WRITE_LINE_MEMBER(iio_w);
- DECLARE_WRITE_LINE_MEMBER(req_w);
+ void iio_w(int state);
+ void req_w(int state);
void sasi_sel_pulse();
void sasi_rst_pulse();
TIMER_CALLBACK_MEMBER(sel_off);
@@ -106,7 +106,7 @@ void asc_sasi_device::device_reset()
m_boot = true;
}
-WRITE_LINE_MEMBER(asc_sasi_device::iio_w)
+void asc_sasi_device::iio_w(int state)
{
// Release data bus when I/O is asserted
if (state)
@@ -115,7 +115,7 @@ WRITE_LINE_MEMBER(asc_sasi_device::iio_w)
m_sasi->data_w(7, m_data_latch);
}
-WRITE_LINE_MEMBER(asc_sasi_device::req_w)
+void asc_sasi_device::req_w(int state)
{
// Clear ACK when REQ is negated
if (!state)
diff --git a/src/devices/bus/s100/dj2db.cpp b/src/devices/bus/s100/dj2db.cpp
index 6ee50a89840..cd160593425 100644
--- a/src/devices/bus/s100/dj2db.cpp
+++ b/src/devices/bus/s100/dj2db.cpp
@@ -71,7 +71,7 @@ static void s100_dj2db_floppies(device_slot_interface &device)
device.option_add("8dsdd", FLOPPY_8_DSDD);
}
-WRITE_LINE_MEMBER( s100_dj2db_device::fdc_intrq_w )
+void s100_dj2db_device::fdc_intrq_w(int state)
{
if (state) m_bus->rdy_w(CLEAR_LINE);
@@ -89,7 +89,7 @@ WRITE_LINE_MEMBER( s100_dj2db_device::fdc_intrq_w )
}
}
-WRITE_LINE_MEMBER( s100_dj2db_device::fdc_drq_w )
+void s100_dj2db_device::fdc_drq_w(int state)
{
if (state) m_bus->rdy_w(CLEAR_LINE);
}
diff --git a/src/devices/bus/s100/dj2db.h b/src/devices/bus/s100/dj2db.h
index e285ab43f42..6be3d63c117 100644
--- a/src/devices/bus/s100/dj2db.h
+++ b/src/devices/bus/s100/dj2db.h
@@ -50,8 +50,8 @@ protected:
virtual void s100_phantom_w(int state) override;
private:
- DECLARE_WRITE_LINE_MEMBER( fdc_intrq_w );
- DECLARE_WRITE_LINE_MEMBER( fdc_drq_w );
+ void fdc_intrq_w(int state);
+ void fdc_drq_w(int state);
// internal state
required_device<mb8866_device> m_fdc;
diff --git a/src/devices/bus/s100/polyvti.cpp b/src/devices/bus/s100/polyvti.cpp
index 242d13a8fe2..e84ea2e7ded 100644
--- a/src/devices/bus/s100/polyvti.cpp
+++ b/src/devices/bus/s100/polyvti.cpp
@@ -54,7 +54,7 @@ private:
u32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
void kbd_put(u8 data);
- DECLARE_WRITE_LINE_MEMBER(kbd_int_w);
+ void kbd_int_w(int state);
// object finders
required_device<i8212_device> m_kbdlatch;
@@ -206,7 +206,7 @@ void poly_vti_device::kbd_put(u8 data)
}
}
-WRITE_LINE_MEMBER(poly_vti_device::kbd_int_w)
+void poly_vti_device::kbd_int_w(int state)
{
m_kbd_int = !state;
diff --git a/src/devices/bus/s100/s100.cpp b/src/devices/bus/s100/s100.cpp
index 67a5df55124..403c0e6e5b6 100644
--- a/src/devices/bus/s100/s100.cpp
+++ b/src/devices/bus/s100/s100.cpp
@@ -29,8 +29,7 @@ DEFINE_DEVICE_TYPE(S100_SLOT, s100_slot_device, "s100_slot", "S100 slot")
device_s100_card_interface::device_s100_card_interface(const machine_config &mconfig, device_t &device) :
device_interface(device, "s100bus"),
- m_bus(nullptr),
- m_next(nullptr)
+ m_bus(nullptr)
{
}
@@ -60,7 +59,7 @@ void s100_slot_device::device_start()
{
device_s100_card_interface *const dev = get_card_device();
if (dev)
- m_bus->add_card(dev);
+ m_bus->add_card(*dev);
}
@@ -90,6 +89,10 @@ s100_bus_device::s100_bus_device(const machine_config &mconfig, const char *tag,
{
}
+s100_bus_device::~s100_bus_device()
+{
+}
+
//-------------------------------------------------
// device_start - device-specific startup
@@ -97,24 +100,6 @@ s100_bus_device::s100_bus_device(const machine_config &mconfig, const char *tag,
void s100_bus_device::device_start()
{
- // resolve callbacks
- m_write_irq.resolve_safe();
- m_write_nmi.resolve_safe();
- m_write_vi0.resolve_safe();
- m_write_vi1.resolve_safe();
- m_write_vi2.resolve_safe();
- m_write_vi3.resolve_safe();
- m_write_vi4.resolve_safe();
- m_write_vi5.resolve_safe();
- m_write_vi6.resolve_safe();
- m_write_vi7.resolve_safe();
- m_write_dma0.resolve_safe();
- m_write_dma1.resolve_safe();
- m_write_dma2.resolve_safe();
- m_write_dma3.resolve_safe();
- m_write_rdy.resolve_safe();
- m_write_hold.resolve_safe();
- m_write_error.resolve_safe();
}
@@ -131,10 +116,10 @@ void s100_bus_device::device_reset()
// add_card - add card
//-------------------------------------------------
-void s100_bus_device::add_card(device_s100_card_interface *card)
+void s100_bus_device::add_card(device_s100_card_interface &card)
{
- card->m_bus = this;
- m_device_list.append(*card);
+ card.m_bus = this;
+ m_device_list.emplace_back(card);
}
@@ -146,13 +131,8 @@ uint8_t s100_bus_device::smemr_r(offs_t offset)
{
uint8_t data = 0xff;
- device_s100_card_interface *entry = m_device_list.first();
-
- while (entry)
- {
- data &= entry->s100_smemr_r(offset);
- entry = entry->next();
- }
+ for (device_s100_card_interface &entry : m_device_list)
+ data &= entry.s100_smemr_r(offset);
return data;
}
@@ -164,13 +144,8 @@ uint8_t s100_bus_device::smemr_r(offs_t offset)
void s100_bus_device::mwrt_w(offs_t offset, uint8_t data)
{
- device_s100_card_interface *entry = m_device_list.first();
-
- while (entry)
- {
- entry->s100_mwrt_w(offset, data);
- entry = entry->next();
- }
+ for (device_s100_card_interface &entry : m_device_list)
+ entry.s100_mwrt_w(offset, data);
}
@@ -182,13 +157,8 @@ uint8_t s100_bus_device::sinp_r(offs_t offset)
{
uint8_t data = 0xff;
- device_s100_card_interface *entry = m_device_list.first();
-
- while (entry)
- {
- data &= entry->s100_sinp_r(offset);
- entry = entry->next();
- }
+ for (device_s100_card_interface &entry : m_device_list)
+ data &= entry.s100_sinp_r(offset);
return data;
}
@@ -200,11 +170,6 @@ uint8_t s100_bus_device::sinp_r(offs_t offset)
void s100_bus_device::sout_w(offs_t offset, uint8_t data)
{
- device_s100_card_interface *entry = m_device_list.first();
-
- while (entry)
- {
- entry->s100_sout_w(offset, data);
- entry = entry->next();
- }
+ for (device_s100_card_interface &entry : m_device_list)
+ entry.s100_sout_w(offset, data);
}
diff --git a/src/devices/bus/s100/s100.h b/src/devices/bus/s100/s100.h
index ae10f4e70bc..337cb4264c3 100644
--- a/src/devices/bus/s100/s100.h
+++ b/src/devices/bus/s100/s100.h
@@ -64,6 +64,8 @@
#pragma once
+#include <functional>
+#include <vector>
@@ -78,11 +80,8 @@ class s100_bus_device;
class device_s100_card_interface : public device_interface
{
friend class s100_bus_device;
- template <class ElementType> friend class simple_list;
public:
- device_s100_card_interface *next() const { return m_next; }
-
// interrupts
virtual void s100_int_w(int state) { }
virtual void s100_nmi_w(int state) { }
@@ -125,9 +124,6 @@ protected:
virtual void interface_pre_start() override;
s100_bus_device *m_bus;
-
-private:
- device_s100_card_interface *m_next;
};
@@ -139,7 +135,7 @@ class s100_bus_device : public device_t
public:
// construction/destruction
s100_bus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- ~s100_bus_device() { m_device_list.detach_all(); }
+ ~s100_bus_device();
auto irq() { return m_write_irq.bind(); }
auto nmi() { return m_write_nmi.bind(); }
@@ -159,7 +155,7 @@ public:
auto hold() { return m_write_hold.bind(); }
auto error() { return m_write_error.bind(); }
- void add_card(device_s100_card_interface *card);
+ void add_card(device_s100_card_interface &card);
uint8_t smemr_r(offs_t offset);
void mwrt_w(offs_t offset, uint8_t data);
@@ -167,30 +163,32 @@ public:
uint8_t sinp_r(offs_t offset);
void sout_w(offs_t offset, uint8_t data);
- DECLARE_WRITE_LINE_MEMBER( irq_w ) { m_write_irq(state); }
- DECLARE_WRITE_LINE_MEMBER( nmi_w ) { m_write_nmi(state); }
- DECLARE_WRITE_LINE_MEMBER( vi0_w ) { m_write_vi0(state); }
- DECLARE_WRITE_LINE_MEMBER( vi1_w ) { m_write_vi1(state); }
- DECLARE_WRITE_LINE_MEMBER( vi2_w ) { m_write_vi2(state); }
- DECLARE_WRITE_LINE_MEMBER( vi3_w ) { m_write_vi3(state); }
- DECLARE_WRITE_LINE_MEMBER( vi4_w ) { m_write_vi4(state); }
- DECLARE_WRITE_LINE_MEMBER( vi5_w ) { m_write_vi5(state); }
- DECLARE_WRITE_LINE_MEMBER( vi6_w ) { m_write_vi6(state); }
- DECLARE_WRITE_LINE_MEMBER( vi7_w ) { m_write_vi7(state); }
- DECLARE_WRITE_LINE_MEMBER( dma0_w ) { m_write_dma0(state); }
- DECLARE_WRITE_LINE_MEMBER( dma1_w ) { m_write_dma1(state); }
- DECLARE_WRITE_LINE_MEMBER( dma2_w ) { m_write_dma2(state); }
- DECLARE_WRITE_LINE_MEMBER( dma3_w ) { m_write_dma3(state); }
- DECLARE_WRITE_LINE_MEMBER( rdy_w ) { m_write_rdy(state); }
- DECLARE_WRITE_LINE_MEMBER( hold_w ) { m_write_hold(state); }
- DECLARE_WRITE_LINE_MEMBER( error_w ) { m_write_error(state); }
+ void irq_w(int state) { m_write_irq(state); }
+ void nmi_w(int state) { m_write_nmi(state); }
+ void vi0_w(int state) { m_write_vi0(state); }
+ void vi1_w(int state) { m_write_vi1(state); }
+ void vi2_w(int state) { m_write_vi2(state); }
+ void vi3_w(int state) { m_write_vi3(state); }
+ void vi4_w(int state) { m_write_vi4(state); }
+ void vi5_w(int state) { m_write_vi5(state); }
+ void vi6_w(int state) { m_write_vi6(state); }
+ void vi7_w(int state) { m_write_vi7(state); }
+ void dma0_w(int state) { m_write_dma0(state); }
+ void dma1_w(int state) { m_write_dma1(state); }
+ void dma2_w(int state) { m_write_dma2(state); }
+ void dma3_w(int state) { m_write_dma3(state); }
+ void rdy_w(int state) { m_write_rdy(state); }
+ void hold_w(int state) { m_write_hold(state); }
+ void error_w(int state) { m_write_error(state); }
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
virtual void device_reset() override;
private:
+ using card_vector = std::vector<std::reference_wrapper<device_s100_card_interface> >;
+
devcb_write_line m_write_irq;
devcb_write_line m_write_nmi;
devcb_write_line m_write_vi0;
@@ -209,7 +207,7 @@ private:
devcb_write_line m_write_hold;
devcb_write_line m_write_error;
- simple_list<device_s100_card_interface> m_device_list;
+ card_vector m_device_list;
};
diff --git a/src/devices/bus/s100/seals8k.cpp b/src/devices/bus/s100/seals8k.cpp
index 58a040efad4..ae81cc50d01 100644
--- a/src/devices/bus/s100/seals8k.cpp
+++ b/src/devices/bus/s100/seals8k.cpp
@@ -164,8 +164,8 @@ void s100_8k_sc_device::device_start()
bool s100_8k_sc_bb_device::nvram_read(util::read_stream &file)
{
- size_t actual;
- return !file.read(m_ram.get(), 0x2000, actual) && actual == 0x2000;
+ auto const [err, actual] = read(file, m_ram.get(), 0x2000);
+ return !err && (actual == 0x2000);
}
@@ -175,8 +175,8 @@ bool s100_8k_sc_bb_device::nvram_read(util::read_stream &file)
bool s100_8k_sc_bb_device::nvram_write(util::write_stream &file)
{
- size_t actual;
- return !file.write(m_ram.get(), 0x2000, actual) && actual == 0x2000;
+ auto const [err, actual] = write(file, m_ram.get(), 0x2000);
+ return !err;
}
diff --git a/src/devices/bus/s100/vectordualmode.cpp b/src/devices/bus/s100/vectordualmode.cpp
new file mode 100644
index 00000000000..c1aec1d746a
--- /dev/null
+++ b/src/devices/bus/s100/vectordualmode.cpp
@@ -0,0 +1,327 @@
+// license:BSD-3-Clause
+// copyright-holders:Eric Anderson
+/***************************************************************************
+
+Vector Graphic had two related disk controllers for the Vector 4. There was
+the "dual-mode" ST506-interface HDD/5.25" FDD controller and a stripped-down
+5.25" FDD-only controller. Both can handle four FDD. The dual-mode version
+supports a HDD as drive 0, replacing a FDD when used.
+
+The floppy and hard drive formatting is not IBM compatible. Instead they are
+based on the Micropolis MFM hard-sectored format which starts and ends the
+sector with 0x00 preamble and postable bytes and starts sector data with a
+0xFF sync byte. The FDD has 16 hard sectors, but the HDD uses a normal
+soft-sectored drive with a PLL on the controller to emulate 32 hard sectors.
+No abnormal MFM clock bits are used.
+
+https://www.bitsavers.org/pdf/vectorGraphic/hardware/7200-1200-02-1_Dual-Mode_Disk_Controller_Board_Engineering_Documentation_Feb81.pdf
+https://archive.org/details/7200-0001-vector-4-technical-information-sep-82
+
+TODO:
+- HDD support
+- ECC
+
+****************************************************************************/
+
+#include "emu.h"
+#include "vectordualmode.h"
+
+#include "formats/vgi_dsk.h"
+
+static const attotime half_bitcell_size = attotime::from_usec(2);
+
+/* Interleave 8 bits with zeros. abcdefgh -> 0a0b0c0d0e0f0g0h */
+static int deposit8(int data)
+{
+ int d = data;
+ d = ((d & 0xf0) << 4) | (d & 0x0f);
+ d = ((d << 2) | d) & 0x3333;
+ d = ((d << 1) | d) & 0x5555;
+ return d;
+}
+
+static uint16_t mfm_byte(uint8_t data, unsigned int prev_data)
+{
+ const unsigned int ext_data = data | (prev_data << 8);
+ const unsigned int clock = ~(ext_data | (ext_data >> 1));
+ return (deposit8(clock) << 1) | deposit8(ext_data);
+}
+
+static uint8_t unmfm_byte(uint16_t mfm)
+{
+ unsigned int d = mfm;
+ d &= 0x5555;
+ d = ((d >> 1) | d) & 0x3333;
+ d = ((d >> 2) | d) & 0x0f0f;
+ d = ((d >> 4) | d) & 0x00ff;
+ return d;
+}
+
+s100_vector_dualmode_device::s100_vector_dualmode_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, S100_VECTOR_DUALMODE, tag, owner, clock)
+ , device_s100_card_interface(mconfig, *this)
+ , m_floppy(*this, "floppy%u", 0U)
+ , m_ram{0}
+ , m_cmar(0)
+ , m_drive(0)
+ , m_sector(0)
+ , m_read(false)
+ , m_pll()
+ , m_byte_timer(nullptr)
+ , m_sector_timer(nullptr)
+ , m_pending_byte(0)
+ , m_pending_size(0)
+{
+}
+
+TIMER_CALLBACK_MEMBER(s100_vector_dualmode_device::motor_off)
+{
+ for (int i = 0; i < m_floppy.size(); i++) {
+ floppy_image_device* flop = m_floppy[m_drive]->get_device();
+ if (flop)
+ flop->mon_w(1);
+ }
+}
+
+bool s100_vector_dualmode_device::hdd_selected()
+{
+ // TODO: HDD support
+ return m_drive == 0 && false;
+}
+
+uint8_t s100_vector_dualmode_device::s100_sinp_r(offs_t offset)
+{
+ // 7200-1200-02-1 page 16 (1-10)
+ uint8_t data;
+ if (offset == 0xc0) { // status (0) port
+ bool write_protect; // FDD
+ bool ready; // HDD
+ bool track0;
+ bool write_fault = false; // HDD
+ bool seek_complete; // HDD
+ bool loss_of_sync; // HDD
+ if (hdd_selected()) {
+ write_protect = false;
+ ready = true;
+ track0 = false;
+ seek_complete = true;
+ loss_of_sync = true;
+ } else {
+ floppy_image_device* flop = m_floppy[m_drive]->get_device();
+ write_protect = flop && flop->wpt_r();
+ ready = false;
+ track0 = flop && !flop->trk00_r();
+ seek_complete = false;
+ loss_of_sync = false;
+ }
+
+ data = (write_protect ? 0x01 : 0)
+ | (ready ? 0x02 : 0)
+ | (track0 ? 0x04 : 0)
+ | (write_fault ? 0x08 : 0)
+ | (seek_complete ? 0x10 : 0)
+ | (loss_of_sync ? 0x20 : 0)
+ | 0xc0;
+ } else if (offset == 0xc1) { // status (1) port
+ bool floppy_disk_selected;
+ bool controller_busy = m_sector_timer->enabled();
+ bool motor_on; // FDD
+ bool type_of_hard_disk = true;
+ if (hdd_selected()) {
+ floppy_disk_selected = false;
+ motor_on = false;
+ } else {
+ floppy_disk_selected = true;
+ motor_on = m_motor_on_timer->enabled();
+ }
+ data = (floppy_disk_selected ? 0x01 : 0)
+ | (controller_busy ? 0x02 : 0)
+ | (motor_on ? 0x04 : 0)
+ | (type_of_hard_disk ? 0x08 : 0)
+ | 0xf0;
+ } else if (offset == 0xc2) { // data port
+ data = m_ram[m_cmar];
+ if (!machine().side_effects_disabled()) {
+ m_cmar++;
+ m_cmar &= 0x1ff;
+ }
+ } else if (offset == 0xc3) { // reset port
+ if (!machine().side_effects_disabled())
+ m_cmar = 0;
+ data = 0xff;
+ } else {
+ data = 0xff;
+ }
+ return data;
+}
+
+void s100_vector_dualmode_device::s100_sout_w(offs_t offset, uint8_t data)
+{
+ // TODO: check actual behavior when controller is busy
+ if (m_sector_timer->enabled()) {
+ return;
+ }
+ // 7200-1200-02-1 page 14 (1-8)
+ if (offset == 0xc0) { // control (0) port
+ m_drive = BIT(data, 0, 2);
+ const uint8_t head = BIT(data, 2, 3);
+ const bool step = BIT(data, 5);
+ const bool step_in = BIT(data, 6);
+ //uint8_t low_current = BIT(data, 7);
+
+ for (int i = 0; i < m_floppy.size(); i++) {
+ floppy_image_device* flop = m_floppy[m_drive]->get_device();
+ if (flop)
+ flop->mon_w(0);
+ }
+ // WR0| triggers U60, a 74LS123 with 100uF cap and 100k res
+ m_motor_on_timer->adjust(attotime::from_usec(2819600));
+
+ floppy_image_device* flop = m_floppy[m_drive]->get_device();
+ if (flop) {
+ flop->ss_w(head & 1);
+ // Software should not change other bits when pulsing step
+ flop->stp_w(!step);
+ flop->dir_w(!step_in);
+ }
+ } else if (offset == 0xc1) { // control (1) port
+ m_sector = BIT(data, 0, 5);
+ m_read = BIT(data, 5);
+ } else if (offset == 0xc2) { // data port
+ m_ram[m_cmar++] = data;
+ m_cmar &= 0x1ff;
+ } else if (offset == 0xc3) { // start port
+ floppy_image_device* flop = m_floppy[m_drive]->get_device();
+ if (!flop || flop->time_next_index().is_never())
+ return;
+ const attotime rot_time = attotime::from_msec(200);
+ attotime sector_time = flop->time_next_index() - machine().time() + (rot_time / 16) * m_sector;
+ if (sector_time > rot_time)
+ sector_time -= rot_time;
+ m_sector_timer->adjust(sector_time, SECTOR_START);
+ }
+}
+
+bool s100_vector_dualmode_device::get_next_bit(attotime &tm, const attotime &limit)
+{
+ int bit = m_pll.get_next_bit(tm, m_floppy[m_drive]->get_device(), limit);
+ if (bit < 0)
+ return false;
+ m_pending_byte <<= 1;
+ m_pending_byte |= bit;
+ m_pending_size++;
+ return true;
+}
+
+TIMER_CALLBACK_MEMBER(s100_vector_dualmode_device::sector_cb)
+{
+ switch (param) {
+ case SECTOR_START:
+ if (m_read) {
+ m_pll.set_clock(half_bitcell_size);
+ m_pll.read_reset(machine().time());
+ attotime tm;
+ attotime limit = machine().time() + half_bitcell_size*512;
+ while (get_next_bit(tm, limit)) {} // init PLL
+ limit += half_bitcell_size*16*30;
+ while (get_next_bit(tm, limit) && m_pending_byte != 0x5554) {}
+ if (m_pending_byte == 0x5554) {
+ m_pending_size = 1;
+ m_byte_timer->adjust(tm - machine().time());
+ }
+ } else {
+ m_pending_size = 0;
+ m_byte_timer->adjust(attotime::zero);
+ }
+ m_sector_timer->adjust(attotime::from_msec(200)/16, SECTOR_END);
+ break;
+
+ case SECTOR_END:
+ m_byte_timer->enable(false);
+ if (m_read)
+ m_ram[274] = 0; // Ignore ECC
+ break;
+ }
+}
+
+TIMER_CALLBACK_MEMBER(s100_vector_dualmode_device::byte_cb)
+{
+ if (m_read) {
+ if (m_pending_size == 16) {
+ m_pending_size = 0;
+ m_ram[m_cmar++] = unmfm_byte(m_pending_byte);
+ m_cmar &= 0x1ff;
+ }
+ attotime tm;
+ while (m_pending_size != 16 && get_next_bit(tm, attotime::never)) {}
+ m_byte_timer->adjust(tm - machine().time());
+ } else {
+ if (m_pending_size == 16) {
+ attotime start_time = machine().time() - half_bitcell_size*m_pending_size;
+ attotime tm = start_time + attotime::from_usec(1);
+ attotime buf[8];
+ int pos = 0;
+ while (m_pending_size) {
+ if (m_pending_byte & (1 << --m_pending_size))
+ buf[pos++] = tm;
+ tm += half_bitcell_size;
+ }
+ floppy_image_device *floppy = m_floppy[m_drive]->get_device();
+ if (floppy)
+ floppy->write_flux(start_time, machine().time(), pos, buf);
+ }
+ uint8_t last = m_cmar ? m_ram[m_cmar-1] : 0;
+ m_pending_byte = mfm_byte(m_ram[m_cmar++], last);
+ m_pending_size = 16;
+ m_cmar &= 0x1ff;
+ m_byte_timer->adjust(half_bitcell_size*16);
+ }
+}
+
+void s100_vector_dualmode_device::device_start()
+{
+ m_motor_on_timer = timer_alloc(FUNC(s100_vector_dualmode_device::motor_off), this);
+ m_byte_timer = timer_alloc(FUNC(s100_vector_dualmode_device::byte_cb), this);
+ m_sector_timer = timer_alloc(FUNC(s100_vector_dualmode_device::sector_cb), this);
+
+ save_item(NAME(m_ram));
+ save_item(NAME(m_cmar));
+ save_item(NAME(m_drive));
+ save_item(NAME(m_sector));
+ save_item(NAME(m_read));
+ save_item(NAME(m_pending_byte));
+ save_item(NAME(m_pending_size));
+}
+
+void s100_vector_dualmode_device::device_reset()
+{
+ // POC| resets
+ // U9
+ m_drive = 0;
+ // U18
+ m_sector = 0;
+ m_read = false;
+ // U60
+ m_motor_on_timer->enable(false);
+}
+
+static void vector4_floppies(device_slot_interface &device)
+{
+ device.option_add("525", FLOPPY_525_QD);
+}
+
+static void vector4_formats(format_registration &fr)
+{
+ fr.add_mfm_containers();
+ fr.add(FLOPPY_VGI_FORMAT);
+}
+
+void s100_vector_dualmode_device::device_add_mconfig(machine_config &config)
+{
+ FLOPPY_CONNECTOR(config, m_floppy[0], vector4_floppies, "525", vector4_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[1], vector4_floppies, "525", vector4_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[2], vector4_floppies, "525", vector4_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[3], vector4_floppies, "525", vector4_formats).enable_sound(true);
+}
+
+DEFINE_DEVICE_TYPE(S100_VECTOR_DUALMODE, s100_vector_dualmode_device, "vectordualmode", "Vector Dual-Mode Disk Controller")
diff --git a/src/devices/bus/s100/vectordualmode.h b/src/devices/bus/s100/vectordualmode.h
new file mode 100644
index 00000000000..e3a924a94c3
--- /dev/null
+++ b/src/devices/bus/s100/vectordualmode.h
@@ -0,0 +1,55 @@
+// license:BSD-3-Clause
+// copyright-holders:Eric Anderson
+#ifndef MAME_BUS_S100_VECTORDUALMODE_H
+#define MAME_BUS_S100_VECTORDUALMODE_H
+
+#pragma once
+
+#include "bus/s100/s100.h"
+#include "imagedev/floppy.h"
+#include "machine/fdc_pll.h"
+
+class s100_vector_dualmode_device :
+ public device_t,
+ public device_s100_card_interface
+{
+public:
+ s100_vector_dualmode_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ void device_start() override;
+ void device_reset() override;
+ void device_add_mconfig(machine_config &config) override;
+
+ uint8_t s100_sinp_r(offs_t offset) override;
+ void s100_sout_w(offs_t offset, uint8_t data) override;
+
+private:
+ TIMER_CALLBACK_MEMBER(motor_off);
+ TIMER_CALLBACK_MEMBER(sector_cb);
+ TIMER_CALLBACK_MEMBER(byte_cb);
+ bool hdd_selected();
+ bool get_next_bit(attotime &tm, const attotime &limit);
+
+ required_device_array<floppy_connector, 4> m_floppy;
+ uint8_t m_ram[512];
+ uint16_t m_cmar;
+ uint8_t m_drive;
+ uint8_t m_sector;
+ bool m_read;
+ emu_timer *m_motor_on_timer;
+
+ enum sector_timer_state {
+ SECTOR_START,
+ SECTOR_END,
+ };
+ fdc_pll_t m_pll;
+ emu_timer *m_byte_timer;
+ emu_timer *m_sector_timer;
+ uint16_t m_pending_byte;
+ uint8_t m_pending_size;
+};
+
+DECLARE_DEVICE_TYPE(S100_VECTOR_DUALMODE, s100_vector_dualmode_device)
+
+#endif // MAME_BUS_S100_VECTORDUALMODE_H
diff --git a/src/devices/bus/s100/wunderbus.cpp b/src/devices/bus/s100/wunderbus.cpp
index 29efc80b185..a331d026506 100644
--- a/src/devices/bus/s100/wunderbus.cpp
+++ b/src/devices/bus/s100/wunderbus.cpp
@@ -53,7 +53,7 @@ DEFINE_DEVICE_TYPE(S100_WUNDERBUS, s100_wunderbus_device, "s100_wunderbus", "Mor
*/
-WRITE_LINE_MEMBER( s100_wunderbus_device::pic_int_w )
+void s100_wunderbus_device::pic_int_w(int state)
{
m_bus->irq_w(state);
}
@@ -71,7 +71,7 @@ DEVICE_INPUT_DEFAULTS_END
// UPD1990A_INTERFACE( rtc_intf )
//-------------------------------------------------
-WRITE_LINE_MEMBER( s100_wunderbus_device::rtc_tp_w )
+void s100_wunderbus_device::rtc_tp_w(int state)
{
if (state)
{
diff --git a/src/devices/bus/s100/wunderbus.h b/src/devices/bus/s100/wunderbus.h
index ca9a6d0e641..a50fbea2d70 100644
--- a/src/devices/bus/s100/wunderbus.h
+++ b/src/devices/bus/s100/wunderbus.h
@@ -48,8 +48,8 @@ protected:
virtual void s100_sout_w(offs_t offset, uint8_t data) override;
private:
- DECLARE_WRITE_LINE_MEMBER( pic_int_w );
- DECLARE_WRITE_LINE_MEMBER( rtc_tp_w );
+ void pic_int_w(int state);
+ void rtc_tp_w(int state);
required_device<pic8259_device> m_pic;
required_device<ins8250_device> m_ace1;
diff --git a/src/devices/bus/saitek_osa/expansion.cpp b/src/devices/bus/saitek_osa/expansion.cpp
index 76a4ac6b6cd..a226a8ffafc 100644
--- a/src/devices/bus/saitek_osa/expansion.cpp
+++ b/src/devices/bus/saitek_osa/expansion.cpp
@@ -1,12 +1,12 @@
// license:BSD-3-Clause
// copyright-holders:Dirk Best, hap
-/***************************************************************************
+/*******************************************************************************
Saitek OSA Expansion Slot
Used by Saitek(SciSys) chess computers Leonardo, Galileo, Renaissance.
-***************************************************************************/
+*******************************************************************************/
#include "emu.h"
#include "expansion.h"
@@ -16,16 +16,16 @@ Used by Saitek(SciSys) chess computers Leonardo, Galileo, Renaissance.
#include "sparc.h"
-//**************************************************************************
+//******************************************************************************
// DEVICE DEFINITIONS
-//**************************************************************************
+//******************************************************************************
DEFINE_DEVICE_TYPE(SAITEKOSA_EXPANSION, saitekosa_expansion_device, "saitekosa_expansion", "Saitek OSA Expansion Bus")
-//**************************************************************************
+//******************************************************************************
// SLOT DEVICE
-//**************************************************************************
+//******************************************************************************
//-------------------------------------------------
// saitekosa_expansion_device - constructor
@@ -56,10 +56,6 @@ void saitekosa_expansion_device::device_start()
// get inserted module
m_module = get_card_device();
- // resolve callbacks
- m_stb_handler.resolve_safe();
- m_rts_handler.resolve_safe();
-
// register for savestates
save_item(NAME(m_data));
save_item(NAME(m_nmi));
@@ -136,9 +132,9 @@ u32 saitekosa_expansion_device::screen_update(screen_device &screen, bitmap_rgb3
}
-//**************************************************************************
+//******************************************************************************
// MODULE INTERFACE
-//**************************************************************************
+//******************************************************************************
//-------------------------------------------------
// device_saitekosa_expansion_interface - constructor
diff --git a/src/devices/bus/saitek_osa/expansion.h b/src/devices/bus/saitek_osa/expansion.h
index 47364d492ec..34afb641a53 100644
--- a/src/devices/bus/saitek_osa/expansion.h
+++ b/src/devices/bus/saitek_osa/expansion.h
@@ -1,6 +1,6 @@
// license:BSD-3-Clause
// copyright-holders:Dirk Best, hap
-/***************************************************************************
+/*******************************************************************************
Saitek OSA Expansion Slot
@@ -22,7 +22,7 @@
NMI-P >
V+ >
-***************************************************************************/
+*******************************************************************************/
#ifndef MAME_BUS_SAITEKOSA_EXPANSION_H
#define MAME_BUS_SAITEKOSA_EXPANSION_H
@@ -34,9 +34,9 @@
DECLARE_DEVICE_TYPE(SAITEKOSA_EXPANSION, saitekosa_expansion_device)
-//**************************************************************************
+//******************************************************************************
// TYPE DEFINITIONS
-//**************************************************************************
+//******************************************************************************
class device_saitekosa_expansion_interface;
@@ -88,8 +88,6 @@ private:
devcb_write_line m_stb_handler;
devcb_write_line m_rts_handler;
- u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
-
// input pins state
u8 m_data = 0;
int m_nmi = 0;
@@ -97,6 +95,8 @@ private:
int m_pw = 0;
device_saitekosa_expansion_interface *m_module;
+
+ u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
};
// ======================> device_saitekosa_expansion_interface
diff --git a/src/devices/bus/saitek_osa/maestro.cpp b/src/devices/bus/saitek_osa/maestro.cpp
index 71df45aae61..2599707130c 100644
--- a/src/devices/bus/saitek_osa/maestro.cpp
+++ b/src/devices/bus/saitek_osa/maestro.cpp
@@ -1,7 +1,7 @@
// license:BSD-3-Clause
// copyright-holders:hap
// thanks-to:Berger
-/***************************************************************************
+/*******************************************************************************
Saitek OSA Module: Kasparov Maestro/Analyst (1987-1990)
This is for the newer versions. For Maestro A, see maestroa.*
@@ -28,25 +28,69 @@ handle the overclock well enough, they went for a slightly lower speed XTAL.
TODO:
- cpu clock divider after writing to 0x2000/0x2200
-***************************************************************************/
+*******************************************************************************/
#include "emu.h"
#include "maestro.h"
#include "bus/generic/carts.h"
+#include "bus/generic/slot.h"
#include "cpu/m6502/r65c02.h"
+#include "video/hd44780.h"
#include "softlist_dev.h"
-
-DEFINE_DEVICE_TYPE(OSA_MAESTRO, saitekosa_maestro_device, "osa_maestro", "Maestro B-D")
-DEFINE_DEVICE_TYPE(OSA_ANALYST, saitekosa_analyst_device, "osa_analyst", "Analyst")
-
+namespace {
//-------------------------------------------------
// initialization
//-------------------------------------------------
+// Maestro / shared
+
+class saitekosa_maestro_device : public device_t, public device_saitekosa_expansion_interface
+{
+public:
+ // construction/destruction
+ saitekosa_maestro_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ DECLARE_INPUT_CHANGED_MEMBER(change_cpu_freq);
+
+ // from host
+ virtual u8 data_r() override;
+ virtual void nmi_w(int state) override;
+ virtual void ack_w(int state) override;
+
+protected:
+ saitekosa_maestro_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
+ virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual ioport_constructor device_input_ports() const override;
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ required_device<cpu_device> m_maincpu;
+ memory_share_creator<u8> m_banked_ram;
+ required_memory_bank m_rambank;
+ required_memory_bank m_rombank;
+ required_device<generic_slot_device> m_extrom;
+
+ u8 m_latch = 0xff;
+ bool m_latch_enable = false;
+ u8 m_extrom_bank = 0;
+
+ virtual void main_map(address_map &map);
+
+ u8 extrom_r(offs_t offset);
+ template <int N> void stall_w(u8 data = 0);
+ u8 rts_r();
+ u8 xdata_r();
+ void xdata_w(u8 data);
+ u8 ack_r();
+ void control_w(u8 data);
+};
+
saitekosa_maestro_device::saitekosa_maestro_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock) :
device_t(mconfig, type, tag, owner, clock),
device_saitekosa_expansion_interface(mconfig, *this),
@@ -61,11 +105,34 @@ saitekosa_maestro_device::saitekosa_maestro_device(const machine_config &mconfig
saitekosa_maestro_device(mconfig, OSA_MAESTRO, tag, owner, clock)
{ }
+
+// Analyst
+
+class saitekosa_analyst_device : public saitekosa_maestro_device
+{
+public:
+ saitekosa_analyst_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) override;
+
+ static auto parent_rom_device_type() { return &OSA_MAESTRO; }
+
+protected:
+ virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override;
+
+private:
+ required_device<hd44780_device> m_lcd;
+
+ virtual void main_map(address_map &map) override;
+};
+
saitekosa_analyst_device::saitekosa_analyst_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
saitekosa_maestro_device(mconfig, OSA_ANALYST, tag, owner, clock),
m_lcd(*this, "lcd")
{ }
+
void saitekosa_maestro_device::device_start()
{
// init banks
@@ -80,164 +147,51 @@ void saitekosa_maestro_device::device_start()
void saitekosa_maestro_device::device_reset()
{
- set_cpu_freq();
control_w(0);
}
-void saitekosa_maestro_device::set_cpu_freq()
+INPUT_CHANGED_MEMBER(saitekosa_maestro_device::change_cpu_freq)
{
static const XTAL xtal[6] = { 4_MHz_XTAL, 5.67_MHz_XTAL, 6_MHz_XTAL, 7.2_MHz_XTAL, 8_MHz_XTAL, 10_MHz_XTAL };
- m_maincpu->set_unscaled_clock(xtal[ioport("FAKE")->read() % 6]);
+ m_maincpu->set_unscaled_clock(xtal[newval % 6]);
}
//-------------------------------------------------
-// rom_region - device-specific ROM region
+// host i/o
//-------------------------------------------------
-ROM_START( maestro )
- ROM_REGION(0x10000, "maincpu", 0)
-
- ROM_DEFAULT_BIOS("d1")
-
- // B (Maestro only)
- ROM_SYSTEM_BIOS(0, "b1", "Maestro B (set 1)")
- ROMX_LOAD("m6c_807e_u2.u2", 0x0000, 0x8000, CRC(a6b11715) SHA1(18e086353d9122034f78bcd75ef5b3462c5983ac), ROM_BIOS(0))
- ROMX_LOAD("b6c_721_u3.u3", 0x8000, 0x8000, CRC(b1e57023) SHA1(6cec5cdc0bf4f8ac88afb0397fcb4738136b0431), ROM_BIOS(0))
-
- ROM_SYSTEM_BIOS(1, "b2", "Maestro B (set 2)")
- ROMX_LOAD("m6c_807c_u2.u2", 0x0000, 0x8000, CRC(57c34b4d) SHA1(1f436687f90b1afd4646e90d5617cf05c4465c98), ROM_BIOS(1))
- ROMX_LOAD("b6c_721_u3.u3", 0x8000, 0x8000, CRC(b1e57023) SHA1(6cec5cdc0bf4f8ac88afb0397fcb4738136b0431), ROM_BIOS(1))
-
- // C (C and above are shared Maestro/Analyst)
- ROM_SYSTEM_BIOS(2, "c1", "Maestro C (set 1)")
- ROMX_LOAD("m6l_b30d_u2.u2", 0x0000, 0x8000, CRC(bb10e15c) SHA1(7b0fb987c49da76a03b46c80d2b4eacaa785ee75), ROM_BIOS(2))
- ROMX_LOAD("b6c_721_u3.u3", 0x8000, 0x8000, CRC(b1e57023) SHA1(6cec5cdc0bf4f8ac88afb0397fcb4738136b0431), ROM_BIOS(2))
-
- ROM_SYSTEM_BIOS(3, "c2", "Maestro C (set 2)")
- ROMX_LOAD("m6l_b30b_u2.u2", 0x0000, 0x8000, CRC(4b5026d7) SHA1(9715a0220c1bd3456480104f1c7ae61cbf1a1d73), ROM_BIOS(3))
- ROMX_LOAD("b6c_721_u3.u3", 0x8000, 0x8000, CRC(b1e57023) SHA1(6cec5cdc0bf4f8ac88afb0397fcb4738136b0431), ROM_BIOS(3))
-
- ROM_SYSTEM_BIOS(4, "c3", "Maestro C (set 3)")
- ROMX_LOAD("m6l_b25_u2.u2", 0x0000, 0x8000, CRC(217ae56c) SHA1(27ec80d0f82723c2710e2ccb477705934a4c2119), ROM_BIOS(4))
- ROMX_LOAD("b6c_721_u3.u3", 0x8000, 0x8000, CRC(b1e57023) SHA1(6cec5cdc0bf4f8ac88afb0397fcb4738136b0431), ROM_BIOS(4))
-
- // D
- ROM_SYSTEM_BIOS(5, "d1", "Maestro D (set 1)")
- ROMX_LOAD("ma3_714a_u2.u2", 0x0000, 0x8000, CRC(435e1e30) SHA1(0d82df7c40443cb341dacebdf65f33c3e03bce70), ROM_BIOS(5))
- ROMX_LOAD("b6m_b15_u3.u3", 0x8000, 0x8000, CRC(6155de90) SHA1(bb5cdf061dde2d1dc7925d455891c3ade1d274e3), ROM_BIOS(5))
-
- ROM_SYSTEM_BIOS(6, "d2", "Maestro D (set 2)")
- ROMX_LOAD("ma3_714a_u2.u2", 0x0000, 0x8000, CRC(435e1e30) SHA1(0d82df7c40443cb341dacebdf65f33c3e03bce70), ROM_BIOS(6))
- ROMX_LOAD("b6m_629_u3.u3", 0x8000, 0x8000, CRC(15e7b1f1) SHA1(d2a757114f13c6141d74a15671aa06b675304b4a), ROM_BIOS(6))
-
- // D+
- ROM_SYSTEM_BIOS(7, "dp", "Maestro D+")
- ROMX_LOAD("m6m_625_u2.u2", 0x0000, 0x8000, CRC(aa7b5cfd) SHA1(e909108fdace633a519fecf0b9876fe6a46b2067), ROM_BIOS(7))
- ROMX_LOAD("b6m_614_u3.u3", 0x8000, 0x8000, CRC(eff75543) SHA1(d7c1b3824bc87d5ffada6f5c8c72a8b292ff3d46), ROM_BIOS(7))
-
- // D++
- ROM_SYSTEM_BIOS(8, "dpp", "Maestro D++")
- ROMX_LOAD("d++_u2.u2", 0x0000, 0x8000, CRC(48ef032c) SHA1(d336cb2096780b4d3bcceda0d2ed1246e780cd8d), ROM_BIOS(8))
- ROMX_LOAD("b6m_614_u3.u3", 0x8000, 0x8000, CRC(eff75543) SHA1(d7c1b3824bc87d5ffada6f5c8c72a8b292ff3d46), ROM_BIOS(8))
-ROM_END
-
-ROM_START( analyst )
- ROM_REGION(0x10000, "maincpu", 0)
-
- ROM_DEFAULT_BIOS("d1")
-
- // B (Analyst only)
- ROM_SYSTEM_BIOS(0, "b", "Analyst B")
- ROMX_LOAD("m6l_a15_u2.u2", 0x0000, 0x8000, CRC(91570897) SHA1(e6db36ffc87ce3941a3e12222678069cff9e47f6), ROM_BIOS(0))
- ROMX_LOAD("b6c_721_u3.u3", 0x8000, 0x8000, CRC(b1e57023) SHA1(6cec5cdc0bf4f8ac88afb0397fcb4738136b0431), ROM_BIOS(0))
-
- // C (C and above are shared Maestro/Analyst)
- ROM_SYSTEM_BIOS(1, "c1", "Analyst C (set 1)")
- ROMX_LOAD("m6l_b30d_u2.u2", 0x0000, 0x8000, CRC(bb10e15c) SHA1(7b0fb987c49da76a03b46c80d2b4eacaa785ee75), ROM_BIOS(1))
- ROMX_LOAD("b6c_721_u3.u3", 0x8000, 0x8000, CRC(b1e57023) SHA1(6cec5cdc0bf4f8ac88afb0397fcb4738136b0431), ROM_BIOS(1))
-
- ROM_SYSTEM_BIOS(2, "c2", "Analyst C (set 2)")
- ROMX_LOAD("m6l_b30b_u2.u2", 0x0000, 0x8000, CRC(4b5026d7) SHA1(9715a0220c1bd3456480104f1c7ae61cbf1a1d73), ROM_BIOS(2))
- ROMX_LOAD("b6c_721_u3.u3", 0x8000, 0x8000, CRC(b1e57023) SHA1(6cec5cdc0bf4f8ac88afb0397fcb4738136b0431), ROM_BIOS(2))
-
- ROM_SYSTEM_BIOS(3, "c3", "Analyst C (set 3)")
- ROMX_LOAD("m6l_b25_u2.u2", 0x0000, 0x8000, CRC(217ae56c) SHA1(27ec80d0f82723c2710e2ccb477705934a4c2119), ROM_BIOS(3))
- ROMX_LOAD("b6c_721_u3.u3", 0x8000, 0x8000, CRC(b1e57023) SHA1(6cec5cdc0bf4f8ac88afb0397fcb4738136b0431), ROM_BIOS(3))
-
- // D
- ROM_SYSTEM_BIOS(4, "d1", "Analyst D (set 1)")
- ROMX_LOAD("ma3_714a_u2.u2", 0x0000, 0x8000, CRC(435e1e30) SHA1(0d82df7c40443cb341dacebdf65f33c3e03bce70), ROM_BIOS(4))
- ROMX_LOAD("b6m_b15_u3.u3", 0x8000, 0x8000, CRC(6155de90) SHA1(bb5cdf061dde2d1dc7925d455891c3ade1d274e3), ROM_BIOS(4))
-
- ROM_SYSTEM_BIOS(5, "d2", "Analyst D (set 2)")
- ROMX_LOAD("ma3_714a_u2.u2", 0x0000, 0x8000, CRC(435e1e30) SHA1(0d82df7c40443cb341dacebdf65f33c3e03bce70), ROM_BIOS(5))
- ROMX_LOAD("b6m_629_u3.u3", 0x8000, 0x8000, CRC(15e7b1f1) SHA1(d2a757114f13c6141d74a15671aa06b675304b4a), ROM_BIOS(5))
-
- // D+
- ROM_SYSTEM_BIOS(6, "dp", "Analyst D+")
- ROMX_LOAD("m6m_625_u2.u2", 0x0000, 0x8000, CRC(aa7b5cfd) SHA1(e909108fdace633a519fecf0b9876fe6a46b2067), ROM_BIOS(6))
- ROMX_LOAD("b6m_614_u3.u3", 0x8000, 0x8000, CRC(eff75543) SHA1(d7c1b3824bc87d5ffada6f5c8c72a8b292ff3d46), ROM_BIOS(6))
-
- // D++
- ROM_SYSTEM_BIOS(7, "dpp", "Analyst D++")
- ROMX_LOAD("d++_u2.u2", 0x0000, 0x8000, CRC(48ef032c) SHA1(d336cb2096780b4d3bcceda0d2ed1246e780cd8d), ROM_BIOS(7))
- ROMX_LOAD("b6m_614_u3.u3", 0x8000, 0x8000, CRC(eff75543) SHA1(d7c1b3824bc87d5ffada6f5c8c72a8b292ff3d46), ROM_BIOS(7))
-ROM_END
-
-const tiny_rom_entry *saitekosa_maestro_device::device_rom_region() const
+u8 saitekosa_maestro_device::data_r()
{
- return ROM_NAME(maestro);
+ return m_latch_enable ? m_latch : 0xff;
}
-const tiny_rom_entry *saitekosa_analyst_device::device_rom_region() const
+void saitekosa_maestro_device::nmi_w(int state)
{
- return ROM_NAME(analyst);
+ m_maincpu->set_input_line(0, !state ? ASSERT_LINE : CLEAR_LINE);
}
-
-//-------------------------------------------------
-// input_ports - device-specific input ports
-//-------------------------------------------------
-
-static INPUT_PORTS_START( maestro )
- PORT_START("FAKE")
- PORT_CONFNAME( 0x07, 0x04, "CPU Frequency" ) PORT_CHANGED_MEMBER(DEVICE_SELF, saitekosa_maestro_device, switch_cpu_freq, 0) // factory set
- PORT_CONFSETTING( 0x00, "4MHz" )
- PORT_CONFSETTING( 0x01, "5.67MHz" )
- PORT_CONFSETTING( 0x02, "6MHz" )
- PORT_CONFSETTING( 0x03, "7.2MHz" )
- PORT_CONFSETTING( 0x04, "8MHz" )
- PORT_CONFSETTING( 0x05, "10MHz" )
-INPUT_PORTS_END
-
-ioport_constructor saitekosa_maestro_device::device_input_ports() const
+void saitekosa_maestro_device::ack_w(int state)
{
- return INPUT_PORTS_NAME(maestro);
+ if (state != m_expansion->ack_state())
+ machine().scheduler().perfect_quantum(attotime::from_usec(100));
}
-
-//-------------------------------------------------
-// device_add_mconfig - add device configuration
-//-------------------------------------------------
-
-void saitekosa_maestro_device::device_add_mconfig(machine_config &config)
+u32 saitekosa_analyst_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
- // basic machine hardware
- R65C02(config, m_maincpu, 8_MHz_XTAL);
- m_maincpu->set_addrmap(AS_PROGRAM, &saitekosa_maestro_device::main_map);
-
- // extension rom
- GENERIC_SOCKET(config, "extrom", generic_plain_slot, "saitek_egr");
- SOFTWARE_LIST(config, "cart_list").set_original("saitek_egr");
-}
+ bitmap.fill(0xffffff, cliprect);
+ const u8 *render = m_lcd->render();
-void saitekosa_analyst_device::device_add_mconfig(machine_config &config)
-{
- saitekosa_maestro_device::device_add_mconfig(config);
+ // draw lcd characters
+ for (int i = 0; i < 16; i++)
+ {
+ const u8 *src = render + 16 * ((i & 7) + BIT(i, 3) * 40);
+ for (int y = 0; y < 8; y++)
+ for (int x = 0; x < 5; x++)
+ bitmap.pix(y + 4, i * 6 + x + 2) = (BIT(src[y], 4 - x) && m_expansion->pw_state()) ? 0x282828 : 0xe8e8e8;
+ }
- // video hardware
- HD44780(config, m_lcd, 0);
+ return 0;
}
@@ -323,38 +277,156 @@ void saitekosa_analyst_device::main_map(address_map &map)
//-------------------------------------------------
-// host i/o
+// input_ports - device-specific input ports
//-------------------------------------------------
-u8 saitekosa_maestro_device::data_r()
+static INPUT_PORTS_START( maestro )
+ PORT_START("CPU")
+ PORT_CONFNAME( 0x07, 0x04, "CPU Frequency" ) PORT_CHANGED_MEMBER(DEVICE_SELF, saitekosa_maestro_device, change_cpu_freq, 0) // factory set
+ PORT_CONFSETTING( 0x00, "4MHz" )
+ PORT_CONFSETTING( 0x01, "5.67MHz" )
+ PORT_CONFSETTING( 0x02, "6MHz" )
+ PORT_CONFSETTING( 0x03, "7.2MHz" )
+ PORT_CONFSETTING( 0x04, "8MHz" )
+ PORT_CONFSETTING( 0x05, "10MHz" )
+INPUT_PORTS_END
+
+ioport_constructor saitekosa_maestro_device::device_input_ports() const
{
- return m_latch_enable ? m_latch : 0xff;
+ return INPUT_PORTS_NAME(maestro);
}
-void saitekosa_maestro_device::nmi_w(int state)
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void saitekosa_maestro_device::device_add_mconfig(machine_config &config)
{
- m_maincpu->set_input_line(0, !state ? ASSERT_LINE : CLEAR_LINE);
+ // basic machine hardware
+ R65C02(config, m_maincpu, 8_MHz_XTAL);
+ m_maincpu->set_addrmap(AS_PROGRAM, &saitekosa_maestro_device::main_map);
+
+ // extension rom
+ GENERIC_SOCKET(config, "extrom", generic_plain_slot, "saitek_egr");
+ SOFTWARE_LIST(config, "cart_list").set_original("saitek_egr");
}
-void saitekosa_maestro_device::ack_w(int state)
+void saitekosa_analyst_device::device_add_mconfig(machine_config &config)
{
- if (state != m_expansion->ack_state())
- machine().scheduler().boost_interleave(attotime::zero, attotime::from_usec(100));
+ saitekosa_maestro_device::device_add_mconfig(config);
+
+ // video hardware
+ HD44780(config, m_lcd, 270'000); // OSC = 91K resistor
}
-u32 saitekosa_analyst_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
-{
- bitmap.fill(0xffffff, cliprect);
- const u8 *render = m_lcd->render();
- // draw lcd characters
- for (int i = 0; i < 16; i++)
- {
- const u8 *src = render + 16 * ((i & 7) + BIT(i, 3) * 40);
- for (int y = 0; y < 8; y++)
- for (int x = 0; x < 5; x++)
- bitmap.pix(y + 4, i * 6 + x + 2) = (BIT(src[y], 4 - x) && m_expansion->pw_state()) ? 0x282828 : 0xe8e8e8;
- }
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
- return 0;
+ROM_START( maestro )
+ ROM_REGION(0x10000, "maincpu", 0)
+
+ ROM_DEFAULT_BIOS("d1")
+
+ // B (Maestro only)
+ ROM_SYSTEM_BIOS(0, "b1", "Maestro B (set 1)")
+ ROMX_LOAD("m6c_807e_u2.u2", 0x0000, 0x8000, CRC(a6b11715) SHA1(18e086353d9122034f78bcd75ef5b3462c5983ac), ROM_BIOS(0))
+ ROMX_LOAD("b6c_721_u3.u3", 0x8000, 0x8000, CRC(b1e57023) SHA1(6cec5cdc0bf4f8ac88afb0397fcb4738136b0431), ROM_BIOS(0))
+
+ ROM_SYSTEM_BIOS(1, "b2", "Maestro B (set 2)")
+ ROMX_LOAD("m6c_807c_u2.u2", 0x0000, 0x8000, CRC(57c34b4d) SHA1(1f436687f90b1afd4646e90d5617cf05c4465c98), ROM_BIOS(1))
+ ROMX_LOAD("b6c_721_u3.u3", 0x8000, 0x8000, CRC(b1e57023) SHA1(6cec5cdc0bf4f8ac88afb0397fcb4738136b0431), ROM_BIOS(1))
+
+ // C (C and above are shared Maestro/Analyst)
+ ROM_SYSTEM_BIOS(2, "c1", "Maestro C (set 1)")
+ ROMX_LOAD("m6l_b30d_u2.u2", 0x0000, 0x8000, CRC(bb10e15c) SHA1(7b0fb987c49da76a03b46c80d2b4eacaa785ee75), ROM_BIOS(2))
+ ROMX_LOAD("b6c_721_u3.u3", 0x8000, 0x8000, CRC(b1e57023) SHA1(6cec5cdc0bf4f8ac88afb0397fcb4738136b0431), ROM_BIOS(2))
+
+ ROM_SYSTEM_BIOS(3, "c2", "Maestro C (set 2)")
+ ROMX_LOAD("m6l_b30b_u2.u2", 0x0000, 0x8000, CRC(4b5026d7) SHA1(9715a0220c1bd3456480104f1c7ae61cbf1a1d73), ROM_BIOS(3))
+ ROMX_LOAD("b6c_721_u3.u3", 0x8000, 0x8000, CRC(b1e57023) SHA1(6cec5cdc0bf4f8ac88afb0397fcb4738136b0431), ROM_BIOS(3))
+
+ ROM_SYSTEM_BIOS(4, "c3", "Maestro C (set 3)")
+ ROMX_LOAD("m6l_b25_u2.u2", 0x0000, 0x8000, CRC(217ae56c) SHA1(27ec80d0f82723c2710e2ccb477705934a4c2119), ROM_BIOS(4))
+ ROMX_LOAD("b6c_721_u3.u3", 0x8000, 0x8000, CRC(b1e57023) SHA1(6cec5cdc0bf4f8ac88afb0397fcb4738136b0431), ROM_BIOS(4))
+
+ // D
+ ROM_SYSTEM_BIOS(5, "d1", "Maestro D (set 1)")
+ ROMX_LOAD("ma3_714a_u2.u2", 0x0000, 0x8000, CRC(435e1e30) SHA1(0d82df7c40443cb341dacebdf65f33c3e03bce70), ROM_BIOS(5))
+ ROMX_LOAD("b6m_b15_u3.u3", 0x8000, 0x8000, CRC(6155de90) SHA1(bb5cdf061dde2d1dc7925d455891c3ade1d274e3), ROM_BIOS(5))
+
+ ROM_SYSTEM_BIOS(6, "d2", "Maestro D (set 2)")
+ ROMX_LOAD("ma3_714a_u2.u2", 0x0000, 0x8000, CRC(435e1e30) SHA1(0d82df7c40443cb341dacebdf65f33c3e03bce70), ROM_BIOS(6))
+ ROMX_LOAD("b6m_629_u3.u3", 0x8000, 0x8000, CRC(15e7b1f1) SHA1(d2a757114f13c6141d74a15671aa06b675304b4a), ROM_BIOS(6))
+
+ // D+
+ ROM_SYSTEM_BIOS(7, "dp", "Maestro D+")
+ ROMX_LOAD("m6m_625_u2.u2", 0x0000, 0x8000, CRC(aa7b5cfd) SHA1(e909108fdace633a519fecf0b9876fe6a46b2067), ROM_BIOS(7))
+ ROMX_LOAD("b6m_614_u3.u3", 0x8000, 0x8000, CRC(eff75543) SHA1(d7c1b3824bc87d5ffada6f5c8c72a8b292ff3d46), ROM_BIOS(7))
+
+ // D++
+ ROM_SYSTEM_BIOS(8, "dpp", "Maestro D++")
+ ROMX_LOAD("d++_u2.u2", 0x0000, 0x8000, CRC(48ef032c) SHA1(d336cb2096780b4d3bcceda0d2ed1246e780cd8d), ROM_BIOS(8))
+ ROMX_LOAD("b6m_614_u3.u3", 0x8000, 0x8000, CRC(eff75543) SHA1(d7c1b3824bc87d5ffada6f5c8c72a8b292ff3d46), ROM_BIOS(8))
+ROM_END
+
+ROM_START( analyst )
+ ROM_REGION(0x10000, "maincpu", 0)
+
+ ROM_DEFAULT_BIOS("d1")
+
+ // B (Analyst only)
+ ROM_SYSTEM_BIOS(0, "b", "Analyst B")
+ ROMX_LOAD("m6l_a15_u2.u2", 0x0000, 0x8000, CRC(91570897) SHA1(e6db36ffc87ce3941a3e12222678069cff9e47f6), ROM_BIOS(0))
+ ROMX_LOAD("b6c_721_u3.u3", 0x8000, 0x8000, CRC(b1e57023) SHA1(6cec5cdc0bf4f8ac88afb0397fcb4738136b0431), ROM_BIOS(0))
+
+ // C (C and above are shared Maestro/Analyst)
+ ROM_SYSTEM_BIOS(1, "c1", "Analyst C (set 1)")
+ ROMX_LOAD("m6l_b30d_u2.u2", 0x0000, 0x8000, CRC(bb10e15c) SHA1(7b0fb987c49da76a03b46c80d2b4eacaa785ee75), ROM_BIOS(1))
+ ROMX_LOAD("b6c_721_u3.u3", 0x8000, 0x8000, CRC(b1e57023) SHA1(6cec5cdc0bf4f8ac88afb0397fcb4738136b0431), ROM_BIOS(1))
+
+ ROM_SYSTEM_BIOS(2, "c2", "Analyst C (set 2)")
+ ROMX_LOAD("m6l_b30b_u2.u2", 0x0000, 0x8000, CRC(4b5026d7) SHA1(9715a0220c1bd3456480104f1c7ae61cbf1a1d73), ROM_BIOS(2))
+ ROMX_LOAD("b6c_721_u3.u3", 0x8000, 0x8000, CRC(b1e57023) SHA1(6cec5cdc0bf4f8ac88afb0397fcb4738136b0431), ROM_BIOS(2))
+
+ ROM_SYSTEM_BIOS(3, "c3", "Analyst C (set 3)")
+ ROMX_LOAD("m6l_b25_u2.u2", 0x0000, 0x8000, CRC(217ae56c) SHA1(27ec80d0f82723c2710e2ccb477705934a4c2119), ROM_BIOS(3))
+ ROMX_LOAD("b6c_721_u3.u3", 0x8000, 0x8000, CRC(b1e57023) SHA1(6cec5cdc0bf4f8ac88afb0397fcb4738136b0431), ROM_BIOS(3))
+
+ // D
+ ROM_SYSTEM_BIOS(4, "d1", "Analyst D (set 1)")
+ ROMX_LOAD("ma3_714a_u2.u2", 0x0000, 0x8000, CRC(435e1e30) SHA1(0d82df7c40443cb341dacebdf65f33c3e03bce70), ROM_BIOS(4))
+ ROMX_LOAD("b6m_b15_u3.u3", 0x8000, 0x8000, CRC(6155de90) SHA1(bb5cdf061dde2d1dc7925d455891c3ade1d274e3), ROM_BIOS(4))
+
+ ROM_SYSTEM_BIOS(5, "d2", "Analyst D (set 2)")
+ ROMX_LOAD("ma3_714a_u2.u2", 0x0000, 0x8000, CRC(435e1e30) SHA1(0d82df7c40443cb341dacebdf65f33c3e03bce70), ROM_BIOS(5))
+ ROMX_LOAD("b6m_629_u3.u3", 0x8000, 0x8000, CRC(15e7b1f1) SHA1(d2a757114f13c6141d74a15671aa06b675304b4a), ROM_BIOS(5))
+
+ // D+
+ ROM_SYSTEM_BIOS(6, "dp", "Analyst D+")
+ ROMX_LOAD("m6m_625_u2.u2", 0x0000, 0x8000, CRC(aa7b5cfd) SHA1(e909108fdace633a519fecf0b9876fe6a46b2067), ROM_BIOS(6))
+ ROMX_LOAD("b6m_614_u3.u3", 0x8000, 0x8000, CRC(eff75543) SHA1(d7c1b3824bc87d5ffada6f5c8c72a8b292ff3d46), ROM_BIOS(6))
+
+ // D++
+ ROM_SYSTEM_BIOS(7, "dpp", "Analyst D++")
+ ROMX_LOAD("d++_u2.u2", 0x0000, 0x8000, CRC(48ef032c) SHA1(d336cb2096780b4d3bcceda0d2ed1246e780cd8d), ROM_BIOS(7))
+ ROMX_LOAD("b6m_614_u3.u3", 0x8000, 0x8000, CRC(eff75543) SHA1(d7c1b3824bc87d5ffada6f5c8c72a8b292ff3d46), ROM_BIOS(7))
+ROM_END
+
+const tiny_rom_entry *saitekosa_maestro_device::device_rom_region() const
+{
+ return ROM_NAME(maestro);
}
+
+const tiny_rom_entry *saitekosa_analyst_device::device_rom_region() const
+{
+ return ROM_NAME(analyst);
+}
+
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(OSA_MAESTRO, device_saitekosa_expansion_interface, saitekosa_maestro_device, "osa_maestro", "Saitek OSA Maestro B-D")
+DEFINE_DEVICE_TYPE_PRIVATE(OSA_ANALYST, device_saitekosa_expansion_interface, saitekosa_analyst_device, "osa_analyst", "Saitek OSA Analyst")
diff --git a/src/devices/bus/saitek_osa/maestro.h b/src/devices/bus/saitek_osa/maestro.h
index 1b79423e424..74b38c132a2 100644
--- a/src/devices/bus/saitek_osa/maestro.h
+++ b/src/devices/bus/saitek_osa/maestro.h
@@ -1,10 +1,10 @@
// license:BSD-3-Clause
// copyright-holders:hap
-/***************************************************************************
+/*******************************************************************************
Saitek OSA Module: Kasparov Maestro/Analyst
-***************************************************************************/
+*******************************************************************************/
#ifndef MAME_BUS_SAITEKOSA_MAESTRO_H
#define MAME_BUS_SAITEKOSA_MAESTRO_H
@@ -13,75 +13,7 @@
#include "expansion.h"
-#include "bus/generic/slot.h"
-#include "video/hd44780.h"
-
-DECLARE_DEVICE_TYPE(OSA_MAESTRO, saitekosa_maestro_device)
-DECLARE_DEVICE_TYPE(OSA_ANALYST, saitekosa_analyst_device)
-
-
-class saitekosa_maestro_device : public device_t, public device_saitekosa_expansion_interface
-{
-public:
- // construction/destruction
- saitekosa_maestro_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
-
- DECLARE_INPUT_CHANGED_MEMBER(switch_cpu_freq) { set_cpu_freq(); }
-
- // from host
- virtual u8 data_r() override;
- virtual void nmi_w(int state) override;
- virtual void ack_w(int state) override;
-
-protected:
- saitekosa_maestro_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
-
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual ioport_constructor device_input_ports() const override;
- virtual void device_add_mconfig(machine_config &config) override;
- virtual void device_start() override;
- virtual void device_reset() override;
-
- required_device<cpu_device> m_maincpu;
- memory_share_creator<u8> m_banked_ram;
- required_memory_bank m_rambank;
- required_memory_bank m_rombank;
- required_device<generic_slot_device> m_extrom;
-
- virtual void main_map(address_map &map);
-
- u8 extrom_r(offs_t offset);
- template <int N> void stall_w(u8 data = 0);
- u8 rts_r();
- u8 xdata_r();
- void xdata_w(u8 data);
- u8 ack_r();
- void control_w(u8 data);
-
- void set_cpu_freq();
-
- u8 m_latch = 0xff;
- bool m_latch_enable = false;
- u8 m_extrom_bank = 0;
-};
-
-class saitekosa_analyst_device : public saitekosa_maestro_device
-{
-public:
- saitekosa_analyst_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
-
- virtual u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) override;
-
- static auto parent_rom_device_type() { return &OSA_MAESTRO; }
-
-protected:
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual void device_add_mconfig(machine_config &config) override;
-
-private:
- required_device<hd44780_device> m_lcd;
-
- virtual void main_map(address_map &map) override;
-};
+DECLARE_DEVICE_TYPE(OSA_MAESTRO, device_saitekosa_expansion_interface)
+DECLARE_DEVICE_TYPE(OSA_ANALYST, device_saitekosa_expansion_interface)
#endif // MAME_BUS_SAITEKOSA_MAESTRO_H
diff --git a/src/devices/bus/saitek_osa/maestroa.cpp b/src/devices/bus/saitek_osa/maestroa.cpp
index 8a2dfa3ec47..0d3cdb07116 100644
--- a/src/devices/bus/saitek_osa/maestroa.cpp
+++ b/src/devices/bus/saitek_osa/maestroa.cpp
@@ -1,7 +1,7 @@
// license:BSD-3-Clause
// copyright-holders:hap
// thanks-to:Berger
-/***************************************************************************
+/*******************************************************************************
Saitek OSA Module: Kasparov Maestro A (SciSys, 1986)
@@ -17,7 +17,7 @@ Hardware notes:
The CPU is a 4MHz part, higher speed modules overclock it. The PCB is not
compatible for upgrading to newer Maestro versions.
-***************************************************************************/
+*******************************************************************************/
#include "emu.h"
#include "maestroa.h"
@@ -28,14 +28,47 @@ compatible for upgrading to newer Maestro versions.
#include "softlist_dev.h"
-
-DEFINE_DEVICE_TYPE(OSA_MAESTROA, saitekosa_maestroa_device, "osa_maestroa", "Maestro A")
-
+namespace {
//-------------------------------------------------
// initialization
//-------------------------------------------------
+class saitekosa_maestroa_device : public device_t, public device_saitekosa_expansion_interface
+{
+public:
+ // construction/destruction
+ saitekosa_maestroa_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ DECLARE_INPUT_CHANGED_MEMBER(change_cpu_freq);
+
+ // from host
+ virtual u8 data_r() override;
+ virtual void nmi_w(int state) override;
+ virtual void ack_w(int state) override;
+
+protected:
+ virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual ioport_constructor device_input_ports() const override;
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+private:
+ required_device<cpu_device> m_maincpu;
+
+ u8 m_latch = 0xff;
+ bool m_latch_enable = false;
+
+ void main_map(address_map &map);
+
+ u8 rts_r();
+ u8 xdata_r();
+ void xdata_w(u8 data);
+ u8 ack_r();
+ void control_w(u8 data);
+};
+
saitekosa_maestroa_device::saitekosa_maestroa_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
device_t(mconfig, OSA_MAESTROA, tag, owner, clock),
device_saitekosa_expansion_interface(mconfig, *this),
@@ -50,71 +83,34 @@ void saitekosa_maestroa_device::device_start()
void saitekosa_maestroa_device::device_reset()
{
- set_cpu_freq();
control_w(0);
}
-void saitekosa_maestroa_device::set_cpu_freq()
+INPUT_CHANGED_MEMBER(saitekosa_maestroa_device::change_cpu_freq)
{
static const XTAL xtal[3] = { 4_MHz_XTAL, 5.67_MHz_XTAL, 6_MHz_XTAL };
- m_maincpu->set_unscaled_clock(xtal[ioport("FAKE")->read() % 3]);
+ m_maincpu->set_unscaled_clock(xtal[newval % 3]);
}
//-------------------------------------------------
-// rom_region - device-specific ROM region
+// host i/o
//-------------------------------------------------
-ROM_START( maestroa )
- ROM_REGION(0x10000, "maincpu", 0)
-
- ROM_DEFAULT_BIOS("a1")
-
- // A
- ROM_SYSTEM_BIOS(0, "a1", "Maestro A (set 1)")
- ROMX_LOAD("m6a_a29b.u6", 0x8000, 0x8000, CRC(6ee0197a) SHA1(61f201ca64576aca582bc9f2a427638bd79e1fee), ROM_BIOS(0))
-
- ROM_SYSTEM_BIOS(1, "a2", "Maestro A (set 2)")
- ROMX_LOAD("m6a_v14b.u6", 0x8000, 0x8000, CRC(d566a476) SHA1(ef81b9a0dcfbd8427025cfe9bf738d42a7a1139a), ROM_BIOS(1))
-ROM_END
-
-const tiny_rom_entry *saitekosa_maestroa_device::device_rom_region() const
+u8 saitekosa_maestroa_device::data_r()
{
- return ROM_NAME(maestroa);
+ return m_latch_enable ? m_latch : 0xff;
}
-
-//-------------------------------------------------
-// input_ports - device-specific input ports
-//-------------------------------------------------
-
-static INPUT_PORTS_START( maestroa )
- PORT_START("FAKE")
- PORT_CONFNAME( 0x03, 0x02, "CPU Frequency" ) PORT_CHANGED_MEMBER(DEVICE_SELF, saitekosa_maestroa_device, switch_cpu_freq, 0) // factory set
- PORT_CONFSETTING( 0x00, "4MHz" )
- PORT_CONFSETTING( 0x01, "5.67MHz" )
- PORT_CONFSETTING( 0x02, "6MHz" )
-INPUT_PORTS_END
-
-ioport_constructor saitekosa_maestroa_device::device_input_ports() const
+void saitekosa_maestroa_device::nmi_w(int state)
{
- return INPUT_PORTS_NAME(maestroa);
+ m_maincpu->set_input_line(INPUT_LINE_NMI, !state ? ASSERT_LINE : CLEAR_LINE);
}
-
-//-------------------------------------------------
-// device_add_mconfig - add device configuration
-//-------------------------------------------------
-
-void saitekosa_maestroa_device::device_add_mconfig(machine_config &config)
+void saitekosa_maestroa_device::ack_w(int state)
{
- // basic machine hardware
- R65C02(config, m_maincpu, 6_MHz_XTAL);
- m_maincpu->set_addrmap(AS_PROGRAM, &saitekosa_maestroa_device::main_map);
-
- // extension rom
- GENERIC_SOCKET(config, "extrom", generic_plain_slot, "saitek_kso");
- SOFTWARE_LIST(config, "cart_list").set_original("saitek_kso");
+ if (state != m_expansion->ack_state())
+ machine().scheduler().perfect_quantum(attotime::from_usec(100));
}
@@ -173,21 +169,62 @@ void saitekosa_maestroa_device::main_map(address_map &map)
//-------------------------------------------------
-// host i/o
+// input_ports - device-specific input ports
//-------------------------------------------------
-u8 saitekosa_maestroa_device::data_r()
+static INPUT_PORTS_START( maestroa )
+ PORT_START("CPU")
+ PORT_CONFNAME( 0x03, 0x02, "CPU Frequency" ) PORT_CHANGED_MEMBER(DEVICE_SELF, saitekosa_maestroa_device, change_cpu_freq, 0) // factory set
+ PORT_CONFSETTING( 0x00, "4MHz" )
+ PORT_CONFSETTING( 0x01, "5.67MHz" )
+ PORT_CONFSETTING( 0x02, "6MHz" )
+INPUT_PORTS_END
+
+ioport_constructor saitekosa_maestroa_device::device_input_ports() const
{
- return m_latch_enable ? m_latch : 0xff;
+ return INPUT_PORTS_NAME(maestroa);
}
-void saitekosa_maestroa_device::nmi_w(int state)
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void saitekosa_maestroa_device::device_add_mconfig(machine_config &config)
{
- m_maincpu->set_input_line(INPUT_LINE_NMI, !state ? ASSERT_LINE : CLEAR_LINE);
+ // basic machine hardware
+ R65C02(config, m_maincpu, 6_MHz_XTAL);
+ m_maincpu->set_addrmap(AS_PROGRAM, &saitekosa_maestroa_device::main_map);
+
+ // extension rom
+ GENERIC_SOCKET(config, "extrom", generic_plain_slot, "saitek_kso");
+ SOFTWARE_LIST(config, "cart_list").set_original("saitek_kso");
}
-void saitekosa_maestroa_device::ack_w(int state)
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+ROM_START( maestroa )
+ ROM_REGION(0x10000, "maincpu", 0)
+
+ ROM_DEFAULT_BIOS("a1")
+
+ // A
+ ROM_SYSTEM_BIOS(0, "a1", "Maestro A (set 1)")
+ ROMX_LOAD("m6a_a29b.u6", 0x8000, 0x8000, CRC(6ee0197a) SHA1(61f201ca64576aca582bc9f2a427638bd79e1fee), ROM_BIOS(0))
+
+ ROM_SYSTEM_BIOS(1, "a2", "Maestro A (set 2)")
+ ROMX_LOAD("m6a_v14b.u6", 0x8000, 0x8000, CRC(d566a476) SHA1(ef81b9a0dcfbd8427025cfe9bf738d42a7a1139a), ROM_BIOS(1))
+ROM_END
+
+const tiny_rom_entry *saitekosa_maestroa_device::device_rom_region() const
{
- if (state != m_expansion->ack_state())
- machine().scheduler().boost_interleave(attotime::zero, attotime::from_usec(100));
+ return ROM_NAME(maestroa);
}
+
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(OSA_MAESTROA, device_saitekosa_expansion_interface, saitekosa_maestroa_device, "osa_maestroa", "Saitek OSA Maestro A")
diff --git a/src/devices/bus/saitek_osa/maestroa.h b/src/devices/bus/saitek_osa/maestroa.h
index 35b5744f07d..b2021501945 100644
--- a/src/devices/bus/saitek_osa/maestroa.h
+++ b/src/devices/bus/saitek_osa/maestroa.h
@@ -1,10 +1,10 @@
// license:BSD-3-Clause
// copyright-holders:hap
-/***************************************************************************
+/*******************************************************************************
Saitek OSA Module: Kasparov Maestro A
-***************************************************************************/
+*******************************************************************************/
#ifndef MAME_BUS_SAITEKOSA_MAESTROA_H
#define MAME_BUS_SAITEKOSA_MAESTROA_H
@@ -13,45 +13,6 @@
#include "expansion.h"
-DECLARE_DEVICE_TYPE(OSA_MAESTROA, saitekosa_maestroa_device)
-
-
-class saitekosa_maestroa_device : public device_t, public device_saitekosa_expansion_interface
-{
-public:
- // construction/destruction
- saitekosa_maestroa_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
-
- DECLARE_INPUT_CHANGED_MEMBER(switch_cpu_freq) { set_cpu_freq(); }
-
- // from host
- virtual u8 data_r() override;
- virtual void nmi_w(int state) override;
- virtual void ack_w(int state) override;
-
-protected:
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual ioport_constructor device_input_ports() const override;
- virtual void device_add_mconfig(machine_config &config) override;
- virtual void device_start() override;
- virtual void device_reset() override;
-
-private:
- required_device<cpu_device> m_maincpu;
-
- void main_map(address_map &map);
-
- u8 rts_r();
- u8 xdata_r();
- void xdata_w(u8 data);
- u8 ack_r();
- void control_w(u8 data);
-
- void set_cpu_freq();
-
- u8 m_latch = 0xff;
- bool m_latch_enable = false;
-};
-
+DECLARE_DEVICE_TYPE(OSA_MAESTROA, device_saitekosa_expansion_interface)
#endif // MAME_BUS_SAITEKOSA_MAESTROA_H
diff --git a/src/devices/bus/saitek_osa/sparc.cpp b/src/devices/bus/saitek_osa/sparc.cpp
index 8fb7ec0537a..3293782c512 100644
--- a/src/devices/bus/saitek_osa/sparc.cpp
+++ b/src/devices/bus/saitek_osa/sparc.cpp
@@ -1,7 +1,7 @@
// license:BSD-3-Clause
// copyright-holders:hap
// thanks-to:Berger
-/***************************************************************************
+/*******************************************************************************
Saitek OSA Module: Kasparov Sparc (1993)
@@ -30,19 +30,58 @@ TODO:
maybe cpu cache related?
- opening book moves take 3 around seconds per ply, should be almost immediate
-***************************************************************************/
+*******************************************************************************/
#include "emu.h"
#include "sparc.h"
+#include "cpu/sparc/sparc.h"
-DEFINE_DEVICE_TYPE(OSA_SPARC, saitekosa_sparc_device, "osa_sparc", "Sparc")
-
+namespace {
//-------------------------------------------------
// initialization
//-------------------------------------------------
+class saitekosa_sparc_device : public device_t, public device_saitekosa_expansion_interface
+{
+public:
+ // construction/destruction
+ saitekosa_sparc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ // from host
+ virtual u8 data_r() override;
+ virtual void nmi_w(int state) override;
+ virtual void ack_w(int state) override;
+
+protected:
+ virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual ioport_constructor device_input_ports() const override;
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+private:
+ required_device<mb86930_device> m_maincpu;
+ required_region_ptr<u32> m_rom;
+ required_shared_ptr<u32> m_ram;
+
+ u32 m_data_out = 0;
+ u32 m_rom_mask = 0;
+ u32 m_ram_mask = 0;
+ bool m_installed = false;
+
+ void debugger_map(address_map &map);
+
+ u32 rom_r(offs_t offset, u32 mem_mask) { return m_rom[offset & m_rom_mask]; }
+ u32 ram_r(offs_t offset, u32 mem_mask) { return m_ram[offset & m_ram_mask]; }
+ void ram_w(offs_t offset, u32 data, u32 mem_mask) { COMBINE_DATA(&m_ram[offset & m_ram_mask]); }
+ u32 host_io_r(offs_t offset, u32 mem_mask = ~0U);
+ void host_io_w(offs_t offset, u32 data, u32 mem_mask = ~0U);
+
+ void set_ram_mask(u8 n) { m_ram_mask = ((1 << n) / 4) - 1; }
+};
+
saitekosa_sparc_device::saitekosa_sparc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
device_t(mconfig, OSA_SPARC, tag, owner, clock),
device_saitekosa_expansion_interface(mconfig, *this),
@@ -77,37 +116,50 @@ void saitekosa_sparc_device::device_reset()
//-------------------------------------------------
-// rom_region - device-specific ROM region
+// host i/o
//-------------------------------------------------
-#define ROM_LOAD32_BYTE_BIOS(bios, name, offset, length, hash) \
- ROMX_LOAD(name, offset, length, hash, ROM_SKIP(3) | ROM_BIOS(bios))
+u8 saitekosa_sparc_device::data_r()
+{
+ return (m_data_out & 0x400) ? 0xff : (u8)m_data_out;
+}
-ROM_START( sparc )
- ROM_REGION32_BE(0x40000, "maincpu", 0)
+void saitekosa_sparc_device::nmi_w(int state)
+{
+ m_maincpu->set_input_line(SPARC_IRQ1, !state ? ASSERT_LINE : CLEAR_LINE);
+}
- ROM_DEFAULT_BIOS("v518")
+void saitekosa_sparc_device::ack_w(int state)
+{
+ if (state != m_expansion->ack_state())
+ machine().scheduler().perfect_quantum(attotime::from_usec(100));
+}
- ROM_SYSTEM_BIOS(0, "v512a", "Sparc (rev. 512A)")
- ROM_LOAD32_BYTE_BIOS(0, "sm16b_512.u5", 0x000000, 0x10000, CRC(96bca59d) SHA1(2c7e693d0cdf69b6e566c6dd03bd24d39e32aa82) )
- ROM_LOAD32_BYTE_BIOS(0, "sm16b_512.u4", 0x000001, 0x10000, CRC(15dd621d) SHA1(e8f7404e84fe027b086fcb918fbcaf2ce4203567) )
- ROM_LOAD32_BYTE_BIOS(0, "sm16b_512.u3", 0x000002, 0x10000, CRC(3201c6e4) SHA1(9a209219a0ab4b4f874381a16773bf33f8f7ba25) )
- ROM_LOAD32_BYTE_BIOS(0, "sm16b_512a.u2", 0x000003, 0x10000, CRC(56dedec7) SHA1(4f9d37e0ca639f892a574aa10a3fb42bba9b82c6) )
- ROM_SYSTEM_BIOS(1, "v518", "Sparc (rev. 518)")
- ROM_LOAD32_BYTE_BIOS(1, "sm16b_518.u5", 0x000000, 0x10000, CRC(cee97a8f) SHA1(541d9d3ee469bacb5a4c537f443836a684e5d168) )
- ROM_LOAD32_BYTE_BIOS(1, "sm16b_518.u4", 0x000001, 0x10000, CRC(7ac37299) SHA1(36f95520fbc9dfed2078d848bf6c3cc7c5823895) )
- ROM_LOAD32_BYTE_BIOS(1, "sm16b_518.u3", 0x000002, 0x10000, CRC(29426d9e) SHA1(ad14f6f2f3e6460d834382faeab78dca9ceb2a63) )
- ROM_LOAD32_BYTE_BIOS(1, "sm16b_518.u2", 0x000003, 0x10000, CRC(b2274cf5) SHA1(d04f41fa1f61439a4655003398f3ae27c2d06f82) )
+//-------------------------------------------------
+// internal i/o
+//-------------------------------------------------
- ROM_REGION(0x1000, "pals", 0)
- ROM_LOAD("palce16v8h.u23.jed", 0x0000, 0x0c25, CRC(de79fabc) SHA1(27e01ec405e261109dbe10c254b7127eda0f1886) )
- ROM_LOAD("palce16v8h.u32.jed", 0x0000, 0x0c25, CRC(422b66c8) SHA1(44b3394e0586c126ee95129c65e6692ffc01fa8e) )
-ROM_END
+u32 saitekosa_sparc_device::host_io_r(offs_t offset, u32 mem_mask)
+{
+ // d0-d7: data input latch, d8: ACK-P
+ return m_expansion->data_state() | (m_expansion->ack_state() ? 0 : 0x100);
+}
-const tiny_rom_entry *saitekosa_sparc_device::device_rom_region() const
+void saitekosa_sparc_device::host_io_w(offs_t offset, u32 data, u32 mem_mask)
{
- return ROM_NAME(sparc);
+ // d0-d7: data output latch, d10: output latch enable
+ COMBINE_DATA(&m_data_out);
+
+ // d8: STB-P, d9: RTS-P
+ m_expansion->stb_w(BIT(m_data_out, 8));
+ m_expansion->rts_w(BIT(~m_data_out, 9));
+}
+
+void saitekosa_sparc_device::debugger_map(address_map &map)
+{
+ map(0x00000000, 0x0003ffff).rom().region("maincpu", 0);
+ map(0x01000000, 0x013fffff).ram().share("ram"); // 4MB
}
@@ -146,48 +198,40 @@ void saitekosa_sparc_device::device_add_mconfig(machine_config &config)
//-------------------------------------------------
-// internal i/o
+// rom_region - device-specific ROM region
//-------------------------------------------------
-u32 saitekosa_sparc_device::host_io_r(offs_t offset, u32 mem_mask)
-{
- // d0-d7: data input latch, d8: ACK-P
- return m_expansion->data_state() | (m_expansion->ack_state() ? 0 : 0x100);
-}
+#define ROM_LOAD32_BYTE_BIOS(bios, name, offset, length, hash) \
+ ROMX_LOAD(name, offset, length, hash, ROM_SKIP(3) | ROM_BIOS(bios))
-void saitekosa_sparc_device::host_io_w(offs_t offset, u32 data, u32 mem_mask)
-{
- // d0-d7: data output latch, d10: output latch enable
- COMBINE_DATA(&m_data_out);
+ROM_START( sparc )
+ ROM_REGION32_BE(0x40000, "maincpu", 0)
- // d8: STB-P, d9: RTS-P
- m_expansion->stb_w(BIT(m_data_out, 8));
- m_expansion->rts_w(BIT(~m_data_out, 9));
-}
+ ROM_DEFAULT_BIOS("v518")
-void saitekosa_sparc_device::debugger_map(address_map &map)
-{
- map(0x00000000, 0x0003ffff).rom().region("maincpu", 0);
- map(0x01000000, 0x013fffff).ram().share("ram"); // 4MB
-}
+ ROM_SYSTEM_BIOS(0, "v512a", "Sparc (rev. 512A)")
+ ROM_LOAD32_BYTE_BIOS(0, "sm16b_512.u5", 0x000000, 0x10000, CRC(96bca59d) SHA1(2c7e693d0cdf69b6e566c6dd03bd24d39e32aa82) )
+ ROM_LOAD32_BYTE_BIOS(0, "sm16b_512.u4", 0x000001, 0x10000, CRC(15dd621d) SHA1(e8f7404e84fe027b086fcb918fbcaf2ce4203567) )
+ ROM_LOAD32_BYTE_BIOS(0, "sm16b_512.u3", 0x000002, 0x10000, CRC(3201c6e4) SHA1(9a209219a0ab4b4f874381a16773bf33f8f7ba25) )
+ ROM_LOAD32_BYTE_BIOS(0, "sm16b_512a.u2", 0x000003, 0x10000, CRC(56dedec7) SHA1(4f9d37e0ca639f892a574aa10a3fb42bba9b82c6) )
+ ROM_SYSTEM_BIOS(1, "v518", "Sparc (rev. 518)")
+ ROM_LOAD32_BYTE_BIOS(1, "sm16b_518.u5", 0x000000, 0x10000, CRC(cee97a8f) SHA1(541d9d3ee469bacb5a4c537f443836a684e5d168) )
+ ROM_LOAD32_BYTE_BIOS(1, "sm16b_518.u4", 0x000001, 0x10000, CRC(7ac37299) SHA1(36f95520fbc9dfed2078d848bf6c3cc7c5823895) )
+ ROM_LOAD32_BYTE_BIOS(1, "sm16b_518.u3", 0x000002, 0x10000, CRC(29426d9e) SHA1(ad14f6f2f3e6460d834382faeab78dca9ceb2a63) )
+ ROM_LOAD32_BYTE_BIOS(1, "sm16b_518.u2", 0x000003, 0x10000, CRC(b2274cf5) SHA1(d04f41fa1f61439a4655003398f3ae27c2d06f82) )
-//-------------------------------------------------
-// host i/o
-//-------------------------------------------------
+ ROM_REGION(0x1000, "pals", 0)
+ ROM_LOAD("palce16v8h.u23.jed", 0x0000, 0x0c25, CRC(de79fabc) SHA1(27e01ec405e261109dbe10c254b7127eda0f1886) )
+ ROM_LOAD("palce16v8h.u32.jed", 0x0000, 0x0c25, CRC(422b66c8) SHA1(44b3394e0586c126ee95129c65e6692ffc01fa8e) )
+ROM_END
-u8 saitekosa_sparc_device::data_r()
+const tiny_rom_entry *saitekosa_sparc_device::device_rom_region() const
{
- return (m_data_out & 0x400) ? 0xff : (u8)m_data_out;
+ return ROM_NAME(sparc);
}
-void saitekosa_sparc_device::nmi_w(int state)
-{
- m_maincpu->set_input_line(SPARC_IRQ1, !state ? ASSERT_LINE : CLEAR_LINE);
-}
+} // anonymous namespace
-void saitekosa_sparc_device::ack_w(int state)
-{
- if (state != m_expansion->ack_state())
- machine().scheduler().boost_interleave(attotime::zero, attotime::from_usec(100));
-}
+
+DEFINE_DEVICE_TYPE_PRIVATE(OSA_SPARC, device_saitekosa_expansion_interface, saitekosa_sparc_device, "osa_sparc", "Saitek OSA Sparc")
diff --git a/src/devices/bus/saitek_osa/sparc.h b/src/devices/bus/saitek_osa/sparc.h
index ffdda735502..94a870740b8 100644
--- a/src/devices/bus/saitek_osa/sparc.h
+++ b/src/devices/bus/saitek_osa/sparc.h
@@ -1,10 +1,10 @@
// license:BSD-3-Clause
// copyright-holders:hap
-/***************************************************************************
+/*******************************************************************************
Saitek OSA Module: Kasparov Sparc
-***************************************************************************/
+*******************************************************************************/
#ifndef MAME_BUS_SAITEKOSA_SPARC_H
#define MAME_BUS_SAITEKOSA_SPARC_H
@@ -13,48 +13,6 @@
#include "expansion.h"
-#include "cpu/sparc/sparc.h"
-
-DECLARE_DEVICE_TYPE(OSA_SPARC, saitekosa_sparc_device)
-
-
-class saitekosa_sparc_device : public device_t, public device_saitekosa_expansion_interface
-{
-public:
- // construction/destruction
- saitekosa_sparc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
-
- // from host
- virtual u8 data_r() override;
- virtual void nmi_w(int state) override;
- virtual void ack_w(int state) override;
-
-protected:
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual ioport_constructor device_input_ports() const override;
- virtual void device_add_mconfig(machine_config &config) override;
- virtual void device_start() override;
- virtual void device_reset() override;
-
-private:
- required_device<mb86930_device> m_maincpu;
- required_region_ptr<u32> m_rom;
- required_shared_ptr<u32> m_ram;
-
- void debugger_map(address_map &map);
-
- u32 rom_r(offs_t offset, u32 mem_mask) { return m_rom[offset & m_rom_mask]; }
- u32 ram_r(offs_t offset, u32 mem_mask) { return m_ram[offset & m_ram_mask]; }
- void ram_w(offs_t offset, u32 data, u32 mem_mask) { COMBINE_DATA(&m_ram[offset & m_ram_mask]); }
- u32 host_io_r(offs_t offset, u32 mem_mask = ~0U);
- void host_io_w(offs_t offset, u32 data, u32 mem_mask = ~0U);
-
- void set_ram_mask(u8 n) { m_ram_mask = ((1 << n) / 4) - 1; }
-
- u32 m_data_out = 0;
- u32 m_rom_mask = 0;
- u32 m_ram_mask = 0;
- bool m_installed = false;
-};
+DECLARE_DEVICE_TYPE(OSA_SPARC, device_saitekosa_expansion_interface)
#endif // MAME_BUS_SAITEKOSA_SPARC_H
diff --git a/src/devices/bus/samcoupe/drive/atom.cpp b/src/devices/bus/samcoupe/drive/atom.cpp
index 5ca86f5d327..d810b27b74d 100644
--- a/src/devices/bus/samcoupe/drive/atom.cpp
+++ b/src/devices/bus/samcoupe/drive/atom.cpp
@@ -14,7 +14,7 @@
// DEVICE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(SAM_ATOM_HDD, sam_atom_hdd_device, "sam_atom_hdd", "SAM Coupe ATOM HDD interface")
+DEFINE_DEVICE_TYPE(SAM_ATOM_HDD, sam_atom_hdd_device, "sam_atom_hdd", u8"SAM Coupé ATOM HDD interface")
//-------------------------------------------------
// device_add_mconfig - add device configuration
diff --git a/src/devices/bus/samcoupe/drive/drive.cpp b/src/devices/bus/samcoupe/drive/drive.cpp
index 564b2299fc2..b5764aa01b7 100644
--- a/src/devices/bus/samcoupe/drive/drive.cpp
+++ b/src/devices/bus/samcoupe/drive/drive.cpp
@@ -16,7 +16,7 @@
// DEVICE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(SAMCOUPE_DRIVE_PORT, samcoupe_drive_port_device, "samcoupe_drive_port", "SAM Coupe Drive Port")
+DEFINE_DEVICE_TYPE(SAMCOUPE_DRIVE_PORT, samcoupe_drive_port_device, "samcoupe_drive_port", u8"SAM Coupé Drive Port")
//**************************************************************************
diff --git a/src/devices/bus/samcoupe/drive/drive.h b/src/devices/bus/samcoupe/drive/drive.h
index 83f7ce0f069..f02b8a8d743 100644
--- a/src/devices/bus/samcoupe/drive/drive.h
+++ b/src/devices/bus/samcoupe/drive/drive.h
@@ -60,7 +60,7 @@ public:
uint8_t read(offs_t offset);
void write(offs_t offset, uint8_t data);
- DECLARE_WRITE_LINE_MEMBER( disk1_w );
+ void disk1_w(int state);
protected:
// device-level overrides
diff --git a/src/devices/bus/samcoupe/drive/floppy.cpp b/src/devices/bus/samcoupe/drive/floppy.cpp
index 3940e9f5ddb..3c2888ab5b0 100644
--- a/src/devices/bus/samcoupe/drive/floppy.cpp
+++ b/src/devices/bus/samcoupe/drive/floppy.cpp
@@ -15,7 +15,7 @@
// DEVICE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(SAM_FLOPPY, sam_floppy_device, "sam_floppy", "SAM Coupe Internal Floppy")
+DEFINE_DEVICE_TYPE(SAM_FLOPPY, sam_floppy_device, "sam_floppy", u8"SAM Coupé Internal Floppy")
void sam_floppy_device::floppy_formats(format_registration &fr)
{
diff --git a/src/devices/bus/samcoupe/expansion/dallas.cpp b/src/devices/bus/samcoupe/expansion/dallas.cpp
index 30e7a1d0005..d877b94e6e1 100644
--- a/src/devices/bus/samcoupe/expansion/dallas.cpp
+++ b/src/devices/bus/samcoupe/expansion/dallas.cpp
@@ -67,8 +67,8 @@ uint8_t sam_dallas_clock_device::iorq_r(offs_t offset)
{
uint8_t data = 0xff;
- if (m_print && (offset & 0xfe07) == 0xfe07)
- data &= m_rtc->read((offset >> 8) & 0x01);
+ if (m_print && (offset & 0xff07) == 0xff07)
+ data &= m_rtc->data_r();
return data;
}
@@ -76,5 +76,10 @@ uint8_t sam_dallas_clock_device::iorq_r(offs_t offset)
void sam_dallas_clock_device::iorq_w(offs_t offset, uint8_t data)
{
if (m_print && (offset & 0xfe07) == 0xfe07)
- m_rtc->write((offset >> 8) & 0x01, data);
+ {
+ if (BIT(offset, 8))
+ m_rtc->data_w(data);
+ else
+ m_rtc->address_w(data);
+ }
}
diff --git a/src/devices/bus/samcoupe/expansion/expansion.cpp b/src/devices/bus/samcoupe/expansion/expansion.cpp
index b52792eb43d..d67d9df1f82 100644
--- a/src/devices/bus/samcoupe/expansion/expansion.cpp
+++ b/src/devices/bus/samcoupe/expansion/expansion.cpp
@@ -16,7 +16,7 @@
// DEVICE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(SAMCOUPE_EXPANSION, samcoupe_expansion_device, "samcoupe_expansion", "SAM Coupe Expansion Bus")
+DEFINE_DEVICE_TYPE(SAMCOUPE_EXPANSION, samcoupe_expansion_device, "samcoupe_expansion", u8"SAM Coupé Expansion Bus")
//**************************************************************************
@@ -51,9 +51,6 @@ void samcoupe_expansion_device::device_start()
{
// get inserted module
m_module = get_card_device();
-
- // resolve callbacks
- m_int_handler.resolve_safe();
}
//-------------------------------------------------
@@ -88,13 +85,13 @@ void samcoupe_expansion_device::iorq_w(offs_t offset, uint8_t data)
m_module->iorq_w(offset, data);
}
-WRITE_LINE_MEMBER( samcoupe_expansion_device::xmem_w )
+void samcoupe_expansion_device::xmem_w(int state)
{
if (m_module)
m_module->xmem_w(state);
}
-WRITE_LINE_MEMBER( samcoupe_expansion_device::print_w )
+void samcoupe_expansion_device::print_w(int state)
{
if (m_module)
m_module->print_w(state);
diff --git a/src/devices/bus/samcoupe/expansion/expansion.h b/src/devices/bus/samcoupe/expansion/expansion.h
index 90390286ac2..2bd8d199866 100644
--- a/src/devices/bus/samcoupe/expansion/expansion.h
+++ b/src/devices/bus/samcoupe/expansion/expansion.h
@@ -76,7 +76,7 @@ public:
auto int_handler() { return m_int_handler.bind(); }
// called from cart device
- DECLARE_WRITE_LINE_MEMBER( int_w ) { m_int_handler(state); }
+ void int_w(int state) { m_int_handler(state); }
// called from host
uint8_t mreq_r(offs_t offset);
@@ -84,8 +84,8 @@ public:
uint8_t iorq_r(offs_t offset);
void iorq_w(offs_t offset, uint8_t data);
- DECLARE_WRITE_LINE_MEMBER( xmem_w );
- DECLARE_WRITE_LINE_MEMBER( print_w );
+ void xmem_w(int state);
+ void print_w(int state);
protected:
// device-level overrides
diff --git a/src/devices/bus/samcoupe/expansion/spi.cpp b/src/devices/bus/samcoupe/expansion/spi.cpp
index 47343f32dc1..e005a39ba70 100644
--- a/src/devices/bus/samcoupe/expansion/spi.cpp
+++ b/src/devices/bus/samcoupe/expansion/spi.cpp
@@ -66,7 +66,7 @@ void sam_spi_device::device_start()
// IMPLEMENTATION
//**************************************************************************
-WRITE_LINE_MEMBER( sam_spi_device::centronics_busy_w )
+void sam_spi_device::centronics_busy_w(int state)
{
m_busy = state;
}
diff --git a/src/devices/bus/samcoupe/expansion/spi.h b/src/devices/bus/samcoupe/expansion/spi.h
index 38e813bd6ee..674ecf3880e 100644
--- a/src/devices/bus/samcoupe/expansion/spi.h
+++ b/src/devices/bus/samcoupe/expansion/spi.h
@@ -41,7 +41,7 @@ private:
required_device<output_latch_device> m_data_out;
required_device<centronics_device> m_centronics;
- DECLARE_WRITE_LINE_MEMBER(centronics_busy_w);
+ void centronics_busy_w(int state);
int m_print;
int m_busy;
diff --git a/src/devices/bus/samcoupe/mouse/mouse.cpp b/src/devices/bus/samcoupe/mouse/mouse.cpp
index fbacfa67c7a..324a9998a17 100644
--- a/src/devices/bus/samcoupe/mouse/mouse.cpp
+++ b/src/devices/bus/samcoupe/mouse/mouse.cpp
@@ -14,7 +14,7 @@
// DEVICE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(SAM_MOUSE, sam_mouse_device, "sam_mouse", "SAM Coupe Mouse Interface")
+DEFINE_DEVICE_TYPE(SAM_MOUSE, sam_mouse_device, "sam_mouse", u8"SAM Coupé Mouse Interface")
//-------------------------------------------------
// input_ports - device-specific input ports
diff --git a/src/devices/bus/samcoupe/mouse/mouseport.cpp b/src/devices/bus/samcoupe/mouse/mouseport.cpp
index 3bfc609c093..e5c3edc09ae 100644
--- a/src/devices/bus/samcoupe/mouse/mouseport.cpp
+++ b/src/devices/bus/samcoupe/mouse/mouseport.cpp
@@ -16,7 +16,7 @@
// DEVICE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(SAMCOUPE_MOUSE_PORT, samcoupe_mouse_port_device, "samcoupe_mouse_port", "SAM Coupe Mouse Port")
+DEFINE_DEVICE_TYPE(SAMCOUPE_MOUSE_PORT, samcoupe_mouse_port_device, "samcoupe_mouse_port", u8"SAM Coupé Mouse Port")
//**************************************************************************
@@ -51,9 +51,6 @@ void samcoupe_mouse_port_device::device_start()
{
// get inserted module
m_module = get_card_device();
-
- // resolve callbacks
- m_mseint_handler.resolve_safe();
}
//-------------------------------------------------
diff --git a/src/devices/bus/samcoupe/mouse/mouseport.h b/src/devices/bus/samcoupe/mouse/mouseport.h
index 92943f39a7c..89233101758 100644
--- a/src/devices/bus/samcoupe/mouse/mouseport.h
+++ b/src/devices/bus/samcoupe/mouse/mouseport.h
@@ -52,7 +52,7 @@ public:
auto mseint_handler() { return m_mseint_handler.bind(); }
// called from cart device
- DECLARE_WRITE_LINE_MEMBER( mseint_w ) { m_mseint_handler(state); }
+ void mseint_w(int state) { m_mseint_handler(state); }
// called from host
uint8_t read();
diff --git a/src/devices/bus/sat_ctrl/keybd.cpp b/src/devices/bus/sat_ctrl/keybd.cpp
index 3ab0d8dc4ab..f37bdcc9bab 100644
--- a/src/devices/bus/sat_ctrl/keybd.cpp
+++ b/src/devices/bus/sat_ctrl/keybd.cpp
@@ -122,7 +122,7 @@ static INPUT_PORTS_START( saturn_keybd )
PORT_START("KEY.10") // 0x50 - 0x57
PORT_BIT(0x01,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("A-1") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x50)
- PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("\xC2\xA5") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x51)
+ PORT_BIT(0x02,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME(u8"¥") /*PORT_CODE(KEYCODE_1) PORT_CHAR('1')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x51)
PORT_BIT(0x04,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME(":") /*PORT_CODE(KEYCODE_2) PORT_CHAR('2')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x52)
PORT_BIT(0x08,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("A-4") /*PORT_CODE(KEYCODE_3) PORT_CHAR('3')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x53)
PORT_BIT(0x10,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("@") /*PORT_CODE(KEYCODE_4) PORT_CHAR('4')*/ PORT_CHANGED_MEMBER(DEVICE_SELF, saturn_keybd_device, key_stroke, 0x54)
diff --git a/src/devices/bus/saturn/bram.cpp b/src/devices/bus/saturn/bram.cpp
index 604948343ed..d8ee2764da0 100644
--- a/src/devices/bus/saturn/bram.cpp
+++ b/src/devices/bus/saturn/bram.cpp
@@ -65,14 +65,14 @@ void saturn_bram_device::device_reset()
bool saturn_bram_device::nvram_read(util::read_stream &file)
{
- size_t actual;
- return !file.read(&m_ext_bram[0], m_ext_bram.size(), actual) && actual == m_ext_bram.size();
+ auto const [err, actual] = read(file, &m_ext_bram[0], m_ext_bram.size());
+ return !err && (actual == m_ext_bram.size());
}
bool saturn_bram_device::nvram_write(util::write_stream &file)
{
- size_t actual;
- return !file.write(&m_ext_bram[0], m_ext_bram.size(), actual) && actual == m_ext_bram.size();
+ auto const [err, actual] = write(file, &m_ext_bram[0], m_ext_bram.size());
+ return !err;
}
void saturn_bram_device::nvram_default()
diff --git a/src/devices/bus/saturn/sat_slot.cpp b/src/devices/bus/saturn/sat_slot.cpp
index 068e34a3f93..34a329b47ef 100644
--- a/src/devices/bus/saturn/sat_slot.cpp
+++ b/src/devices/bus/saturn/sat_slot.cpp
@@ -57,11 +57,11 @@ device_sat_cart_interface::~device_sat_cart_interface()
// rom_alloc - alloc the space for the cart
//-------------------------------------------------
-void device_sat_cart_interface::rom_alloc(uint32_t size, const char *tag)
+void device_sat_cart_interface::rom_alloc(uint32_t size)
{
if (m_rom == nullptr)
{
- m_rom = (uint32_t *)device().machine().memory().region_alloc(std::string(tag).append(SATSLOT_ROM_REGION_TAG).c_str(), size, 4, ENDIANNESS_LITTLE)->base();
+ m_rom = (uint32_t *)device().machine().memory().region_alloc(device().subtag("^cart:rom"), size, 4, ENDIANNESS_LITTLE)->base();
m_rom_size = size;
}
}
@@ -135,7 +135,7 @@ void sat_cart_slot_device::device_start()
-------------------------------------------------*/
-image_init_result sat_cart_slot_device::call_load()
+std::pair<std::error_condition, std::string> sat_cart_slot_device::call_load()
{
if (m_cart)
{
@@ -145,10 +145,9 @@ image_init_result sat_cart_slot_device::call_load()
{
// from fullpath, only ROM carts
uint32_t len = loaded_through_softlist() ? get_software_region_length("rom") : length();
- uint32_t *ROM;
- m_cart->rom_alloc(len, tag());
- ROM = m_cart->get_rom_base();
+ m_cart->rom_alloc(len);
+ uint32_t *const ROM = m_cart->get_rom_base();
if (loaded_through_softlist())
memcpy(ROM, get_software_region("rom"), len);
@@ -157,15 +156,7 @@ image_init_result sat_cart_slot_device::call_load()
// fix endianness....
for (int i = 0; i < len/4; i ++)
- ROM[i] = bitswap<32>(ROM[i],7,6,5,4,3,2,1,0,15,14,13,12,11,10,9,8,23,22,21,20,19,18,17,16,31,30,29,28,27,26,25,24);
-// {
-// uint8_t tempa = ROM[i+0];
-// uint8_t tempb = ROM[i+1];
-// ROM[i+1] = ROM[i+2];
-// ROM[i+0] = ROM[i+3];
-// ROM[i+3] = tempa;
-// ROM[i+2] = tempb;
-// }
+ ROM[i] = big_endianize_int32(ROM[i]);
}
else
{
@@ -177,10 +168,9 @@ image_init_result sat_cart_slot_device::call_load()
if (get_software_region("dram1"))
m_cart->dram1_alloc(get_software_region_length("dram1"));
}
- return image_init_result::PASS;
}
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
diff --git a/src/devices/bus/saturn/sat_slot.h b/src/devices/bus/saturn/sat_slot.h
index e4370e4c592..eff07096f79 100644
--- a/src/devices/bus/saturn/sat_slot.h
+++ b/src/devices/bus/saturn/sat_slot.h
@@ -31,7 +31,7 @@ public:
int get_cart_type() const { return m_cart_type; }
- void rom_alloc(uint32_t size, const char *tag);
+ void rom_alloc(uint32_t size);
void bram_alloc(uint32_t size);
void dram0_alloc(uint32_t size);
void dram1_alloc(uint32_t size);
@@ -79,15 +79,15 @@ public:
sat_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
virtual ~sat_cart_slot_device();
- // image-level overrides
- virtual image_init_result call_load() override;
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
virtual void call_unload() override;
virtual bool is_reset_on_load() const noexcept override { return true; }
virtual const char *image_interface() const noexcept override { return "sat_cart"; }
virtual const char *file_extensions() const noexcept override { return "bin"; }
- // slot interface overrides
+ // device_slot_interface implementation
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
int get_cart_type();
@@ -102,7 +102,7 @@ public:
virtual void write_ext_bram(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
private:
@@ -113,11 +113,4 @@ private:
// device type definition
DECLARE_DEVICE_TYPE(SATURN_CART_SLOT, sat_cart_slot_device)
-
-/***************************************************************************
- DEVICE CONFIGURATION MACROS
- ***************************************************************************/
-
-#define SATSLOT_ROM_REGION_TAG ":cart:rom"
-
#endif // MAME_BUS_SATURN_SAT_SLOT_H
diff --git a/src/devices/bus/sbus/cgsix.cpp b/src/devices/bus/sbus/cgsix.cpp
index 4ae3301c285..46685deb58a 100644
--- a/src/devices/bus/sbus/cgsix.cpp
+++ b/src/devices/bus/sbus/cgsix.cpp
@@ -1274,7 +1274,7 @@ void sbus_cgsix_device::thc_misc_w(offs_t offset, uint32_t data, uint32_t mem_ma
m_thc_misc &= THC_MISC_WRITE_MASK;
}
-WRITE_LINE_MEMBER(sbus_cgsix_device::vblank_w)
+void sbus_cgsix_device::vblank_w(int state)
{
int old_state = BIT(m_thc_misc, THC_MISC_VSYNC_BIT);
if (old_state != state)
diff --git a/src/devices/bus/sbus/cgsix.h b/src/devices/bus/sbus/cgsix.h
index b6f3fe7520d..40392f250df 100644
--- a/src/devices/bus/sbus/cgsix.h
+++ b/src/devices/bus/sbus/cgsix.h
@@ -50,7 +50,7 @@ protected:
void cursor_address_w(uint32_t data);
uint32_t cursor_ram_r(offs_t offset);
void cursor_ram_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
- DECLARE_WRITE_LINE_MEMBER(vblank_w);
+ void vblank_w(int state);
uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
uint8_t perform_rasterop(uint8_t src, uint8_t dst, uint8_t mask = 0xff);
diff --git a/src/devices/bus/sbus/sbus.cpp b/src/devices/bus/sbus/sbus.cpp
index 6640509d3ec..efd0a6991b5 100644
--- a/src/devices/bus/sbus/sbus.cpp
+++ b/src/devices/bus/sbus/sbus.cpp
@@ -91,13 +91,6 @@ sbus_device::sbus_device(const machine_config &mconfig, device_type type, const
{
}
-void sbus_device::device_resolve_objects()
-{
- // resolve callbacks
- m_irq_cb.resolve_all_safe();
- m_buserr.resolve_safe();
-}
-
void sbus_device::device_start()
{
std::fill(std::begin(m_device_list), std::end(m_device_list), nullptr);
diff --git a/src/devices/bus/sbus/sbus.h b/src/devices/bus/sbus/sbus.h
index 2c66318c8aa..8f395afa253 100644
--- a/src/devices/bus/sbus/sbus.h
+++ b/src/devices/bus/sbus/sbus.h
@@ -38,7 +38,7 @@ public:
protected:
sbus_slot_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
- // device-level overrides
+ // device_t implementation
virtual void device_validity_check(validity_checker &valid) const override;
virtual void device_resolve_objects() override;
virtual void device_start() override;
@@ -93,8 +93,7 @@ public:
protected:
sbus_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
- // device-level overrides
- virtual void device_resolve_objects() override;
+ // device_t implementation
virtual void device_start() override;
// internal state
diff --git a/src/devices/bus/scsi/omti5100.cpp b/src/devices/bus/scsi/omti5100.cpp
index a76893fd12c..b4c46de8553 100644
--- a/src/devices/bus/scsi/omti5100.cpp
+++ b/src/devices/bus/scsi/omti5100.cpp
@@ -33,7 +33,7 @@ omti5100_device::omti5100_device(const machine_config &mconfig, const char *tag,
void omti5100_device::device_start()
{
- if(!m_image0->get_hard_disk_file())
+ if(!m_image0->exists())
m_image = m_image1;
m_image = m_image0;
scsihle_device::device_start();
@@ -42,8 +42,8 @@ void omti5100_device::device_start()
void omti5100_device::ExecCommand()
{
int drive = (command[1] >> 5) & 1;
- hard_disk_file *image = (drive ? m_image1 : m_image0)->get_hard_disk_file();
- if(!image)
+ harddisk_image_device *image = drive ? m_image1 : m_image0;
+ if(!image->exists())
{
if(command[0] == T10SPC_CMD_REQUEST_SENSE)
return scsihd_device::ExecCommand();
@@ -86,7 +86,6 @@ void omti5100_device::ExecCommand()
}
else
{
- SetDevice(image);
scsihd_device::ExecCommand();
}
break;
@@ -114,7 +113,6 @@ void omti5100_device::ExecCommand()
break;
}
default:
- SetDevice(image);
scsihd_device::ExecCommand();
break;
}
@@ -144,10 +142,10 @@ void omti5100_device::WriteData( uint8_t *data, int dataLength )
case OMTI_ASSIGN_DISK_PARAM:
{
int drive = ((command[1] >> 5) & 1);
- hard_disk_file *image = (drive ? m_image1 : m_image0)->get_hard_disk_file();
+ harddisk_image_device *image = drive ? m_image1 : m_image0;
m_param[drive].heads = data[3] + 1;
m_param[drive].cylinders = ((data[4] << 8) | data[5]) + 1;
- if(!data[8] && image)
+ if(!data[8] && image->exists())
{
switch(image->get_info().sectorbytes)
{
diff --git a/src/devices/bus/scsi/s1410.cpp b/src/devices/bus/scsi/s1410.cpp
index 0aec38db1b2..2873a281783 100644
--- a/src/devices/bus/scsi/s1410.cpp
+++ b/src/devices/bus/scsi/s1410.cpp
@@ -173,7 +173,7 @@ void s1410_device::device_add_mconfig(machine_config &config)
z8400a.set_addrmap(AS_IO, &s1410_device::s1410_io);
z8400a.set_disable();
- HARDDISK(config, "image");
+ HARDDISK(config, m_image).set_interface("scsi_hdd");
}
@@ -187,7 +187,8 @@ void s1410_device::device_add_mconfig(machine_config &config)
//-------------------------------------------------
s1410_device::s1410_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : scsihd_device(mconfig, S1410, tag, owner, clock)
+ : scsihd_device(mconfig, S1410, tag, owner, clock),
+ m_image(*this, "image")
{
}
@@ -248,14 +249,14 @@ void s1410_device::ExecCommand()
logerror("S1410: FORMAT TRACK at LBA %x for %x blocks\n", m_lba, m_blocks);
- if ((m_disk) && (m_blocks))
+ if (m_image->exists() && m_blocks)
{
std::vector<uint8_t> data(m_sector_bytes);
memset(&data[0], 0xc6, m_sector_bytes);
while (m_blocks > 0)
{
- if (!m_disk->write(m_lba, &data[0]))
+ if (!m_image->write(m_lba, &data[0]))
{
logerror("S1410: HD write error!\n");
}
diff --git a/src/devices/bus/scsi/s1410.h b/src/devices/bus/scsi/s1410.h
index 03ec288b76a..305b63a1141 100644
--- a/src/devices/bus/scsi/s1410.h
+++ b/src/devices/bus/scsi/s1410.h
@@ -29,6 +29,8 @@ protected:
virtual void ReadData( uint8_t *data, int dataLength ) override;
private:
+ required_device<harddisk_image_device> m_image;
+
void s1410_io(address_map &map);
void s1410_mem(address_map &map);
};
diff --git a/src/devices/bus/scsi/scsi.cpp b/src/devices/bus/scsi/scsi.cpp
index a4477483766..d42e0a527da 100644
--- a/src/devices/bus/scsi/scsi.cpp
+++ b/src/devices/bus/scsi/scsi.cpp
@@ -79,24 +79,6 @@ void scsi_port_device::device_start()
m_device_count = i + 1;
}
- m_bsy_handler.resolve_safe();
- m_sel_handler.resolve_safe();
- m_cd_handler.resolve_safe();
- m_io_handler.resolve_safe();
- m_msg_handler.resolve_safe();
- m_req_handler.resolve_safe();
- m_ack_handler.resolve_safe();
- m_atn_handler.resolve_safe();
- m_rst_handler.resolve_safe();
- m_data0_handler.resolve_safe();
- m_data1_handler.resolve_safe();
- m_data2_handler.resolve_safe();
- m_data3_handler.resolve_safe();
- m_data4_handler.resolve_safe();
- m_data5_handler.resolve_safe();
- m_data6_handler.resolve_safe();
- m_data7_handler.resolve_safe();
-
m_data0_handler(0);
m_data1_handler(0);
m_data2_handler(0);
@@ -491,7 +473,7 @@ void scsi_port_device::update_data7()
}
}
-WRITE_LINE_MEMBER( scsi_port_device::write_bsy )
+void scsi_port_device::write_bsy(int state)
{
if (m_bsy_in != state)
{
@@ -500,7 +482,7 @@ WRITE_LINE_MEMBER( scsi_port_device::write_bsy )
}
}
-WRITE_LINE_MEMBER( scsi_port_device::write_sel )
+void scsi_port_device::write_sel(int state)
{
if (m_sel_in != state)
{
@@ -509,7 +491,7 @@ WRITE_LINE_MEMBER( scsi_port_device::write_sel )
}
}
-WRITE_LINE_MEMBER( scsi_port_device::write_cd )
+void scsi_port_device::write_cd(int state)
{
if (m_cd_in != state)
{
@@ -518,7 +500,7 @@ WRITE_LINE_MEMBER( scsi_port_device::write_cd )
}
}
-WRITE_LINE_MEMBER( scsi_port_device::write_io )
+void scsi_port_device::write_io(int state)
{
if (m_io_in != state)
{
@@ -527,7 +509,7 @@ WRITE_LINE_MEMBER( scsi_port_device::write_io )
}
}
-WRITE_LINE_MEMBER( scsi_port_device::write_msg )
+void scsi_port_device::write_msg(int state)
{
if (m_msg_in != state)
{
@@ -536,7 +518,7 @@ WRITE_LINE_MEMBER( scsi_port_device::write_msg )
}
}
-WRITE_LINE_MEMBER( scsi_port_device::write_req )
+void scsi_port_device::write_req(int state)
{
if (m_req_in != state)
{
@@ -545,7 +527,7 @@ WRITE_LINE_MEMBER( scsi_port_device::write_req )
}
}
-WRITE_LINE_MEMBER( scsi_port_device::write_ack )
+void scsi_port_device::write_ack(int state)
{
if (m_ack_in != state)
{
@@ -554,7 +536,7 @@ WRITE_LINE_MEMBER( scsi_port_device::write_ack )
}
}
-WRITE_LINE_MEMBER( scsi_port_device::write_atn )
+void scsi_port_device::write_atn(int state)
{
if (m_atn_in != state)
{
@@ -563,7 +545,7 @@ WRITE_LINE_MEMBER( scsi_port_device::write_atn )
}
}
-WRITE_LINE_MEMBER( scsi_port_device::write_rst )
+void scsi_port_device::write_rst(int state)
{
if (m_rst_in != state)
{
@@ -572,7 +554,7 @@ WRITE_LINE_MEMBER( scsi_port_device::write_rst )
}
}
-WRITE_LINE_MEMBER( scsi_port_device::write_data0 )
+void scsi_port_device::write_data0(int state)
{
if (m_data0_in != state)
{
@@ -581,7 +563,7 @@ WRITE_LINE_MEMBER( scsi_port_device::write_data0 )
}
}
-WRITE_LINE_MEMBER( scsi_port_device::write_data1 )
+void scsi_port_device::write_data1(int state)
{
if (m_data1_in != state)
{
@@ -590,7 +572,7 @@ WRITE_LINE_MEMBER( scsi_port_device::write_data1 )
}
}
-WRITE_LINE_MEMBER( scsi_port_device::write_data2 )
+void scsi_port_device::write_data2(int state)
{
if (m_data2_in != state)
{
@@ -599,7 +581,7 @@ WRITE_LINE_MEMBER( scsi_port_device::write_data2 )
}
}
-WRITE_LINE_MEMBER( scsi_port_device::write_data3 )
+void scsi_port_device::write_data3(int state)
{
if (m_data3_in != state)
{
@@ -608,7 +590,7 @@ WRITE_LINE_MEMBER( scsi_port_device::write_data3 )
}
}
-WRITE_LINE_MEMBER( scsi_port_device::write_data4 )
+void scsi_port_device::write_data4(int state)
{
if (m_data4_in != state)
{
@@ -617,7 +599,7 @@ WRITE_LINE_MEMBER( scsi_port_device::write_data4 )
}
}
-WRITE_LINE_MEMBER( scsi_port_device::write_data5 )
+void scsi_port_device::write_data5(int state)
{
if (m_data5_in != state)
{
@@ -626,7 +608,7 @@ WRITE_LINE_MEMBER( scsi_port_device::write_data5 )
}
}
-WRITE_LINE_MEMBER( scsi_port_device::write_data6 )
+void scsi_port_device::write_data6(int state)
{
if (m_data6_in != state)
{
@@ -635,7 +617,7 @@ WRITE_LINE_MEMBER( scsi_port_device::write_data6 )
}
}
-WRITE_LINE_MEMBER( scsi_port_device::write_data7 )
+void scsi_port_device::write_data7(int state)
{
if (m_data7_in != state)
{
diff --git a/src/devices/bus/scsi/scsi.h b/src/devices/bus/scsi/scsi.h
index 07e64d5f102..4906125cf56 100644
--- a/src/devices/bus/scsi/scsi.h
+++ b/src/devices/bus/scsi/scsi.h
@@ -62,23 +62,23 @@ public:
void set_output_latch(output_latch_device &latch);
- DECLARE_WRITE_LINE_MEMBER( write_bsy );
- DECLARE_WRITE_LINE_MEMBER( write_sel );
- DECLARE_WRITE_LINE_MEMBER( write_cd );
- DECLARE_WRITE_LINE_MEMBER( write_io );
- DECLARE_WRITE_LINE_MEMBER( write_msg );
- DECLARE_WRITE_LINE_MEMBER( write_req );
- DECLARE_WRITE_LINE_MEMBER( write_ack );
- DECLARE_WRITE_LINE_MEMBER( write_atn );
- DECLARE_WRITE_LINE_MEMBER( write_rst );
- DECLARE_WRITE_LINE_MEMBER( write_data0 );
- DECLARE_WRITE_LINE_MEMBER( write_data1 );
- DECLARE_WRITE_LINE_MEMBER( write_data2 );
- DECLARE_WRITE_LINE_MEMBER( write_data3 );
- DECLARE_WRITE_LINE_MEMBER( write_data4 );
- DECLARE_WRITE_LINE_MEMBER( write_data5 );
- DECLARE_WRITE_LINE_MEMBER( write_data6 );
- DECLARE_WRITE_LINE_MEMBER( write_data7 );
+ void write_bsy(int state);
+ void write_sel(int state);
+ void write_cd(int state);
+ void write_io(int state);
+ void write_msg(int state);
+ void write_req(int state);
+ void write_ack(int state);
+ void write_atn(int state);
+ void write_rst(int state);
+ void write_data0(int state);
+ void write_data1(int state);
+ void write_data2(int state);
+ void write_data3(int state);
+ void write_data4(int state);
+ void write_data5(int state);
+ void write_data6(int state);
+ void write_data7(int state);
scsi_port_slot_device &slot(int index);
void set_slot_device(int index, const char *option, const device_type &type, const input_device_default *id);
@@ -214,41 +214,41 @@ class scsi_port_interface : public device_interface
public:
virtual ~scsi_port_interface();
- virtual DECLARE_WRITE_LINE_MEMBER( input_bsy ) { }
- virtual DECLARE_WRITE_LINE_MEMBER( input_sel ) { }
- virtual DECLARE_WRITE_LINE_MEMBER( input_cd ) { }
- virtual DECLARE_WRITE_LINE_MEMBER( input_io ) { }
- virtual DECLARE_WRITE_LINE_MEMBER( input_msg ) { }
- virtual DECLARE_WRITE_LINE_MEMBER( input_req ) { }
- virtual DECLARE_WRITE_LINE_MEMBER( input_ack ) { }
- virtual DECLARE_WRITE_LINE_MEMBER( input_atn ) { }
- virtual DECLARE_WRITE_LINE_MEMBER( input_rst ) { }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data0 ) { }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data1 ) { }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data2 ) { }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data3 ) { }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data4 ) { }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data5 ) { }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data6 ) { }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data7 ) { }
-
- DECLARE_WRITE_LINE_MEMBER( output_bsy ) { if (m_slot->m_bsy != state) { m_slot->m_bsy = state; m_slot->port()->update_bsy(); } }
- DECLARE_WRITE_LINE_MEMBER( output_sel ) { if (m_slot->m_sel != state) { m_slot->m_sel = state; m_slot->port()->update_sel(); } }
- DECLARE_WRITE_LINE_MEMBER( output_cd ) { if (m_slot->m_cd != state) { m_slot->m_cd = state; m_slot->port()->update_cd(); } }
- DECLARE_WRITE_LINE_MEMBER( output_io ) { if (m_slot->m_io != state) { m_slot->m_io = state; m_slot->port()->update_io(); } }
- DECLARE_WRITE_LINE_MEMBER( output_msg ) { if (m_slot->m_msg != state) { m_slot->m_msg = state; m_slot->port()->update_msg(); } }
- DECLARE_WRITE_LINE_MEMBER( output_req ) { if (m_slot->m_req != state) { m_slot->m_req = state; m_slot->port()->update_req(); } }
- DECLARE_WRITE_LINE_MEMBER( output_ack ) { if (m_slot->m_ack != state) { m_slot->m_ack = state; m_slot->port()->update_ack(); } }
- DECLARE_WRITE_LINE_MEMBER( output_atn ) { if (m_slot->m_atn != state) { m_slot->m_atn = state; m_slot->port()->update_atn(); } }
- DECLARE_WRITE_LINE_MEMBER( output_rst ) { if (m_slot->m_rst != state) { m_slot->m_rst = state; m_slot->port()->update_rst(); } }
- DECLARE_WRITE_LINE_MEMBER( output_data0 ) { if (m_slot->m_data0 != state) { m_slot->m_data0 = state; m_slot->port()->update_data0(); } }
- DECLARE_WRITE_LINE_MEMBER( output_data1 ) { if (m_slot->m_data1 != state) { m_slot->m_data1 = state; m_slot->port()->update_data1(); } }
- DECLARE_WRITE_LINE_MEMBER( output_data2 ) { if (m_slot->m_data2 != state) { m_slot->m_data2 = state; m_slot->port()->update_data2(); } }
- DECLARE_WRITE_LINE_MEMBER( output_data3 ) { if (m_slot->m_data3 != state) { m_slot->m_data3 = state; m_slot->port()->update_data3(); } }
- DECLARE_WRITE_LINE_MEMBER( output_data4 ) { if (m_slot->m_data4 != state) { m_slot->m_data4 = state; m_slot->port()->update_data4(); } }
- DECLARE_WRITE_LINE_MEMBER( output_data5 ) { if (m_slot->m_data5 != state) { m_slot->m_data5 = state; m_slot->port()->update_data5(); } }
- DECLARE_WRITE_LINE_MEMBER( output_data6 ) { if (m_slot->m_data6 != state) { m_slot->m_data6 = state; m_slot->port()->update_data6(); } }
- DECLARE_WRITE_LINE_MEMBER( output_data7 ) { if (m_slot->m_data7 != state) { m_slot->m_data7 = state; m_slot->port()->update_data7(); } }
+ virtual void input_bsy(int state) { }
+ virtual void input_sel(int state) { }
+ virtual void input_cd(int state) { }
+ virtual void input_io(int state) { }
+ virtual void input_msg(int state) { }
+ virtual void input_req(int state) { }
+ virtual void input_ack(int state) { }
+ virtual void input_atn(int state) { }
+ virtual void input_rst(int state) { }
+ virtual void input_data0(int state) { }
+ virtual void input_data1(int state) { }
+ virtual void input_data2(int state) { }
+ virtual void input_data3(int state) { }
+ virtual void input_data4(int state) { }
+ virtual void input_data5(int state) { }
+ virtual void input_data6(int state) { }
+ virtual void input_data7(int state) { }
+
+ void output_bsy(int state) { if (m_slot->m_bsy != state) { m_slot->m_bsy = state; m_slot->port()->update_bsy(); } }
+ void output_sel(int state) { if (m_slot->m_sel != state) { m_slot->m_sel = state; m_slot->port()->update_sel(); } }
+ void output_cd(int state) { if (m_slot->m_cd != state) { m_slot->m_cd = state; m_slot->port()->update_cd(); } }
+ void output_io(int state) { if (m_slot->m_io != state) { m_slot->m_io = state; m_slot->port()->update_io(); } }
+ void output_msg(int state) { if (m_slot->m_msg != state) { m_slot->m_msg = state; m_slot->port()->update_msg(); } }
+ void output_req(int state) { if (m_slot->m_req != state) { m_slot->m_req = state; m_slot->port()->update_req(); } }
+ void output_ack(int state) { if (m_slot->m_ack != state) { m_slot->m_ack = state; m_slot->port()->update_ack(); } }
+ void output_atn(int state) { if (m_slot->m_atn != state) { m_slot->m_atn = state; m_slot->port()->update_atn(); } }
+ void output_rst(int state) { if (m_slot->m_rst != state) { m_slot->m_rst = state; m_slot->port()->update_rst(); } }
+ void output_data0(int state) { if (m_slot->m_data0 != state) { m_slot->m_data0 = state; m_slot->port()->update_data0(); } }
+ void output_data1(int state) { if (m_slot->m_data1 != state) { m_slot->m_data1 = state; m_slot->port()->update_data1(); } }
+ void output_data2(int state) { if (m_slot->m_data2 != state) { m_slot->m_data2 = state; m_slot->port()->update_data2(); } }
+ void output_data3(int state) { if (m_slot->m_data3 != state) { m_slot->m_data3 = state; m_slot->port()->update_data3(); } }
+ void output_data4(int state) { if (m_slot->m_data4 != state) { m_slot->m_data4 = state; m_slot->port()->update_data4(); } }
+ void output_data5(int state) { if (m_slot->m_data5 != state) { m_slot->m_data5 = state; m_slot->port()->update_data5(); } }
+ void output_data6(int state) { if (m_slot->m_data6 != state) { m_slot->m_data6 = state; m_slot->port()->update_data6(); } }
+ void output_data7(int state) { if (m_slot->m_data7 != state) { m_slot->m_data7 = state; m_slot->port()->update_data7(); } }
protected:
scsi_port_interface(const machine_config &mconfig, device_t &device);
diff --git a/src/devices/bus/scsi/scsicd.cpp b/src/devices/bus/scsi/scsicd.cpp
index 0f577ea44d3..2833917984f 100644
--- a/src/devices/bus/scsi/scsicd.cpp
+++ b/src/devices/bus/scsi/scsicd.cpp
@@ -30,8 +30,20 @@ void scsicd_device::device_start()
scsihle_device::device_start();
}
+void scsicd_device::device_reset()
+{
+ scsihle_device::device_reset();
+}
+
void scsicd_device::device_add_mconfig(machine_config &config)
{
CDROM(config, "image").set_interface("cdrom");
- CDDA(config, "cdda");
+ CDDA(config, "cdda").set_cdrom_tag("image");
}
+
+bool scsicd_device::exists() const
+{
+ // cd drive is visible even if there's no cd in it
+ return true;
+}
+
diff --git a/src/devices/bus/scsi/scsicd.h b/src/devices/bus/scsi/scsicd.h
index 9d88f6bd1a8..6416352880d 100644
--- a/src/devices/bus/scsi/scsicd.h
+++ b/src/devices/bus/scsi/scsicd.h
@@ -21,8 +21,9 @@ public:
protected:
scsicd_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
virtual void device_start() override;
-
+ virtual void device_reset() override;
virtual void device_add_mconfig(machine_config &config) override;
+ virtual bool exists() const override;
};
// device type definition
diff --git a/src/devices/bus/scsi/scsihd.cpp b/src/devices/bus/scsi/scsihd.cpp
index 4fb01e02130..433ec26313a 100644
--- a/src/devices/bus/scsi/scsihd.cpp
+++ b/src/devices/bus/scsi/scsihd.cpp
@@ -33,3 +33,8 @@ void scsihd_device::device_add_mconfig(machine_config &config)
{
HARDDISK(config, "image", "scsi_hdd");
}
+
+bool scsihd_device::exists() const
+{
+ return m_image->exists();
+}
diff --git a/src/devices/bus/scsi/scsihd.h b/src/devices/bus/scsi/scsihd.h
index 3cc50af8ec2..734e1ef4547 100644
--- a/src/devices/bus/scsi/scsihd.h
+++ b/src/devices/bus/scsi/scsihd.h
@@ -23,8 +23,8 @@ public:
protected:
scsihd_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
virtual void device_start() override;
-
virtual void device_add_mconfig(machine_config &config) override;
+ virtual bool exists() const override;
};
// device type definition
diff --git a/src/devices/bus/scsi/scsihle.cpp b/src/devices/bus/scsi/scsihle.cpp
index 09a0fa84eca..da0d6c45817 100644
--- a/src/devices/bus/scsi/scsihle.cpp
+++ b/src/devices/bus/scsi/scsihle.cpp
@@ -405,7 +405,7 @@ void scsihle_device::scsi_change_phase(uint8_t newphase)
}
}
-WRITE_LINE_MEMBER( scsihle_device::input_sel )
+void scsihle_device::input_sel(int state)
{
// printf( "sel %d %d %02x\n", state, m_phase, m_input_data );
switch (m_phase)
@@ -415,11 +415,9 @@ WRITE_LINE_MEMBER( scsihle_device::input_sel )
// only one line active.
if (scsibus_driveno(m_input_data) == scsiID)
{
- void *hdfile = nullptr;
// Check to see if device had image file mounted, if not, do not set busy,
// and stay busfree.
- GetDevice(&hdfile);
- if (hdfile != nullptr)
+ if (exists())
{
if (!state)
{
@@ -435,7 +433,7 @@ WRITE_LINE_MEMBER( scsihle_device::input_sel )
}
}
-WRITE_LINE_MEMBER( scsihle_device::input_ack )
+void scsihle_device::input_ack(int state)
{
switch (m_phase)
{
@@ -494,7 +492,7 @@ WRITE_LINE_MEMBER( scsihle_device::input_ack )
if (IS_COMMAND(SCSI_CMD_FORMAT_UNIT))
{
- // If we have the first byte, then cancel the dataout timout
+ // If we have the first byte, then cancel the dataout timeout
if (data_idx == 1)
dataout_timer->adjust(attotime::never);
@@ -573,7 +571,7 @@ WRITE_LINE_MEMBER( scsihle_device::input_ack )
}
}
-WRITE_LINE_MEMBER( scsihle_device::input_rst )
+void scsihle_device::input_rst(int state)
{
if (state)
{
diff --git a/src/devices/bus/scsi/scsihle.h b/src/devices/bus/scsi/scsihle.h
index ea6f577a592..95849f34332 100644
--- a/src/devices/bus/scsi/scsihle.h
+++ b/src/devices/bus/scsi/scsihle.h
@@ -23,17 +23,19 @@ class scsihle_device : public device_t,
public:
virtual int GetDeviceID(); // hack for legacy_scsi_host_adapter::get_device
- virtual DECLARE_WRITE_LINE_MEMBER( input_sel ) override;
- virtual DECLARE_WRITE_LINE_MEMBER( input_ack ) override;
- virtual DECLARE_WRITE_LINE_MEMBER( input_rst ) override;
- virtual DECLARE_WRITE_LINE_MEMBER( input_data0 ) override { if (state) m_input_data |= 0x01; else m_input_data &= ~0x01; }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data1 ) override { if (state) m_input_data |= 0x02; else m_input_data &= ~0x02; }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data2 ) override { if (state) m_input_data |= 0x04; else m_input_data &= ~0x04; }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data3 ) override { if (state) m_input_data |= 0x08; else m_input_data &= ~0x08; }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data4 ) override { if (state) m_input_data |= 0x10; else m_input_data &= ~0x10; }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data5 ) override { if (state) m_input_data |= 0x20; else m_input_data &= ~0x20; }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data6 ) override { if (state) m_input_data |= 0x40; else m_input_data &= ~0x40; }
- virtual DECLARE_WRITE_LINE_MEMBER( input_data7 ) override { if (state) m_input_data |= 0x80; else m_input_data &= ~0x80; }
+ virtual void input_sel(int state) override;
+ virtual void input_ack(int state) override;
+ virtual void input_rst(int state) override;
+ virtual void input_data0(int state) override { if (state) m_input_data |= 0x01; else m_input_data &= ~0x01; }
+ virtual void input_data1(int state) override { if (state) m_input_data |= 0x02; else m_input_data &= ~0x02; }
+ virtual void input_data2(int state) override { if (state) m_input_data |= 0x04; else m_input_data &= ~0x04; }
+ virtual void input_data3(int state) override { if (state) m_input_data |= 0x08; else m_input_data &= ~0x08; }
+ virtual void input_data4(int state) override { if (state) m_input_data |= 0x10; else m_input_data &= ~0x10; }
+ virtual void input_data5(int state) override { if (state) m_input_data |= 0x20; else m_input_data &= ~0x20; }
+ virtual void input_data6(int state) override { if (state) m_input_data |= 0x40; else m_input_data &= ~0x40; }
+ virtual void input_data7(int state) override { if (state) m_input_data |= 0x80; else m_input_data &= ~0x80; }
+
+ virtual bool exists() const = 0;
protected:
// construction/destruction
diff --git a/src/devices/bus/scv/slot.cpp b/src/devices/bus/scv/slot.cpp
index 448131cbd17..b6ef651cdf5 100644
--- a/src/devices/bus/scv/slot.cpp
+++ b/src/devices/bus/scv/slot.cpp
@@ -44,11 +44,11 @@ device_scv_cart_interface::~device_scv_cart_interface()
// rom_alloc - alloc the space for the cart
//-------------------------------------------------
-void device_scv_cart_interface::rom_alloc(uint32_t size, const char *tag)
+void device_scv_cart_interface::rom_alloc(uint32_t size)
{
if (m_rom == nullptr)
{
- m_rom = device().machine().memory().region_alloc(std::string(tag).append(SCVSLOT_ROM_REGION_TAG).c_str(), size, 1, ENDIANNESS_LITTLE)->base();
+ m_rom = device().machine().memory().region_alloc(device().subtag("^cart:rom"), size, 1, ENDIANNESS_LITTLE)->base();
m_rom_size = size;
}
}
@@ -147,25 +147,21 @@ static const char *scv_get_slot(int type)
call load
-------------------------------------------------*/
-image_init_result scv_cart_slot_device::call_load()
+std::pair<std::error_condition, std::string> scv_cart_slot_device::call_load()
{
if (m_cart)
{
- uint8_t *ROM;
- uint32_t len = !loaded_through_softlist() ? length() : get_software_region_length("rom");
- bool has_ram = loaded_through_softlist() && get_software_region("ram");
+ uint32_t const len = !loaded_through_softlist() ? length() : get_software_region_length("rom");
+ bool const has_ram = loaded_through_softlist() && get_software_region("ram");
if (len > 0x20000)
- {
- seterror(image_error::INVALIDIMAGE, "Unsupported cartridge size");
- return image_init_result::FAIL;
- }
+ return std::make_pair(image_error::INVALIDLENGTH, "Unsupported cartridge size (must be no more than 128K)");
- m_cart->rom_alloc(len, tag());
+ m_cart->rom_alloc(len);
if (has_ram)
m_cart->ram_alloc(get_software_region_length("ram"));
- ROM = m_cart->get_rom_base();
+ uint8_t *const ROM = m_cart->get_rom_base();
if (!loaded_through_softlist())
fread(ROM, len);
@@ -189,11 +185,9 @@ image_init_result scv_cart_slot_device::call_load()
m_type = SCV_128K_RAM;
//printf("Type: %s\n", scv_get_slot(m_type));
-
- return image_init_result::PASS;
}
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
@@ -242,8 +236,7 @@ std::string scv_cart_slot_device::get_default_card_software(get_default_card_sof
hook.image_file()->length(len); // FIXME: check error return, guard against excessively large files
std::vector<uint8_t> rom(len);
- size_t actual;
- hook.image_file()->read(&rom[0], len, actual); // FIXME: check error return or read returning short
+ read(*hook.image_file(), &rom[0], len); // FIXME: check error return or read returning short
int const type = get_cart_type(&rom[0], len);
char const *const slot_string = scv_get_slot(type);
diff --git a/src/devices/bus/scv/slot.h b/src/devices/bus/scv/slot.h
index 8d818221be2..1836a517cdb 100644
--- a/src/devices/bus/scv/slot.h
+++ b/src/devices/bus/scv/slot.h
@@ -39,7 +39,7 @@ public:
virtual void write_cart(offs_t offset, uint8_t data) { }
virtual void write_bank(uint8_t data) { }
- void rom_alloc(uint32_t size, const char *tag);
+ void rom_alloc(uint32_t size);
void ram_alloc(uint32_t size);
uint8_t* get_rom_base() { return m_rom; }
uint8_t* get_ram_base() { return &m_ram[0]; }
@@ -79,15 +79,15 @@ public:
scv_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
virtual ~scv_cart_slot_device();
- // image-level overrides
- virtual image_init_result call_load() override;
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
virtual void call_unload() override { }
virtual bool is_reset_on_load() const noexcept override { return true; }
virtual const char *image_interface() const noexcept override { return "scv_cart"; }
virtual const char *file_extensions() const noexcept override { return "bin"; }
- // slot interface overrides
+ // device_slot_interface implementation
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
int get_type() { return m_type; }
@@ -101,11 +101,11 @@ public:
void write_bank(uint8_t data);
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
int m_type;
- device_scv_cart_interface* m_cart;
+ device_scv_cart_interface *m_cart;
};
@@ -113,11 +113,4 @@ protected:
// device type definition
DECLARE_DEVICE_TYPE(SCV_CART_SLOT, scv_cart_slot_device)
-
-/***************************************************************************
- DEVICE CONFIGURATION MACROS
- ***************************************************************************/
-
-#define SCVSLOT_ROM_REGION_TAG ":cart:rom"
-
#endif // MAME_BUS_SCV_SLOT_H
diff --git a/src/devices/bus/sdk85/memexp.cpp b/src/devices/bus/sdk85/memexp.cpp
index a5a752c4339..58a05e2fc88 100644
--- a/src/devices/bus/sdk85/memexp.cpp
+++ b/src/devices/bus/sdk85/memexp.cpp
@@ -22,14 +22,14 @@ sdk85_romexp_device::sdk85_romexp_device(const machine_config &mconfig, const ch
{
}
-image_init_result sdk85_romexp_device::call_load()
+std::pair<std::error_condition, std::string> sdk85_romexp_device::call_load()
{
- if (get_card_device() != nullptr)
+ if (get_card_device())
{
- u32 size = loaded_through_softlist() ? get_software_region_length("rom") : length();
- u8 *base = get_card_device()->get_rom_base(size);
- if (base == nullptr)
- return image_init_result::FAIL;
+ u32 const size = loaded_through_softlist() ? get_software_region_length("rom") : length();
+ u8 *const base = get_card_device()->get_rom_base(size);
+ if (!base)
+ return std::make_pair(image_error::INTERNAL, std::string());
if (loaded_through_softlist())
memcpy(base, get_software_region("rom"), size);
@@ -37,7 +37,7 @@ image_init_result sdk85_romexp_device::call_load()
fread(base, size);
}
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
std::string sdk85_romexp_device::get_default_card_software(get_default_card_software_hook &hook) const
diff --git a/src/devices/bus/sdk85/memexp.h b/src/devices/bus/sdk85/memexp.h
index fbd005c48c2..1c82d1dc807 100644
--- a/src/devices/bus/sdk85/memexp.h
+++ b/src/devices/bus/sdk85/memexp.h
@@ -52,18 +52,18 @@ public:
void io_w(offs_t offset, u8 data);
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
- // image-level overrides
- virtual image_init_result call_load() override;
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
virtual void call_unload() override { }
virtual bool is_reset_on_load() const noexcept override { return true; }
virtual const char *image_interface() const noexcept override { return "sdk85_rom"; }
virtual const char *file_extensions() const noexcept override { return "bin"; }
- // slot interface overrides
+ // device_slot_interface implementation
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
private:
diff --git a/src/devices/bus/sega8/sega8_slot.cpp b/src/devices/bus/sega8/sega8_slot.cpp
index fdde1bb9401..d30b5c4e869 100644
--- a/src/devices/bus/sega8/sega8_slot.cpp
+++ b/src/devices/bus/sega8/sega8_slot.cpp
@@ -28,6 +28,8 @@
#include "emu.h"
#include "sega8_slot.h"
+#include "multibyte.h"
+
#define VERBOSE 0
#include "logmacro.h"
@@ -83,11 +85,11 @@ device_sega8_cart_interface::~device_sega8_cart_interface()
// rom_alloc - alloc the space for the cart
//-------------------------------------------------
-void device_sega8_cart_interface::rom_alloc(uint32_t size, const char *tag)
+void device_sega8_cart_interface::rom_alloc(uint32_t size)
{
if (m_rom == nullptr)
{
- m_rom = device().machine().memory().region_alloc(std::string(tag).append(S8SLOT_ROM_REGION_TAG).c_str(), size, 1, ENDIANNESS_LITTLE)->base();
+ m_rom = device().machine().memory().region_alloc(device().subtag("^cart:rom"), size, 1, ENDIANNESS_LITTLE)->base();
m_rom_size = size;
m_rom_page_count = size / 0x4000;
if (!m_rom_page_count)
@@ -264,21 +266,23 @@ static const char *sega8_get_slot(int type)
call load
-------------------------------------------------*/
-image_verify_result sega8_cart_slot_device::verify_cart( uint8_t *magic, int size )
+std::error_condition sega8_cart_slot_device::verify_cart( const uint8_t *magic, int size )
{
- image_verify_result retval(image_verify_result::FAIL);
+ std::error_condition retval;
// Verify the file is a valid image - check $7ff0 for "TMR SEGA"
if (size >= 0x8000)
{
- if (!strncmp((char*)&magic[0x7ff0], "TMR SEGA", 8))
- retval = image_verify_result::PASS;
+ if (strncmp((const char*)&magic[0x7ff0], "TMR SEGA", 8))
+ retval = image_error::INVALIDIMAGE;
}
+ else
+ retval = image_error::INVALIDLENGTH;
return retval;
}
-void sega8_cart_slot_device::set_lphaser_xoffset( uint8_t *rom, int size )
+void sega8_cart_slot_device::set_lphaser_xoffset( const uint8_t *rom, int size )
{
static const uint8_t signatures[7][16] =
{
@@ -388,33 +392,29 @@ void sega8_cart_slot_device::setup_ram()
}
}
-image_init_result sega8_cart_slot_device::call_load()
+std::pair<std::error_condition, std::string> sega8_cart_slot_device::call_load()
{
if (m_cart)
{
uint32_t len = !loaded_through_softlist() ? length() : get_software_region_length("rom");
- uint32_t offset = 0;
- uint8_t *ROM;
if (m_is_card && len > 0x8000)
- {
- seterror(image_error::INVALIDIMAGE, "Attempted loading a card larger than 32KB");
- return image_init_result::FAIL;
- }
+ return std::make_pair(image_error::INVALIDLENGTH, "Sega Card images must be no larger than 32K");
// check for header
+ uint32_t offset = 0;
if ((len % 0x4000) == 512)
{
offset = 512;
len -= 512;
}
- // make sure that we only get complete (0x4000) rom banks
+ // make sure that we only get complete (0x4000) ROM banks
if (len & 0x3fff)
len = ((len >> 14) + 1) << 14;
- m_cart->rom_alloc(len, tag());
- ROM = m_cart->get_rom_base();
+ m_cart->rom_alloc(len);
+ uint8_t *const ROM = m_cart->get_rom_base();
if (!loaded_through_softlist())
{
@@ -424,8 +424,8 @@ image_init_result sega8_cart_slot_device::call_load()
else
memcpy(ROM, get_software_region("rom"), get_software_region_length("rom"));
- /* check the image */
- if (verify_cart(ROM, len) != image_verify_result::PASS)
+ // check the image
+ if (verify_cart(ROM, len))
logerror("Warning loading image: verify_cart failed\n");
if (loaded_through_softlist())
@@ -453,11 +453,9 @@ image_init_result sega8_cart_slot_device::call_load()
//printf("Type: %s\n", sega8_get_slot(type));
internal_header_logging(ROM + offset, len, m_cart->get_ram_size());
-
- return image_init_result::PASS;
}
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
@@ -541,7 +539,7 @@ int sega8_cart_slot_device::get_cart_type(const uint8_t *ROM, uint32_t len) cons
{
if (ROM[i] == 0x32) // Z80 opcode for: LD (xxxx), A
{
- uint16_t addr = (ROM[i + 2] << 8) | ROM[i + 1];
+ uint16_t addr = get_u16le(&ROM[i + 1]);
if (addr == 0xffff)
{ i += 2; _ffff++; continue; }
if (addr == 0x0002 || addr == 0x0003 || addr == 0x0004)
@@ -590,7 +588,7 @@ int sega8_cart_slot_device::get_cart_type(const uint8_t *ROM, uint32_t len) cons
{
if (ROM[i] == 0x32)
{
- uint16_t addr = ROM[i + 1] | (ROM[i + 2] << 8);
+ uint16_t addr = get_u16le(&ROM[i + 1]);
switch (addr & 0xf000)
{
@@ -671,8 +669,7 @@ std::string sega8_cart_slot_device::get_default_card_software(get_default_card_s
hook.image_file()->length(len); // FIXME: check error return, guard against excessively large files
std::vector<uint8_t> rom(len);
- size_t actual;
- hook.image_file()->read(&rom[0], len, actual); // FIXME: check error return or read returning short
+ /*auto const [err, actual] =*/ read(*hook.image_file(), &rom[0], len); // FIXME: check error return or read returning short
uint32_t const offset = ((len % 0x4000) == 512) ? 512 : 0;
@@ -751,7 +748,7 @@ void sega8_cart_slot_device::write_io(offs_t offset, uint8_t data)
Internal header logging
-------------------------------------------------*/
-void sega8_cart_slot_device::internal_header_logging(uint8_t *ROM, uint32_t len, uint32_t nvram_len)
+void sega8_cart_slot_device::internal_header_logging(const uint8_t *ROM, uint32_t len, uint32_t nvram_len)
{
static const char *const system_region[] =
{
@@ -793,11 +790,6 @@ void sega8_cart_slot_device::internal_header_logging(uint8_t *ROM, uint32_t len,
0x20000,
};
- char reserved[10];
- uint8_t version, csum_size, region, serial[3];
- uint16_t checksum, csum = 0;
- uint32_t csum_end;
-
// LOG FILE DETAILS
logerror("FILE DETAILS\n" );
logerror("============\n" );
@@ -815,41 +807,39 @@ void sega8_cart_slot_device::internal_header_logging(uint8_t *ROM, uint32_t len,
if (len < 0x8000)
return;
+ char reserved[10];
for (int i = 0; i < 10; i++)
reserved[i] = ROM[0x7ff0 + i];
- checksum = ROM[0x7ffa] | (ROM[0x7ffb] << 8);
+ uint16_t checksum = get_u16le(&ROM[0x7ffa]);
+ uint8_t serial[3];
for (int i = 0; i < 3; i++)
serial[i] = ROM[0x7ffc + i];
serial[2] &= 0x0f;
- version = (ROM[0x7ffe] & 0xf0) >> 4;
+ uint8_t version = (ROM[0x7ffe] & 0xf0) >> 4;
- csum_size = ROM[0x7fff] & 0x0f;
- csum_end = csum_length[csum_size];
+ uint8_t csum_size = ROM[0x7fff] & 0x0f;
+ uint32_t csum_end = csum_length[csum_size];
if (!csum_end || csum_end > len)
csum_end = len;
- region = (ROM[0x7fff] & 0xf0) >> 4;
+ uint8_t region = (ROM[0x7fff] & 0xf0) >> 4;
// compute cart checksum to compare with expected one
- for (int i = 0; i < csum_end; i++)
- {
- if (i < 0x7ff0 || i >= 0x8000)
- {
- csum += ROM[i];
- csum &= 0xffff;
- }
- }
+ util::sum16_creator sum16;
+ sum16.append(ROM, std::min<uint32_t>(csum_end, 0x7ff0));
+ if (csum_end > 0x8000)
+ sum16.append(&ROM[0x8000], csum_end - 0x8000);
logerror("INTERNAL HEADER\n" );
logerror("===============\n" );
logerror("Reserved String: %.10s\n", reserved);
logerror("Region: %s\n", system_region[region]);
- logerror("Checksum: (Expected) 0x%x - (Computed) 0x%x\n", checksum, csum);
+ logerror("Checksum: (Expected) 0x%x - (Computed) 0x%x\n", checksum, sum16.finish());
logerror(" [checksum over 0x%X bytes]\n", csum_length[csum_size]);
- logerror("Serial String: %X\n", serial[0] | (serial[1] << 8) | (serial[2] << 16));
+ logerror("Serial String: %X\n", get_u24le(serial));
logerror("Software Revision: %x\n", version);
logerror("\n" );
@@ -857,14 +847,14 @@ void sega8_cart_slot_device::internal_header_logging(uint8_t *ROM, uint32_t len,
if (m_type == SEGA8_CODEMASTERS)
{
uint8_t day, month, year, hour, minute;
- csum = 0;
+ uint16_t csum = 0;
day = ROM[0x7fe1];
month = ROM[0x7fe2];
year = ROM[0x7fe3];
hour = ROM[0x7fe4];
minute = ROM[0x7fe5];
- checksum = ROM[0x7fe6] | (ROM[0x7fe7] << 8);
+ checksum = get_u16le(&ROM[0x7fe6]);
csum_size = ROM[0x7fe0];
// compute cart checksum to compare with expected one
@@ -872,7 +862,7 @@ void sega8_cart_slot_device::internal_header_logging(uint8_t *ROM, uint32_t len,
{
if (i < 0x7ff0 || i >= 0x8000)
{
- csum += (ROM[i] | (ROM[i + 1] << 8));
+ csum += get_u16le(&ROM[i]);
csum &= 0xffff;
}
}
diff --git a/src/devices/bus/sega8/sega8_slot.h b/src/devices/bus/sega8/sega8_slot.h
index 831d0500f0a..bc2d7d8e27e 100644
--- a/src/devices/bus/sega8/sega8_slot.h
+++ b/src/devices/bus/sega8/sega8_slot.h
@@ -64,7 +64,7 @@ public:
virtual uint8_t read_io(offs_t offset) { return 0xff; }
virtual void write_io(offs_t offset, uint8_t data) { }
- void rom_alloc(uint32_t size, const char *tag);
+ void rom_alloc(uint32_t size);
void ram_alloc(uint32_t size);
virtual void late_bank_setup() { }
@@ -116,24 +116,24 @@ public:
sega8_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual ~sega8_cart_slot_device();
- // image-level overrides
- virtual image_init_result call_load() override;
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
virtual void call_unload() override;
virtual bool is_reset_on_load() const noexcept override { return true; }
virtual const char *image_interface() const noexcept override { return "sms_cart"; }
virtual const char *file_extensions() const noexcept override { return "bin"; }
- // slot interface overrides
+ // device_slot_interface implementation
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
int get_type() { return m_type; }
int get_cart_type(const uint8_t *ROM, uint32_t len) const;
void setup_ram();
- void internal_header_logging(uint8_t *ROM, uint32_t len, uint32_t nvram_len);
- image_verify_result verify_cart(uint8_t *magic, int size);
- void set_lphaser_xoffset(uint8_t *rom, int size);
+ void internal_header_logging(const uint8_t *ROM, uint32_t len, uint32_t nvram_len);
+ std::error_condition verify_cart(const uint8_t *magic, int size);
+ void set_lphaser_xoffset(const uint8_t *rom, int size);
void save_ram() { if (m_cart && m_cart->get_ram_size()) m_cart->save_ram(); }
@@ -152,12 +152,12 @@ public:
protected:
sega8_cart_slot_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, bool is_card = false);
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
int m_type;
bool const m_is_card;
- device_sega8_cart_interface* m_cart;
+ device_sega8_cart_interface *m_cart;
};
// ======================> sega8_card_slot_device
@@ -346,12 +346,6 @@ DECLARE_DEVICE_TYPE(GAMEGEAR_CART_SLOT, gamegear_cart_slot_device)
DECLARE_DEVICE_TYPE(SMS_CARD_SLOT, sms_card_slot_device)
DECLARE_DEVICE_TYPE(SG1000_CARD_SLOT, sg1000_card_slot_device)
-/***************************************************************************
- DEVICE CONFIGURATION MACROS
- ***************************************************************************/
-
-#define S8SLOT_ROM_REGION_TAG ":cart:rom"
-
// slot interfaces
void sg1000_cart(device_slot_interface &device);
diff --git a/src/devices/bus/segaai/rom.cpp b/src/devices/bus/segaai/rom.cpp
new file mode 100644
index 00000000000..1d7d613416e
--- /dev/null
+++ b/src/devices/bus/segaai/rom.cpp
@@ -0,0 +1,93 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+/***********************************************************************************************************
+
+ Sega AI card emulation
+
+ ***********************************************************************************************************/
+
+
+#include "emu.h"
+#include "rom.h"
+
+
+namespace {
+
+class segaai_rom_128_device : public device_t,
+ public segaai_card_interface
+{
+public:
+ segaai_rom_128_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : segaai_rom_128_device(mconfig, SEGAAI_ROM_128, tag, owner, clock)
+ { }
+
+ virtual void install_memory_handlers(address_space *space) override;
+
+protected:
+ segaai_rom_128_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, type, tag, owner, clock)
+ , segaai_card_interface(mconfig, *this)
+ { }
+
+ virtual void device_start() override { }
+};
+
+void segaai_rom_128_device::install_memory_handlers(address_space *space)
+{
+ space->install_rom(0xa0000, 0xbffff, cart_rom_region()->base());
+}
+
+
+
+class segaai_rom_256_device : public segaai_rom_128_device
+{
+public:
+ segaai_rom_256_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : segaai_rom_128_device(mconfig, SEGAAI_ROM_256, tag, owner, clock)
+ , m_rom_bank(*this, "rombank%u", 0U)
+ { }
+
+ virtual void install_memory_handlers(address_space *space) override;
+
+private:
+ template <int Bank> void bank_w(u8 data);
+ void unknown0_w(u8 data);
+ void unknown1_w(u8 data);
+
+ memory_bank_array_creator<2> m_rom_bank;
+};
+
+void segaai_rom_256_device::install_memory_handlers(address_space *space)
+{
+ for (int i = 0; i < 2; i++)
+ m_rom_bank[i]->configure_entries(0, cart_rom_region()->bytes() / 0x4000, cart_rom_region()->base(), 0x4000);
+
+ space->install_rom(0xa0000, 0xa3fff, 0x10000, cart_rom_region()->base());
+ space->install_read_bank(0xa4000, 0xa7fff, 0x10000, m_rom_bank[0]);
+ space->install_read_bank(0xa8000, 0xabfff, 0x10000, m_rom_bank[1]);
+ space->install_write_handler(0xafffc, 0xafffc, 0, 0x10000, 0, emu::rw_delegate(*this, FUNC(segaai_rom_256_device::unknown0_w)));
+ space->install_write_handler(0xafffd, 0xafffd, 0, 0x10000, 0, emu::rw_delegate(*this, FUNC(segaai_rom_256_device::unknown1_w)));
+ space->install_write_handler(0xafffe, 0xafffe, 0, 0x10000, 0, emu::rw_delegate(*this, FUNC(segaai_rom_256_device::bank_w<0>)));
+ space->install_write_handler(0xaffff, 0xaffff, 0, 0x10000, 0, emu::rw_delegate(*this, FUNC(segaai_rom_256_device::bank_w<1>)));
+}
+
+template <int Bank>
+void segaai_rom_256_device::bank_w(u8 data)
+{
+ m_rom_bank[Bank]->set_entry(data & 0x0f);
+}
+
+void segaai_rom_256_device::unknown0_w(u8 data)
+{
+ // Unknown, upon start $00 is written and sometimes $80 after that
+}
+
+void segaai_rom_256_device::unknown1_w(u8 data)
+{
+ // Unknown, upon start $00 is written
+}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(SEGAAI_ROM_128, segaai_card_interface, segaai_rom_128_device, "segaai_rom_128", "Sega AI Card - 128KB")
+DEFINE_DEVICE_TYPE_PRIVATE(SEGAAI_ROM_256, segaai_card_interface, segaai_rom_256_device, "segaai_rom_256", "Sega AI Card - 256KB")
diff --git a/src/devices/bus/segaai/rom.h b/src/devices/bus/segaai/rom.h
new file mode 100644
index 00000000000..a9a830c7b78
--- /dev/null
+++ b/src/devices/bus/segaai/rom.h
@@ -0,0 +1,14 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#ifndef MAME_BUS_SEGAAI_ROM_H
+#define MAME_BUS_SEGAAI_ROM_H
+
+#pragma once
+
+#include "segaai_slot.h"
+
+
+DECLARE_DEVICE_TYPE(SEGAAI_ROM_128, segaai_card_interface);
+DECLARE_DEVICE_TYPE(SEGAAI_ROM_256, segaai_card_interface);
+
+#endif
diff --git a/src/devices/bus/segaai/segaai_exp.cpp b/src/devices/bus/segaai/segaai_exp.cpp
new file mode 100644
index 00000000000..926cfd84d9b
--- /dev/null
+++ b/src/devices/bus/segaai/segaai_exp.cpp
@@ -0,0 +1,48 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+/***********************************************************************************************************
+
+ Sega AI Expansion slot emulation
+
+ ***********************************************************************************************************/
+
+
+#include "emu.h"
+#include "segaai_exp.h"
+
+DEFINE_DEVICE_TYPE(SEGAAI_EXP_SLOT, segaai_exp_slot_device, "segaai_exp_slot", "Sega AI Expansion Slot")
+
+
+segaai_exp_interface::segaai_exp_interface(const machine_config &mconfig, device_t &device)
+ : device_interface(device, "segaai_exp")
+ , m_slot(dynamic_cast<segaai_exp_slot_device *>(device.owner()))
+{
+}
+
+segaai_exp_interface::~segaai_exp_interface()
+{
+}
+
+
+
+segaai_exp_slot_device::segaai_exp_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, SEGAAI_EXP_SLOT, tag, owner, clock)
+ , device_single_card_slot_interface<segaai_exp_interface>(mconfig, *this)
+ , m_mem_space(*this, finder_base::DUMMY_TAG, -1)
+ , m_io_space(*this, finder_base::DUMMY_TAG, -1)
+{
+}
+
+segaai_exp_slot_device::~segaai_exp_slot_device()
+{
+}
+
+
+// slot interfaces
+#include "soundbox.h"
+
+void segaai_exp(device_slot_interface &device)
+{
+ device.option_add("soundbox", SEGAAI_SOUNDBOX);
+}
+
diff --git a/src/devices/bus/segaai/segaai_exp.h b/src/devices/bus/segaai/segaai_exp.h
new file mode 100644
index 00000000000..c1d96166a11
--- /dev/null
+++ b/src/devices/bus/segaai/segaai_exp.h
@@ -0,0 +1,63 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#ifndef MAME_BUS_SEGAAI_EXP_H
+#define MAME_BUS_SEGAAI_EXP_H
+
+#pragma once
+
+
+DECLARE_DEVICE_TYPE(SEGAAI_EXP_SLOT, segaai_exp_slot_device);
+
+
+class segaai_exp_interface;
+
+class segaai_exp_slot_device : public device_t,
+ public device_single_card_slot_interface<segaai_exp_interface>
+{
+public:
+ template <typename T>
+ segaai_exp_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock, T &&opts, const char *dflt)
+ : segaai_exp_slot_device(mconfig, tag, owner, clock)
+ {
+ option_reset();
+ opts(*this);
+ set_default_option(dflt);
+ set_fixed(false);
+ }
+ segaai_exp_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+ virtual ~segaai_exp_slot_device();
+
+ template <typename T> void set_mem_space(T &&tag, int no) { m_mem_space.set_tag(std::forward<T>(tag), no); }
+ template <typename T> void set_io_space(T &&tag, int no) { m_io_space.set_tag(std::forward<T>(tag), no); }
+
+ address_space& mem_space() { return *m_mem_space; }
+ address_space& io_space() { return *m_io_space; }
+
+protected:
+ virtual void device_start() override { }
+
+private:
+ optional_address_space m_mem_space;
+ optional_address_space m_io_space;
+};
+
+
+class segaai_exp_interface : public device_interface
+{
+public:
+ segaai_exp_interface(const machine_config &mconfig, device_t &device);
+ virtual ~segaai_exp_interface();
+
+protected:
+ address_space& mem_space() { return m_slot->mem_space(); }
+ address_space& io_space() { return m_slot->io_space(); }
+
+private:
+ segaai_exp_slot_device *const m_slot;
+};
+
+
+// slot interfaces
+void segaai_exp(device_slot_interface &device);
+
+#endif
diff --git a/src/devices/bus/segaai/segaai_slot.cpp b/src/devices/bus/segaai/segaai_slot.cpp
new file mode 100644
index 00000000000..c7e10d59c54
--- /dev/null
+++ b/src/devices/bus/segaai/segaai_slot.cpp
@@ -0,0 +1,99 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+/***********************************************************************************************************
+
+ Sega AI card emulation
+
+ ***********************************************************************************************************/
+
+
+#include "emu.h"
+#include "segaai_slot.h"
+
+
+DEFINE_DEVICE_TYPE(SEGAAI_CARD_SLOT, segaai_card_slot_device, "segaai_card_slot", "Sega AI Card Slot")
+
+
+static char const *const ROM_128 = "rom_128";
+static char const *const ROM_256 = "rom_256";
+
+
+segaai_card_interface::segaai_card_interface(const machine_config &mconfig, device_t &device)
+ : device_interface(device, "segaai_card")
+ , m_slot(dynamic_cast<segaai_card_slot_device *>(device.owner()))
+{
+}
+
+segaai_card_interface::~segaai_card_interface()
+{
+}
+
+
+
+segaai_card_slot_device::segaai_card_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, SEGAAI_CARD_SLOT, tag, owner, clock)
+ , device_cartrom_image_interface(mconfig, *this)
+ , device_single_card_slot_interface<segaai_card_interface>(mconfig, *this)
+ , m_address_space(*this, finder_base::DUMMY_TAG, -1, 8)
+{
+}
+
+segaai_card_slot_device::~segaai_card_slot_device()
+{
+}
+
+void segaai_card_slot_device::device_start()
+{
+ m_cart = get_card_device();
+}
+
+std::pair<std::error_condition, std::string> segaai_card_slot_device::call_load()
+{
+ if (m_cart)
+ {
+ const u32 length = !loaded_through_softlist() ? this->length() : get_software_region_length("rom");
+
+ if (length != 0x20000 && length != 0x40000)
+ {
+ return std::make_pair(image_error::INVALIDIMAGE, "Invalid card size. Supported sizes are: 128KB, 256KB");
+ }
+
+ if (!loaded_through_softlist())
+ {
+ memory_region *const romregion = machine().memory().region_alloc(subtag("rom"), length, 1, ENDIANNESS_LITTLE);
+ if (fread(romregion->base(), length) != length)
+ return std::make_pair(image_error::UNSPECIFIED, "Unable to fully read file");
+ }
+
+ m_cart->install_memory_handlers(m_address_space.target());
+
+ return std::make_pair(std::error_condition(), std::string());
+ }
+
+ return std::make_pair(std::error_condition(), std::string());
+}
+
+std::string segaai_card_slot_device::get_default_card_software(get_default_card_software_hook &hook) const
+{
+ if (hook.image_file())
+ {
+ uint64_t length;
+ hook.image_file()->length(length);
+
+ return std::string(length == 0x40000 ? ROM_256 : ROM_128);
+ }
+
+ return software_get_default_slot(ROM_128);
+}
+
+
+
+// slot interfaces
+#include "rom.h"
+
+
+void segaai_cards(device_slot_interface &device)
+{
+ device.option_add_internal(ROM_128, SEGAAI_ROM_128);
+ device.option_add_internal(ROM_256, SEGAAI_ROM_256);
+}
diff --git a/src/devices/bus/segaai/segaai_slot.h b/src/devices/bus/segaai/segaai_slot.h
new file mode 100644
index 00000000000..5e8723fe471
--- /dev/null
+++ b/src/devices/bus/segaai/segaai_slot.h
@@ -0,0 +1,73 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+#ifndef MAME_BUS_SEGAAI_SLOT_H
+#define MAME_BUS_SEGAAI_SLOT_H
+
+#pragma once
+
+#include "imagedev/cartrom.h"
+
+
+DECLARE_DEVICE_TYPE(SEGAAI_CARD_SLOT, segaai_card_slot_device);
+
+
+class segaai_card_interface;
+
+
+class segaai_card_slot_device : public device_t,
+ public device_cartrom_image_interface,
+ public device_single_card_slot_interface<segaai_card_interface>
+{
+public:
+ template <typename T>
+ segaai_card_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, T &&opts, const char *dflt)
+ : segaai_card_slot_device(mconfig, tag, owner, u32(0))
+ {
+ option_reset();
+ opts(*this);
+ set_default_option(dflt);
+ set_fixed(false);
+ }
+ segaai_card_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+ virtual ~segaai_card_slot_device();
+
+ template <typename T> void set_address_space(T &&tag, int no) { m_address_space.set_tag(std::forward<T>(tag), no); }
+ virtual std::pair<std::error_condition, std::string> call_load() override;
+ virtual void call_unload() override {}
+ virtual const char *image_type_name() const noexcept override { return "card"; }
+ virtual const char *image_brief_type_name() const noexcept override { return "card"; }
+
+ virtual bool is_reset_on_load() const noexcept override { return true; }
+ virtual const char *image_interface() const noexcept override { return "segaai_card"; }
+ virtual const char *file_extensions() const noexcept override { return "aic,bin"; }
+
+ virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
+
+protected:
+ virtual void device_start() override;
+
+private:
+ optional_address_space m_address_space;
+ segaai_card_interface* m_cart;
+};
+
+
+class segaai_card_interface : public device_interface
+{
+public:
+ segaai_card_interface(const machine_config &mconfig, device_t &device);
+ virtual ~segaai_card_interface();
+
+ virtual void install_memory_handlers(address_space *space) { }
+
+protected:
+ memory_region *cart_rom_region() { return m_slot ? m_slot->memregion("rom") : nullptr; }
+
+private:
+ segaai_card_slot_device *const m_slot;
+};
+
+
+void segaai_cards(device_slot_interface &device);
+
+#endif
diff --git a/src/devices/bus/segaai/soundbox.cpp b/src/devices/bus/segaai/soundbox.cpp
new file mode 100644
index 00000000000..5730ab0042d
--- /dev/null
+++ b/src/devices/bus/segaai/soundbox.cpp
@@ -0,0 +1,320 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol, Fabio Priuli
+// thanks-to:Chris Covell
+/***********************************************************************************************************
+
+ Sega AI Soundbox expansion emulation
+
+
+ Sega AI Computer Sound Box, Model "AI-2002" quick PCB overview by Chris Covell
+
+ICs on board:
+
+IC 2 TMP82C53F-2 (91/09) Toshiba (Peripheral Timer)
+IC 3 HN27512G-25 (87/12) Hitachi 64K EPROM
+IC 6 YM2151 (91/10) Yamaha FM chip
+IC 7 TMP82C55AF-10 (88/15) Toshiba (Peripheral Interface)
+IC 8 YM3012 (91/10) Yamaha Stereo DAC
+IC 9 HA17358 Hitachi Dual Op-Amp
+IC 10 LC7537N Sanyo (Volume Control IC)
+IC 11 C324C (90/42) NEC Quad Op-Amp
+IC 12 LA4520 (Sanyo Power Audio Amp?)
+IC 16-19 MB81464-12 (91/12) Fujitsu 32K DRAMs
+
+
+Misc Flat DIPs
+
+IC ?? LS125A Hitachi (near C41)
+IC ?? 74HC04 TI (near C38)
+IC ?? 74HC157A x2 Toshiba (near C37)
+IC ?? 74HC138 TI (near C44, furthest)
+IC ?? 74HC139 TI (near C44, closest)
+
+TODO:
+- Connections of the 8253
+- Keyboard matrix is scanned on a timer irq (#FC) from 8253??
+- LC7537N
+
+
+HC04
+pin 1 A1 - PB7
+pin 2 Y1 -> HC04 pin 3 A2
+pin 3 A2 <- HC04 pin 2 Y1
+pin 4 Y2 -> 4th point, 1st row below HC04?
+pin 5 A3 -
+pin 6 Y3 -
+pin 7 GND -
+pin 8 Y4 - 1st point, 2nd row below HC04
+pin 9 A4 - 1st point, 1st row below HC04
+pin 10 Y5 -
+pin 11 A5 <- HC04 pin 12 Y6
+pin 12 Y6 -> HC04 pin 11 A5
+pin 13 A6 - point just below C38 then continues to DRAMs
+pin 14 VCC -
+
+8255 PB7 - connected to HC04 pin 1?, pulled low
+
+TMP8253
+pin 9 CLK0 - seems to be tied to pin 24 in ym2151
+pin 14 OUT0 - --> 2nd point, 2nd row below HC04
+pin 15 GATE0 - NC
+pin 18 OUT1 - 7th point, 1st row below HC04 -> 8th point, 1st row below HC04 -> LS125 pin 2?
+pin 19 GATE1 - 6th point, 1st row below HC04 -> 4th point, 1st row below HC04
+pin 20 CLK1 - 5th point, 1st row below HC04 -> 2nd point, 1st row below HC04 -> left point above C37 -> pin 1 2 lc157s to the right of IC16 (can't be right)
+
+timer 0 - mode 3 - square wave (000A), gate not involved
+timer 1 - mode 2 - rate generator (0E90), gate involved
+0e90 = 3818
+
+ ***********************************************************************************************************/
+
+
+#include "emu.h"
+#include "soundbox.h"
+
+#include "machine/i8255.h"
+#include "machine/pit8253.h"
+#include "sound/ymopm.h"
+
+#include "speaker.h"
+
+//#define VERBOSE (LOG_GENERAL)
+#include "logmacro.h"
+
+
+namespace {
+
+class segaai_soundbox_device : public device_t,
+ public segaai_exp_interface
+{
+public:
+ segaai_soundbox_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, SEGAAI_SOUNDBOX, tag, owner, clock)
+ , segaai_exp_interface(mconfig, *this)
+ , m_tmp8253(*this, "tmp8253")
+ , m_tmp8255(*this, "tmp8255")
+ , m_ym2151(*this, "ym2151")
+ , m_rom(*this, "soundbox")
+ , m_rows(*this, "ROW%u", 0U)
+ , m_row(0)
+ { }
+
+ static constexpr feature_type unemulated_features() { return feature::KEYBOARD; }
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual ioport_constructor device_input_ports() const override;
+ virtual void device_start() override;
+
+private:
+ static constexpr u32 EXPANSION_RAM_SIZE = 0x20000;
+
+ u8 tmp8255_porta_r();
+ void tmp8255_portb_w(u8 data);
+ void tmp8255_portc_w(u8 data);
+ void ym2151_irq_w(int state);
+ void tmp8253_out0_w(int state);
+ void tmp8253_out1_w(int state);
+
+ required_device<pit8253_device> m_tmp8253;
+ required_device<i8255_device> m_tmp8255;
+ required_device<ym2151_device> m_ym2151;
+ required_region_ptr<u8> m_rom;
+ required_ioport_array<8> m_rows;
+ std::unique_ptr<u8[]> m_ram;
+ u8 m_row;
+};
+
+void segaai_soundbox_device::device_add_mconfig(machine_config &config)
+{
+ PIT8253(config, m_tmp8253);
+ m_tmp8253->set_clk<0>(clock()); // ~3.58 MHz, seems to be tied to pin 24 in ym2151
+ m_tmp8253->out_handler<0>().set(FUNC(segaai_soundbox_device::tmp8253_out0_w));
+ // gate0 not connected
+ m_tmp8253->set_clk<1>(clock()); // 3.58 MHz?
+ m_tmp8253->out_handler<1>().set(FUNC(segaai_soundbox_device::tmp8253_out1_w));
+ // timer 2 is not connected, also not set up by the code
+
+ I8255(config, m_tmp8255);
+ m_tmp8255->in_pa_callback().set(FUNC(segaai_soundbox_device::tmp8255_porta_r));
+ m_tmp8255->in_pb_callback().set_constant(0xff);
+ m_tmp8255->out_pb_callback().set(FUNC(segaai_soundbox_device::tmp8255_portb_w));
+ m_tmp8255->out_pc_callback().set(FUNC(segaai_soundbox_device::tmp8255_portc_w));
+
+ SPEAKER(config, "lspeaker").front_left();
+ SPEAKER(config, "rspeaker").front_right();
+ YM2151(config, m_ym2151, DERIVED_CLOCK(1,1)); // ~3.58MHz
+ m_ym2151->irq_handler().set(FUNC(segaai_soundbox_device::ym2151_irq_w));
+ m_ym2151->add_route(0, "lspeaker", 1.00);
+ m_ym2151->add_route(1, "rspeaker", 1.00);
+}
+
+ROM_START(soundbox)
+ ROM_REGION(0x10000, "soundbox", 0)
+ ROM_LOAD("ai-snd-2002-cecb.bin", 0x0000, 0x10000, CRC(ef2dabc0) SHA1(b60cd9f6f46b6c77dba8610df6fd83368569e713))
+ROM_END
+
+const tiny_rom_entry *segaai_soundbox_device::device_rom_region() const
+{
+ return ROM_NAME(soundbox);
+}
+
+static INPUT_PORTS_START(soundbox)
+ PORT_START("ROW0")
+ PORT_BIT(0x0001, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x0002, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x0004, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x0008, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x0010, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x0020, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x0040, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x0080, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("ROW1")
+ PORT_BIT(0x0001, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x0002, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x0004, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x0008, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x0010, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x0020, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x0040, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x0080, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("ROW2")
+ PORT_BIT(0x0001, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x0002, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x0004, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x0008, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x0010, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x0020, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x0040, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x0080, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("ROW3")
+ PORT_BIT(0x0001, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x0002, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x0004, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x0008, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x0010, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x0020, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x0040, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x0080, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("ROW4")
+ PORT_BIT(0x0001, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x0002, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x0004, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x0008, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x0010, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x0020, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x0040, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x0080, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("ROW5")
+ PORT_BIT(0x0001, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x0002, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x0004, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x0008, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x0010, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x0020, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x0040, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x0080, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("ROW6")
+ PORT_BIT(0x0001, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x0002, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x0004, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x0008, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x0010, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x0020, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x0040, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x0080, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("ROW7")
+ PORT_BIT(0x0001, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x0002, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x0004, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x0008, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x0010, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x0020, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x0040, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x0080, IP_ACTIVE_LOW, IPT_UNUSED)
+INPUT_PORTS_END
+
+ioport_constructor segaai_soundbox_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(soundbox);
+}
+
+void segaai_soundbox_device::device_start()
+{
+ m_row = 0;
+ m_ram = std::make_unique<u8[]>(EXPANSION_RAM_SIZE);
+
+ save_pointer(NAME(m_ram), EXPANSION_RAM_SIZE);
+ save_item(NAME(m_row));
+
+ mem_space().install_ram(0x20000, 0x3ffff, &m_ram[0]);
+ mem_space().install_rom(0x80000, 0x8ffff, m_rom);
+ io_space().install_read_handler(0x20, 0x23, emu::rw_delegate(*m_ym2151, FUNC(ym2151_device::read)));
+ io_space().install_write_handler(0x20, 0x23, emu::rw_delegate(*m_ym2151, FUNC(ym2151_device::write)));
+ io_space().install_read_handler(0x24, 0x27, emu::rw_delegate(*m_tmp8253, FUNC(pit8253_device::read)));
+ io_space().install_write_handler(0x24, 0x27, emu::rw_delegate(*m_tmp8253, FUNC(pit8253_device::write)));
+ io_space().install_read_handler(0x28, 0x2b, emu::rw_delegate(*m_tmp8255, FUNC(i8255_device::read)));
+ io_space().install_write_handler(0x28, 0x2b, emu::rw_delegate(*m_tmp8255, FUNC(i8255_device::write)));
+}
+
+u8 segaai_soundbox_device::tmp8255_porta_r()
+{
+ // Read pressed keys on music keyboard row (see routine @0x82399)
+ u8 result = 0xff;
+ for (int i = 0; i < 8; i++)
+ if (BIT(m_row, i)) result &= m_rows[i]->read();
+ return result;
+}
+
+/*
+ 8255 port B
+
+ 76543210
+ +-------- 8253 GATE1
+ +-------
+ +------
+ +-----
+ +----
+ +--- LC7537N pin22 DI
+ +-- LC7537N pin21 CLK
+ +- LC7537N pin20 DI
+*/
+void segaai_soundbox_device::tmp8255_portb_w(u8 data)
+{
+ LOG("soundbox 8255 port B write $%02X\n", data);
+ m_tmp8253->write_gate1(BIT(data, 7));
+}
+
+void segaai_soundbox_device::tmp8255_portc_w(u8 data)
+{
+ // Selects music keyboard row to scan (see routine @0x82399)
+ LOG("soundbox m_row = $%02X\n", data);
+ m_row = data;
+}
+
+void segaai_soundbox_device::ym2151_irq_w(int state)
+{
+ LOG("Soundbox: IRQ from ym2151 is '%s'\n", state ? "ASSERT" : "CLEAR");
+}
+
+void segaai_soundbox_device::tmp8253_out0_w(int state)
+{
+// LOG("Soundbox: OUT0 from tmp8253 is '%s'\n", state ? "ASSERT" : "CLEAR");
+}
+
+void segaai_soundbox_device::tmp8253_out1_w(int state)
+{
+// LOG("Soundbox: OUT1 from tmp8253 is '%s'\n", state ? "ASSERT" : "CLEAR");
+}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(SEGAAI_SOUNDBOX, segaai_exp_interface, segaai_soundbox_device, "segaai_soundbox", "Sega AI Expansion - Soundbox")
diff --git a/src/devices/bus/segaai/soundbox.h b/src/devices/bus/segaai/soundbox.h
new file mode 100644
index 00000000000..041c50195f0
--- /dev/null
+++ b/src/devices/bus/segaai/soundbox.h
@@ -0,0 +1,14 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol, Fabio Priuli
+// thanks-to:Chris Covell
+#ifndef MAME_BUS_SEGAAI_SOUNDBOX_H
+#define MAME_BUS_SEGAAI_SOUNDBOX_H
+
+#pragma once
+
+#include "segaai_exp.h"
+
+
+DECLARE_DEVICE_TYPE(SEGAAI_SOUNDBOX, segaai_exp_interface);
+
+#endif
diff --git a/src/devices/bus/sg1000_exp/kblink.h b/src/devices/bus/sg1000_exp/kblink.h
index 561c1b79455..ee0aec9315d 100644
--- a/src/devices/bus/sg1000_exp/kblink.h
+++ b/src/devices/bus/sg1000_exp/kblink.h
@@ -40,12 +40,12 @@ protected:
virtual void device_add_mconfig(machine_config &config) override;
// device_sk1100_link_cable_interface overrides
- virtual DECLARE_WRITE_LINE_MEMBER( input_data ) override { m_data = state; set_data_transfer(); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_reset ) override { m_reset = state; set_data_transfer(); }
- virtual DECLARE_WRITE_LINE_MEMBER( input_feed ) override { m_feed = state; set_data_transfer(); }
+ virtual void input_data(int state) override { m_data = state; set_data_transfer(); }
+ virtual void input_reset(int state) override { m_reset = state; set_data_transfer(); }
+ virtual void input_feed(int state) override { m_feed = state; set_data_transfer(); }
- virtual DECLARE_READ_LINE_MEMBER( output_fault ) override { set_data_read(); return m_fault; }
- virtual DECLARE_READ_LINE_MEMBER( output_busy ) override { set_data_read(); return m_busy; }
+ virtual int output_fault() override { set_data_read(); return m_fault; }
+ virtual int output_busy() override { set_data_read(); return m_busy; }
TIMER_CALLBACK_MEMBER(update_queue);
TIMER_CALLBACK_MEMBER(send_tick);
diff --git a/src/devices/bus/sg1000_exp/sk1100.cpp b/src/devices/bus/sg1000_exp/sk1100.cpp
index 95884acfb30..8f0d3d6eb5d 100644
--- a/src/devices/bus/sg1000_exp/sk1100.cpp
+++ b/src/devices/bus/sg1000_exp/sk1100.cpp
@@ -20,6 +20,8 @@ TODO:
#include "sk1100.h"
#include "softlist_dev.h"
+#include "formats/sc3000_bit.h"
+
//**************************************************************************
@@ -70,7 +72,7 @@ static INPUT_PORTS_START( sk1100_keys )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F) PORT_CHAR('F') PORT_CHAR('f')
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_V) PORT_CHAR('V') PORT_CHAR('v')
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("INS DEL") PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8)
- PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(UTF8_SMALL_PI) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR(0x03c0)
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR(U'π')
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(':') PORT_CHAR('*')
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('@') PORT_CHAR('`')
@@ -80,7 +82,7 @@ static INPUT_PORTS_START( sk1100_keys )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_G) PORT_CHAR('G') PORT_CHAR('g')
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_B) PORT_CHAR('B') PORT_CHAR('b')
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED )
- PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(UTF8_DOWN) PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN))
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"\u2193") PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN)) // U+2193 = ↓
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR(']') PORT_CHAR('}')
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR('[') PORT_CHAR('{')
@@ -90,7 +92,7 @@ static INPUT_PORTS_START( sk1100_keys )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_H) PORT_CHAR('H') PORT_CHAR('h')
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_N) PORT_CHAR('N') PORT_CHAR('n')
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED )
- PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(UTF8_LEFT) PORT_CODE(KEYCODE_LEFT) PORT_CHAR(UCHAR_MAMEKEY(LEFT))
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"\u2190") PORT_CODE(KEYCODE_LEFT) PORT_CHAR(UCHAR_MAMEKEY(LEFT)) // U+2190 = ←
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("CR") PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13)
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED )
@@ -100,8 +102,8 @@ static INPUT_PORTS_START( sk1100_keys )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_J) PORT_CHAR('J') PORT_CHAR('j')
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_M) PORT_CHAR('M') PORT_CHAR('m')
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED )
- PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(UTF8_RIGHT) PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT))
- PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(UTF8_UP) PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP))
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"\u2192") PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT)) // U+2192 = →
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME(u8"\u2191") PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP)) // U+2191 = ↑
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_START("PA7")
@@ -128,7 +130,7 @@ static INPUT_PORTS_START( sk1100_keys )
PORT_BIT( 0x0e, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_START("PB5")
- PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("\xc2\xa5") PORT_CODE(KEYCODE_TILDE) PORT_CHAR(0x00a5)
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_TILDE) PORT_CHAR(U'¥')
PORT_BIT( 0x06, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("FUNC") PORT_CODE(KEYCODE_TAB)
diff --git a/src/devices/bus/sg1000_exp/sk1100.h b/src/devices/bus/sg1000_exp/sk1100.h
index f2e94920e22..edaea0a706d 100644
--- a/src/devices/bus/sg1000_exp/sk1100.h
+++ b/src/devices/bus/sg1000_exp/sk1100.h
@@ -14,7 +14,6 @@
#include "sg1000exp.h"
#include "sk1100prn.h"
-#include "formats/sc3000_bit.h"
#include "imagedev/cassette.h"
#include "machine/i8255.h"
diff --git a/src/devices/bus/sg1000_exp/sk1100prn.cpp b/src/devices/bus/sg1000_exp/sk1100prn.cpp
index 8f80306588b..2b24864d75b 100644
--- a/src/devices/bus/sg1000_exp/sk1100prn.cpp
+++ b/src/devices/bus/sg1000_exp/sk1100prn.cpp
@@ -80,25 +80,25 @@ void sk1100_printer_port_device::device_start()
m_device = get_card_device();
}
-WRITE_LINE_MEMBER(sk1100_printer_port_device::data_w)
+void sk1100_printer_port_device::data_w(int state)
{
if (m_device)
m_device->input_data(state);
}
-WRITE_LINE_MEMBER(sk1100_printer_port_device::reset_w)
+void sk1100_printer_port_device::reset_w(int state)
{
if (m_device)
m_device->input_reset(state);
}
-WRITE_LINE_MEMBER(sk1100_printer_port_device::feed_w)
+void sk1100_printer_port_device::feed_w(int state)
{
if (m_device)
m_device->input_feed(state);
}
-READ_LINE_MEMBER(sk1100_printer_port_device::fault_r)
+int sk1100_printer_port_device::fault_r()
{
if (m_device)
return m_device->output_fault();
@@ -106,7 +106,7 @@ READ_LINE_MEMBER(sk1100_printer_port_device::fault_r)
return 1;
}
-READ_LINE_MEMBER(sk1100_printer_port_device::busy_r)
+int sk1100_printer_port_device::busy_r()
{
if (m_device)
return m_device->output_busy();
diff --git a/src/devices/bus/sg1000_exp/sk1100prn.h b/src/devices/bus/sg1000_exp/sk1100prn.h
index 8e1988102c8..56771a774b7 100644
--- a/src/devices/bus/sg1000_exp/sk1100prn.h
+++ b/src/devices/bus/sg1000_exp/sk1100prn.h
@@ -40,12 +40,12 @@ public:
sk1100_printer_port_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);
virtual ~sk1100_printer_port_device();
- DECLARE_READ_LINE_MEMBER(fault_r);
- DECLARE_READ_LINE_MEMBER(busy_r);
+ int fault_r();
+ int busy_r();
- DECLARE_WRITE_LINE_MEMBER(data_w);
- DECLARE_WRITE_LINE_MEMBER(reset_w);
- DECLARE_WRITE_LINE_MEMBER(feed_w);
+ void data_w(int state);
+ void reset_w(int state);
+ void feed_w(int state);
protected:
// device-level overrides
@@ -69,12 +69,12 @@ public:
protected:
device_sk1100_printer_port_interface(const machine_config &mconfig, device_t &device);
- virtual DECLARE_WRITE_LINE_MEMBER( input_data ) { }
- virtual DECLARE_WRITE_LINE_MEMBER( input_reset ) { }
- virtual DECLARE_WRITE_LINE_MEMBER( input_feed ) { }
+ virtual void input_data(int state) { }
+ virtual void input_reset(int state) { }
+ virtual void input_feed(int state) { }
- virtual DECLARE_READ_LINE_MEMBER( output_fault ) { return 1; }
- virtual DECLARE_READ_LINE_MEMBER( output_busy ) { return 1; }
+ virtual int output_fault() { return 1; }
+ virtual int output_busy() { return 1; }
};
diff --git a/src/devices/bus/sgikbd/hlekbd.cpp b/src/devices/bus/sgikbd/hlekbd.cpp
deleted file mode 100644
index 42ffb0eb76c..00000000000
--- a/src/devices/bus/sgikbd/hlekbd.cpp
+++ /dev/null
@@ -1,406 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Ryan Holtz
-#include "emu.h"
-#include "hlekbd.h"
-
-#include "machine/keyboard.ipp"
-#include "speaker.h"
-
-DEFINE_DEVICE_TYPE(SGI_HLE_KEYBOARD, bus::sgikbd::hle_device, "hlekbd", "SGI Indigo Keyboard (HLE)")
-
-namespace bus::sgikbd {
-
-namespace {
-
-INPUT_PORTS_START( hle_device )
- PORT_START("ROW0")
- PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_UNUSED )
- PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_UNUSED )
- PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("L Control") PORT_CODE(KEYCODE_LCONTROL) PORT_CHAR(UCHAR_MAMEKEY(LCONTROL))
- PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Caps Lock") PORT_CODE(KEYCODE_CAPSLOCK) PORT_CHAR(UCHAR_MAMEKEY(CAPSLOCK))
- PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("R Shift") PORT_CODE(KEYCODE_RSHIFT) PORT_CHAR(UCHAR_MAMEKEY(RSHIFT))
- PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("L Shift") PORT_CODE(KEYCODE_LSHIFT) PORT_CHAR(UCHAR_SHIFT_1)
- PORT_BIT( 0x0040, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Esc") PORT_CODE(KEYCODE_ESC) PORT_CHAR(UCHAR_MAMEKEY(ESC))
- PORT_BIT( 0x0080, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!')
- PORT_BIT( 0x0100, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Tab") PORT_CODE(KEYCODE_TAB) PORT_CHAR(9)
- PORT_BIT( 0x0200, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q')
- PORT_BIT( 0x0400, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A')
- PORT_BIT( 0x0800, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S')
- PORT_BIT( 0x1000, IP_ACTIVE_HIGH, IPT_UNUSED )
- PORT_BIT( 0x2000, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('@')
- PORT_BIT( 0x4000, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#')
- PORT_BIT( 0x8000, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W')
-
- PORT_START("ROW1")
- PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E')
- PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D')
- PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F')
- PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z')
- PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X')
- PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$')
- PORT_BIT( 0x0040, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%')
- PORT_BIT( 0x0080, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R')
- PORT_BIT( 0x0100, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T')
- PORT_BIT( 0x0200, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G')
- PORT_BIT( 0x0400, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H')
- PORT_BIT( 0x0800, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C')
- PORT_BIT( 0x1000, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V')
- PORT_BIT( 0x2000, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('^')
- PORT_BIT( 0x4000, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('&')
- PORT_BIT( 0x8000, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y')
-
- PORT_START("ROW2")
- PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U')
- PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J')
- PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K')
- PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B')
- PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N')
- PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('*')
- PORT_BIT( 0x0040, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR('(')
- PORT_BIT( 0x0080, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I')
- PORT_BIT( 0x0100, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O')
- PORT_BIT( 0x0200, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L')
- PORT_BIT( 0x0400, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR(':')
- PORT_BIT( 0x0800, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M')
- PORT_BIT( 0x1000, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<')
- PORT_BIT( 0x2000, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR(')')
- PORT_BIT( 0x4000, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHAR('_')
- PORT_BIT( 0x8000, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P')
-
- PORT_START("ROW3")
- PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('[') PORT_CHAR('{')
- PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR('\'') PORT_CHAR('"')
- PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Return") PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13)
- PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>')
- PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?')
- PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=') PORT_CHAR('+')
- PORT_BIT( 0x0040, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_TILDE) PORT_CHAR('`') PORT_CHAR('~')
- PORT_BIT( 0x0080, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(']') PORT_CHAR('}')
- PORT_BIT( 0x0100, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('\\') PORT_CHAR('|')
- PORT_BIT( 0x0200, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("KP 1") PORT_CODE(KEYCODE_1_PAD) PORT_CHAR(UCHAR_MAMEKEY(1_PAD))
- PORT_BIT( 0x0400, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("KP 0") PORT_CODE(KEYCODE_0_PAD) PORT_CHAR(UCHAR_MAMEKEY(0_PAD))
- PORT_BIT( 0x0800, IP_ACTIVE_HIGH, IPT_UNUSED )
- PORT_BIT( 0x1000, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Backspace") PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8)
- PORT_BIT( 0x2000, IP_ACTIVE_HIGH, IPT_UNUSED )
- PORT_BIT( 0x4000, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("KP 4") PORT_CODE(KEYCODE_4_PAD) PORT_CHAR(UCHAR_MAMEKEY(4_PAD))
- PORT_BIT( 0x8000, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("KP 2") PORT_CODE(KEYCODE_2_PAD) PORT_CHAR(UCHAR_MAMEKEY(2_PAD))
-
- PORT_START("ROW4")
- PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("KP 3") PORT_CODE(KEYCODE_3_PAD) PORT_CHAR(UCHAR_MAMEKEY(3_PAD))
- PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("KP .") PORT_CODE(KEYCODE_DEL_PAD) PORT_CHAR(UCHAR_MAMEKEY(DEL_PAD))
- PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("KP 7") PORT_CODE(KEYCODE_7_PAD) PORT_CHAR(UCHAR_MAMEKEY(7_PAD))
- PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("KP 8") PORT_CODE(KEYCODE_8_PAD) PORT_CHAR(UCHAR_MAMEKEY(8_PAD))
- PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("KP 5") PORT_CODE(KEYCODE_5_PAD) PORT_CHAR(UCHAR_MAMEKEY(5_PAD))
- PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("KP 6") PORT_CODE(KEYCODE_6_PAD) PORT_CHAR(UCHAR_MAMEKEY(6_PAD))
- PORT_BIT( 0x0040, IP_ACTIVE_HIGH, IPT_UNUSED )
- PORT_BIT( 0x0080, IP_ACTIVE_HIGH, IPT_UNUSED )
- PORT_BIT( 0x0100, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Left") PORT_CODE(KEYCODE_LEFT) PORT_CHAR(UCHAR_MAMEKEY(LEFT))
- PORT_BIT( 0x0200, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Down") PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN))
- PORT_BIT( 0x0400, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("KP 9") PORT_CODE(KEYCODE_9_PAD) PORT_CHAR(UCHAR_MAMEKEY(9_PAD))
- PORT_BIT( 0x0800, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("KP -") PORT_CODE(KEYCODE_MINUS_PAD) PORT_CHAR(UCHAR_MAMEKEY(MINUS_PAD))
- PORT_BIT( 0x1000, IP_ACTIVE_HIGH, IPT_UNUSED )
- PORT_BIT( 0x2000, IP_ACTIVE_HIGH, IPT_UNUSED )
- PORT_BIT( 0x4000, IP_ACTIVE_HIGH, IPT_UNUSED )
- PORT_BIT( 0x8000, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Right") PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT))
-
- PORT_START("ROW5")
- PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Up") PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP))
- PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Enter") PORT_CODE(KEYCODE_ENTER_PAD)
- PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Space") PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ')
- PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("L Alt") PORT_CODE(KEYCODE_LALT) PORT_CHAR(UCHAR_MAMEKEY(LALT))
- PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("R Alt") PORT_CODE(KEYCODE_RALT) PORT_CHAR(UCHAR_MAMEKEY(RALT))
- PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("R Control") PORT_CODE(KEYCODE_RCONTROL) PORT_CHAR(UCHAR_MAMEKEY(RCONTROL))
- PORT_BIT( 0x0040, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("F1") PORT_CODE(KEYCODE_F1) PORT_CHAR(UCHAR_MAMEKEY(F1))
- PORT_BIT( 0x0080, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("F2") PORT_CODE(KEYCODE_F2) PORT_CHAR(UCHAR_MAMEKEY(F2))
- PORT_BIT( 0x0100, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("F3") PORT_CODE(KEYCODE_F3) PORT_CHAR(UCHAR_MAMEKEY(F3))
- PORT_BIT( 0x0200, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("F4") PORT_CODE(KEYCODE_F4) PORT_CHAR(UCHAR_MAMEKEY(F4))
- PORT_BIT( 0x0400, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("F5") PORT_CODE(KEYCODE_F5) PORT_CHAR(UCHAR_MAMEKEY(F5))
- PORT_BIT( 0x0800, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("F6") PORT_CODE(KEYCODE_F6) PORT_CHAR(UCHAR_MAMEKEY(F6))
- PORT_BIT( 0x1000, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("F7") PORT_CODE(KEYCODE_F7) PORT_CHAR(UCHAR_MAMEKEY(F7))
- PORT_BIT( 0x2000, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("F8") PORT_CODE(KEYCODE_F8) PORT_CHAR(UCHAR_MAMEKEY(F8))
- PORT_BIT( 0x4000, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("F9") PORT_CODE(KEYCODE_F9) PORT_CHAR(UCHAR_MAMEKEY(F9))
- PORT_BIT( 0x8000, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("F10") PORT_CODE(KEYCODE_F10) PORT_CHAR(UCHAR_MAMEKEY(F10))
-
- PORT_START("ROW6")
- PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("F11") PORT_CODE(KEYCODE_F11) PORT_CHAR(UCHAR_MAMEKEY(F11))
- PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("F12") PORT_CODE(KEYCODE_F12) PORT_CHAR(UCHAR_MAMEKEY(F12))
- PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Print Screen") PORT_CODE(KEYCODE_PRTSCR) PORT_CHAR(UCHAR_MAMEKEY(PRTSCR))
- PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Scroll Lock") PORT_CODE(KEYCODE_SCRLOCK) PORT_CHAR(UCHAR_MAMEKEY(SCRLOCK))
- PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Pause") PORT_CODE(KEYCODE_PAUSE)
- PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Insert") PORT_CODE(KEYCODE_INSERT) PORT_CHAR(UCHAR_MAMEKEY(INSERT))
- PORT_BIT( 0x0040, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Home") PORT_CODE(KEYCODE_HOME) PORT_CHAR(UCHAR_MAMEKEY(HOME))
- PORT_BIT( 0x0080, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Page Up") PORT_CODE(KEYCODE_PGUP) PORT_CHAR(UCHAR_MAMEKEY(PGUP))
- PORT_BIT( 0x0100, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("End") PORT_CODE(KEYCODE_END) PORT_CHAR(UCHAR_MAMEKEY(END))
- PORT_BIT( 0x0200, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Page Down") PORT_CODE(KEYCODE_PGDN) PORT_CHAR(UCHAR_MAMEKEY(PGDN))
- PORT_BIT( 0x0400, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("Num Lock") PORT_CODE(KEYCODE_NUMLOCK) PORT_CHAR(UCHAR_MAMEKEY(NUMLOCK))
- PORT_BIT( 0x0800, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("KP /") PORT_CODE(KEYCODE_SLASH_PAD)
- PORT_BIT( 0x1000, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("KP *") PORT_CODE(KEYCODE_ASTERISK) PORT_CHAR(UCHAR_MAMEKEY(ASTERISK))
- PORT_BIT( 0x2000, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("KP +") PORT_CODE(KEYCODE_PLUS_PAD) PORT_CHAR(UCHAR_MAMEKEY(PLUS_PAD))
- PORT_BIT( 0x4000, IP_ACTIVE_HIGH, IPT_UNUSED )
- PORT_BIT( 0x8000, IP_ACTIVE_HIGH, IPT_UNUSED )
-
- PORT_START("ROW7")
- PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_UNUSED )
- PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_UNUSED )
- PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_UNUSED )
- PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_UNUSED )
- PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_UNUSED )
- PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_UNUSED )
- PORT_BIT( 0x0040, IP_ACTIVE_HIGH, IPT_UNUSED )
- PORT_BIT( 0x0080, IP_ACTIVE_HIGH, IPT_UNUSED )
- PORT_BIT( 0x0100, IP_ACTIVE_HIGH, IPT_UNUSED )
- PORT_BIT( 0x0200, IP_ACTIVE_HIGH, IPT_UNUSED )
- PORT_BIT( 0x0400, IP_ACTIVE_HIGH, IPT_UNUSED )
- PORT_BIT( 0x0800, IP_ACTIVE_HIGH, IPT_UNUSED )
- PORT_BIT( 0x1000, IP_ACTIVE_HIGH, IPT_UNUSED )
- PORT_BIT( 0x2000, IP_ACTIVE_HIGH, IPT_UNUSED )
- PORT_BIT( 0x4000, IP_ACTIVE_HIGH, IPT_UNUSED )
- PORT_BIT( 0x8000, IP_ACTIVE_HIGH, IPT_UNUSED )
-INPUT_PORTS_END
-
-} // anonymous namespace
-
-hle_device::hle_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, SGI_HLE_KEYBOARD, tag, owner, clock)
- , device_buffered_serial_interface(mconfig, *this)
- , device_sgi_keyboard_port_interface(mconfig, *this)
- , device_matrix_keyboard_interface(mconfig, *this, "ROW0", "ROW1", "ROW2", "ROW3", "ROW4", "ROW5", "ROW6", "ROW7")
- , m_click_timer(nullptr)
- , m_beep_timer(nullptr)
- , m_beeper(*this, "beeper")
- , m_leds(*this, "led%u", 0U)
- , m_make_count(0)
- , m_keyclick(true)
- , m_auto_repeat(false)
- , m_beeper_state(0)
- , m_led_state(0)
-{
-}
-
-hle_device::~hle_device()
-{
-}
-
-ioport_constructor hle_device::device_input_ports() const
-{
- return INPUT_PORTS_NAME(hle_device);
-}
-
-WRITE_LINE_MEMBER(hle_device::input_txd)
-{
- device_buffered_serial_interface::rx_w(state);
-}
-
-void hle_device::device_add_mconfig(machine_config &config)
-{
- SPEAKER(config, "bell").front_center();
- BEEP(config, m_beeper, ATTOSECONDS_TO_HZ(480 * ATTOSECONDS_PER_MICROSECOND));
- m_beeper->add_route(ALL_OUTPUTS, "bell", 1.0);
-}
-
-void hle_device::device_start()
-{
- m_leds.resolve();
- m_click_timer = timer_alloc(FUNC(hle_device::click_off), this);
- m_beep_timer = timer_alloc(FUNC(hle_device::beep_off), this);
-
- save_item(NAME(m_make_count));
- save_item(NAME(m_keyclick));
- save_item(NAME(m_auto_repeat));
- save_item(NAME(m_beeper_state));
- save_item(NAME(m_led_state));
-}
-
-void hle_device::device_reset()
-{
- // initialise state
- clear_fifo();
- m_make_count = 0;
- m_keyclick = true;
- m_auto_repeat = false;
- m_beeper_state = 0;
- m_led_state = 0;
-
- // configure device_buffered_serial_interface
- set_data_frame(START_BIT_COUNT, DATA_BIT_COUNT, PARITY, STOP_BITS);
- set_rate(BAUD);
- receive_register_reset();
- transmit_register_reset();
-
- // set device_sgi_keyboard_port_interface lines
- output_rxd(1);
-
- // start with keyboard LEDs off
- m_leds[LED_NUM] = 0;
- m_leds[LED_CAPS] = 0;
- m_leds[LED_SCROLL] = 0;
- m_leds[LED_USER1] = 0;
- m_leds[LED_USER2] = 0;
- m_leds[LED_USER3] = 0;
- m_leds[LED_USER4] = 0;
-
- m_click_timer->adjust(attotime::never);
- m_beep_timer->adjust(attotime::never);
-
- // kick the base
- reset_key_state();
- start_processing(attotime::from_hz(600));
-}
-
-TIMER_CALLBACK_MEMBER(hle_device::click_off)
-{
- m_beeper_state &= ~BEEPER_CLICK;
- m_beeper->set_state(m_beeper_state ? 1 : 0);
-}
-
-TIMER_CALLBACK_MEMBER(hle_device::beep_off)
-{
- m_beeper_state &= ~BEEPER_BELL;
- m_beeper->set_state(m_beeper_state ? 1 : 0);
-}
-
-void hle_device::tra_callback()
-{
- output_rxd(transmit_register_get_data_bit());
-}
-
-void hle_device::tra_complete()
-{
- if (fifo_full())
- start_processing(attotime::from_hz(600));
-
- device_buffered_serial_interface::tra_complete();
-}
-
-void hle_device::key_make(uint8_t row, uint8_t column)
-{
- // we should have stopped processing if we filled the FIFO
- assert(!fifo_full());
-
- // send the make code, click if desired
- transmit_byte((row << 4) | column);
- if (m_keyclick)
- {
- m_beeper_state |= uint8_t(BEEPER_CLICK);
- m_beeper->set_state(m_beeper_state ? 1 : 0);
- m_click_timer->reset(attotime::from_msec(5));
- }
-
- // count keys
- ++m_make_count;
- assert(m_make_count);
-}
-
-void hle_device::key_break(uint8_t row, uint8_t column)
-{
- // we should have stopped processing if we filled the FIFO
- assert(!fifo_full());
- assert(m_make_count);
-
- // send the break code, and the idle code if no other keys are down
- transmit_byte(0x80 | (row << 4) | column);
- if (!--m_make_count)
- transmit_byte(0xf0);
-}
-
-void hle_device::transmit_byte(uint8_t byte)
-{
- device_buffered_serial_interface::transmit_byte(byte);
- if (fifo_full())
- stop_processing();
-}
-
-void hle_device::received_byte(uint8_t byte)
-{
- if (BIT(byte, CTRL_B))
- {
- if (BIT(byte, CTRL_B_CMPL_DS1_2))
- {
- logerror("Not Yet Implemented: Complement DS1/2\n");
- }
-
- if (BIT(byte, CTRL_B_SCRLK))
- {
- logerror("Toggle Scroll Lock LED\n");
- m_led_state ^= (1 << LED_SCROLL);
- m_leds[LED_SCROLL] = BIT(m_led_state, LED_SCROLL);
- }
- if (BIT(byte, CTRL_B_L1))
- {
- logerror("Toggle User LED 1\n");
- m_led_state ^= (1 << LED_USER1);
- m_leds[LED_USER1] = BIT(m_led_state, LED_USER1);
- }
- if (BIT(byte, CTRL_B_L2))
- {
- logerror("Toggle User LED 2\n");
- m_led_state ^= (1 << LED_USER2);
- m_leds[LED_USER2] = BIT(m_led_state, LED_USER2);
- }
- if (BIT(byte, CTRL_B_L3))
- {
- logerror("Toggle User LED 3\n");
- m_led_state ^= (1 << LED_USER3);
- m_leds[LED_USER3] = BIT(m_led_state, LED_USER3);
- }
- if (BIT(byte, CTRL_B_L4))
- {
- logerror("Toggle User LED 4\n");
- m_led_state ^= (1 << LED_USER4);
- m_leds[LED_USER3] = BIT(m_led_state, LED_USER4);
- }
- }
- else
- {
- if (BIT(byte, CTRL_A_SBEEP))
- {
- logerror("Short Beep\n");
- m_beeper_state |= uint8_t(BEEPER_BELL);
- m_beeper->set_state(m_beeper_state ? 1 : 0);
- m_click_timer->adjust(attotime::from_msec(200));
- }
-
- if (BIT(byte, CTRL_A_LBEEP))
- {
- logerror("Long Beep\n");
- m_beeper_state |= uint8_t(BEEPER_BELL);
- m_beeper->set_state(m_beeper_state ? 1 : 0);
- m_click_timer->adjust(attotime::from_msec(1000));
- }
-
- if (BIT(byte, CTRL_A_NOCLICK))
- {
- logerror("Keyclick Off\n");
- m_keyclick = false;
- }
-
- if (BIT(byte, CTRL_A_RCB))
- {
- logerror("Receive Config Byte\n");
- transmit_byte(0x6e);
- transmit_byte(0x00); // US layout
- }
-
- if (BIT(byte, CTRL_A_NUMLK))
- {
- logerror("Toggle Num Lock LED\n");
- m_led_state ^= (1 << LED_NUM);
- m_leds[LED_NUM] = BIT(m_led_state, LED_NUM);
- }
-
- if (BIT(byte, CTRL_A_CAPSLK))
- {
- logerror("Toggle Caps Lock LED\n");
- m_led_state ^= (1 << LED_CAPS);
- m_leds[LED_CAPS] = BIT(m_led_state, LED_CAPS);
- }
-
- if (BIT(byte, CTRL_A_AUTOREP))
- {
- logerror("Toggle Auto Repeat\n");
- m_auto_repeat = !m_auto_repeat;
- }
- }
-}
-
-} // namespace bus::sgikbd
diff --git a/src/devices/bus/sgikbd/hlekbd.h b/src/devices/bus/sgikbd/hlekbd.h
deleted file mode 100644
index ce066e90c55..00000000000
--- a/src/devices/bus/sgikbd/hlekbd.h
+++ /dev/null
@@ -1,113 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Ryan Holtz
-#ifndef DEVICES_BUS_SGIKBD_HLEKBD_H
-#define DEVICES_BUS_SGIKBD_HLEKBD_H
-
-#pragma once
-
-#include "sgikbd.h"
-#include "machine/keyboard.h"
-#include "sound/beep.h"
-#include "diserial.h"
-
-
-namespace bus::sgikbd {
-
-class hle_device : public device_t
- , public device_buffered_serial_interface<16U>
- , public device_sgi_keyboard_port_interface
- , protected device_matrix_keyboard_interface<8U>
-{
-public:
- // constructor/destructor
- hle_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock);
-
- virtual ~hle_device() override;
-
- virtual DECLARE_WRITE_LINE_MEMBER(input_txd) override;
-
-protected:
- // device overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual ioport_constructor device_input_ports() const override;
-
- // device_buffered_serial_interface overrides
- virtual void tra_callback() override;
- virtual void tra_complete() override;
-
- // device_matrix_keyboard_interface overrides
- virtual void key_make(uint8_t row, uint8_t column) override;
- virtual void key_break(uint8_t row, uint8_t column) override;
-
- // customised transmit_byte method
- void transmit_byte(uint8_t byte);
-
- TIMER_CALLBACK_MEMBER(click_off);
- TIMER_CALLBACK_MEMBER(beep_off);
-
-private:
- enum
- {
- LED_NUM,
- LED_CAPS,
- LED_SCROLL,
- LED_USER1,
- LED_USER2,
- LED_USER3,
- LED_USER4
- };
-
- enum
- {
- BEEPER_BELL = 0x01,
- BEEPER_CLICK = 0x02
- };
-
- enum
- {
- RX_IDLE,
- };
-
- enum
- {
- CTRL_A_SBEEP = 1,
- CTRL_A_LBEEP = 2,
- CTRL_A_NOCLICK = 3,
- CTRL_A_RCB = 4,
- CTRL_A_NUMLK = 5,
- CTRL_A_CAPSLK = 6,
- CTRL_A_AUTOREP = 7,
-
- CTRL_B = 0,
- CTRL_B_CMPL_DS1_2 = 1,
- CTRL_B_SCRLK = 2,
- CTRL_B_L1 = 3,
- CTRL_B_L2 = 4,
- CTRL_B_L3 = 5,
- CTRL_B_L4 = 6
- };
-
- // device_buffered_serial_interface overrides
- virtual void received_byte(uint8_t byte) override;
-
- emu_timer *m_click_timer;
- emu_timer *m_beep_timer;
- required_device<beep_device> m_beeper;
- output_finder<7> m_leds;
-
- uint8_t m_make_count;
-
- bool m_keyclick;
- bool m_auto_repeat;
- uint8_t m_beeper_state;
- uint8_t m_led_state;
-};
-
-} // namespace bus::sgikbd
-
-
-DECLARE_DEVICE_TYPE_NS(SGI_HLE_KEYBOARD, bus::sgikbd, hle_device)
-
-#endif // DEVICES_BUS_SGIKBD_HLEKBD_H
diff --git a/src/devices/bus/sgikbd/sgikbd.cpp b/src/devices/bus/sgikbd/sgikbd.cpp
deleted file mode 100644
index 80138f1d7a3..00000000000
--- a/src/devices/bus/sgikbd/sgikbd.cpp
+++ /dev/null
@@ -1,69 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Ryan Holtz
-
-#include "emu.h"
-#include "sgikbd.h"
-
-
-DEFINE_DEVICE_TYPE(SGIKBD_PORT, sgi_keyboard_port_device, "sgikbd", "SGI Keyboard Port")
-
-
-sgi_keyboard_port_device::sgi_keyboard_port_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock)
- : sgi_keyboard_port_device(mconfig, SGIKBD_PORT, tag, owner, clock)
-{
-}
-
-sgi_keyboard_port_device::sgi_keyboard_port_device(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, type, tag, owner, clock)
- , device_single_card_slot_interface<device_sgi_keyboard_port_interface>(mconfig, *this)
- , m_rxd(0)
- , m_rxd_handler(*this)
- , m_dev(nullptr)
-{
-}
-
-sgi_keyboard_port_device::~sgi_keyboard_port_device()
-{
-}
-
-void sgi_keyboard_port_device::device_config_complete()
-{
- m_dev = get_card_device();
-}
-
-void sgi_keyboard_port_device::device_resolve_objects()
-{
- m_rxd_handler.resolve_safe();
-}
-
-void sgi_keyboard_port_device::device_start()
-{
- save_item(NAME(m_rxd));
-
- m_rxd = 1;
- m_rxd_handler(m_rxd);
-}
-
-WRITE_LINE_MEMBER(sgi_keyboard_port_device::write_txd)
-{
- if (m_dev)
- m_dev->input_txd(state);
-}
-
-device_sgi_keyboard_port_interface::device_sgi_keyboard_port_interface(machine_config const &mconfig, device_t &device)
- : device_interface(device, "sgikbd")
- , m_port(dynamic_cast<sgi_keyboard_port_device *>(device.owner()))
-{
-}
-
-device_sgi_keyboard_port_interface::~device_sgi_keyboard_port_interface()
-{
-}
-
-
-#include "hlekbd.h"
-
-void default_sgi_keyboard_devices(device_slot_interface &device)
-{
- device.option_add("hlekbd", SGI_HLE_KEYBOARD);
-}
diff --git a/src/devices/bus/sgikbd/sgikbd.h b/src/devices/bus/sgikbd/sgikbd.h
deleted file mode 100644
index bf64fd34b6a..00000000000
--- a/src/devices/bus/sgikbd/sgikbd.h
+++ /dev/null
@@ -1,81 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Ryan Holtz
-#ifndef DEVICES_BUS_SGIKBD_SGIKBD_H
-#define DEVICES_BUS_SGIKBD_SGIKBD_H
-
-#pragma once
-
-#include "diserial.h"
-
-class device_sgi_keyboard_port_interface;
-
-class sgi_keyboard_port_device : public device_t, public device_single_card_slot_interface<device_sgi_keyboard_port_interface>
-{
- friend class device_sgi_keyboard_port_interface;
-
-public:
- template <typename T>
- sgi_keyboard_port_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts, char const *dflt)
- : sgi_keyboard_port_device(mconfig, tag, owner, 0)
- {
- option_reset();
- opts(*this);
- set_default_option(dflt);
- set_fixed(false);
- }
- sgi_keyboard_port_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock = 0);
- virtual ~sgi_keyboard_port_device();
-
- // configuration helpers
- auto rxd_handler() { return m_rxd_handler.bind(); }
-
- DECLARE_WRITE_LINE_MEMBER( write_txd );
-
- DECLARE_READ_LINE_MEMBER( rxd_r ) { return m_rxd; }
-
-protected:
- sgi_keyboard_port_device(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, uint32_t clock);
-
- virtual void device_config_complete() override;
- virtual void device_resolve_objects() override;
- virtual void device_start() override;
-
- int m_rxd;
-
- devcb_write_line m_rxd_handler;
-
-private:
- device_sgi_keyboard_port_interface *m_dev;
-};
-
-
-class device_sgi_keyboard_port_interface : public device_interface
-{
- friend class sgi_keyboard_port_device;
-
-public:
- virtual ~device_sgi_keyboard_port_interface() override;
-
-protected:
- device_sgi_keyboard_port_interface(machine_config const &mconfig, device_t &device);
-
- virtual DECLARE_WRITE_LINE_MEMBER(input_txd) { }
-
- DECLARE_WRITE_LINE_MEMBER(output_rxd) { m_port->m_rxd = state; m_port->m_rxd_handler(state); }
-
- sgi_keyboard_port_device *m_port;
-
- static constexpr int START_BIT_COUNT = 1;
- static constexpr int DATA_BIT_COUNT = 8;
- static constexpr device_serial_interface::parity_t PARITY = device_serial_interface::PARITY_ODD;
- static constexpr device_serial_interface::stop_bits_t STOP_BITS = device_serial_interface::STOP_BITS_1;
- static constexpr int BAUD = 600;
-};
-
-
-DECLARE_DEVICE_TYPE(SGIKBD_PORT, sgi_keyboard_port_device)
-
-
-void default_sgi_keyboard_devices(device_slot_interface &device);
-
-#endif // DEVICES_BUS_SGIKBD_SGIKBD_H
diff --git a/src/devices/bus/sms_ctrl/controllers.cpp b/src/devices/bus/sms_ctrl/controllers.cpp
new file mode 100644
index 00000000000..77b2925f98e
--- /dev/null
+++ b/src/devices/bus/sms_ctrl/controllers.cpp
@@ -0,0 +1,82 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/**********************************************************************
+
+ Sega 9-pin controllers
+
+ Unemulated Mega Drive peripherals:
+ * Mega Modem (connects to EXP port on Mega Drive)
+ * Sega Menacer (infrared wireless lightgun)
+ * Konami Justifier (dual wired lightguns)
+ * EA 4-Play (impractical - connects to both CTRL1 and CTRL2)
+
+**********************************************************************/
+
+#include "emu.h"
+#include "controllers.h"
+
+#include "diypaddle.h"
+#include "hypershot.h"
+#include "graphic.h"
+#include "joypad.h"
+#include "lphaser.h"
+#include "md6bt.h"
+#include "mdpad.h"
+#include "mouse.h"
+#include "multitap.h"
+#include "paddle.h"
+#include "rfu.h"
+#include "rs232adapt.h"
+#include "sports.h"
+#include "sportsjp.h"
+#include "teamplayer.h"
+#include "xe1ap.h"
+
+
+char const *const SMS_CTRL_OPTION_DIY_PADDLE = "diypaddle";
+char const *const SMS_CTRL_OPTION_HYPERSHOT = "hypershot";
+char const *const SMS_CTRL_OPTION_GRAPHIC = "graphic";
+char const *const SMS_CTRL_OPTION_LPHASER = "lphaser";
+char const *const SMS_CTRL_OPTION_MD_6BUTTON = "md6button";
+char const *const SMS_CTRL_OPTION_MD_PAD = "mdpad";
+char const *const SMS_CTRL_OPTION_MEGA_MOUSE = "mouseus";
+char const *const SMS_CTRL_OPTION_MULTITAP = "multitap";
+char const *const SMS_CTRL_OPTION_JOYPAD = "mspad";
+char const *const SMS_CTRL_OPTION_PADDLE = "paddle";
+char const *const SMS_CTRL_OPTION_RAPID_FIRE = "rapidfire";
+char const *const SMS_CTRL_OPTION_RS232 = "rs232";
+char const *const SMS_CTRL_OPTION_SEGA_MOUSE = "mouse";
+char const *const SMS_CTRL_OPTION_SPORTS = "sports";
+char const *const SMS_CTRL_OPTION_SPORTS_JP = "sportsjp";
+char const *const SMS_CTRL_OPTION_TEAM_PLAYER = "teamplay";
+char const *const SMS_CTRL_OPTION_XE1AP = "xe1ap";
+
+
+
+void sms_control_port_devices(device_slot_interface &device)
+{
+ device.option_add(SMS_CTRL_OPTION_DIY_PADDLE, SMS_DIY_PADDLE);
+ device.option_add(SMS_CTRL_OPTION_HYPERSHOT, SMS_HYPERSHOT);
+ device.option_add(SMS_CTRL_OPTION_GRAPHIC, SMS_GRAPHIC);
+ device.option_add(SMS_CTRL_OPTION_LPHASER, SMS_LIGHT_PHASER);
+ device.option_add(SMS_CTRL_OPTION_MD_6BUTTON, SMS_MD6BUTTON);
+ device.option_add(SMS_CTRL_OPTION_MD_PAD, SMS_MDPAD);
+ device.option_add(SMS_CTRL_OPTION_MEGA_MOUSE, SMS_MEGAMOUSE);
+ device.option_add(SMS_CTRL_OPTION_MULTITAP, SMS_MULTITAP);
+ device.option_add(SMS_CTRL_OPTION_JOYPAD, SMS_JOYPAD);
+ device.option_add(SMS_CTRL_OPTION_PADDLE, SMS_PADDLE);
+ device.option_add(SMS_CTRL_OPTION_RAPID_FIRE, SMS_RAPID_FIRE);
+ device.option_add(SMS_CTRL_OPTION_RS232, SMS_RS232);
+ device.option_add(SMS_CTRL_OPTION_SEGA_MOUSE, SMS_SEGAMOUSE);
+ device.option_add(SMS_CTRL_OPTION_SPORTS, SMS_SPORTS_PAD);
+ device.option_add(SMS_CTRL_OPTION_SPORTS_JP, SMS_SPORTS_PAD_JP);
+ device.option_add(SMS_CTRL_OPTION_TEAM_PLAYER, SMS_TEAM_PLAYER);
+ device.option_add(SMS_CTRL_OPTION_XE1AP, SMS_XE1AP);
+}
+
+
+void sms_control_port_passive_devices(device_slot_interface &device)
+{
+ device.option_add(SMS_CTRL_OPTION_HYPERSHOT, SMS_HYPERSHOT);
+ device.option_add(SMS_CTRL_OPTION_JOYPAD, SMS_JOYPAD);
+}
diff --git a/src/devices/bus/sms_ctrl/controllers.h b/src/devices/bus/sms_ctrl/controllers.h
new file mode 100644
index 00000000000..a6cdbc14ed8
--- /dev/null
+++ b/src/devices/bus/sms_ctrl/controllers.h
@@ -0,0 +1,35 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/**********************************************************************
+
+ Sega 9-pin controllers
+
+**********************************************************************/
+#ifndef MAME_BUS_SMS_CTRL_CONTROLLERS_H
+#define MAME_BUS_SMS_CTRL_CONTROLLERS_H
+
+#pragma once
+
+
+extern char const *const SMS_CTRL_OPTION_DIY_PADDLE;
+extern char const *const SMS_CTRL_OPTION_HYPERSHOT;
+extern char const *const SMS_CTRL_OPTION_GRAPHIC;
+extern char const *const SMS_CTRL_OPTION_LPHASER;
+extern char const *const SMS_CTRL_OPTION_MD_6BUTTON;
+extern char const *const SMS_CTRL_OPTION_MD_PAD;
+extern char const *const SMS_CTRL_OPTION_MEGA_MOUSE;
+extern char const *const SMS_CTRL_OPTION_MULTITAP;
+extern char const *const SMS_CTRL_OPTION_JOYPAD;
+extern char const *const SMS_CTRL_OPTION_PADDLE;
+extern char const *const SMS_CTRL_OPTION_RAPID_FIRE;
+extern char const *const SMS_CTRL_OPTION_RS232;
+extern char const *const SMS_CTRL_OPTION_SEGA_MOUSE;
+extern char const *const SMS_CTRL_OPTION_SPORTS;
+extern char const *const SMS_CTRL_OPTION_SPORTS_JP;
+extern char const *const SMS_CTRL_OPTION_TEAM_PLAYER;
+extern char const *const SMS_CTRL_OPTION_XE1AP;
+
+void sms_control_port_devices(device_slot_interface &device);
+void sms_control_port_passive_devices(device_slot_interface &device);
+
+#endif // MAME_BUS_SMS_CTRL_CONTROLLERS_H
diff --git a/src/devices/bus/sms_ctrl/diypaddle.cpp b/src/devices/bus/sms_ctrl/diypaddle.cpp
new file mode 100644
index 00000000000..e84b8e9212b
--- /dev/null
+++ b/src/devices/bus/sms_ctrl/diypaddle.cpp
@@ -0,0 +1,227 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/**********************************************************************
+
+ Raphaël Assenat's DIY SMS/Mark III Paddle Controller
+
+ English description:
+ https://www.raphnet.net/electronique/sms_paddle/index_en.php
+
+ French description:
+ https://www.raphnet.net/electronique/sms_paddle/index.php
+
+ Firmware source:
+ https://github.com/raphnet/sms_paddle
+
+ TODO:
+ * Add ATmega8 variant - need CPU core.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "diypaddle.h"
+
+#include "cpu/avr8/avr8.h"
+
+
+namespace {
+
+ROM_START( sms_diy_paddle )
+ ROM_REGION(0x4000, "u1", ROMREGION_ERASEFF)
+ ROM_LOAD( "sms_paddle.bin", 0x0000, 0x0138, CRC(97c7d334) SHA1(dd9e20f2447c43dbe29a49bb3a4fd8049775acd3) )
+
+ ROM_REGION(0x200, "eeprom", ROMREGION_ERASEFF)
+ROM_END
+
+
+INPUT_PORTS_START( sms_diy_paddle )
+ PORT_START("BUTTON")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 )
+
+ PORT_START("PADDLE")
+ PORT_BIT( 0x3ff, 0x200, IPT_PADDLE) PORT_MINMAX(0, 1023) PORT_REVERSE PORT_SENSITIVITY(160) PORT_KEYDELTA(20) PORT_CENTERDELTA(0)
+
+ PORT_START("MODE")
+ PORT_CONFNAME( 0x01, 0x00, "Mode" )
+ PORT_CONFSETTING( 0x00, "HPD-200" )
+ PORT_CONFSETTING( 0x01, "Export paddle" )
+INPUT_PORTS_END
+
+
+
+class sms_diy_paddle_device : public device_t, public device_sms_control_interface
+{
+public:
+ sms_diy_paddle_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+ virtual u8 in_r() override;
+ virtual void out_w(u8 data, u8 mem_mask) override;
+
+protected:
+ virtual tiny_rom_entry const *device_rom_region() const override { return ROM_NAME(sms_diy_paddle); }
+ virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(sms_diy_paddle); }
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_start() override;
+
+private:
+ void program_map(address_map &map);
+ void data_map(address_map &map);
+
+ u8 portb_in();
+ u8 portc_in();
+ u8 portd_in();
+ void portb_out(u8 data);
+ void portc_out(u8 data);
+
+ TIMER_CALLBACK_MEMBER(set_lines);
+ TIMER_CALLBACK_MEMBER(set_portd);
+
+ required_device<atmega168_device> m_mcu;
+ required_ioport m_button;
+ required_ioport m_paddle;
+ required_ioport m_mode;
+
+ u8 m_lines;
+ u8 m_portb;
+ u8 m_portc;
+ u8 m_portd;
+};
+
+
+sms_diy_paddle_device::sms_diy_paddle_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) :
+ device_t(mconfig, SMS_DIY_PADDLE, tag, owner, clock),
+ device_sms_control_interface(mconfig, *this),
+ m_mcu(*this, "u1"),
+ m_button(*this, "BUTTON"),
+ m_paddle(*this, "PADDLE"),
+ m_mode(*this, "MODE"),
+ m_lines(0x2f),
+ m_portb(0xff),
+ m_portc(0xff),
+ m_portd(0xff)
+{
+}
+
+
+u8 sms_diy_paddle_device::in_r()
+{
+ if (!machine().side_effects_disabled())
+ machine().scheduler().add_quantum(attotime::from_usec(5), attotime::from_usec(100));
+
+ // button connected to TL directly
+ return m_lines | (BIT(m_button->read(), 0) << 4);
+}
+
+
+void sms_diy_paddle_device::out_w(u8 data, u8 mem_mask)
+{
+ // TH connected to PD2
+ machine().scheduler().synchronize(
+ timer_expired_delegate(FUNC(sms_diy_paddle_device::set_portd), this),
+ 0xfb | (BIT(data, 6) << 2));
+ machine().scheduler().add_quantum(attotime::from_usec(1), attotime::from_usec(20));
+}
+
+
+void sms_diy_paddle_device::device_add_mconfig(machine_config &config)
+{
+ ATMEGA168(config, m_mcu, 8'000'000); // internally-generated clock
+ m_mcu->set_addrmap(AS_PROGRAM, &sms_diy_paddle_device::program_map);
+ m_mcu->set_addrmap(AS_DATA, &sms_diy_paddle_device::data_map);
+ m_mcu->set_eeprom_tag("eeprom");
+ m_mcu->set_low_fuses(0xe2);
+ m_mcu->set_high_fuses(0xdd);
+ m_mcu->set_extended_fuses(0xf9);
+ m_mcu->gpio_in<atmega168_device::GPIOB>().set(FUNC(sms_diy_paddle_device::portb_in));
+ m_mcu->gpio_in<atmega168_device::GPIOC>().set(FUNC(sms_diy_paddle_device::portc_in));
+ m_mcu->gpio_in<atmega168_device::GPIOD>().set(FUNC(sms_diy_paddle_device::portd_in));
+ m_mcu->gpio_out<atmega168_device::GPIOB>().set(FUNC(sms_diy_paddle_device::portb_out));
+ m_mcu->gpio_out<atmega168_device::GPIOC>().set(FUNC(sms_diy_paddle_device::portc_out));
+ m_mcu->adc_in<atmega168_device::ADC0>().set_ioport("PADDLE");
+}
+
+
+void sms_diy_paddle_device::device_start()
+{
+ m_lines = 0x2f;
+ m_portb = 0xff;
+ m_portc = 0xff;
+ m_portd = 0xff;
+
+ save_item(NAME(m_lines));
+ save_item(NAME(m_portb));
+ save_item(NAME(m_portc));
+ save_item(NAME(m_portd));
+}
+
+
+void sms_diy_paddle_device::program_map(address_map &map)
+{
+ map(0x0000, 0x3fff).rom();
+}
+
+
+void sms_diy_paddle_device::data_map(address_map &map)
+{
+ map(0x0100, 0x04ff).ram();
+}
+
+
+u8 sms_diy_paddle_device::portb_in()
+{
+ // PB0 looped back to PB1 via mode switch
+ if (BIT(m_mode->read(), 0))
+ return 0xfc | bitswap<2>(m_portb, 0, 0);
+ else
+ return 0xfe | BIT(m_portb, 0);
+}
+
+
+u8 sms_diy_paddle_device::portc_in()
+{
+ return (m_portc & 0x3e) | 0xc0 | ((m_paddle->read() > 0x1ff) ? 0x01 : 0x00);
+}
+
+
+u8 sms_diy_paddle_device::portd_in()
+{
+ return m_portd;
+}
+
+
+void sms_diy_paddle_device::portb_out(u8 data)
+{
+ m_portb = data;
+}
+
+
+void sms_diy_paddle_device::portc_out(u8 data)
+{
+ // PC1 -> TR, PC2 -> Up, PC3 -> Down, PC4 -> Left, PC5 -> Right
+ if (data != m_portc)
+ {
+ m_portc = data;
+ machine().scheduler().synchronize(
+ timer_expired_delegate(FUNC(sms_diy_paddle_device::set_lines), this),
+ (BIT(data, 1) << 5) | BIT(data, 2, 4));
+ machine().scheduler().add_quantum(attotime::from_usec(1), attotime::from_usec(20));
+ }
+}
+
+
+TIMER_CALLBACK_MEMBER(sms_diy_paddle_device::set_lines)
+{
+ m_lines = param & 0x2f;
+}
+
+
+TIMER_CALLBACK_MEMBER(sms_diy_paddle_device::set_portd)
+{
+ m_portd = param & 0xff;
+}
+
+} // anonymous namespace
+
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(SMS_DIY_PADDLE, device_sms_control_interface, sms_diy_paddle_device, "sms_diypaddle", "raphnet DIY SMS/Mark III Paddle Controller")
diff --git a/src/devices/bus/sms_ctrl/diypaddle.h b/src/devices/bus/sms_ctrl/diypaddle.h
new file mode 100644
index 00000000000..75a3ef4514f
--- /dev/null
+++ b/src/devices/bus/sms_ctrl/diypaddle.h
@@ -0,0 +1,18 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/**********************************************************************
+
+ Raphaël Assenat's DIY SMS/Mark III Paddle Controller
+
+**********************************************************************/
+#ifndef MAME_BUS_SMS_CTRL_DIYPADDLE_H
+#define MAME_BUS_SMS_CTRL_DIYPADDLE_H
+
+#pragma once
+
+#include "smsctrl.h"
+
+
+DECLARE_DEVICE_TYPE(SMS_DIY_PADDLE, device_sms_control_interface)
+
+#endif // MAME_BUS_SMS_CTRL_DIYPADDLE_H
diff --git a/src/devices/bus/sms_ctrl/graphic.cpp b/src/devices/bus/sms_ctrl/graphic.cpp
index 1ada76748e7..c2ea024ebf2 100644
--- a/src/devices/bus/sms_ctrl/graphic.cpp
+++ b/src/devices/bus/sms_ctrl/graphic.cpp
@@ -36,55 +36,69 @@ Then 2 nibbles are read to form a byte containing the absolute Y coordiante.
#include "graphic.h"
-
-//**************************************************************************
-// DEVICE DEFINITIONS
-//**************************************************************************
-
-DEFINE_DEVICE_TYPE(SMS_GRAPHIC, sms_graphic_device, "sms_graphic", "Sega SMS Graphic Board")
-
+namespace {
static INPUT_PORTS_START( sms_graphic )
PORT_START("BUTTONS")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 ) // MENU
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON2 ) // DO
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON3 ) // PEN
- PORT_BIT( 0xf8, IP_ACTIVE_LOW, IPT_UNUSED )
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_UNKNOWN ) // some kind of ready signal?
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_TOGGLE PORT_NAME("%p Pen") // pretend pen pressure is all-or-nothing
PORT_START("X")
- PORT_BIT( 0xff, 0x00, IPT_LIGHTGUN_X) PORT_CROSSHAIR(X, 1.0, 0.0, 0) PORT_SENSITIVITY(50) PORT_KEYDELTA(15)
+ PORT_BIT( 0xff, 0x00, IPT_LIGHTGUN_X) PORT_CROSSHAIR(X, 254 / 268.0, 6 / 268.0, 0) PORT_SENSITIVITY(50) PORT_KEYDELTA(1)
PORT_START("Y")
- PORT_BIT( 0xff, 0x00, IPT_LIGHTGUN_Y) PORT_CROSSHAIR(Y, 1.0, 0.0, 0) PORT_SENSITIVITY(50) PORT_KEYDELTA(15)
+ PORT_BIT( 0xff, 0x00, IPT_LIGHTGUN_Y) PORT_CROSSHAIR(Y, 255 / 224.0, -19 / 224.0, 0) PORT_SENSITIVITY(50) PORT_KEYDELTA(1)
INPUT_PORTS_END
-//-------------------------------------------------
-// input_ports - device-specific input ports
-//-------------------------------------------------
-
-ioport_constructor sms_graphic_device::device_input_ports() const
-{
- return INPUT_PORTS_NAME( sms_graphic );
-}
//**************************************************************************
-// LIVE DEVICE
+// TYPE DEFINITIONS
//**************************************************************************
+class sms_graphic_device : public device_t, public device_sms_control_interface
+{
+public:
+ // construction/destruction
+ sms_graphic_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ // device_sms_control_interface implementation
+ virtual uint8_t in_r() override;
+ virtual void out_w(uint8_t data, uint8_t mem_mask) override;
+
+protected:
+ // device_t implementation
+ virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(sms_graphic); }
+ virtual void device_start() override;
+
+private:
+ required_ioport m_buttons;
+ required_ioport m_x_axis;
+ required_ioport m_y_axis;
+
+ uint8_t m_phase;
+ uint8_t m_select;
+ uint8_t m_data;
+};
+
+
//-------------------------------------------------
// sms_graphic_device - constructor
//-------------------------------------------------
-sms_graphic_device::sms_graphic_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, SMS_GRAPHIC, tag, owner, clock)
- , device_sms_control_port_interface(mconfig, *this)
- , m_buttons(*this, "BUTTONS")
- , m_x(*this, "X")
- , m_y(*this, "Y")
- , m_index(0)
- , m_previous_write(0xff)
- , m_pressure(0xfd)
+sms_graphic_device::sms_graphic_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, SMS_GRAPHIC, tag, owner, clock),
+ device_sms_control_interface(mconfig, *this),
+ m_buttons(*this, "BUTTONS"),
+ m_x_axis(*this, "X"),
+ m_y_axis(*this, "Y"),
+ m_phase(0),
+ m_select(0x7f),
+ m_data(0xff)
{
}
@@ -95,8 +109,12 @@ sms_graphic_device::sms_graphic_device(const machine_config &mconfig, const char
void sms_graphic_device::device_start()
{
- save_item(NAME(m_index));
- save_item(NAME(m_previous_write));
+ m_phase = 0;
+ m_data = 0xff;
+
+ save_item(NAME(m_phase));
+ save_item(NAME(m_select));
+ save_item(NAME(m_data));
}
@@ -104,54 +122,55 @@ void sms_graphic_device::device_start()
// sms_peripheral_r - joypad read
//-------------------------------------------------
-uint8_t sms_graphic_device::peripheral_r()
+uint8_t sms_graphic_device::in_r()
{
- switch (m_index)
- {
- case 0: // Initial state / "I am a board"
- // If any regular button is pressed raise/lower TL ?
-// if ((m_buttons->read() & 0x07) != 0x07)
-// return 0xf0;
- return 0xd0;
-
- case 1: // Read buttons (active low)
- return m_buttons->read();
-
- case 2: // Some thing only FD, FE, and FF cause the other values to be read
- return m_pressure >> 4;
-
- case 3:
- return m_pressure & 0x0f;
-
- case 4: // High nibble X?
- return m_x->read() >> 4;
-
- case 5: // Low nibble X?
- return m_x->read() & 0x0f;
-
- case 6: // High nibble Y?
- return m_y->read() >> 4;
-
- case 7: // Low Nibble Y?
- return m_y->read() & 0x0f;
- }
-
- return 0xff;
+ if (BIT(m_select, 5))
+ return 0x20; // low four bits must be low to recognise Graphic Board, TL is a kind of active-low ready flag
+ else if (m_phase)
+ return BIT(m_data, BIT(m_select, 6) ? 0 : 4, 4) | 0x30;
+ else
+ return (m_buttons->read() & 0x1f) | 0x20;
}
-void sms_graphic_device::peripheral_w(uint8_t data)
+
+void sms_graphic_device::out_w(uint8_t data, uint8_t mem_mask)
{
- // Check for toggle on TH/TL
- if ((data ^ m_previous_write) & 0xc0)
+ if (BIT(data, 5))
{
- m_index++;
+ // TR high - deselected
+ m_phase = 0;
}
-
- // If TR is high, restart
- if (data & 0x80)
+ else if (!BIT(m_select, 5) && BIT(m_select, 6) && !BIT(data, 6))
{
- m_index = 0;
+ // negative edge on TH seems to trigger acquisition
+ switch (m_phase)
+ {
+ case 0:
+ m_data = BIT(m_buttons->read(), 5) ? 0xfe : 0x00; // values made up to satisfy software
+ m_phase = 1;
+ break;
+ case 1:
+ m_data = m_x_axis->read();
+ m_phase = 2;
+ break;
+ case 2:
+ m_data = m_y_axis->read();
+ m_phase = 3;
+ break;
+ default:
+ break; // TODO: what actually happens if you keep clocking TH?
+ }
}
- m_previous_write = data;
+ m_select = data;
}
+
+} // anonymous namespace
+
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(SMS_GRAPHIC, device_sms_control_interface, sms_graphic_device, "sms_graphic", "Sega Master System Graphic Board")
diff --git a/src/devices/bus/sms_ctrl/graphic.h b/src/devices/bus/sms_ctrl/graphic.h
index 036f4660033..b186dc2367f 100644
--- a/src/devices/bus/sms_ctrl/graphic.h
+++ b/src/devices/bus/sms_ctrl/graphic.h
@@ -5,54 +5,14 @@
Sega Master System "Graphic Board" emulation
**********************************************************************/
-
#ifndef MAME_BUS_SMS_CTRL_GRAPHIC_H
#define MAME_BUS_SMS_CTRL_GRAPHIC_H
#pragma once
-
#include "smsctrl.h"
-
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-// ======================> sms_graphic_device
-
-class sms_graphic_device : public device_t,
- public device_sms_control_port_interface
-{
-public:
- // construction/destruction
- sms_graphic_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- // optional information overrides
- virtual ioport_constructor device_input_ports() const override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
-
- // device_sms_control_port_interface overrides
- virtual uint8_t peripheral_r() override;
- virtual void peripheral_w(uint8_t data) override;
-
-private:
- required_ioport m_buttons;
- required_ioport m_x;
- required_ioport m_y;
-
- int m_index;
- uint8_t m_previous_write;
- uint8_t m_pressure;
-};
-
-
-// device type definition
-DECLARE_DEVICE_TYPE(SMS_GRAPHIC, sms_graphic_device)
-
+DECLARE_DEVICE_TYPE(SMS_GRAPHIC, device_sms_control_interface)
#endif // MAME_BUS_SMS_CTRL_GRAPHIC_H
diff --git a/src/devices/bus/sms_ctrl/hypershot.cpp b/src/devices/bus/sms_ctrl/hypershot.cpp
new file mode 100644
index 00000000000..53356eed2a9
--- /dev/null
+++ b/src/devices/bus/sms_ctrl/hypershot.cpp
@@ -0,0 +1,66 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/**********************************************************************
+
+ Konami JE 502/JE 503 Hyper Shot emulation
+
+ Very simple controller with two buttons. RUN is connected to
+ both right and down, and JUMP is connected to TL. Symmetrical
+ case allows use with either button to the left.
+
+ Known versions:
+ * JE 502 original Japanese version, metal case
+ * JE 503 cost-reduced Japanese version, plastic case
+ * JE 503-X02 cost-reduced export version, plastic case
+
+**********************************************************************/
+
+#include "emu.h"
+#include "hypershot.h"
+
+
+namespace {
+
+INPUT_PORTS_START( sms_hypershot )
+ PORT_START("BUTTONS")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_BUTTON2) PORT_NAME("%p Run")
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_NAME("%p Jump")
+INPUT_PORTS_END
+
+
+
+class sms_hypershot_device : public device_t, public device_sms_control_interface
+{
+public:
+ sms_hypershot_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+ virtual u8 in_r() override;
+
+protected:
+ virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(sms_hypershot); }
+ virtual void device_start() override { }
+
+private:
+ required_ioport m_buttons;
+};
+
+
+sms_hypershot_device::sms_hypershot_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) :
+ device_t(mconfig, SMS_HYPERSHOT, tag, owner, clock),
+ device_sms_control_interface(mconfig, *this),
+ m_buttons(*this, "BUTTONS")
+{
+}
+
+
+u8 sms_hypershot_device::in_r()
+{
+ u8 const inputs = m_buttons->read();
+ return 0x25 | (BIT(inputs, 1) << 4) | (BIT(inputs, 0) ? 0x0a : 0x00);
+}
+
+} // anonymous namespace
+
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(SMS_HYPERSHOT, device_sms_control_interface, sms_hypershot_device, "sms_hypershot", "Konami Hyper Shot (JE 502/JE 503, Sega)")
diff --git a/src/devices/bus/sms_ctrl/hypershot.h b/src/devices/bus/sms_ctrl/hypershot.h
new file mode 100644
index 00000000000..f6ee4131131
--- /dev/null
+++ b/src/devices/bus/sms_ctrl/hypershot.h
@@ -0,0 +1,18 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/**********************************************************************
+
+ Konami JE 502/JE 503 Hyper Shot emulation
+
+**********************************************************************/
+#ifndef MAME_BUS_SMS_CTRL_HYPERSHOT_H
+#define MAME_BUS_SMS_CTRL_HYPERSHOT_H
+
+#pragma once
+
+#include "smsctrl.h"
+
+
+DECLARE_DEVICE_TYPE(SMS_HYPERSHOT, device_sms_control_interface)
+
+#endif // MAME_BUS_SMS_CTRL_HYPERSHOT_H
diff --git a/src/devices/bus/sms_ctrl/joypad.cpp b/src/devices/bus/sms_ctrl/joypad.cpp
index 4cd664a952e..ac33fdf8b80 100644
--- a/src/devices/bus/sms_ctrl/joypad.cpp
+++ b/src/devices/bus/sms_ctrl/joypad.cpp
@@ -25,41 +25,42 @@ Release data from the Sega Retro project:
#include "joypad.h"
+namespace {
-//**************************************************************************
-// DEVICE DEFINITIONS
-//**************************************************************************
-
-DEFINE_DEVICE_TYPE(SMS_JOYPAD, sms_joypad_device, "sms_joypad", "Sega SMS Control Pad")
-
-
-static INPUT_PORTS_START( sms_joypad )
+INPUT_PORTS_START( sms_joypad )
PORT_START("JOYPAD")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY
- PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED ) // Vcc
- PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 ) // TL
- PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED ) // TH
- PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON2 ) // TR
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) // TL
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON2 ) // TR
INPUT_PORTS_END
-//-------------------------------------------------
-// input_ports - device-specific input ports
-//-------------------------------------------------
-ioport_constructor sms_joypad_device::device_input_ports() const
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class sms_joypad_device : public device_t, public device_sms_control_interface
{
- return INPUT_PORTS_NAME( sms_joypad );
-}
+public:
+ // construction/destruction
+ sms_joypad_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ // device_sms_control_interface implementation
+ virtual uint8_t in_r() override { return m_joypad->read(); }
+protected:
+ // device_t implementation
+ virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(sms_joypad); }
+ virtual void device_start() override { }
+
+private:
+ required_ioport m_joypad;
+};
-//**************************************************************************
-// LIVE DEVICE
-//**************************************************************************
//-------------------------------------------------
// sms_joypad_device - constructor
@@ -67,26 +68,17 @@ ioport_constructor sms_joypad_device::device_input_ports() const
sms_joypad_device::sms_joypad_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, SMS_JOYPAD, tag, owner, clock),
- device_sms_control_port_interface(mconfig, *this),
+ device_sms_control_interface(mconfig, *this),
m_joypad(*this, "JOYPAD")
{
}
+} // anonymous namespace
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-
-void sms_joypad_device::device_start()
-{
-}
-//-------------------------------------------------
-// sms_peripheral_r - joypad read
-//-------------------------------------------------
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
-uint8_t sms_joypad_device::peripheral_r()
-{
- return m_joypad->read();
-}
+DEFINE_DEVICE_TYPE_PRIVATE(SMS_JOYPAD, device_sms_control_interface, sms_joypad_device, "sms_joypad", "Sega Master System Control Pad")
diff --git a/src/devices/bus/sms_ctrl/joypad.h b/src/devices/bus/sms_ctrl/joypad.h
index 60b4fe9f4c0..a711b86b11d 100644
--- a/src/devices/bus/sms_ctrl/joypad.h
+++ b/src/devices/bus/sms_ctrl/joypad.h
@@ -5,47 +5,14 @@
Sega Mark III "Joypad" / Master System "Control Pad" emulation
**********************************************************************/
-
#ifndef MAME_BUS_SMS_CTRL_JOYPAD_H
#define MAME_BUS_SMS_CTRL_JOYPAD_H
#pragma once
-
#include "smsctrl.h"
-
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-// ======================> sms_joypad_device
-
-class sms_joypad_device : public device_t,
- public device_sms_control_port_interface
-{
-public:
- // construction/destruction
- sms_joypad_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- // optional information overrides
- virtual ioport_constructor device_input_ports() const override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
-
- // device_sms_control_port_interface overrides
- virtual uint8_t peripheral_r() override;
-
-private:
- required_ioport m_joypad;
-};
-
-
-// device type definition
-DECLARE_DEVICE_TYPE(SMS_JOYPAD, sms_joypad_device)
-
+DECLARE_DEVICE_TYPE(SMS_JOYPAD, device_sms_control_interface)
#endif // MAME_BUS_SMS_CTRL_JOYPAD_H
diff --git a/src/devices/bus/sms_ctrl/lphaser.cpp b/src/devices/bus/sms_ctrl/lphaser.cpp
index 7e64e7c7236..dd518c1c5e1 100644
--- a/src/devices/bus/sms_ctrl/lphaser.cpp
+++ b/src/devices/bus/sms_ctrl/lphaser.cpp
@@ -19,43 +19,57 @@ Notes:
**********************************************************************/
#include "emu.h"
-#include "screen.h"
#include "lphaser.h"
+#include "screen.h"
+
+//#define VERBOSE 1
+#include "logmacro.h"
+namespace {
+
//**************************************************************************
-// DEVICE DEFINITIONS
+// TYPE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(SMS_LIGHT_PHASER, sms_light_phaser_device, "sms_light_phaser", "Sega SMS Light Phaser")
+class sms_light_phaser_device : public device_t, public device_sms_control_interface
+{
+public:
+ // construction/destruction
+ sms_light_phaser_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ DECLARE_INPUT_CHANGED_MEMBER(position_changed) { sensor_check(0); }
-#define LGUN_RADIUS 6
-#define LGUN_X_INTERVAL 4
+ // device_sms_control_interface implementation
+ virtual uint8_t in_r() override { return m_trigger->read(); }
+protected:
+ // device_t implementation
+ virtual ioport_constructor device_input_ports() const override;
+ virtual void device_start() override;
+ virtual void device_reset() override;
-READ_LINE_MEMBER( sms_light_phaser_device::th_pin_r )
-{
- // The returned value is inverted due to IP_ACTIVE_LOW mapping.
- return ~m_sensor_last_state;
-}
+private:
+ required_ioport m_trigger;
+ required_ioport m_x_axis;
+ required_ioport m_y_axis;
+ emu_timer *m_update_timer;
-INPUT_CHANGED_MEMBER( sms_light_phaser_device::position_changed )
-{
- if (newval != oldval)
- {
- sensor_check(0);
- }
-}
+ int m_sensor_last_state;
+
+ TIMER_CALLBACK_MEMBER(sensor_check);
+ int bright_aim_area(int lgun_x, int lgun_y );
+ uint16_t screen_hpos_nonscaled(int scaled_hpos);
+ uint16_t screen_vpos_nonscaled(int scaled_vpos);
+};
-static INPUT_PORTS_START( sms_light_phaser )
- PORT_START("CTRL_PORT")
- PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 ) // TL (trigger)
- PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_CUSTOM ) PORT_READ_LINE_DEVICE_MEMBER(DEVICE_SELF, sms_light_phaser_device, th_pin_r)
- PORT_BIT( 0x9f, IP_ACTIVE_LOW, IPT_UNUSED )
+INPUT_PORTS_START(sms_light_phaser)
+ PORT_START("LPHASER_T")
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) // TL (trigger)
+ PORT_BIT( 0x2f, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_START("LPHASER_X")
PORT_BIT( 0xff, 0x00, IPT_LIGHTGUN_X) PORT_CROSSHAIR(X, 1.0, 0.0, 0) PORT_SENSITIVITY(50) PORT_KEYDELTA(15) PORT_CHANGED_MEMBER(DEVICE_SELF, sms_light_phaser_device, position_changed, 0)
@@ -71,27 +85,22 @@ INPUT_PORTS_END
ioport_constructor sms_light_phaser_device::device_input_ports() const
{
- return INPUT_PORTS_NAME( sms_light_phaser );
+ return INPUT_PORTS_NAME(sms_light_phaser);
}
-
-//**************************************************************************
-// LIVE DEVICE
-//**************************************************************************
-
//-------------------------------------------------
// sms_light_phaser_device - constructor
//-------------------------------------------------
sms_light_phaser_device::sms_light_phaser_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, SMS_LIGHT_PHASER, tag, owner, clock),
- device_sms_control_port_interface(mconfig, *this),
- m_lphaser_pins(*this, "CTRL_PORT"),
- m_lphaser_x(*this, "LPHASER_X"),
- m_lphaser_y(*this, "LPHASER_Y"),
- m_sensor_last_state(0),
- m_lphaser_timer(nullptr)
+ device_sms_control_interface(mconfig, *this),
+ m_trigger(*this, "LPHASER_T"),
+ m_x_axis(*this, "LPHASER_X"),
+ m_y_axis(*this, "LPHASER_Y"),
+ m_update_timer(nullptr),
+ m_sensor_last_state(0)
{
}
@@ -102,24 +111,17 @@ sms_light_phaser_device::sms_light_phaser_device(const machine_config &mconfig,
void sms_light_phaser_device::device_start()
{
- save_item(NAME(m_sensor_last_state));
- m_lphaser_timer = timer_alloc(FUNC(sms_light_phaser_device::sensor_check), this);
-}
+ m_update_timer = timer_alloc(FUNC(sms_light_phaser_device::sensor_check), this);
+ m_sensor_last_state = 1;
-void sms_light_phaser_device::device_reset()
-{
- m_sensor_last_state = 1; // off (1)
+ save_item(NAME(m_sensor_last_state));
}
-//-------------------------------------------------
-// sms_peripheral_r - light phaser read
-//-------------------------------------------------
-
-uint8_t sms_light_phaser_device::peripheral_r()
+void sms_light_phaser_device::device_reset()
{
- return m_lphaser_pins->read();
+ // TODO: sensor check now? The device itself doesn't respond to system reset
}
@@ -148,13 +150,21 @@ uint8_t sms_light_phaser_device::peripheral_r()
*/
int sms_light_phaser_device::bright_aim_area(int lgun_x, int lgun_y)
{
+
+ constexpr int LGUN_RADIUS = 6;
+ constexpr int LGUN_X_INTERVAL = 4;
+
+ // brightness of the lightgray color in the frame drawn by Light Phaser games
+ constexpr uint8_t SENSOR_MIN_BRIGHTNESS = 0x7f;
+
+ screen_device &scr(*screen());
const int r_x_r = LGUN_RADIUS * LGUN_RADIUS;
- const rectangle &visarea = m_port->m_screen->visible_area();
+ const rectangle &visarea = scr.visible_area();
rectangle aim_area;
- int beam_x = m_port->m_screen->hpos();
- int beam_y = m_port->m_screen->vpos();
- int beam_x_orig = beam_x;
- int beam_y_orig = beam_y;
+ int beam_x = scr.hpos();
+ int beam_y = scr.vpos();
+ const int beam_x_orig = beam_x;
+ const int beam_y_orig = beam_y;
int result = 1;
bool new_check_point = false;
@@ -163,16 +173,14 @@ int sms_light_phaser_device::bright_aim_area(int lgun_x, int lgun_y)
while (!new_check_point)
{
- /* If beam's y doesn't point to a line where the aim area is,
- change it to the first line where the beam enters that area. */
+ // If beam's y doesn't point to a line where the aim area is, change it to the first line where the beam enters that area.
if (beam_y < aim_area.min_y || beam_y > aim_area.max_y)
{
beam_y = aim_area.min_y;
}
int dy = abs(beam_y - lgun_y);
- /* Caculate distance in x of the radius, relative to beam's y distance.
- First try some shortcuts. */
+ // Calculate distance in x of the radius, relative to beam's y distance. First try some shortcuts.
double dx_radius = 0;
if (dy == 0)
{
@@ -180,9 +188,9 @@ int sms_light_phaser_device::bright_aim_area(int lgun_x, int lgun_y)
}
else if (dy != LGUN_RADIUS)
{
- /* step 1: r^2 = dx^2 + dy^2 */
- /* step 2: dx^2 = r^2 - dy^2 */
- /* step 3: dx = sqrt(r^2 - dy^2) */
+ // step 1: r^2 = dx^2 + dy^2
+ // step 2: dx^2 = r^2 - dy^2
+ // step 3: dx = sqrt(r^2 - dy^2)
dx_radius = ceil(sqrt(double(r_x_r - (dy * dy))));
}
@@ -191,8 +199,7 @@ int sms_light_phaser_device::bright_aim_area(int lgun_x, int lgun_y)
while (!new_check_point)
{
- /* If beam's x has passed the aim area, change it to the
- next line and go back to recheck y/x coordinates. */
+ // If beam's x has passed the aim area, change it to the next line and go back to recheck y/x coordinates.
if (beam_x > aim_area.max_x)
{
beam_x = visarea.min_x;
@@ -200,8 +207,7 @@ int sms_light_phaser_device::bright_aim_area(int lgun_x, int lgun_y)
break;
}
- /* If beam's x isn't in the aim area, change it to the
- next point where the beam enters that area. */
+ // If beam's x isn't in the aim area, change it to the next point where the beam enters that area.
if (beam_x < aim_area.min_x)
{
beam_x = aim_area.min_x;
@@ -209,58 +215,52 @@ int sms_light_phaser_device::bright_aim_area(int lgun_x, int lgun_y)
if (beam_x_orig != beam_x || beam_y_orig != beam_y)
{
- /* adopt the new coordinates to adjust the timer */
+ // adopt the new coordinates to adjust the timer
new_check_point = true;
break;
}
if (m_sensor_last_state == 0)
{
- /* sensor is already on */
- /* keep sensor on until out of the aim area */
+ // sensor is already on - keep sensor on until out of the aim area
result = 0;
}
else
{
- rgb_t color;
- uint8_t brightness;
- /* brightness of the lightgray color in the frame drawn by Light Phaser games */
- const uint8_t sensor_min_brightness = 0x7f;
-
- m_port->m_screen->update_now();
- color = m_port->m_screen->pixel(beam_x, beam_y);
+ scr.update_now();
+ const rgb_t color = scr.pixel(beam_x, beam_y);
- /* reference: http://www.w3.org/TR/AERT#color-contrast */
- brightness = (color.r() * 0.299) + (color.g() * 0.587) + (color.b() * 0.114);
- //printf ("color brightness: %2X for x %d y %d\n", brightness, beam_x, beam_y);
+ // reference: http://www.w3.org/TR/AERT#color-contrast
+ const uint8_t brightness = (color.r() * 0.299) + (color.g() * 0.587) + (color.b() * 0.114);
+ LOG("color brightness: %2X for x %d y %d\n", brightness, beam_x, beam_y);
- result = (brightness >= sensor_min_brightness) ? 0 : 1;
+ result = (brightness >= SENSOR_MIN_BRIGHTNESS) ? 0 : 1;
}
- if (result == 0) /* sensor on */
+ if (result == 0) // sensor on
{
- /* Set next check for when sensor will be off */
+ // Set next check for when sensor will be off
beam_x = aim_area.max_x + 1;
- /* adopt the new coordinates to adjust the timer */
+ // adopt the new coordinates to adjust the timer
new_check_point = true;
}
else
{
- /* Next check will happen after the minimum interval */
+ // Next check will happen after the minimum interval
beam_x += LGUN_X_INTERVAL;
}
}
}
- m_lphaser_timer->adjust(m_port->m_screen->time_until_pos(beam_y, beam_x));
+ m_update_timer->adjust(scr.time_until_pos(beam_y, beam_x));
return result;
}
uint16_t sms_light_phaser_device::screen_hpos_nonscaled(int scaled_hpos)
{
- const rectangle &visarea = m_port->m_screen->visible_area();
+ const rectangle &visarea = screen()->visible_area();
int offset_x = (scaled_hpos * (visarea.max_x - visarea.min_x)) / 255;
return visarea.min_x + offset_x;
}
@@ -268,7 +268,7 @@ uint16_t sms_light_phaser_device::screen_hpos_nonscaled(int scaled_hpos)
uint16_t sms_light_phaser_device::screen_vpos_nonscaled(int scaled_vpos)
{
- const rectangle &visarea = m_port->m_screen->visible_area();
+ const rectangle &visarea = screen()->visible_area();
int offset_y = (scaled_vpos * (visarea.max_y - visarea.min_y)) / 255;
return visarea.min_y + offset_y;
}
@@ -276,13 +276,26 @@ uint16_t sms_light_phaser_device::screen_vpos_nonscaled(int scaled_vpos)
TIMER_CALLBACK_MEMBER(sms_light_phaser_device::sensor_check)
{
- const int x = screen_hpos_nonscaled(m_lphaser_x->read());
- const int y = screen_vpos_nonscaled(m_lphaser_y->read());
-
- int sensor_new_state = bright_aim_area(x, y);
- if (sensor_new_state != m_sensor_last_state)
+ if (screen())
{
- m_port->th_pin_w(sensor_new_state);
- m_sensor_last_state = sensor_new_state;
+ const int x = screen_hpos_nonscaled(m_x_axis->read());
+ const int y = screen_vpos_nonscaled(m_y_axis->read());
+
+ int sensor_new_state = bright_aim_area(x, y);
+ if (sensor_new_state != m_sensor_last_state)
+ {
+ th_w(sensor_new_state);
+ m_sensor_last_state = sensor_new_state;
+ }
}
}
+
+} // anonymous namespace
+
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(SMS_LIGHT_PHASER, device_sms_control_interface, sms_light_phaser_device, "sms_light_phaser", "Sega Master System Light Phaser")
diff --git a/src/devices/bus/sms_ctrl/lphaser.h b/src/devices/bus/sms_ctrl/lphaser.h
index a75f4a0d042..c9d3a2b6eb5 100644
--- a/src/devices/bus/sms_ctrl/lphaser.h
+++ b/src/devices/bus/sms_ctrl/lphaser.h
@@ -5,61 +5,14 @@
Sega Master System "Light Phaser" (light gun) emulation
**********************************************************************/
-
#ifndef MAME_BUS_SMS_CTRL_LPHASER_H
#define MAME_BUS_SMS_CTRL_LPHASER_H
#pragma once
-
#include "smsctrl.h"
-
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-// ======================> sms_light_phaser_device
-
-class sms_light_phaser_device : public device_t,
- public device_sms_control_port_interface
-{
-public:
- // construction/destruction
- sms_light_phaser_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- // optional information overrides
- virtual ioport_constructor device_input_ports() const override;
-
- DECLARE_READ_LINE_MEMBER( th_pin_r );
- DECLARE_INPUT_CHANGED_MEMBER( position_changed );
-
-protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
-
- // device_sms_control_port_interface overrides
- virtual uint8_t peripheral_r() override;
-
-private:
- required_ioport m_lphaser_pins;
- required_ioport m_lphaser_x;
- required_ioport m_lphaser_y;
-
- int m_sensor_last_state;
- emu_timer *m_lphaser_timer;
-
- TIMER_CALLBACK_MEMBER(sensor_check);
- int bright_aim_area(int lgun_x, int lgun_y );
- uint16_t screen_hpos_nonscaled(int scaled_hpos);
- uint16_t screen_vpos_nonscaled(int scaled_vpos);
-};
-
-
-// device type definition
-DECLARE_DEVICE_TYPE(SMS_LIGHT_PHASER, sms_light_phaser_device)
-
+DECLARE_DEVICE_TYPE(SMS_LIGHT_PHASER, device_sms_control_interface)
#endif // MAME_BUS_SMS_CTRL_LPHASER_H
diff --git a/src/devices/bus/sms_ctrl/md6bt.cpp b/src/devices/bus/sms_ctrl/md6bt.cpp
new file mode 100644
index 00000000000..0e8ee72a258
--- /dev/null
+++ b/src/devices/bus/sms_ctrl/md6bt.cpp
@@ -0,0 +1,170 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/**********************************************************************
+
+ Sega Mega Drive Six Button Control Pad emulation
+
+ Called "Fighting Pad 6B" (ファイティングパッド6B) in Japan
+ Called "6 Button Arcade Pad" in North America
+ Called "Bloc d’arcade à 6 boutons" in Canada
+ Called "Joystick 6 Botões" in Brazil
+
+**********************************************************************/
+
+#include "emu.h"
+#include "md6bt.h"
+
+//#define VERBOSE 1
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+
+namespace {
+
+INPUT_PORTS_START( sms_md6button )
+ PORT_START("PAD")
+ PORT_BIT( 0x001, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY
+ PORT_BIT( 0x002, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY
+ PORT_BIT( 0x004, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY
+ PORT_BIT( 0x008, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY
+ PORT_BIT( 0x010, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("%p B")
+ PORT_BIT( 0x020, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("%p C")
+ PORT_BIT( 0x040, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("%p A")
+ PORT_BIT( 0x080, IP_ACTIVE_LOW, IPT_START )
+ PORT_BIT( 0x100, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_NAME("%p Z")
+ PORT_BIT( 0x200, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_NAME("%p Y")
+ PORT_BIT( 0x400, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_NAME("%p X")
+ PORT_BIT( 0x800, IP_ACTIVE_LOW, IPT_SELECT ) PORT_NAME("%p Mode")
+INPUT_PORTS_END
+
+
+
+class sms_md6button_device : public device_t, public device_sms_control_interface
+{
+public:
+ sms_md6button_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+ virtual u8 in_r() override;
+ virtual void out_w(u8 data, u8 mem_mask) override;
+
+protected:
+ virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(sms_md6button); }
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+private:
+ TIMER_CALLBACK_MEMBER(timeout);
+
+ required_ioport m_pad;
+
+ emu_timer *m_idle_timer;
+
+ u8 m_th;
+ u8 m_phase;
+ u8 m_mode;
+};
+
+
+sms_md6button_device::sms_md6button_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) :
+ device_t(mconfig, SMS_MD6BUTTON, tag, owner, clock),
+ device_sms_control_interface(mconfig, *this),
+ m_pad(*this, "PAD"),
+ m_idle_timer(nullptr),
+ m_th(1),
+ m_phase(0),
+ m_mode(0)
+{
+}
+
+
+u8 sms_md6button_device::in_r()
+{
+ ioport_value const lines = m_pad->read();
+ u8 result;
+ switch (m_phase)
+ {
+ default:
+ case 0:
+ case 1:
+ if (m_th)
+ result = BIT(lines, 0, 6); // CBRLDU
+ else
+ result = (BIT(lines, 6, 2) << 4) | BIT(lines, 0, 2); // SA00DU
+ break;
+ case 2:
+ if (m_th)
+ result = BIT(lines, 0, 6); // CBRLDU
+ else
+ result = BIT(lines, 6, 2) << 4; // SA0000
+ break;
+ case 3:
+ if (m_th)
+ result = (BIT(lines, 4, 2) << 4) | BIT(lines, 8, 4); // CBMXYZ
+ else
+ result = (BIT(lines, 6, 2) << 4) | 0x0f; // SA----
+ break;
+ }
+ LOG("%s: TH = %u read 0x%02X\n", machine().describe_context(), m_th, result);
+ return result;
+}
+
+
+void sms_md6button_device::out_w(u8 data, u8 mem_mask)
+{
+ u8 const th = BIT(data, 6);
+
+ if (!th)
+ {
+ m_idle_timer->reset();
+ }
+ else if (m_th)
+ {
+ // not an edge
+ }
+ else if (BIT(m_mode, 0))
+ {
+ m_idle_timer->adjust(attotime::from_usec(1500));
+ m_phase = (m_phase + 1) & 0x03;
+ LOG("%s: 6-button mode, TH rising, phase = %u\n", machine().describe_context(), m_phase);
+ }
+ else
+ {
+ LOG("%s: 3-button mode, TH rising, phase = %u\n", machine().describe_context(), m_phase);
+ }
+
+ m_th = th;
+}
+
+
+void sms_md6button_device::device_start()
+{
+ m_idle_timer = timer_alloc(FUNC(sms_md6button_device::timeout), this);
+
+ m_phase = 0;
+ m_mode = 0;
+
+ save_item(NAME(m_th));
+ save_item(NAME(m_phase));
+ save_item(NAME(m_mode));
+}
+
+
+void sms_md6button_device::device_reset()
+{
+ // TODO: doesn't work - reset happens before host inputs are read for the first time
+ if (!m_mode)
+ m_mode = BIT(m_pad->read(), 11) | 0x02;
+}
+
+
+TIMER_CALLBACK_MEMBER(sms_md6button_device::timeout)
+{
+ m_phase = 0;
+ LOG("timeout, phase = %u\n", m_phase);
+}
+
+} // anonymous namespace
+
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(SMS_MD6BUTTON, device_sms_control_interface, sms_md6button_device, "sms_md6button", "Sega Mega Drive Six Button Control Pad")
diff --git a/src/devices/bus/sms_ctrl/md6bt.h b/src/devices/bus/sms_ctrl/md6bt.h
new file mode 100644
index 00000000000..4a843f5ddec
--- /dev/null
+++ b/src/devices/bus/sms_ctrl/md6bt.h
@@ -0,0 +1,18 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/**********************************************************************
+
+ Sega Mega Drive Six Button Control Pad emulation
+
+**********************************************************************/
+#ifndef MAME_BUS_SMS_CTRL_MD6BT_H
+#define MAME_BUS_SMS_CTRL_MD6BT_H
+
+#pragma once
+
+#include "smsctrl.h"
+
+
+DECLARE_DEVICE_TYPE(SMS_MD6BUTTON, device_sms_control_interface)
+
+#endif // MAME_BUS_SMS_CTRL_MD6BT_H
diff --git a/src/devices/bus/sms_ctrl/mdpad.cpp b/src/devices/bus/sms_ctrl/mdpad.cpp
new file mode 100644
index 00000000000..d0c22c42085
--- /dev/null
+++ b/src/devices/bus/sms_ctrl/mdpad.cpp
@@ -0,0 +1,82 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/**********************************************************************
+
+ Sega Mega Drive Control Pad emulation
+
+**********************************************************************/
+
+#include "emu.h"
+#include "mdpad.h"
+
+
+namespace {
+
+INPUT_PORTS_START( sms_mdpad )
+ PORT_START("PAD")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("%p B")
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("%p C")
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("%p A")
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_START )
+INPUT_PORTS_END
+
+
+
+class sms_mdpad_device : public device_t, public device_sms_control_interface
+{
+public:
+ sms_mdpad_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+ virtual u8 in_r() override;
+ virtual void out_w(u8 data, u8 mem_mask) override;
+
+protected:
+ virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(sms_mdpad); }
+ virtual void device_start() override;
+
+private:
+ required_ioport m_pad;
+
+ u8 m_th;
+};
+
+
+sms_mdpad_device::sms_mdpad_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) :
+ device_t(mconfig, SMS_MDPAD, tag, owner, clock),
+ device_sms_control_interface(mconfig, *this),
+ m_pad(*this, "PAD"),
+ m_th(1)
+{
+}
+
+
+u8 sms_mdpad_device::in_r()
+{
+ ioport_value const lines = m_pad->read();
+ if (m_th)
+ return BIT(lines, 0, 6);
+ else
+ return (BIT(lines, 6, 2) << 4) | BIT(lines, 0, 2);
+}
+
+
+void sms_mdpad_device::out_w(u8 data, u8 mem_mask)
+{
+ m_th = BIT(data, 6);
+}
+
+
+void sms_mdpad_device::device_start()
+{
+ save_item(NAME(m_th));
+}
+
+} // anonymous namespace
+
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(SMS_MDPAD, device_sms_control_interface, sms_mdpad_device, "sms_mdpad", "Sega Mega Drive Control Pad")
diff --git a/src/devices/bus/sms_ctrl/mdpad.h b/src/devices/bus/sms_ctrl/mdpad.h
new file mode 100644
index 00000000000..8cb045e682e
--- /dev/null
+++ b/src/devices/bus/sms_ctrl/mdpad.h
@@ -0,0 +1,18 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/**********************************************************************
+
+ Sega Mega Drive Control Pad emulation
+
+**********************************************************************/
+#ifndef MAME_BUS_SMS_CTRL_MDPAD_H
+#define MAME_BUS_SMS_CTRL_MDPAD_H
+
+#pragma once
+
+#include "smsctrl.h"
+
+
+DECLARE_DEVICE_TYPE(SMS_MDPAD, device_sms_control_interface)
+
+#endif // MAME_BUS_SMS_CTRL_MDPAD_H
diff --git a/src/devices/bus/sms_ctrl/mouse.cpp b/src/devices/bus/sms_ctrl/mouse.cpp
new file mode 100644
index 00000000000..bb39fcd8bcd
--- /dev/null
+++ b/src/devices/bus/sms_ctrl/mouse.cpp
@@ -0,0 +1,264 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/**********************************************************************
+
+ Sega Mega Mouse emulation
+
+ The Sega Mouse sold in Japan and Europe has only two buttons but
+ is otherwise compatible.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "mouse.h"
+
+#include <algorithm>
+
+//#define VERBOSE 1
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+
+namespace {
+
+INPUT_PORTS_START( sms_megamouse )
+ PORT_START("BUTTONS")
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_NAME("%p A (Left Button)")
+ PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_BUTTON2) PORT_NAME("%p C (Right Button)")
+ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_BUTTON3) PORT_NAME("%p B (Middle Button)")
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_START)
+
+ PORT_START("X")
+ PORT_BIT( 0x1fff, 0x0000, IPT_MOUSE_X ) PORT_SENSITIVITY(50) PORT_KEYDELTA(1)
+
+ PORT_START("Y")
+ PORT_BIT( 0x1fff, 0x0000, IPT_MOUSE_Y ) PORT_SENSITIVITY(50) PORT_KEYDELTA(1) PORT_REVERSE
+INPUT_PORTS_END
+
+
+INPUT_PORTS_START( sms_segamouse )
+ PORT_INCLUDE(sms_megamouse)
+
+ PORT_MODIFY("BUTTONS")
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_NAME("%p Left Button")
+ PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_BUTTON2) PORT_NAME("%p Right Button")
+ PORT_BIT(0x0c, IP_ACTIVE_HIGH, IPT_UNUSED)
+INPUT_PORTS_END
+
+
+
+class sms_megamouse_device : public device_t, public device_sms_control_interface
+{
+public:
+ sms_megamouse_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+ virtual u8 in_r() override { return m_out; }
+ virtual void out_w(u8 data, u8 mem_mask) override;
+
+protected:
+ sms_megamouse_device(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock);
+
+ virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(sms_megamouse); }
+ virtual void device_start() override;
+
+private:
+ TIMER_CALLBACK_MEMBER(next_step);
+
+ required_ioport m_buttons;
+ required_ioport_array<2> m_axes;
+
+ emu_timer *m_busy_timer;
+
+ u16 m_base[2];
+ s16 m_count[2];
+ u8 m_th_in;
+ u8 m_tr_in;
+ u8 m_out;
+ u8 m_phase;
+};
+
+
+sms_megamouse_device::sms_megamouse_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) :
+ sms_megamouse_device(mconfig, SMS_MEGAMOUSE, tag, owner, clock)
+{
+}
+
+
+sms_megamouse_device::sms_megamouse_device(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock) :
+ device_t(mconfig, type, tag, owner, clock),
+ device_sms_control_interface(mconfig, *this),
+ m_buttons(*this, "BUTTONS"),
+ m_axes(*this, "%c", 'X'),
+ m_busy_timer(nullptr),
+ m_th_in(1),
+ m_tr_in(1),
+ m_out(0x30),
+ m_phase(0)
+{
+}
+
+
+void sms_megamouse_device::out_w(u8 data, u8 mem_mask)
+{
+ u8 const th = BIT(data, 6);
+ u8 const tr = BIT(data, 5);
+ if (th != m_th_in)
+ {
+ // seems to respond to TH pretty quickly
+ if (th)
+ {
+ LOG("%s: TH rising, deselected\n", machine().describe_context());
+ m_busy_timer->enable(false);
+ m_out = 0x30;
+ m_phase = 0;
+ }
+ else
+ {
+ LOG("%s: TH falling, selected\n", machine().describe_context());
+ m_out = 0x3b;
+
+ if (!tr)
+ {
+ LOG("%s: TR low, wait for data update\n", machine().describe_context());
+ m_busy_timer->adjust(attotime::from_nsec(7200), 0);
+ }
+ }
+ m_th_in = th;
+ m_tr_in = tr;
+ }
+ else if (!m_th_in && (tr != m_tr_in))
+ {
+ if (m_busy_timer->enabled())
+ {
+ LOG(
+ "%s: busy, deferring response to TH %s\n",
+ machine().describe_context(),
+ th ? "rising" : "falling");
+ }
+ else
+ {
+ LOG(
+ "%s: TR %s, wait for data update\n",
+ machine().describe_context(),
+ tr ? "rising" : "falling");
+ m_busy_timer->adjust(attotime::from_nsec(7200), tr);
+ }
+ m_tr_in = tr;
+ }
+}
+
+
+void sms_megamouse_device::device_start()
+{
+ m_busy_timer = timer_alloc(FUNC(sms_megamouse_device::next_step), this);
+
+ std::fill(std::begin(m_base), std::end(m_base), 0);
+ std::fill(std::begin(m_count), std::end(m_count), 0);
+ m_out = 0x30;
+ m_phase = 0;
+
+ save_item(NAME(m_base));
+ save_item(NAME(m_count));
+ save_item(NAME(m_th_in));
+ save_item(NAME(m_tr_in));
+ save_item(NAME(m_out));
+ save_item(NAME(m_phase));
+}
+
+
+TIMER_CALLBACK_MEMBER(sms_megamouse_device::next_step)
+{
+ if (BIT(param, 1))
+ {
+ u8 const tr = BIT(param, 0);
+ LOG("update TL = %u\n", tr);
+ if (tr)
+ m_out |= 0x10;
+ else
+ m_out &= ~0x10;
+
+ assert(!m_th_in);
+ if (tr != m_tr_in)
+ {
+ LOG("TR %s, wait for data update\n", tr ? "high" : "low");
+ m_busy_timer->adjust(attotime::from_nsec(7200), tr);
+ }
+ }
+ else
+ {
+ switch (m_phase)
+ {
+ case 0:
+ if (!BIT(param, 0))
+ {
+ for (unsigned i = 0; m_axes.size() > i; ++i)
+ {
+ u16 const current = m_axes[i]->read();
+ m_count[i] = s16(current) - s16(m_base[i]);
+ m_base[i] = current;
+ if (0x1000 < m_count[i])
+ m_count[i] -= 0x2000;
+ else if (-0x1000 > m_count[i])
+ m_count[i] += 0x2000;
+ }
+ LOG("movement (%d %d)\n", m_count[0], m_count[1]);
+ }
+ m_out = (m_out & 0x30) | 0x0f;
+ LOG("update data unused = 0x%X\n", m_out & 0x0f);
+ break;
+ case 1:
+ if (BIT(param, 0))
+ {
+ m_out = (m_out & 0x30) | (m_buttons->read() & 0x0f);
+ LOG("update data buttons = 0x%X\n", m_out & 0x0f);
+ }
+ else
+ {
+ m_out =
+ (m_out & 0x30) |
+ ((util::sext(m_count[1], 9) != m_count[1]) ? 0x80 : 0x00) |
+ ((util::sext(m_count[0], 9) != m_count[0]) ? 0x40 : 0x00) |
+ (BIT(m_count[1], 8) << 1) |
+ (BIT(m_count[0], 8) << 0);
+ LOG("update data flags = 0x%X\n", m_out & 0x0f);
+ }
+ break;
+ case 2:
+ case 3:
+ m_out = (m_out & 0x30) | BIT(m_count[BIT(m_phase, 0)], BIT(param, 0) ? 0 : 4, 4);
+ LOG(
+ "update data %c %s = 0x%X\n",
+ 'X' + BIT(m_phase, 0),
+ BIT(param, 0) ? "low" : "high",
+ m_out & 0x0f);
+ break;
+ }
+ if (BIT(param, 0))
+ m_phase = (m_phase + 1) & 0x03;
+ m_busy_timer->adjust(attotime::from_nsec(4800), param | 0x02);
+ }
+}
+
+
+
+class sms_segamouse_device : public sms_megamouse_device
+{
+public:
+ sms_segamouse_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(sms_segamouse); }
+};
+
+
+sms_segamouse_device::sms_segamouse_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) :
+ sms_megamouse_device(mconfig, SMS_SEGAMOUSE, tag, owner, clock)
+{
+}
+
+} // anonymous namespace
+
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(SMS_MEGAMOUSE, device_sms_control_interface, sms_megamouse_device, "sms_megamouse", "Sega Mega Mouse (US)")
+DEFINE_DEVICE_TYPE_PRIVATE(SMS_SEGAMOUSE, device_sms_control_interface, sms_segamouse_device, "sms_segamouse", "Sega Mega Drive Mouse (World)")
diff --git a/src/devices/bus/sms_ctrl/mouse.h b/src/devices/bus/sms_ctrl/mouse.h
new file mode 100644
index 00000000000..1d316204e6e
--- /dev/null
+++ b/src/devices/bus/sms_ctrl/mouse.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/**********************************************************************
+
+ Sega Mega Mouse emulation
+
+**********************************************************************/
+#ifndef MAME_BUS_SMS_CTRL_MOUSE_H
+#define MAME_BUS_SMS_CTRL_MOUSE_H
+
+#pragma once
+
+#include "smsctrl.h"
+
+
+DECLARE_DEVICE_TYPE(SMS_MEGAMOUSE, device_sms_control_interface)
+DECLARE_DEVICE_TYPE(SMS_SEGAMOUSE, device_sms_control_interface)
+
+#endif // MAME_BUS_SMS_CTRL_MOUSE_H
diff --git a/src/devices/bus/sms_ctrl/multitap.cpp b/src/devices/bus/sms_ctrl/multitap.cpp
index 74d6c749cb5..6d5017095a5 100644
--- a/src/devices/bus/sms_ctrl/multitap.cpp
+++ b/src/devices/bus/sms_ctrl/multitap.cpp
@@ -4,25 +4,56 @@
Furrtek's homemade multitap emulation
+ Schematic: http://www.smspower.org/uploads/Homebrew/BOoM-SMS-sms4p_2.png
+
+ Works by pulling ground low on one of the four ports at a time.
+ Doesn't pass through power, only works with passive devices.
+
**********************************************************************/
#include "emu.h"
#include "multitap.h"
+#include "controllers.h"
+
+//#define VERBOSE 1
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
-// Scheme: http://www.smspower.org/uploads/Homebrew/BOoM-SMS-sms4p_2.png
+namespace {
//**************************************************************************
-// DEVICE DEFINITIONS
+// TYPE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(SMS_MULTITAP, sms_multitap_device, "sms_multitap", "Furrtek SMS Multitap")
+class sms_multitap_device : public device_t, public device_sms_control_interface
+{
+public:
+ // construction/destruction
+ sms_multitap_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ // device_sms_control_interface implementation
+ virtual uint8_t in_r() override;
+ virtual void out_w(uint8_t data, uint8_t mem_mask) override;
+protected:
+ // device_t implementation
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_resolve_objects() override;
+ virtual void device_start() override;
+
+private:
+ TIMER_CALLBACK_MEMBER(reset_timeout);
+
+ required_device_array<sms_control_port_device, 4> m_subctrl_ports;
+
+ emu_timer *m_reset_timer;
+
+ uint8_t m_read_state;
+ uint8_t m_th_state;
+};
-//**************************************************************************
-// LIVE DEVICE
-//**************************************************************************
//-------------------------------------------------
// sms_multitap_device - constructor
@@ -30,14 +61,19 @@ DEFINE_DEVICE_TYPE(SMS_MULTITAP, sms_multitap_device, "sms_multitap", "Furrtek S
sms_multitap_device::sms_multitap_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, SMS_MULTITAP, tag, owner, clock),
- device_sms_control_port_interface(mconfig, *this),
- m_subctrl1_port(*this, "ctrl1"),
- m_subctrl2_port(*this, "ctrl2"),
- m_subctrl3_port(*this, "ctrl3"),
- m_subctrl4_port(*this, "ctrl4"),
+ device_sms_control_interface(mconfig, *this),
+ m_subctrl_ports(*this, "ctrl%u", 1U),
+ m_reset_timer(nullptr),
m_read_state(0),
- m_last_data(0)
+ m_th_state(1)
+{
+}
+
+
+void sms_multitap_device::device_resolve_objects()
{
+ m_read_state = 0;
+ m_th_state = 1;
}
@@ -47,8 +83,10 @@ sms_multitap_device::sms_multitap_device(const machine_config &mconfig, const ch
void sms_multitap_device::device_start()
{
+ m_reset_timer = timer_alloc(FUNC(sms_multitap_device::reset_timeout), this);
+
save_item(NAME(m_read_state));
- save_item(NAME(m_last_data));
+ save_item(NAME(m_th_state));
}
@@ -56,30 +94,13 @@ void sms_multitap_device::device_start()
// sms_peripheral_r - multitap read
//-------------------------------------------------
-uint8_t sms_multitap_device::peripheral_r()
+uint8_t sms_multitap_device::in_r()
{
- uint8_t data = 0xff;
-
- switch(m_read_state)
- {
- case 0:
- data = m_subctrl1_port->port_r();
- break;
- case 1:
- data = m_subctrl2_port->port_r();
- break;
- case 2:
- data = m_subctrl3_port->port_r();
- break;
- case 3:
- data = m_subctrl4_port->port_r();
- break;
- }
-
- // force TH level high (1), as the line is not connected to subports.
- data |= 0x40;
-
- return data;
+ // only low two bits of count value are decoded
+ uint8_t const port = m_read_state & 0x03;
+ uint8_t const result = m_subctrl_ports[port]->in_r();
+ LOG("%s: read player %u = 0x%02X\n", machine().describe_context(), port + 1, result);
+ return result;
}
@@ -87,35 +108,27 @@ uint8_t sms_multitap_device::peripheral_r()
// sms_peripheral_w - multitap write
//-------------------------------------------------
-void sms_multitap_device::peripheral_w(uint8_t data)
+void sms_multitap_device::out_w(uint8_t data, uint8_t mem_mask)
{
- uint8_t output_data;
-
- // check if TH level is low (0) and was high (1)
- if (!(data & 0x40) && (m_last_data & 0x40))
+ uint8_t const th_state = BIT(data, 6);
+ if (!th_state)
{
- m_read_state = (m_read_state + 1) & 3;
+ m_reset_timer->reset(); // capacitor discharged through diode
+ if (m_th_state)
+ {
+ m_read_state = (m_read_state + 1) & 0x0f; // 74LS393 4-bit counter
+ LOG("%s: TH falling, count = 0x%X (player %u)\n", machine().describe_context(), m_read_state, (m_read_state & 0x03) + 1);
+ }
}
- m_last_data = data;
-
- // output default TH level (1), as the line is not connected to subports.
- output_data = data | 0x40;
-
- switch(m_read_state)
+ else if (!m_th_state)
{
- case 0:
- m_subctrl1_port->port_w(output_data);
- break;
- case 1:
- m_subctrl2_port->port_w(output_data);
- break;
- case 2:
- m_subctrl3_port->port_w(output_data);
- break;
- case 3:
- m_subctrl4_port->port_w(output_data);
- break;
+ // start charging 0.1u capacitor via 100k resistor - timeout approximated
+ m_reset_timer->adjust(attotime::from_msec(10));
}
+ m_th_state = th_state;
+
+ for (auto &port : m_subctrl_ports)
+ port->out_w(data | 0x40, mem_mask & ~0x40); // TH not connected to controllers
}
@@ -125,17 +138,24 @@ void sms_multitap_device::peripheral_w(uint8_t data)
void sms_multitap_device::device_add_mconfig(machine_config &config)
{
- // Controller subports setup, without the TH callback declaration,
- // because the circuit scheme shows TH of subports without connection.
- SMS_CONTROL_PORT(config, m_subctrl1_port, sms_control_port_devices, "joypad");
- SMS_CONTROL_PORT(config, m_subctrl2_port, sms_control_port_devices, "joypad");
- SMS_CONTROL_PORT(config, m_subctrl3_port, sms_control_port_devices, "joypad");
- SMS_CONTROL_PORT(config, m_subctrl4_port, sms_control_port_devices, "joypad");
- if (m_port != nullptr)
- {
- m_subctrl1_port->set_screen_tag(m_port->m_screen);
- m_subctrl2_port->set_screen_tag(m_port->m_screen);
- m_subctrl3_port->set_screen_tag(m_port->m_screen);
- m_subctrl4_port->set_screen_tag(m_port->m_screen);
- }
+ // TH not connected, no point configuring screen when power isn't passed through
+ for (auto port : m_subctrl_ports)
+ SMS_CONTROL_PORT(config, port, sms_control_port_passive_devices, SMS_CTRL_OPTION_JOYPAD);
+}
+
+
+TIMER_CALLBACK_MEMBER(sms_multitap_device::reset_timeout)
+{
+ m_read_state = 0;
+ LOG("Timeout, count = 0x%X (player %u)\n", m_read_state, (m_read_state & 0x03) + 1);
}
+
+} // anonymous namespace
+
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(SMS_MULTITAP, device_sms_control_interface, sms_multitap_device, "sms_multitap", "Furrtek Sega Master System Multitap")
diff --git a/src/devices/bus/sms_ctrl/multitap.h b/src/devices/bus/sms_ctrl/multitap.h
index 6a2351c48f5..7484c0d1c68 100644
--- a/src/devices/bus/sms_ctrl/multitap.h
+++ b/src/devices/bus/sms_ctrl/multitap.h
@@ -5,52 +5,14 @@
Furrtek's homemade multitap emulation
**********************************************************************/
-
#ifndef MAME_BUS_SMS_CTRL_MULTITAP_H
#define MAME_BUS_SMS_CTRL_MULTITAP_H
#pragma once
-
#include "smsctrl.h"
-
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-// ======================> sms_multitap_device
-
-class sms_multitap_device : public device_t,
- public device_sms_control_port_interface
-{
-public:
- // construction/destruction
- sms_multitap_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_add_mconfig(machine_config &config) override;
-
- // device_sms_control_port_interface overrides
- virtual uint8_t peripheral_r() override;
- virtual void peripheral_w(uint8_t data) override;
-
-private:
- required_device<sms_control_port_device> m_subctrl1_port;
- required_device<sms_control_port_device> m_subctrl2_port;
- required_device<sms_control_port_device> m_subctrl3_port;
- required_device<sms_control_port_device> m_subctrl4_port;
-
- uint8_t m_read_state;
- uint8_t m_last_data;
-};
-
-
-// device type definition
-DECLARE_DEVICE_TYPE(SMS_MULTITAP, sms_multitap_device)
-
+DECLARE_DEVICE_TYPE(SMS_MULTITAP, device_sms_control_interface)
#endif // MAME_BUS_SMS_CTRL_MULTITAP_H
diff --git a/src/devices/bus/sms_ctrl/paddle.cpp b/src/devices/bus/sms_ctrl/paddle.cpp
index 06f1c9bfa16..04ce2d749ca 100644
--- a/src/devices/bus/sms_ctrl/paddle.cpp
+++ b/src/devices/bus/sms_ctrl/paddle.cpp
@@ -1,25 +1,36 @@
// license:BSD-3-Clause
-// copyright-holders:Fabio Priuli
+// copyright-holders:Vas Crabb
/**********************************************************************
Sega Mark III "Paddle Control" emulation
-Release data from the Sega Retro project:
+ Release data from the Sega Retro project:
- Year: 1987 Country/region: JP Model code: HPD-200
+ Year: 1987 Country/region: JP Model code: HPD-200
-Notes:
+ Notes:
- The main chip contained in the device is labeled 315-5243.
+ The main chip contained in the device is labeled 315-5243.
- The Paddle Control was only released in Japan. To work with the device,
- paddle games need to detect the system region as Japanese, else they switch
- to a different mode that uses the TH line as output to select which nibble
- of the X axis will be read. This other mode is similar to how the US Sports
- Pad works, so on an Export system, paddle games are somewhat playable with
- that device, though it needs to be used inverted and the trackball needs to
- be moved slowly, else the software for the paddle think it's moving backward.
+ On Japanese systems (Mark III and Master System), the games
+ read the port and expect the value on the low four bits
+ (usually used joystick switches) to alternate between the low
+ and high nybbles of the paddle position, with TR indicating
+ the current state.
+
+ On export consoles, the games toggle the TH output before
+ reading a nybble, expecting to be able to select the high or
+ low nybble of the paddle position. It spins for longer between
+ pulling TH low and reading the low nybble than it does between
+ pulling TH high and reading the high nybble, suggesting that
+ pulling TH low triggers acquisition.
+
+ Only a single model of paddle controller was released for the
+ Japanese market. Photos show no connection to pin 7. There
+ are a few reports of paddle controllers working on export
+ consoles, but this is not possible unless another hardware
+ revision exists.
**********************************************************************/
@@ -27,101 +38,67 @@ Notes:
#include "paddle.h"
+namespace {
-//**************************************************************************
-// DEVICE DEFINITIONS
-//**************************************************************************
-
-DEFINE_DEVICE_TYPE(SMS_PADDLE, sms_paddle_device, "sms_paddle", "Sega SMS Paddle")
-
-// time interval not verified
-// Player 2 of Galactic Protector is the most sensible to this timming.
-#define PADDLE_INTERVAL attotime::from_hz(XTAL(10'738'635)/3/100)
-
+INPUT_PORTS_START( sms_paddle )
+ PORT_START("BUTTON")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 )
-CUSTOM_INPUT_MEMBER( sms_paddle_device::rldu_pins_r )
-{
- uint8_t data = m_paddle_x->read();
+ PORT_START("PADDLE")
+ PORT_BIT( 0xff, 0x80, IPT_PADDLE) PORT_MINMAX(0, 255) PORT_SENSITIVITY(40) PORT_KEYDELTA(20) PORT_CENTERDELTA(0)
+INPUT_PORTS_END
- if (m_read_state)
- data >>= 4;
- // The returned value is inverted due to IP_ACTIVE_LOW mapping.
- return ~data;
-}
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
-READ_LINE_MEMBER( sms_paddle_device::tr_pin_r )
+class sms_paddle_device : public device_t, public device_sms_control_interface
{
- // The returned value is inverted due to IP_ACTIVE_LOW mapping.
- return ~m_read_state;
-}
-
-
-static INPUT_PORTS_START( sms_paddle )
- PORT_START("CTRL_PORT")
- PORT_BIT( 0x0f, IP_ACTIVE_LOW, IPT_CUSTOM ) PORT_CUSTOM_MEMBER(sms_paddle_device, rldu_pins_r) // R,L,D,U
- PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED ) // Vcc
- PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 ) // TL
- PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED ) // TH
- PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_CUSTOM ) PORT_READ_LINE_MEMBER(sms_paddle_device, tr_pin_r) // TR
+public:
+ // construction/destruction
+ sms_paddle_device(const machine_config &mconfig, char const *tag, device_t *owner, u32 clock);
- PORT_START("PADDLE_X") // Paddle knob
- PORT_BIT( 0xff, 0x80, IPT_PADDLE) PORT_SENSITIVITY(40) PORT_KEYDELTA(20) PORT_CENTERDELTA(0) PORT_MINMAX(0,255)
-INPUT_PORTS_END
-
-
-//-------------------------------------------------
-// input_ports - device-specific input ports
-//-------------------------------------------------
-
-ioport_constructor sms_paddle_device::device_input_ports() const
-{
- return INPUT_PORTS_NAME( sms_paddle );
-}
+ // device_sms_control_interface implementation
+ virtual u8 in_r() override;
+protected:
+ // device_t implementation
+ virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(sms_paddle); }
+ virtual void device_start() override { }
+private:
+ TIMER_CALLBACK_MEMBER(timeout);
-//**************************************************************************
-// LIVE DEVICE
-//**************************************************************************
+ required_ioport m_button;
+ required_ioport m_axis;
+};
-//-------------------------------------------------
-// sms_paddle_device - constructor
-//-------------------------------------------------
-sms_paddle_device::sms_paddle_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+sms_paddle_device::sms_paddle_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) :
device_t(mconfig, SMS_PADDLE, tag, owner, clock),
- device_sms_control_port_interface(mconfig, *this),
- m_paddle_pins(*this, "CTRL_PORT"),
- m_paddle_x(*this, "PADDLE_X"),
- m_read_state(0),
- m_interval(PADDLE_INTERVAL)
+ device_sms_control_interface(mconfig, *this),
+ m_button(*this, "BUTTON"),
+ m_axis(*this, "PADDLE")
{
}
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-
-void sms_paddle_device::device_start()
+u8 sms_paddle_device::in_r()
{
- m_start_time = machine().time();
-
- save_item(NAME(m_start_time));
- save_item(NAME(m_read_state));
+ // time interval guessed
+ // Player 2 of Galactic Protector is the most sensitive to this timing
+ uint8_t const nybble = machine().time().as_ticks(XTAL(10'738'635) / 3 / 100) & 1;
+ return (nybble << 5) | (m_button->read() << 4) | BIT(m_axis->read(), nybble ? 4 : 0, 4);
}
+} // anonymous namespace
-//-------------------------------------------------
-// sms_peripheral_r - paddle read
-//-------------------------------------------------
-uint8_t sms_paddle_device::peripheral_r()
-{
- int num_intervals = (machine().time() - m_start_time).as_double() / m_interval.as_double();
- m_read_state = num_intervals & 1;
- return m_paddle_pins->read();
-}
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(SMS_PADDLE, device_sms_control_interface, sms_paddle_device, "sms_paddle", "Sega Mark III Paddle (Japan)")
diff --git a/src/devices/bus/sms_ctrl/paddle.h b/src/devices/bus/sms_ctrl/paddle.h
index 21604a882ed..d61e21042ad 100644
--- a/src/devices/bus/sms_ctrl/paddle.h
+++ b/src/devices/bus/sms_ctrl/paddle.h
@@ -1,58 +1,18 @@
// license:BSD-3-Clause
-// copyright-holders:Fabio Priuli
+// copyright-holders:Vas Crabb
/**********************************************************************
Sega Mark III "Paddle Control" emulation
**********************************************************************/
-
#ifndef MAME_BUS_SMS_CTRL_PADDLE_H
#define MAME_BUS_SMS_CTRL_PADDLE_H
#pragma once
-
#include "smsctrl.h"
-
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-// ======================> sms_paddle_device
-
-class sms_paddle_device : public device_t,
- public device_sms_control_port_interface
-{
-public:
- // construction/destruction
- sms_paddle_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- // optional information overrides
- virtual ioport_constructor device_input_ports() const override;
-
- DECLARE_CUSTOM_INPUT_MEMBER( rldu_pins_r ); // Right, Left, Down and Up lines.
- DECLARE_READ_LINE_MEMBER( tr_pin_r );
-
-protected:
- // device-level overrides
- virtual void device_start() override;
-
- // device_sms_control_port_interface overrides
- virtual uint8_t peripheral_r() override;
-
-private:
- required_ioport m_paddle_pins;
- required_ioport m_paddle_x;
-
- uint8_t m_read_state;
- attotime m_start_time;
- const attotime m_interval;
-};
-
-
-// device type definition
-DECLARE_DEVICE_TYPE(SMS_PADDLE, sms_paddle_device)
+DECLARE_DEVICE_TYPE(SMS_PADDLE, device_sms_control_interface)
#endif // MAME_BUS_SMS_CTRL_PADDLE_H
diff --git a/src/devices/bus/sms_ctrl/rfu.cpp b/src/devices/bus/sms_ctrl/rfu.cpp
index d28a2ded703..4f3307759ca 100644
--- a/src/devices/bus/sms_ctrl/rfu.cpp
+++ b/src/devices/bus/sms_ctrl/rfu.cpp
@@ -14,76 +14,98 @@ Release data from the Sega Retro project:
Notes:
- This emulated device is the version released by Sega. In Brazil, Tec Toy
- released a version that does not have any switch to turn on/off auto-repeat.
+ This emulated device is the version released by Sega. In Brazil,
+ Tec Toy released a version that does not have any switch to turn
+ on/off auto-repeat.
+
+ Uses a separate oscillator consisting of a 27k resistor, a 1u
+ capacitor, and two NOR gates from a 74HCTLS02 for each button. In
+ reality, the two oscillators will run at slightly different speeds
+ and drift away from each other, so the buttons won't be
+ synchronised.
+
+ The rapid fire oscillators should start when the button is pressed,
+ but this would require pushing TL and TR state from the controller
+ to the port.
**********************************************************************/
#include "emu.h"
#include "rfu.h"
+#include "controllers.h"
+
+namespace {
//**************************************************************************
-// DEVICE DEFINITIONS
+// TYPE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(SMS_RAPID_FIRE, sms_rapid_fire_device, "sms_rapid_fire", "Sega SMS Rapid Fire Unit")
-
-// time interval not verified
-#define RAPID_FIRE_INTERVAL attotime::from_hz(10)
-
-
-static INPUT_PORTS_START( sms_rapid_fire )
- PORT_START("rfu_sw") // Rapid Fire Unit switches
- PORT_CONFNAME( 0x03, 0x00, "Rapid Fire Unit" )
- PORT_CONFSETTING( 0x00, DEF_STR( Off ) )
- PORT_CONFSETTING( 0x01, "Button 1" )
- PORT_CONFSETTING( 0x02, "Button 2" )
- PORT_CONFSETTING( 0x03, "Button 1 + 2" )
+class sms_rapid_fire_device : public device_t, public device_sms_control_interface
+{
+public:
+ // construction/destruction
+ sms_rapid_fire_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ // device_sms_control_interface implementation
+ virtual uint8_t in_r() override;
+ virtual void out_w(uint8_t data, uint8_t mem_mask) override;
+
+ void rapid_changed(int state);
+
+protected:
+ // device_t implementation
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual ioport_constructor device_input_ports() const override;
+ virtual void device_config_complete() override;
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+private:
+ required_device<sms_control_port_device> m_subctrl_port;
+ required_ioport m_rfire_sw;
+
+ uint8_t m_in;
+ uint8_t m_drive;
+ uint8_t m_rapid;
+};
+
+
+INPUT_PORTS_START( sms_rapid_fire )
+ PORT_START("rfu_sw")
+ PORT_BIT( 0x00, IP_ACTIVE_HIGH, IPT_UNUSED )
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_TOGGLE PORT_NAME("Rapid Fire 1") PORT_WRITE_LINE_MEMBER(sms_rapid_fire_device, rapid_changed)
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_TOGGLE PORT_NAME("Rapid Fire 2") PORT_WRITE_LINE_MEMBER(sms_rapid_fire_device, rapid_changed)
INPUT_PORTS_END
-//-------------------------------------------------
-// input_ports - device-specific input ports
-//-------------------------------------------------
-
ioport_constructor sms_rapid_fire_device::device_input_ports() const
{
- return INPUT_PORTS_NAME( sms_rapid_fire );
+ return INPUT_PORTS_NAME(sms_rapid_fire);
}
-
-//**************************************************************************
-// LIVE DEVICE
-//**************************************************************************
-
//-------------------------------------------------
// sms_rapid_fire_device - constructor
//-------------------------------------------------
sms_rapid_fire_device::sms_rapid_fire_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, SMS_RAPID_FIRE, tag, owner, clock),
- device_sms_control_port_interface(mconfig, *this),
- m_rfire_sw(*this, "rfu_sw"),
+ device_sms_control_interface(mconfig, *this),
m_subctrl_port(*this, "ctrl"),
- m_read_state(0),
- m_interval(RAPID_FIRE_INTERVAL)
+ m_rfire_sw(*this, "rfu_sw"),
+ m_in(0x03),
+ m_drive(0x00),
+ m_rapid(0x00)
{
}
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-
-void sms_rapid_fire_device::device_start()
+void sms_rapid_fire_device::rapid_changed(int state)
{
- m_start_time = machine().time();
-
- save_item(NAME(m_start_time));
- save_item(NAME(m_read_state));
+ m_rapid = m_rfire_sw->read();
+ m_subctrl_port->out_w(m_in | m_rapid, m_drive & ~m_rapid);
}
@@ -91,51 +113,57 @@ void sms_rapid_fire_device::device_start()
// sms_peripheral_r - rapid fire read
//-------------------------------------------------
-uint8_t sms_rapid_fire_device::peripheral_r()
+uint8_t sms_rapid_fire_device::in_r()
{
- uint8_t data;
+ uint8_t const read_state = machine().time().as_ticks(10) & 1; // time interval not verified
- int num_intervals = (machine().time() - m_start_time).as_double() / m_interval.as_double();
- m_read_state = num_intervals & 1;
+ return m_subctrl_port->in_r() | (read_state ? m_rfire_sw->read() : 0U);
+}
- data = m_subctrl_port->port_r();
- /* Check Rapid Fire switch for Button 1 (TL) */
- if (!(data & 0x20) && (m_rfire_sw->read() & 0x01))
- data |= m_read_state << 5;
+void sms_rapid_fire_device::out_w(uint8_t data, uint8_t mem_mask)
+{
+ // TR pulled up via a 4k7 resistor, connected directly to console pin when rapid fire disabled
+ m_subctrl_port->out_w(data | m_rapid, mem_mask & ~m_rapid);
+ m_in = data;
+ m_drive = mem_mask;
+}
- /* Check Rapid Fire switch for Button 2 (TR) */
- if (!(data & 0x80) && (m_rfire_sw->read() & 0x02))
- data |= m_read_state << 7;
- return data;
+void sms_rapid_fire_device::device_add_mconfig(machine_config &config)
+{
+ SMS_CONTROL_PORT(config, m_subctrl_port, sms_control_port_devices, SMS_CTRL_OPTION_JOYPAD);
+ m_subctrl_port->th_handler().set(FUNC(sms_rapid_fire_device::th_w));
}
-//-------------------------------------------------
-// sms_peripheral_w - rapid fire write
-//-------------------------------------------------
-
-void sms_rapid_fire_device::peripheral_w(uint8_t data)
+void sms_rapid_fire_device::device_config_complete()
{
- m_subctrl_port->port_w(data);
+ configure_screen(
+ [this] (auto const &s)
+ { subdevice<sms_control_port_device>("ctrl")->set_screen(s); });
}
-//-------------------------------------------------
-// device_add_mconfig - add device configuration
-//-------------------------------------------------
-
-WRITE_LINE_MEMBER( sms_rapid_fire_device::th_pin_w )
+void sms_rapid_fire_device::device_start()
{
- m_port->th_pin_w(state);
+ save_item(NAME(m_in));
+ save_item(NAME(m_drive));
+ save_item(NAME(m_rapid));
}
-void sms_rapid_fire_device::device_add_mconfig(machine_config &config)
+void sms_rapid_fire_device::device_reset()
{
- SMS_CONTROL_PORT(config, m_subctrl_port, sms_control_port_devices, "joypad");
- if (m_port != nullptr)
- m_subctrl_port->set_screen_tag(m_port->m_screen);
- m_subctrl_port->th_input_handler().set(FUNC(sms_rapid_fire_device::th_pin_w));
+ m_rapid = m_rfire_sw->read();
}
+
+} // anonymous namespace
+
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(SMS_RAPID_FIRE, device_sms_control_interface, sms_rapid_fire_device, "sms_rapid_fire", "Sega Master System Rapid Fire Unit")
diff --git a/src/devices/bus/sms_ctrl/rfu.h b/src/devices/bus/sms_ctrl/rfu.h
index f37b70b1c92..8cb4a32f253 100644
--- a/src/devices/bus/sms_ctrl/rfu.h
+++ b/src/devices/bus/sms_ctrl/rfu.h
@@ -5,56 +5,14 @@
Sega SG-1000/Mark-III/SMS "Rapid Fire Unit" emulation
**********************************************************************/
-
#ifndef MAME_BUS_SMS_CTRL_RFU_H
#define MAME_BUS_SMS_CTRL_RFU_H
#pragma once
-
#include "smsctrl.h"
-
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-// ======================> sms_rapid_fire_device
-
-class sms_rapid_fire_device : public device_t,
- public device_sms_control_port_interface
-{
-public:
- // construction/destruction
- sms_rapid_fire_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- // device-level overrides
- virtual void device_start() override;
-
- // optional information overrides
- virtual ioport_constructor device_input_ports() const override;
- virtual void device_add_mconfig(machine_config &config) override;
-
- // device_sms_control_port_interface overrides
- virtual uint8_t peripheral_r() override;
- virtual void peripheral_w(uint8_t data) override;
-
-private:
- DECLARE_WRITE_LINE_MEMBER(th_pin_w);
-
- required_ioport m_rfire_sw;
- required_device<sms_control_port_device> m_subctrl_port;
-
- uint8_t m_read_state;
- attotime m_start_time;
- const attotime m_interval;
-};
-
-
-// device type definition
-DECLARE_DEVICE_TYPE(SMS_RAPID_FIRE, sms_rapid_fire_device)
-
+DECLARE_DEVICE_TYPE(SMS_RAPID_FIRE, device_sms_control_interface)
#endif // MAME_BUS_SMS_CTRL_RFU_H
diff --git a/src/devices/bus/sms_ctrl/rs232adapt.cpp b/src/devices/bus/sms_ctrl/rs232adapt.cpp
new file mode 100644
index 00000000000..64fdf1db195
--- /dev/null
+++ b/src/devices/bus/sms_ctrl/rs232adapt.cpp
@@ -0,0 +1,56 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/**********************************************************************
+
+ Mega Drive RS-232 Adapter emulation
+
+**********************************************************************/
+
+#include "emu.h"
+#include "rs232adapt.h"
+
+#include "bus/rs232/rs232.h"
+
+
+namespace {
+
+class sms_rs232_device : public device_t, public device_sms_control_interface
+{
+public:
+ sms_rs232_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+ virtual void out_w(u8 data, u8 mem_mask) override;
+
+protected:
+ virtual void device_start() override { }
+ virtual void device_add_mconfig(machine_config &config) override;
+
+private:
+ required_device<rs232_port_device> m_port;
+};
+
+
+sms_rs232_device::sms_rs232_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) :
+ device_t(mconfig, SMS_RS232, tag, owner, clock),
+ device_sms_control_interface(mconfig, *this),
+ m_port(*this, "com")
+{
+}
+
+
+void sms_rs232_device::out_w(u8 data, u8 mem_mask)
+{
+ m_port->write_txd(BIT(data, 4));
+}
+
+
+void sms_rs232_device::device_add_mconfig(machine_config &config)
+{
+ RS232_PORT(config, m_port, default_rs232_devices, nullptr);
+}
+
+} // anonymous namespace
+
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(SMS_RS232, device_sms_control_interface, sms_rs232_device, "sms_rs232", "Mega Drive RS-232 Adapter")
diff --git a/src/devices/bus/sms_ctrl/rs232adapt.h b/src/devices/bus/sms_ctrl/rs232adapt.h
new file mode 100644
index 00000000000..ae98dbb8dc5
--- /dev/null
+++ b/src/devices/bus/sms_ctrl/rs232adapt.h
@@ -0,0 +1,18 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/**********************************************************************
+
+ Mega Drive RS-232 Adapter emulation
+
+**********************************************************************/
+#ifndef MAME_BUS_SMS_CTRL_RS232_H
+#define MAME_BUS_SMS_CTRL_RS232_H
+
+#pragma once
+
+#include "smsctrl.h"
+
+
+DECLARE_DEVICE_TYPE(SMS_RS232, device_sms_control_interface)
+
+#endif // MAME_BUS_SMS_CTRL_RS232_H
diff --git a/src/devices/bus/sms_ctrl/smsctrl.cpp b/src/devices/bus/sms_ctrl/smsctrl.cpp
index cec153b863e..7323a77bec9 100644
--- a/src/devices/bus/sms_ctrl/smsctrl.cpp
+++ b/src/devices/bus/sms_ctrl/smsctrl.cpp
@@ -1,132 +1,72 @@
// license:BSD-3-Clause
-// copyright-holders:Fabio Priuli
+// copyright-holders:Vas Crabb
/**********************************************************************
- Sega Master System controller port emulation
+ Sega 7-bit I/O port emulation
**********************************************************************/
#include "emu.h"
-#include "screen.h"
#include "smsctrl.h"
-// slot devices
-#include "joypad.h"
-#include "lphaser.h"
-#include "paddle.h"
-#include "sports.h"
-#include "sportsjp.h"
-#include "rfu.h"
-#include "multitap.h"
-#include "graphic.h"
-
//**************************************************************************
// GLOBAL VARIABLES
//**************************************************************************
-DEFINE_DEVICE_TYPE(SMS_CONTROL_PORT, sms_control_port_device, "sms_control_port", "Sega SMS controller port")
+DEFINE_DEVICE_TYPE(SMS_CONTROL_PORT, sms_control_port_device, "sms_control_port", "Sega 9-pin I/O port")
//**************************************************************************
-// CARD INTERFACE
+// CONTROLLER INTERFACE
//**************************************************************************
-//-------------------------------------------------
-// device_sms_control_port_interface - constructor
-//-------------------------------------------------
-
-device_sms_control_port_interface::device_sms_control_port_interface(const machine_config &mconfig, device_t &device)
- : device_interface(device, "smsctrl")
+device_sms_control_interface::device_sms_control_interface(machine_config const &mconfig, device_t &device) :
+ device_interface(device, "smsctrl"),
+ m_port(dynamic_cast<sms_control_port_device *>(device.owner()))
{
- m_port = dynamic_cast<sms_control_port_device *>(device.owner());
}
-//-------------------------------------------------
-// ~device_sms_control_port_interface - destructor
-//-------------------------------------------------
-
-device_sms_control_port_interface::~device_sms_control_port_interface()
+device_sms_control_interface::~device_sms_control_interface()
{
}
-
-//**************************************************************************
-// LIVE DEVICE
-//**************************************************************************
-
-//-------------------------------------------------
-// sms_control_port_device - constructor
-//-------------------------------------------------
-
-sms_control_port_device::sms_control_port_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, SMS_CONTROL_PORT, tag, owner, clock),
- device_slot_interface(mconfig, *this),
- m_screen(*this, finder_base::DUMMY_TAG),
- m_device(nullptr),
- m_th_pin_handler(*this)
+u8 device_sms_control_interface::in_r()
{
+ return 0xff;
}
-//-------------------------------------------------
-// sms_control_port_device - destructor
-//-------------------------------------------------
-
-sms_control_port_device::~sms_control_port_device()
+void device_sms_control_interface::out_w(u8 data, u8 mem_mask)
{
}
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-void sms_control_port_device::device_start()
-{
- m_device = dynamic_cast<device_sms_control_port_interface *>(get_card_device());
-
- m_th_pin_handler.resolve_safe();
-}
-
-
-uint8_t sms_control_port_device::port_r()
-{
- uint8_t data = 0xff;
- if (m_device)
- data = m_device->peripheral_r();
- return data;
-}
+//**************************************************************************
+// SLOT DEVICE
+//**************************************************************************
-void sms_control_port_device::port_w( uint8_t data )
+sms_control_port_device::sms_control_port_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) :
+ device_t(mconfig, SMS_CONTROL_PORT, tag, owner, clock),
+ device_single_card_slot_interface<device_sms_control_interface>(mconfig, *this),
+ m_screen(*this, finder_base::DUMMY_TAG),
+ m_th_handler(*this),
+ m_controller(nullptr)
{
- if (m_device)
- m_device->peripheral_w(data);
}
-void sms_control_port_device::th_pin_w(int state)
+sms_control_port_device::~sms_control_port_device()
{
- m_th_pin_handler(state);
}
-//-------------------------------------------------
-// SLOT_INTERFACE( sms_control_port_devices )
-//-------------------------------------------------
-
-void sms_control_port_devices(device_slot_interface &device)
+void sms_control_port_device::device_start()
{
- device.option_add("joypad", SMS_JOYPAD);
- device.option_add("lphaser", SMS_LIGHT_PHASER);
- device.option_add("paddle", SMS_PADDLE);
- device.option_add("sportspad", SMS_SPORTS_PAD);
- device.option_add("sportspadjp", SMS_SPORTS_PAD_JP);
- device.option_add("rapidfire", SMS_RAPID_FIRE);
- device.option_add("multitap", SMS_MULTITAP);
- device.option_add("graphic", SMS_GRAPHIC);
+ m_controller = get_card_device();
}
diff --git a/src/devices/bus/sms_ctrl/smsctrl.h b/src/devices/bus/sms_ctrl/smsctrl.h
index cee1daa0cb9..4f6e7f5a919 100644
--- a/src/devices/bus/sms_ctrl/smsctrl.h
+++ b/src/devices/bus/sms_ctrl/smsctrl.h
@@ -1,38 +1,57 @@
// license:BSD-3-Clause
-// copyright-holders:Fabio Priuli
+// copyright-holders:Vas Crabb
/**********************************************************************
- Sega Master System controller port emulation
-
-**********************************************************************
-
+ Sega 7-bit I/O port emulation
+
+ Pin 1 2 3 4 5 6 7 8 9 10
+ Up Down Left Right TL TH TR
+ TxD RXD
+ PC0 PC1 PC2 PC3 PC4 PC6 PC5
+ SC-3000 I I I I N/C I N/C GND I
+ SG-1000 I I I I N/C I GND GND I
+ SG-1000 Mark III I I I I +5V I GND GND I
+ Master System I I I I +5V I I/O GND I/O
+ Mega Drive I/O I/O I/O I/O +5V I/O I/O GND I/O
+ Game Gear I/O I/O I/O I/O +5V I/O I/O GND I/O N/C
+
+ * Male DE-9 connector on most systems.
+ * Female DE-9 connector for Mega Drive EXP port.
+ * 10-pin tongue connector on Game Gear (Hoshiden HDC-0492).
+ * TH/PC6 can latch the VDP's horizontal counter and/or raise
+ interrupts on some systems.
+ * Mega Drive and Game Gear can route TL/PC4 and TR/PC5 to a
+ UART for serial communication.
**********************************************************************/
-
#ifndef MAME_BUS_SMS_CTRL_SMSCTRL_H
#define MAME_BUS_SMS_CTRL_SMSCTRL_H
+#pragma once
+
#include "screen.h"
-#pragma once
+#include <utility>
//**************************************************************************
-// TYPE DEFINITIONS
+// FORWARD DECLARATIONS
//**************************************************************************
-// ======================> sms_control_port_device
+class device_sms_control_interface;
+
-class device_sms_control_port_interface;
-class sms_control_port_device : public device_t,
- public device_slot_interface
+//**************************************************************************
+// CLASS DECLARATIONS
+//**************************************************************************
+
+class sms_control_port_device : public device_t, public device_single_card_slot_interface<device_sms_control_interface>
{
public:
- // construction/destruction
template <typename T>
- sms_control_port_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts, char const *dflt)
- : sms_control_port_device(mconfig, tag, owner, 0)
+ sms_control_port_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts, char const *dflt) :
+ sms_control_port_device(mconfig, tag, owner, 0)
{
option_reset();
opts(*this);
@@ -40,70 +59,94 @@ public:
set_fixed(false);
}
- sms_control_port_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ sms_control_port_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
virtual ~sms_control_port_device();
- // static configuration helpers
- auto th_input_handler() { return m_th_pin_handler.bind(); }
-
- // Physical DE-9 connector interface
-
- // Data returned by the port_r methods:
- // bit 0 - pin 1 - Up
- // bit 1 - pin 2 - Down
- // bit 2 - pin 3 - Left
- // bit 3 - pin 4 - Right
- // bit 4 - pin 5 - Vcc (no data)
- // bit 5 - pin 6 - TL (Button 1/Light Phaser Trigger)
- // bit 6 - pin 7 - TH (Light Phaser sensor)
- // pin 8 - GND
- // bit 7 - pin 9 - TR (Button 2)
- //
- uint8_t port_r();
- void port_w( uint8_t data );
-
- void th_pin_w(int state);
+ auto th_handler() { return m_th_handler.bind(); } // 0 for pulled low, 1 for pulled high or high impedance
+ template <typename T> void set_screen(T &&tag) { m_screen.set_tag(std::forward<T>(tag)); }
- template <typename T> void set_screen_tag(T &&tag) { m_screen.set_tag(std::forward<T>(tag)); }
-
- // for peripherals that interact with the machine's screen
- required_device<screen_device> m_screen;
+ // Bit Pin Signal
+ // 0 1 Up
+ // 1 2 Down
+ // 2 3 Left
+ // 3 4 Right
+ // 4 6 TL
+ // 5 9 TR
+ //
+ // return bits set for pulled high or high impedance
+ // return bits clear for pulled low
+ u8 in_r();
+
+ // Bit Pin Signal
+ // 0 1 Up
+ // 1 2 Down
+ // 2 3 Left
+ // 3 4 Right
+ // 4 6 TL
+ // 5 9 TR
+ // 6 7 TH
+ //
+ // mem_mask bits set for lines driven by low impedance output
+ // mem_mask bits clear for lines with high-impedance pull-up/pull-down
+ void out_w(u8 data, u8 mem_mask);
protected:
- // device-level overrides
virtual void device_start() override;
- device_sms_control_port_interface *m_device;
-
private:
- devcb_write_line m_th_pin_handler;
-};
+ optional_device<screen_device> m_screen;
+ devcb_write_line m_th_handler;
+ device_sms_control_interface *m_controller;
-// ======================> device_sms_control_port_interface
+ friend class device_sms_control_interface;
+};
-// class representing interface-specific live sms_expansion card
-class device_sms_control_port_interface : public device_interface
+
+class device_sms_control_interface : public device_interface
{
public:
- // construction/destruction
- virtual ~device_sms_control_port_interface();
+ virtual ~device_sms_control_interface();
- virtual uint8_t peripheral_r() { return 0xff; }
- virtual void peripheral_w(uint8_t data) { }
+ virtual u8 in_r();
+ virtual void out_w(u8 data, u8 mem_mask);
protected:
- device_sms_control_port_interface(const machine_config &mconfig, device_t &device);
+ device_sms_control_interface(machine_config const &mconfig, device_t &device);
+
+ template <typename T> void configure_screen(T &&act) { if (m_port) act(std::as_const(m_port->m_screen)); }
+
+ screen_device *screen() const { return m_port ? m_port->m_screen.target() : nullptr; }
+ void th_w(int state) { if (m_port) m_port->m_th_handler(state); }
- sms_control_port_device *m_port;
+private:
+ sms_control_port_device *const m_port;
};
-// device type definition
-DECLARE_DEVICE_TYPE(SMS_CONTROL_PORT, sms_control_port_device)
+//**************************************************************************
+// INLINE MEMBER FUNCTIONS
+//**************************************************************************
+
+inline u8 sms_control_port_device::in_r()
+{
+ return m_controller ? m_controller->in_r() : 0xff;
+}
-void sms_control_port_devices(device_slot_interface &device);
+inline void sms_control_port_device::out_w(u8 data, u8 mem_mask)
+{
+ if (m_controller)
+ m_controller->out_w(data, mem_mask);
+}
+
+
+
+//**************************************************************************
+// DEVICE TYPE DECLARATIONS
+//**************************************************************************
+
+DECLARE_DEVICE_TYPE(SMS_CONTROL_PORT, sms_control_port_device)
#endif // MAME_BUS_SMS_CTRL_SMSCTRL_H
diff --git a/src/devices/bus/sms_ctrl/sports.cpp b/src/devices/bus/sms_ctrl/sports.cpp
index d58cfb68095..62a11a7d882 100644
--- a/src/devices/bus/sms_ctrl/sports.cpp
+++ b/src/devices/bus/sms_ctrl/sports.cpp
@@ -23,7 +23,7 @@ Notes:
when it does not detect use by a Japanese SMS console, because the Sega
Mark III lacks the TH line. There was a different Sports Pad model released
in Japan and no information was found about it supporting both modes, so
- that model is currently emulated as a different device (see sportsjp.c).
+ that model is currently emulated as a different device (see sportsjp.cpp).
It was discovered that games designed for the Paddle Controller, released
in Japan, will switch to a mode incompatible with the original Paddle when
@@ -40,130 +40,75 @@ Notes:
#include "emu.h"
#include "sports.h"
+//#define VERBOSE 1
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
-//**************************************************************************
-// DEVICE DEFINITIONS
-//**************************************************************************
-
-DEFINE_DEVICE_TYPE(SMS_SPORTS_PAD, sms_sports_pad_device, "sms_sports_pad", "Sega SMS Sports Pad (US)")
+namespace {
-// time interval not verified
-#define SPORTS_PAD_INTERVAL attotime::from_hz(XTAL(10'738'635)/3/512)
-
-
-TIMER_CALLBACK_MEMBER(sms_sports_pad_device::read_tick)
-{
- // values for x and y axis need to be reset for Sports Pad games, but
- // are not reset for paddle games, so it was assumed the reset occurs
- // only when this timer fires after the read state reaches its maximum value.
- if (m_read_state == 3)
- {
- m_x_axis_reset_value = m_sports_x->read();
- m_y_axis_reset_value = m_sports_y->read();
- }
- else
- {
- // set to maximum value, so it wraps to 0 at next increment
- m_read_state = 3;
- }
-}
+INPUT_PORTS_START( sms_sports_pad )
+ PORT_START("SPORTS_BT")
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) // TL
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON2 ) // TR
+ PORT_START("SPORTS_X") // X axis
+ PORT_BIT( 0xff, 0x00, IPT_TRACKBALL_X ) PORT_SENSITIVITY(50) PORT_KEYDELTA(40) PORT_REVERSE
-READ_LINE_MEMBER( sms_sports_pad_device::th_pin_r )
-{
- return m_th_pin_state;
-}
+ PORT_START("SPORTS_Y") // Y axis
+ PORT_BIT( 0xff, 0x00, IPT_TRACKBALL_Y ) PORT_SENSITIVITY(50) PORT_KEYDELTA(40) PORT_REVERSE
+INPUT_PORTS_END
-WRITE_LINE_MEMBER( sms_sports_pad_device::th_pin_w )
-{
- m_read_state = (m_read_state + 1) & 3;
- m_sportspad_timer->adjust(m_interval);
- m_th_pin_state = state;
-}
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
-CUSTOM_INPUT_MEMBER( sms_sports_pad_device::rldu_pins_r )
+class sms_sports_pad_device : public device_t, public device_sms_control_interface
{
- uint8_t data = 0;
+public:
+ // construction/destruction
+ sms_sports_pad_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- switch (m_read_state)
- {
- case 0:
- data = (m_sports_x->read() - m_x_axis_reset_value) >> 4;
- break;
- case 1:
- data = (m_sports_x->read() - m_x_axis_reset_value);
- break;
- case 2:
- data = (m_sports_y->read() - m_y_axis_reset_value) >> 4;
- break;
- case 3:
- data = (m_sports_y->read() - m_y_axis_reset_value);
- break;
- }
+ // device_sms_control_interface implementation
+ virtual uint8_t in_r() override;
+ virtual void out_w(uint8_t data, uint8_t mem_mask) override;
- // The returned value is inverted due to IP_ACTIVE_LOW mapping.
- return ~(data & 0x0f);
-}
+protected:
+ // device_t implementation
+ virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(sms_sports_pad); }
+ virtual void device_start() override;
+private:
+ TIMER_CALLBACK_MEMBER(timeout);
-static INPUT_PORTS_START( sms_sports_pad )
- PORT_START("SPORTS_IN")
- PORT_BIT( 0x0f, IP_ACTIVE_LOW, IPT_CUSTOM ) PORT_CUSTOM_MEMBER(sms_sports_pad_device, rldu_pins_r) // R,L,D,U
- PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED ) // Vcc
- PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 ) // TL (Button 1)
- PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_CUSTOM ) PORT_READ_LINE_MEMBER(sms_sports_pad_device, th_pin_r) // TH
- PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON2 ) // TR (Button 2)
+ required_ioport m_buttons;
+ required_ioport_array<2> m_axes;
- PORT_START("SPORTS_OUT")
- PORT_BIT( 0x0f, IP_ACTIVE_LOW, IPT_UNUSED ) // Directional pins
- PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED ) // Vcc
- PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED ) // TL (Button 1)
- PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_OUTPUT ) PORT_WRITE_LINE_MEMBER(sms_sports_pad_device, th_pin_w) // TH
- PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED ) // TR (Button 2)
+ emu_timer *m_timeout_timer;
- PORT_START("SPORTS_X") /* Sports Pad X axis */
- PORT_BIT( 0xff, 0x00, IPT_TRACKBALL_X ) PORT_SENSITIVITY(50) PORT_KEYDELTA(40) PORT_REVERSE
-
- PORT_START("SPORTS_Y") /* Sports Pad Y axis */
- PORT_BIT( 0xff, 0x00, IPT_TRACKBALL_Y ) PORT_SENSITIVITY(50) PORT_KEYDELTA(40) PORT_REVERSE
-INPUT_PORTS_END
+ uint8_t m_th_state;
+ uint8_t m_phase;
+ uint8_t m_output;
+ uint8_t m_base[2];
+ uint8_t m_data[2];
+};
//-------------------------------------------------
-// input_ports - device-specific input ports
-//-------------------------------------------------
-
-ioport_constructor sms_sports_pad_device::device_input_ports() const
-{
- return INPUT_PORTS_NAME( sms_sports_pad );
-}
-
-
-
-//**************************************************************************
-// LIVE DEVICE
-//**************************************************************************
-
-//-------------------------------------------------
// sms_sports_pad_device - constructor
//-------------------------------------------------
sms_sports_pad_device::sms_sports_pad_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, SMS_SPORTS_PAD, tag, owner, clock),
- device_sms_control_port_interface(mconfig, *this),
- m_sports_in(*this, "SPORTS_IN"),
- m_sports_out(*this, "SPORTS_OUT"),
- m_sports_x(*this, "SPORTS_X"),
- m_sports_y(*this, "SPORTS_Y"),
- m_read_state(0),
- m_th_pin_state(0),
- m_x_axis_reset_value(0x80), // value 0x80 helps when starting paddle games.
- m_y_axis_reset_value(0x80),
- m_interval(SPORTS_PAD_INTERVAL),
- m_sportspad_timer(nullptr)
+ device_sms_control_interface(mconfig, *this),
+ m_buttons(*this, "SPORTS_BT"),
+ m_axes(*this, "SPORTS_%c", 'X'),
+ m_timeout_timer(nullptr),
+ m_th_state(1),
+ m_phase(0),
+ m_output(0x0f)
{
}
@@ -174,20 +119,87 @@ sms_sports_pad_device::sms_sports_pad_device(const machine_config &mconfig, cons
void sms_sports_pad_device::device_start()
{
- m_sportspad_timer = timer_alloc(FUNC(sms_sports_pad_device::read_tick), this);
+ m_timeout_timer = timer_alloc(FUNC(sms_sports_pad_device::timeout), this);
+
+ m_phase = 0;
+ m_output = 0x0f;
+ m_base[0] = 0x80; // value 0x80 helps when starting paddle games.
+ m_base[1] = 0x80;
+ m_data[0] = 0x00;
+ m_data[1] = 0x00;
+
+ save_item(NAME(m_th_state));
+ save_item(NAME(m_phase));
+ save_item(NAME(m_output));
+ save_item(NAME(m_base));
+ save_item(NAME(m_data));
+}
+
- save_item(NAME(m_read_state));
- save_item(NAME(m_th_pin_state));
- save_item(NAME(m_x_axis_reset_value));
- save_item(NAME(m_y_axis_reset_value));
+uint8_t sms_sports_pad_device::in_r()
+{
+ return m_buttons->read() | m_output;
}
-uint8_t sms_sports_pad_device::peripheral_r()
+
+void sms_sports_pad_device::out_w(uint8_t data, uint8_t mem_mask)
{
- return m_sports_in->read();
+ // Sequence used to read Sports Pad:
+ // * TH = 0, spin for 80 microseconds, read X high nybble
+ // * TH = 1, spin for 40 microseconds, read X low nybble
+ // * TH = 0, spin for 40 microseconds, read Y high nybble
+ // * TH = 1, spin for 40 microseconds, read Y low nybble
+ uint8_t const th_state = BIT(data, 6);
+ if (th_state != m_th_state)
+ {
+ if (!th_state)
+ {
+ LOG(
+ "%s: TH falling, output %c high nybble\n",
+ machine().describe_context(),
+ m_phase ? 'Y' : 'X');
+
+ m_timeout_timer->reset();
+ m_data[m_phase] = m_axes[m_phase]->read();
+ m_output = BIT(m_data[m_phase] - m_base[m_phase], 4, 4);
+ }
+ else
+ {
+ LOG(
+ "%s: TH rising, output %c low nybble%s\n",
+ machine().describe_context(),
+ m_phase ? 'Y' : 'X',
+ m_phase ? ", zero counts" : "");
+
+ m_timeout_timer->adjust(attotime::from_hz(XTAL(10'738'635) / 3 / 512)); // timeout not verified
+ m_output = BIT(m_data[m_phase] - m_base[m_phase], 0, 4);
+ if (m_phase)
+ {
+ // assume the rising edge when Y is output zeroes the axes
+ m_base[0] = m_data[0];
+ m_base[1] = m_data[1];
+ }
+ m_phase ^= 1;
+ }
+ }
+
+ m_th_state = th_state;
}
-void sms_sports_pad_device::peripheral_w(uint8_t data)
+
+TIMER_CALLBACK_MEMBER(sms_sports_pad_device::timeout)
{
- m_sports_out->write(data);
+ // assume it just flips back to X, allowing paddle games to "work"
+ LOG("timeout, select X axis\n");
+ m_phase = 0;
}
+
+} // anonymous namespace
+
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(SMS_SPORTS_PAD, device_sms_control_interface, sms_sports_pad_device, "sms_sports_pad", "Sega SMS Sports Pad (US)")
diff --git a/src/devices/bus/sms_ctrl/sports.h b/src/devices/bus/sms_ctrl/sports.h
index cdf1202befd..ac6e75e5626 100644
--- a/src/devices/bus/sms_ctrl/sports.h
+++ b/src/devices/bus/sms_ctrl/sports.h
@@ -5,64 +5,14 @@
Sega Master System "Sports Pad" (US model) emulation
**********************************************************************/
-
#ifndef MAME_BUS_SMS_CTRL_SPORTS_H
#define MAME_BUS_SMS_CTRL_SPORTS_H
#pragma once
-
#include "smsctrl.h"
-
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-// ======================> sms_sports_pad_device
-
-class sms_sports_pad_device : public device_t,
- public device_sms_control_port_interface
-{
-public:
- // construction/destruction
- sms_sports_pad_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- // optional information overrides
- virtual ioport_constructor device_input_ports() const override;
-
- DECLARE_CUSTOM_INPUT_MEMBER( rldu_pins_r ); // Right, Left, Down and Up lines.
- DECLARE_READ_LINE_MEMBER( th_pin_r );
- DECLARE_WRITE_LINE_MEMBER( th_pin_w );
-
-protected:
- // device-level overrides
- virtual void device_start() override;
-
- // device_sms_control_port_interface overrides
- virtual uint8_t peripheral_r() override;
- virtual void peripheral_w(uint8_t data) override;
-
-private:
- required_ioport m_sports_in;
- required_ioport m_sports_out;
- required_ioport m_sports_x;
- required_ioport m_sports_y;
-
- uint8_t m_read_state;
- uint8_t m_th_pin_state;
- uint8_t m_x_axis_reset_value;
- uint8_t m_y_axis_reset_value;
- const attotime m_interval;
- emu_timer *m_sportspad_timer;
-
- TIMER_CALLBACK_MEMBER(read_tick);
-};
-
-
-// device type definition
-DECLARE_DEVICE_TYPE(SMS_SPORTS_PAD, sms_sports_pad_device)
-
+DECLARE_DEVICE_TYPE(SMS_SPORTS_PAD, device_sms_control_interface)
#endif // MAME_BUS_SMS_CTRL_SPORTS_H
diff --git a/src/devices/bus/sms_ctrl/sportsjp.cpp b/src/devices/bus/sms_ctrl/sportsjp.cpp
index a0c2a69d2ad..ecdbc1a7967 100644
--- a/src/devices/bus/sms_ctrl/sportsjp.cpp
+++ b/src/devices/bus/sms_ctrl/sportsjp.cpp
@@ -45,59 +45,47 @@ Notes:
#include "sportsjp.h"
+namespace {
-//**************************************************************************
-// DEVICE DEFINITIONS
-//**************************************************************************
-
-DEFINE_DEVICE_TYPE(SMS_SPORTS_PAD_JP, sms_sports_pad_jp_device, "sms_sports_pad_jp", "Sega SMS Sports Pad (JP)")
-
-// time interval not verified
-#define SPORTS_PAD_JP_INTERVAL attotime::from_hz(20000)
-
-
-
-// The returned value is inverted due to IP_ACTIVE_LOW mapping.
-READ_LINE_MEMBER( sms_sports_pad_jp_device::tl_pin_r ) { return ~m_tl_pin_state; }
-READ_LINE_MEMBER( sms_sports_pad_jp_device::tr_pin_r ) { return ~m_tr_pin_state; }
-CUSTOM_INPUT_MEMBER( sms_sports_pad_jp_device::rldu_pins_r ) { return ~(m_rldu_pins_state & 0x0f); }
-
-
-static INPUT_PORTS_START( sms_sports_pad_jp )
- PORT_START("SPORTS_JP_IN")
- PORT_BIT( 0x0f, IP_ACTIVE_LOW, IPT_CUSTOM ) PORT_CUSTOM_MEMBER(sms_sports_pad_jp_device, rldu_pins_r) // R,L,D,U
- PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED ) // Vcc
- PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_CUSTOM ) PORT_READ_LINE_MEMBER(sms_sports_pad_jp_device, tl_pin_r) // TL
- PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED ) // TH
- PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_CUSTOM ) PORT_READ_LINE_MEMBER(sms_sports_pad_jp_device, tr_pin_r) // TR
-
- PORT_START("SPORTS_JP_BT") /* Sports Pad buttons nibble */
- PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 )
- PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON2 )
+INPUT_PORTS_START( sms_sports_pad_jp )
+ PORT_START("SPORTS_JP_BT") // buttons
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 ) // TL
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON2 ) // TR
PORT_BIT( 0x0c, IP_ACTIVE_LOW, IPT_UNUSED )
- PORT_START("SPORTS_JP_X") /* Sports Pad X axis */
+ PORT_START("SPORTS_JP_X") // X axis
PORT_BIT( 0xff, 0x00, IPT_TRACKBALL_X ) PORT_SENSITIVITY(50) PORT_KEYDELTA(40)
- PORT_START("SPORTS_JP_Y") /* Sports Pad Y axis */
+ PORT_START("SPORTS_JP_Y") // Y axis
PORT_BIT( 0xff, 0x00, IPT_TRACKBALL_Y ) PORT_SENSITIVITY(50) PORT_KEYDELTA(40)
INPUT_PORTS_END
-//-------------------------------------------------
-// input_ports - device-specific input ports
-//-------------------------------------------------
-ioport_constructor sms_sports_pad_jp_device::device_input_ports() const
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class sms_sports_pad_jp_device : public device_t, public device_sms_control_interface
{
- return INPUT_PORTS_NAME( sms_sports_pad_jp );
-}
+public:
+ // construction/destruction
+ sms_sports_pad_jp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ // device_sms_control_interface implementation
+ virtual uint8_t in_r() override;
+protected:
+ // device_t implementation
+ virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(sms_sports_pad_jp); }
+ virtual void device_start() override { }
+
+private:
+ required_ioport m_buttons;
+ required_ioport m_x_axis;
+ required_ioport m_y_axis;
+};
-//**************************************************************************
-// LIVE DEVICE
-//**************************************************************************
//-------------------------------------------------
// sms_sports_pad_jp_device - constructor
@@ -105,75 +93,44 @@ ioport_constructor sms_sports_pad_jp_device::device_input_ports() const
sms_sports_pad_jp_device::sms_sports_pad_jp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, SMS_SPORTS_PAD_JP, tag, owner, clock),
- device_sms_control_port_interface(mconfig, *this),
- m_sports_jp_in(*this, "SPORTS_JP_IN"),
- m_sports_jp_bt(*this, "SPORTS_JP_BT"),
- m_sports_jp_x(*this, "SPORTS_JP_X"),
- m_sports_jp_y(*this, "SPORTS_JP_Y"),
- m_rldu_pins_state(0x0f),
- m_tl_pin_state(1),
- m_tr_pin_state(1),
- m_interval(SPORTS_PAD_JP_INTERVAL)
+ device_sms_control_interface(mconfig, *this),
+ m_buttons(*this, "SPORTS_JP_BT"),
+ m_x_axis(*this, "SPORTS_JP_X"),
+ m_y_axis(*this, "SPORTS_JP_Y")
{
}
//-------------------------------------------------
-// device_start - device-specific startup
+// sms_peripheral_r - sports pad read
//-------------------------------------------------
-void sms_sports_pad_jp_device::device_start()
+uint8_t sms_sports_pad_jp_device::in_r()
{
- m_start_time = machine().time();
+ int const num_intervals = machine().time().as_ticks(20000); // time interval not verified
- save_item(NAME(m_start_time));
- save_item(NAME(m_rldu_pins_state));
- save_item(NAME(m_tl_pin_state));
- save_item(NAME(m_tr_pin_state));
+ switch (num_intervals % 5)
+ {
+ default: // shut up dumb compilers
+ case 0: // X high nibble
+ return 0x00 | ((m_x_axis->read() >> 4) & 0x0f);
+ case 1: // X low nibble
+ return 0x10 | (m_x_axis->read() & 0x0f);
+ case 2: // Y high nibble
+ return 0x00 | ((m_y_axis->read() >> 4) & 0x0f);
+ case 3: // Y low nibble
+ return 0x10 | (m_y_axis->read() & 0x0f);
+ case 4: // buttons 1 and 2
+ return 0x30 | m_buttons->read();
+ }
}
+} // anonymous namespace
-//-------------------------------------------------
-// sms_peripheral_r - sports pad read
-//-------------------------------------------------
-uint8_t sms_sports_pad_jp_device::peripheral_r()
-{
- int num_intervals = (machine().time() - m_start_time).as_double() / m_interval.as_double();
- switch (num_intervals % 5)
- {
- case 0:
- // X high nibble
- m_rldu_pins_state = m_sports_jp_x->read() >> 4;
- m_tl_pin_state = 0;
- m_tr_pin_state = 0;
- break;
- case 1:
- // X low nibble
- m_rldu_pins_state = m_sports_jp_x->read();
- m_tl_pin_state = 1;
- m_tr_pin_state = 0;
- break;
- case 2:
- // Y high nibble
- m_rldu_pins_state = m_sports_jp_y->read() >> 4;
- m_tl_pin_state = 0;
- m_tr_pin_state = 0;
- break;
- case 3:
- // Y low nibble
- m_rldu_pins_state = m_sports_jp_y->read();
- m_tl_pin_state = 1;
- m_tr_pin_state = 0;
- break;
- case 4:
- // buttons 1 and 2
- m_rldu_pins_state = m_sports_jp_bt->read();
- m_tl_pin_state = 1;
- m_tr_pin_state = 1;
- break;
- }
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
- return m_sports_jp_in->read();
-}
+DEFINE_DEVICE_TYPE_PRIVATE(SMS_SPORTS_PAD_JP, device_sms_control_interface, sms_sports_pad_jp_device, "sms_sports_pad_jp", "Sega Mark III Sports Pad (Japan)")
diff --git a/src/devices/bus/sms_ctrl/sportsjp.h b/src/devices/bus/sms_ctrl/sportsjp.h
index 92ee2ccd70c..016605c5d2e 100644
--- a/src/devices/bus/sms_ctrl/sportsjp.h
+++ b/src/devices/bus/sms_ctrl/sportsjp.h
@@ -5,60 +5,14 @@
Sega Master System "Sports Pad" (Japanese model) emulation
**********************************************************************/
-
#ifndef MAME_BUS_SMS_CTROL_SPORTSJP_H
#define MAME_BUS_SMS_CTROL_SPORTSJP_H
#pragma once
-
#include "smsctrl.h"
-
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-// ======================> sms_sports_pad_jp_device
-
-class sms_sports_pad_jp_device : public device_t,
- public device_sms_control_port_interface
-{
-public:
- // construction/destruction
- sms_sports_pad_jp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- // optional information overrides
- virtual ioport_constructor device_input_ports() const override;
-
- DECLARE_CUSTOM_INPUT_MEMBER( rldu_pins_r ); // Right, Left, Down and Up lines.
- DECLARE_READ_LINE_MEMBER( tl_pin_r );
- DECLARE_READ_LINE_MEMBER( tr_pin_r );
-
-protected:
- // device-level overrides
- virtual void device_start() override;
-
- // device_sms_control_port_interface overrides
- virtual uint8_t peripheral_r() override;
-
-private:
- required_ioport m_sports_jp_in;
- required_ioport m_sports_jp_bt;
- required_ioport m_sports_jp_x;
- required_ioport m_sports_jp_y;
-
- uint8_t m_rldu_pins_state;
- uint8_t m_tl_pin_state;
- uint8_t m_tr_pin_state;
- attotime m_start_time;
- const attotime m_interval;
-};
-
-
-// device type definition
-DECLARE_DEVICE_TYPE(SMS_SPORTS_PAD_JP, sms_sports_pad_jp_device)
-
+DECLARE_DEVICE_TYPE(SMS_SPORTS_PAD_JP, device_sms_control_interface)
#endif // MAME_BUS_SMS_CTROL_SPORTSJP_H
diff --git a/src/devices/bus/sms_ctrl/teamplayer.cpp b/src/devices/bus/sms_ctrl/teamplayer.cpp
new file mode 100644
index 00000000000..c73af605e60
--- /dev/null
+++ b/src/devices/bus/sms_ctrl/teamplayer.cpp
@@ -0,0 +1,556 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/**********************************************************************
+
+ Sega Mega Drive 4-Player Adaptor emulation
+
+ Known as Team Player Multi-Player Adaptor in the US
+ Known as Sega Tap (セガタップ) in Japan
+
+ Everything here is guessed based on behaviour expected by
+ software. It isn't clear exactly how downstream devices are
+ clocked, and how controllers are identified.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "teamplayer.h"
+
+#include "controllers.h"
+
+#include <algorithm>
+
+//#define VERBOSE 1
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+
+namespace {
+
+class sms_teamplayer_device : public device_t, public device_sms_control_interface
+{
+public:
+ sms_teamplayer_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+ virtual u8 in_r() override;
+ virtual void out_w(u8 data, u8 mem_mask) override;
+
+ DECLARE_INPUT_CHANGED_MEMBER(reselect);
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual ioport_constructor device_input_ports() const override;
+ virtual void device_resolve_objects() override;
+ virtual void device_start() override;
+
+private:
+ enum : u8
+ {
+ IDENT_3BUTTON = 0x0,
+ IDENT_6BUTTON = 0x1,
+ IDENT_MOUSE = 0x2,
+ IDENT_UNSUPPORTED = 0xf
+ };
+
+ enum : u8
+ {
+ PHASE_START = 0,
+ PHASE_UNUSED,
+ PHASE_IDENT1,
+ PHASE_IDENT2,
+ PHASE_PORT_A,
+ PHASE_PORT_B,
+ PHASE_PORT_C,
+ PHASE_PORT_D,
+ PHASE_FINAL
+ };
+
+ template <unsigned N> void th_up_w(int state);
+
+ TIMER_CALLBACK_MEMBER(probe_step);
+
+ void selected();
+ void deselected();
+ void th_falling();
+ void th_rising();
+ void probe(unsigned step);
+ void next_port(u8 tl);
+ void next_nybble(u8 tl);
+
+ static u8 identify(u8 const (&response)[8]);
+
+ required_device_array<sms_control_port_device, 4> m_ports;
+ required_ioport m_select;
+
+ emu_timer *m_probe_timer;
+
+ u8 m_data_down;
+ u8 m_mask_down;
+ u8 m_th_up[4];
+ u8 m_out;
+
+ u8 m_phase;
+ u8 m_nybble;
+
+ u8 m_probe[4][8];
+ u8 m_ident[4];
+};
+
+
+
+INPUT_PORTS_START( sms_teamplayer )
+ PORT_START("SELECT")
+ PORT_CONFNAME(0x07, 0x04, "Switch") PORT_CHANGED_MEMBER(DEVICE_SELF, sms_teamplayer_device, reselect, 0)
+ PORT_CONFSETTING( 0x00, "A")
+ PORT_CONFSETTING( 0x01, "B")
+ PORT_CONFSETTING( 0x02, "C")
+ PORT_CONFSETTING( 0x03, "D")
+ PORT_CONFSETTING( 0x04, "Multi")
+INPUT_PORTS_END
+
+
+
+sms_teamplayer_device::sms_teamplayer_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) :
+ device_t(mconfig, SMS_TEAM_PLAYER, tag, owner, clock),
+ device_sms_control_interface(mconfig, *this),
+ m_ports(*this, "%c", 'a'),
+ m_select(*this, "SELECT"),
+ m_probe_timer(nullptr),
+ m_data_down(0x3f),
+ m_mask_down(0x00),
+ m_out(0x33),
+ m_phase(PHASE_START),
+ m_nybble(0)
+{
+}
+
+
+INPUT_CHANGED_MEMBER(sms_teamplayer_device::reselect)
+{
+ if (!BIT(m_data_down, 6))
+ {
+ if (m_ports.size() <= oldval)
+ {
+ deselected();
+ }
+ else if (m_ports.size() <= newval)
+ {
+ selected();
+ if (!BIT(m_data_down, 5))
+ th_falling();
+ }
+ }
+
+ if ((m_ports.size() > newval) || BIT(m_data_down, 6))
+ {
+ for (unsigned i = 0; m_ports.size() > i; ++i)
+ m_ports[i]->out_w((newval == i) ? m_data_down : 0x7f, (newval == i) ? m_mask_down : 0x00);
+ }
+ th_w((m_ports.size() > newval) ? m_th_up[newval] : 1);
+}
+
+
+u8 sms_teamplayer_device::in_r()
+{
+ u8 const sel = m_select->read();
+ if (m_ports.size() > sel)
+ {
+ u8 const result = m_ports[sel]->in_r();
+ LOG(
+ "%s: read passthrough %c = 0x%02X\n",
+ machine().describe_context(),
+ 'A' + sel,
+ result);
+ return result;
+ }
+ else if (PHASE_UNUSED == m_phase)
+ {
+ bool ready = true;
+ for (unsigned i = 0; ready && (m_ports.size() > i); ++i)
+ {
+ if ((IDENT_MOUSE == m_ident[i]) && BIT(m_ports[i]->in_r() ^ m_out, 4))
+ ready = false;
+ }
+ u8 const result = m_out ^ (ready ? 0x00 : 0x10);
+
+ LOG("%s: read mouse ready = 0x%02X\n", machine().describe_context(), result);
+ return result;
+ }
+ else if ((PHASE_PORT_A <= m_phase) && (PHASE_PORT_D >= m_phase))
+ {
+ u8 const port = m_phase - PHASE_PORT_A;
+ if (IDENT_MOUSE == m_ident[port])
+ {
+ u8 const result = m_ports[port]->in_r() ^ ((BIT(m_nybble, 0) ^ BIT(m_out, 4)) << 4);
+ LOG(
+ "%s: read mouse passthrough %c = 0x%02X\n",
+ machine().describe_context(),
+ 'A' + port,
+ result);
+ return result;
+ }
+ }
+
+ LOG("%s: read data = 0x%02X\n", machine().describe_context(), m_out);
+ return m_out;
+}
+
+
+void sms_teamplayer_device::out_w(u8 data, u8 mem_mask)
+{
+ u8 const sel = m_select->read();
+ if (m_ports.size() > sel)
+ {
+ m_ports[sel]->out_w(data, mem_mask);
+ }
+ else
+ {
+ u8 const changed = data ^ m_data_down;
+ if (BIT(changed, 6))
+ {
+ if (BIT(data, 6))
+ {
+ deselected();
+ }
+ else
+ {
+ selected();
+ if (!BIT(data, 5))
+ th_falling();
+ }
+ }
+ else if (!BIT(m_data_down, 6) && BIT(changed, 5))
+ {
+ if (BIT(data, 5))
+ th_rising();
+ else
+ th_falling();
+ }
+ }
+ m_data_down = data;
+ m_mask_down = mem_mask;
+}
+
+
+void sms_teamplayer_device::device_add_mconfig(machine_config &config)
+{
+ SMS_CONTROL_PORT(config, m_ports[0], sms_control_port_devices, SMS_CTRL_OPTION_MD_PAD);
+ m_ports[0]->th_handler().set(FUNC(sms_teamplayer_device::th_up_w<0>));
+
+ SMS_CONTROL_PORT(config, m_ports[1], sms_control_port_devices, SMS_CTRL_OPTION_MD_PAD);
+ m_ports[1]->th_handler().set(FUNC(sms_teamplayer_device::th_up_w<1>));
+
+ SMS_CONTROL_PORT(config, m_ports[2], sms_control_port_devices, SMS_CTRL_OPTION_MD_PAD);
+ m_ports[2]->th_handler().set(FUNC(sms_teamplayer_device::th_up_w<2>));
+
+ SMS_CONTROL_PORT(config, m_ports[3], sms_control_port_devices, SMS_CTRL_OPTION_MD_PAD);
+ m_ports[3]->th_handler().set(FUNC(sms_teamplayer_device::th_up_w<3>));
+}
+
+
+ioport_constructor sms_teamplayer_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(sms_teamplayer);
+}
+
+
+void sms_teamplayer_device::device_resolve_objects()
+{
+ m_data_down = 0x3f;
+ m_mask_down = 0x00;
+ std::fill(std::begin(m_th_up), std::end(m_th_up), 1);
+}
+
+
+void sms_teamplayer_device::device_start()
+{
+ m_probe_timer = timer_alloc(FUNC(sms_teamplayer_device::probe_step), this);
+
+ m_out = 0x30;
+ m_phase = PHASE_START;
+ m_nybble = 0;
+
+ for (auto &response : m_probe)
+ std::fill(std::begin(response), std::end(response), 0x3f);
+ std::fill(std::begin(m_ident), std::end(m_ident), IDENT_UNSUPPORTED);
+
+ save_item(NAME(m_data_down));
+ save_item(NAME(m_mask_down));
+ save_item(NAME(m_th_up));
+ save_item(NAME(m_out));
+ save_item(NAME(m_phase));
+ save_item(NAME(m_nybble));
+ save_item(NAME(m_probe));
+ save_item(NAME(m_ident));
+}
+
+
+template <unsigned N>
+void sms_teamplayer_device::th_up_w(int state)
+{
+ if (bool(state) != bool(m_th_up[N]))
+ {
+ m_th_up[N] = state;
+ if (m_select->read() == N)
+ th_w(state);
+ }
+}
+
+
+TIMER_CALLBACK_MEMBER(sms_teamplayer_device::probe_step)
+{
+ probe(param + 1);
+
+ if (6 > param)
+ {
+ for (auto &port : m_ports)
+ port->out_w(BIT(param, 0) ? 0x3f : 0x7f, BIT(param, 0) ? 0x40 : 0x00);
+ m_probe_timer->adjust(attotime::from_usec(1), param + 1);
+ }
+ else
+ {
+ for (unsigned i = 0; m_ports.size() > i; ++i)
+ {
+ m_ident[i] = identify(m_probe[i]);
+ if (IDENT_MOUSE != m_ident[i])
+ m_ports[i]->out_w(0x7f, 0x00);
+ else if ((PHASE_UNUSED == m_phase) && !BIT(m_data_down, 5))
+ m_ports[i]->out_w(0x1f, 0x60);
+
+ LOG(
+ "port %c probe response %02X %02X %02X %02X %02X %02X %02X %02X ident %02X\n",
+ 'A' + i,
+ m_probe[i][0],
+ m_probe[i][1],
+ m_probe[i][2],
+ m_probe[i][3],
+ m_probe[i][4],
+ m_probe[i][5],
+ m_probe[i][6],
+ m_probe[i][7],
+ m_ident[i]);
+ }
+
+ if ((PHASE_UNUSED == m_phase) && !BIT(m_data_down, 5))
+ m_out = 0x20;
+ }
+}
+
+
+void sms_teamplayer_device::selected()
+{
+ LOG("%s: selected\n", machine().describe_context());
+ probe(0);
+ for (auto &port : m_ports)
+ port->out_w(0x3f, 0x40);
+ m_probe_timer->adjust(attotime::from_usec(1), 0);
+ m_out = 0x3f;
+ m_phase = PHASE_START;
+ m_nybble = 0;
+}
+
+
+void sms_teamplayer_device::deselected()
+{
+ LOG("%s: deselected\n", machine().describe_context());
+ m_probe_timer->enable(false);
+ for (auto &port : m_ports)
+ port->out_w(0x7f, 0x00);
+ m_out = 0x33;
+ m_phase = PHASE_START;
+ m_nybble = 0;
+}
+
+
+void sms_teamplayer_device::th_falling()
+{
+ LOG("%s: TR falling\n", machine().describe_context());
+ switch (m_phase)
+ {
+ case PHASE_START:
+ if (!m_probe_timer->enabled())
+ {
+ for (unsigned i = 0; m_ports.size() > i; ++i)
+ {
+ if (IDENT_MOUSE == m_ident[i])
+ m_ports[i]->out_w(0x1f, 0x60);
+ }
+ m_out = 0x20;
+ }
+ ++m_phase;
+ break;
+
+ case PHASE_UNUSED:
+ case PHASE_IDENT1:
+ {
+ ++m_phase;
+ u8 const val = m_ident[(m_phase - PHASE_IDENT1) * 2];
+ LOG(
+ "%s: report port %c ident 0x%X\n",
+ machine().describe_context(),
+ 'A' + ((m_phase - PHASE_IDENT1) * 2),
+ val);
+ m_out = 0x20 | val;
+ }
+ break;
+
+ case PHASE_IDENT2:
+ next_port(0x00);
+ break;
+
+ case PHASE_PORT_A:
+ case PHASE_PORT_B:
+ case PHASE_PORT_C:
+ case PHASE_PORT_D:
+ next_nybble(0x00);
+ break;
+
+ default:
+ m_out = 0x20;
+ }
+}
+
+
+void sms_teamplayer_device::th_rising()
+{
+ LOG("%s: TR rising\n", machine().describe_context());
+ switch (m_phase)
+ {
+ case PHASE_UNUSED:
+ for (unsigned i = 0; m_ports.size() > i; ++i)
+ {
+ if (IDENT_MOUSE == m_ident[i])
+ m_ports[i]->out_w(0x3f, 0x40);
+ }
+ m_out = 0x30;
+ break;
+
+ case PHASE_IDENT1:
+ case PHASE_IDENT2:
+ {
+ assert(!m_probe_timer->enabled());
+ u8 const val = m_ident[((m_phase - PHASE_IDENT1) * 2) + 1];
+ LOG(
+ "%s: report port %c ident 0x%X\n",
+ machine().describe_context(),
+ 'A' + ((m_phase - PHASE_IDENT1) * 2) + 1,
+ val);
+ m_out = 0x30 | val;
+ }
+ break;
+
+ case PHASE_PORT_A:
+ case PHASE_PORT_B:
+ case PHASE_PORT_C:
+ case PHASE_PORT_D:
+ next_nybble(0x10);
+ break;
+
+ default:
+ m_out = 0x30;
+ }
+}
+
+
+void sms_teamplayer_device::probe(unsigned step)
+{
+ for (unsigned i = 0; m_ports.size() > i; ++i)
+ m_probe[i][step] = m_ports[i]->in_r();
+}
+
+
+void sms_teamplayer_device::next_port(u8 tl)
+{
+ ++m_phase;
+ m_nybble = 0;
+ while ((PHASE_PORT_D >= m_phase) && (IDENT_UNSUPPORTED == m_ident[m_phase - PHASE_PORT_A]))
+ ++m_phase;
+
+ if (PHASE_PORT_D >= m_phase)
+ {
+ u8 const port = m_phase - PHASE_PORT_A;
+ LOG(
+ "%s: report port %c data\n",
+ machine().describe_context(),
+ 'A' + port);
+ switch (m_ident[port])
+ {
+ case IDENT_3BUTTON:
+ case IDENT_6BUTTON:
+ m_out = 0x20 | tl | (m_probe[port][0] & 0x0f);
+ break;
+ case IDENT_MOUSE: // FIXME: mouse support
+ m_ports[port]->out_w(0x1f, 0x60);
+ m_out = 0x20 | tl;
+ break;
+ }
+ }
+ else
+ {
+ LOG("%s: no more ports with supported controllers\n", machine().describe_context());
+ m_out = 0x20 | tl;
+ }
+}
+
+
+void sms_teamplayer_device::next_nybble(u8 tl)
+{
+ u8 const port = m_phase - PHASE_PORT_A;
+ switch (m_ident[port])
+ {
+ case IDENT_3BUTTON:
+ if (!m_nybble++)
+ m_out = 0x20 | tl | (BIT(m_probe[port][1], 4, 2) << 2) | BIT(m_probe[port][0], 4, 2);
+ else
+ next_port(tl);
+ break;
+ case IDENT_6BUTTON:
+ switch (m_nybble++)
+ {
+ case 0:
+ m_out = 0x20 | tl | (BIT(m_probe[port][1], 4, 2) << 2) | BIT(m_probe[port][0], 4, 2);
+ break;
+ case 1:
+ m_out = 0x20 | tl | (m_probe[port][6] & 0x0f);
+ break;
+ default:
+ next_port(tl);
+ }
+ break;
+ case IDENT_MOUSE:
+ // FIXME: mouse support
+ if (5 > m_nybble++)
+ {
+ u8 const odd = BIT(m_nybble, 0);
+ m_ports[port]->out_w(odd ? 0x3f : 0x1f, odd ? 0x40 : 0x60);
+ m_out = 0x20 | tl;
+ }
+ else
+ {
+ m_ports[port]->out_w(0x7f, 0x40);
+ next_port(tl);
+ }
+ break;
+ default:
+ next_port(tl);
+ }
+}
+
+
+u8 sms_teamplayer_device::identify(u8 const (&response)[8])
+{
+ if (!(response[0] & 0x0f) && (0x0b == (response[1] & 0x0f)) && !(response[2] & 0x0f) && (0x0b == (response[3] & 0x0f)))
+ return IDENT_MOUSE;
+ else if ((response[1] & 0x0c) || (response[3] & 0x0c) || (response[5] & 0x0c))
+ return IDENT_UNSUPPORTED; // Mega Drive pads pull these bits down for detection
+ else if (!(response[5] & 0x03))
+ return IDENT_6BUTTON;
+ else
+ return IDENT_3BUTTON;
+}
+
+} // anonymous namespace
+
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(SMS_TEAM_PLAYER, device_sms_control_interface, sms_teamplayer_device, "sms_teamplayer", "Sega Mega Drive 4-Player Adaptor")
diff --git a/src/devices/bus/sms_ctrl/teamplayer.h b/src/devices/bus/sms_ctrl/teamplayer.h
new file mode 100644
index 00000000000..4eb9a2a01ce
--- /dev/null
+++ b/src/devices/bus/sms_ctrl/teamplayer.h
@@ -0,0 +1,18 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/**********************************************************************
+
+ Sega Mega Drive 4-Player Adaptor emulation
+
+**********************************************************************/
+#ifndef MAME_BUS_SMS_CTRL_TEAMPLAYER_H
+#define MAME_BUS_SMS_CTRL_TEAMPLAYER_H
+
+#pragma once
+
+#include "smsctrl.h"
+
+
+DECLARE_DEVICE_TYPE(SMS_TEAM_PLAYER, device_sms_control_interface)
+
+#endif // MAME_BUS_SMS_CTRL_TEAMPLAYER_H
diff --git a/src/devices/bus/sms_ctrl/xe1ap.cpp b/src/devices/bus/sms_ctrl/xe1ap.cpp
new file mode 100644
index 00000000000..74ee2e9d13a
--- /dev/null
+++ b/src/devices/bus/sms_ctrl/xe1ap.cpp
@@ -0,0 +1,107 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/**********************************************************************
+
+ Dempa Micom Soft Analog/Digital Controller XE-1AP emulation
+
+**********************************************************************/
+
+#include "emu.h"
+#include "xe1ap.h"
+
+#include "machine/micomxe1a.h"
+
+
+namespace {
+
+INPUT_PORTS_START( sms_xe1ap )
+ PORT_START("BUTTONS")
+ PORT_BIT(0x0001, IP_ACTIVE_LOW, IPT_BUTTON4) PORT_NAME("%p D") // left shoulder lower
+ PORT_BIT(0x0002, IP_ACTIVE_LOW, IPT_BUTTON3) PORT_NAME("%p C") // left shoulder upper
+ PORT_BIT(0x0004, IP_ACTIVE_LOW, IPT_BUTTON2) PORT_NAME("%p B") // right shoulder lower
+ PORT_BIT(0x0008, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_NAME("%p A") // right shoulder upper
+ PORT_BIT(0x0010, IP_ACTIVE_LOW, IPT_SELECT) // left face bottom
+ PORT_BIT(0x0020, IP_ACTIVE_LOW, IPT_START) // right face bottom
+ PORT_BIT(0x0040, IP_ACTIVE_LOW, IPT_BUTTON6) PORT_NAME("%p E2") // left face top inner
+ PORT_BIT(0x0080, IP_ACTIVE_LOW, IPT_BUTTON5) PORT_NAME("%p E1") // left face top outer
+ PORT_BIT(0x0100, IP_ACTIVE_LOW, IPT_BUTTON8) PORT_NAME("%p B'") // right face top inner
+ PORT_BIT(0x0200, IP_ACTIVE_LOW, IPT_BUTTON7) PORT_NAME("%p A'") // right face top outer
+ PORT_BIT(0xfc00, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("CH0")
+ PORT_BIT(0xff, 0x80, IPT_AD_STICK_Y) PORT_SENSITIVITY(50) PORT_KEYDELTA(50)
+
+ PORT_START("CH1")
+ PORT_BIT(0xff, 0x80, IPT_AD_STICK_X) PORT_SENSITIVITY(50) PORT_KEYDELTA(50)
+
+ PORT_START("CH2")
+ PORT_BIT(0xff, 0x80, IPT_AD_STICK_Z) PORT_SENSITIVITY(50) PORT_KEYDELTA(50) PORT_NAME("%p Throttle")
+
+ PORT_START("CH3")
+ PORT_BIT(0xff, 0x00, IPT_UNUSED)
+
+ PORT_START("MODE")
+ PORT_CONFNAME(0x01, 0x01, "Mode") PORT_WRITE_LINE_DEVICE_MEMBER("xe1", micom_xe_1a_device, mode_w)
+ PORT_CONFSETTING( 0x00, "Digital")
+ PORT_CONFSETTING( 0x01, "Analog")
+ PORT_CONFNAME(0x02, 0x02, "Interface") PORT_WRITE_LINE_DEVICE_MEMBER("xe1", micom_xe_1a_device, interface_w)
+ PORT_CONFSETTING( 0x00, "Personal Computer")
+ PORT_CONFSETTING( 0x02, "MD")
+INPUT_PORTS_END
+
+
+
+class sms_xe1ap_device : public device_t, public device_sms_control_interface
+{
+public:
+ sms_xe1ap_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) ATTR_COLD;
+
+ virtual u8 in_r() override { return m_xe1->out_r(); }
+ virtual void out_w(u8 data, u8 mem_mask) override { m_xe1->req_w(BIT(data, 6)); }
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual ioport_constructor device_input_ports() const override ATTR_COLD { return INPUT_PORTS_NAME(sms_xe1ap); }
+ virtual void device_start() override ATTR_COLD { }
+ virtual void device_reset() override ATTR_COLD;
+
+private:
+ u8 read_channel(offs_t offset) { return m_axes[offset]->read(); }
+
+ required_device<micom_xe_1a_device> m_xe1;
+ required_ioport_array<4> m_axes;
+ required_ioport m_mode;
+};
+
+
+
+sms_xe1ap_device::sms_xe1ap_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) :
+ device_t(mconfig, SMS_XE1AP, tag, owner, clock),
+ device_sms_control_interface(mconfig, *this),
+ m_xe1(*this, "xe1"),
+ m_axes(*this, "CH%u", 0U),
+ m_mode(*this, "MODE")
+{
+}
+
+
+void sms_xe1ap_device::device_add_mconfig(machine_config &config)
+{
+ MICOM_XE_1A(config, m_xe1);
+ m_xe1->buttons_handler().set_ioport("BUTTONS");
+ m_xe1->analog_handler().set(FUNC(sms_xe1ap_device::read_channel));
+}
+
+
+void sms_xe1ap_device::device_reset()
+{
+ auto const mode = m_mode->read();
+ m_xe1->mode_w(BIT(mode, 0));
+ m_xe1->interface_w(BIT(mode, 1));
+}
+
+} // anonymous namespace
+
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(SMS_XE1AP, device_sms_control_interface, sms_xe1ap_device, "sms_xe1ap", "Dempa Micom Soft Analog Controller (XE-1AP, Sega)")
diff --git a/src/devices/bus/sms_ctrl/xe1ap.h b/src/devices/bus/sms_ctrl/xe1ap.h
new file mode 100644
index 00000000000..537f0c99562
--- /dev/null
+++ b/src/devices/bus/sms_ctrl/xe1ap.h
@@ -0,0 +1,19 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/**********************************************************************
+
+ Dempa Micom Soft Analog/Digital Controller XE-1AP emulation
+
+**********************************************************************/
+#ifndef MAME_BUS_SMS_CTRL_XE1AP_H
+#define MAME_BUS_SMS_CTRL_XE1AP_H
+
+#pragma once
+
+#include "smsctrl.h"
+
+
+DECLARE_DEVICE_TYPE(SMS_XE1AP, device_sms_control_interface)
+DECLARE_DEVICE_TYPE(SMS_XE1AP, device_sms_control_interface)
+
+#endif // MAME_BUS_SMS_CTRL_XE1AP_H
diff --git a/src/devices/bus/snes/profighter.cpp b/src/devices/bus/snes/profighter.cpp
new file mode 100644
index 00000000000..6453c27bde7
--- /dev/null
+++ b/src/devices/bus/snes/profighter.cpp
@@ -0,0 +1,266 @@
+// license:BSD-3-Clause
+// copyright-holders:
+
+/***********************************************************************************************************
+
+ Super Pro Fighter Q (3 variants)
+ Super Pro Fighter X (MB03D)
+
+ TODO: everything
+
+ ***********************************************************************************************************/
+
+
+#include "emu.h"
+#include "profighter.h"
+
+#include "snes_carts.h"
+
+#include "imagedev/floppy.h"
+#include "machine/upd765.h"
+
+
+DEFINE_DEVICE_TYPE(SNS_PRO_FIGHTER_Q, sns_pro_fighter_q_device, "profighterq", "Super Pro. Fighter Q (variant 1)");
+DEFINE_DEVICE_TYPE(SNS_PRO_FIGHTER_QA, sns_pro_fighter_qa_device, "profighterqa", "Super Pro. Fighter Q (variant 2)");
+DEFINE_DEVICE_TYPE(SNS_PRO_FIGHTER_QB, sns_pro_fighter_qb_device, "profighterqb", "Super Pro. Fighter Q (variant 3)");
+DEFINE_DEVICE_TYPE(SNS_PRO_FIGHTER_X, sns_pro_fighter_x_device, "profighterx", "Pro Fighter X (MB03D)");
+
+
+static void profght_floppies(device_slot_interface &device)
+{
+ device.option_add("35dd", FLOPPY_35_DD);
+}
+
+
+/*
+Super Pro. Fighter Q copier (variant 1)
+
+Main components:
+
+MCCS3201FN floppy disk controller
+24 MHz XTAL (for the FDC)
+ST10198P CIC replacement
+HM6264LP-15 standard SRAM
+MCM60L256AF10 standard SRAM
+*/
+
+sns_pro_fighter_q_device::sns_pro_fighter_q_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, SNS_PRO_FIGHTER_Q, tag, owner, clock)
+ , device_sns_cart_interface(mconfig, *this)
+{
+}
+
+ROM_START( profghtq )
+ ROM_REGION( 0x4000, "program", 0 )
+ ROM_LOAD( "u9", 0x0000, 0x4000, CRC(4f27e1fe) SHA1(ee11ac36b5e51476ab92c66135a2353e038c014b) )
+
+ ROM_REGION( 0x1200, "plds", ROMREGION_ERASE00 )
+ ROM_LOAD( "palce16v8h.u1", 0x0000, 0x0117, CRC(3191765b) SHA1(3042c29cad1c6eebfa756514939da973b5856bd2) ) // this is actually a recreation targeted for a GAL16V8 device
+ ROM_LOAD( "palce20v8h.u5", 0x0200, 0x0157, CRC(5fa3c6bf) SHA1(edb825a15256a3a0c2fefdb3d8bf2482fd630744) ) // this is actually a recreation targeted for a GAL20V8 device
+ ROM_LOAD( "palce16v8h.u6", 0x0400, 0x0117, CRC(f9a94549) SHA1(48eab926a13d4015e91833ea4b2e3da8a461392e) ) // this is actually a recreation targeted for a GAL16V8 device
+ ROM_LOAD( "palce20v8h.u7", 0x0600, 0x0157, CRC(b321697d) SHA1(902459c06e1e35b3ad052f9439fd54add6ad2e5b) ) // this is actually a recreation targeted for a GAL20V8 device
+ ROM_LOAD( "palce16v8h.u12", 0x0800, 0x0117, CRC(40f86bce) SHA1(97edea87fc3bcfa296202fc106b1838ceffb1730) ) // this is actually a recreation targeted for a GAL16V8 device
+ ROM_LOAD( "palce16v8h.u13", 0x0a00, 0x0117, CRC(691d8a86) SHA1(f61a93cd661035440461076ee42ec7bee98ce8ff) ) // this is actually a recreation targeted for a GAL16V8 device
+ ROM_LOAD( "ami18cv8b.u14", 0x0c00, 0x0155, CRC(472405e4) SHA1(615196f1ab9819b2e22f5f48d5edd35d4db70098) ) // this is actually a recreation targeted for a PEEL18CV8 device
+ ROM_LOAD( "palce16v8h.u15", 0x0e00, 0x0117, CRC(0b8a2c8f) SHA1(0cc9c9ed671f85a3ad8622b65f94b546bb13e6b6) ) // this is actually a recreation targeted for a GAL16V8 device
+ ROM_LOAD( "palce16v8h.u16", 0x1000, 0x0117, CRC(70346ef5) SHA1(d9c0a7a2c466fa1fcc1680ee5dc3777714c05fe5) ) // this is actually a recreation targeted for a GAL16V8 device
+ROM_END
+
+
+void sns_pro_fighter_q_device::device_start()
+{
+}
+
+void sns_pro_fighter_q_device::device_reset()
+{
+
+}
+
+const tiny_rom_entry *sns_pro_fighter_q_device::device_rom_region() const
+{
+ return ROM_NAME( profghtq );
+}
+
+void sns_pro_fighter_q_device::device_add_mconfig(machine_config &config)
+{
+ N82077AA(config, "fdc", 24_MHz_XTAL); // actually MCCS3201FN, divider?
+ FLOPPY_CONNECTOR(config, "fdc:0", profght_floppies, "35dd", floppy_image_device::default_pc_floppy_formats).enable_sound(true);
+
+ SNS_CART_SLOT(config, "cartslot", 0, snes_cart, nullptr);
+}
+
+
+/*
+Super Pro. Fighter Q copier (variant 2)
+
+Main components:
+
+GM82C765B floppy disk controller
+16 MHz XTAL (for the FDC)
+74LS216 CIC replacement (not to be confused with the TTL)
+MK4864N-120 standard SRAM
+M5M5256FP CMOS Static RAM
+6 x HY524800J-80 Fast Page DRAM (on a sub board)
+*/
+
+sns_pro_fighter_qa_device::sns_pro_fighter_qa_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, SNS_PRO_FIGHTER_QA, tag, owner, clock)
+ , device_sns_cart_interface(mconfig, *this)
+{
+}
+
+ROM_START( profghtqa )
+ ROM_REGION( 0x8000, "program", 0 )
+ ROM_LOAD( "u10", 0x0000, 0x8000, CRC(56132c4e) SHA1(6649b1f13a96d144907ebab65ce00ac168b0dbe5) )
+
+ ROM_REGION( 0x1400, "plds", ROMREGION_ERASE00 )
+ ROM_LOAD( "ami18cv8b.u2", 0x0000, 0x0155, CRC(4ee0c889) SHA1(a5d060c8892dd24cbc1c14bc937ad5c301831dea) ) // this is actually a recreation targeted for a PEEL18CV8 device
+ ROM_LOAD( "palce16v8h.u3", 0x0200, 0x0117, CRC(17e897b9) SHA1(e4e9806187ffb51d4363ef9fd34d5b4a3e62e1d3) ) // this is actually a recreation targeted for a GAL16V8 device
+ ROM_LOAD( "palce20v8h.u4", 0x0400, 0x0157, CRC(5fa3c6bf) SHA1(edb825a15256a3a0c2fefdb3d8bf2482fd630744) ) // this is actually a recreation targeted for a GAL20V8 device
+ ROM_LOAD( "palce20v8h.u8", 0x0600, 0x0157, CRC(a9f5c9ed) SHA1(395f523b77d9d9ed4f20c124153697c7b301cfcc) ) // this is actually a recreation targeted for a GAL20V8 device
+ ROM_LOAD( "palce16v8h.u13", 0x0800, 0x0117, CRC(c77839b0) SHA1(6370c3862caee28dd9cc543c42c1ee9e87bdd64d) ) // this is actually a recreation targeted for a GAL16V8 device
+ ROM_LOAD( "palce16v8h.u14", 0x0a00, 0x0117, CRC(12c79d25) SHA1(9796270dd2897803686638bbd87aca1364e41933) ) // this is actually a recreation targeted for a GAL16V8 device
+ ROM_LOAD( "palce16v8h.u15", 0x0c00, 0x0117, CRC(0b8a2c8f) SHA1(0cc9c9ed671f85a3ad8622b65f94b546bb13e6b6) ) // this is actually a recreation targeted for a GAL16V8 device
+ ROM_LOAD( "ami18cv8b.u16", 0x0e00, 0x0155, CRC(481a6974) SHA1(aff914837a7d8ef804b0ac4049d6f23ab23a1cda) ) // this is actually a recreation targeted for a PEEL18CV8 device
+ ROM_LOAD( "palce16v8h.u17", 0x1000, 0x0117, CRC(70346ef5) SHA1(d9c0a7a2c466fa1fcc1680ee5dc3777714c05fe5) ) // this is actually a recreation targeted for a GAL16V8 device
+ ROM_LOAD( "palce16v8h.u18", 0x1200, 0x0117, CRC(a3bbb6b1) SHA1(bdf291d2e3601d7b48c348b1d99b8872b1b4fedd) ) // this is actually a recreation targeted for a GAL16V8 device
+ROM_END
+
+
+void sns_pro_fighter_qa_device::device_start()
+{
+}
+
+void sns_pro_fighter_qa_device::device_reset()
+{
+
+}
+
+const tiny_rom_entry *sns_pro_fighter_qa_device::device_rom_region() const
+{
+ return ROM_NAME( profghtqa );
+}
+
+void sns_pro_fighter_qa_device::device_add_mconfig(machine_config &config)
+{
+ WD37C65C(config, "fdc", 16_MHz_XTAL); // actually GM82C765B
+ FLOPPY_CONNECTOR(config, "fdc:0", profght_floppies, "35dd", floppy_image_device::default_pc_floppy_formats).enable_sound(true);
+
+ SNS_CART_SLOT(config, "cartslot", 0, snes_cart, nullptr);
+}
+
+
+/*
+Super Pro. Fighter Q copier (variant 3)
+
+Main components:
+
+ACCMicro 3201 floppy disk controller
+24 MHz XTAL (for the FDC)
+unmarked CIC replacement
+D43256AGU-15LL CMOS Static RAM
+4 x GM71C4400BJ70 + 4 x KM44C1000BLJ-6 Fast Page DRAM (on a sub board)
+*/
+
+sns_pro_fighter_qb_device::sns_pro_fighter_qb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, SNS_PRO_FIGHTER_QB, tag, owner, clock)
+ , device_sns_cart_interface(mconfig, *this)
+{
+}
+
+ROM_START( profghtqb ) // same program as profghtrq but different plds
+ ROM_REGION( 0x4000, "program", 0 )
+ ROM_LOAD( "u7", 0x0000, 0x4000, CRC(4f27e1fe) SHA1(ee11ac36b5e51476ab92c66135a2353e038c014b) )
+
+ ROM_REGION( 0xe00, "plds", ROMREGION_ERASE00 ) // probably all recreations, but chip types match
+ ROM_LOAD( "peel18cv8p.u2", 0x000, 0x155, CRC(e40bc5c0) SHA1(207437a41ae04bf4d5093775a6f2e602d0840d12) )
+ ROM_LOAD( "peel18cv8p.u4", 0x200, 0x155, CRC(bd152ad4) SHA1(bc79994d63efa7ef6e3cea4bd6f7940b68c40176) )
+ ROM_LOAD( "peel18cv8p.u5", 0x400, 0x155, CRC(b03c21a0) SHA1(dde7644cca7b383ab19e3598f30250a6695816fd) )
+ ROM_LOAD( "gal16v8b.u9", 0x600, 0x117, CRC(c9d37428) SHA1(9c06739d34a25095c0b0420910b82252ab0d05f8) )
+ ROM_LOAD( "peel18cv8p.u10", 0x800, 0x155, CRC(e0a3a486) SHA1(20162b8c174e73fb7d57d9a221eef87fb88005a5) )
+ ROM_LOAD( "gal16v8b.u11", 0xa00, 0x117, CRC(0b8a2c8f) SHA1(0cc9c9ed671f85a3ad8622b65f94b546bb13e6b6) )
+ ROM_LOAD( "gal16v8b.u12", 0xc00, 0x117, CRC(a1d23a1a) SHA1(d83dc1b50771f5d8b68293c85b0b94e257521bd3) )
+ROM_END
+
+
+void sns_pro_fighter_qb_device::device_start()
+{
+}
+
+void sns_pro_fighter_qb_device::device_reset()
+{
+
+}
+
+const tiny_rom_entry *sns_pro_fighter_qb_device::device_rom_region() const
+{
+ return ROM_NAME( profghtqb );
+}
+
+void sns_pro_fighter_qb_device::device_add_mconfig(machine_config &config)
+{
+ N82077AA(config, "fdc", 24_MHz_XTAL); // actually ACCMicro 3201, divider?
+ FLOPPY_CONNECTOR(config, "fdc:0", profght_floppies, "35dd", floppy_image_device::default_pc_floppy_formats).enable_sound(true);
+
+ SNS_CART_SLOT(config, "cartslot", 0, snes_cart, nullptr);
+}
+
+
+/*
+Pro Fighter X (MB03D) copier
+
+Main components:
+
+GM82C765B floppy disk controller
+16 MHz XTAL (for the FDC)
+96813 CIC replacement on one PCB, 265111 CIC replacement on another
+DDP1 custom (GRAPHIC DDP1-1 on one PCB, GINGER DDP1 9407 on another)
+MK4864N-120 standard SRAM, 8k x 8
+MS62256L-10PC CMOS Static RAM on one PCB; CXK58257M-10LL Static RAM on another
+2 x D421700G5-80L-7JD Fast Page DRAM (on a sub board)
+*/
+
+sns_pro_fighter_x_device::sns_pro_fighter_x_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, SNS_PRO_FIGHTER_X, tag, owner, clock)
+ , device_sns_cart_interface(mconfig, *this)
+{
+}
+
+ROM_START( profghtx )
+ ROM_REGION( 0x10000, "program", 0 )
+ ROM_LOAD( "pfx ver1.20.u3", 0x00000, 0x10000, CRC(04635d41) SHA1(e2765907d03f62329db224c6570d65aea5df5154) )
+
+ ROM_REGION( 0x1200, "plds", ROMREGION_ERASE00 )
+ ROM_LOAD( "palce20v8h.u7", 0x0000, 0x0157, CRC(2a46e9b7) SHA1(3c2aca7dfa943e00b4227194ce90dfa89290d1a6) ) // this is actually a recreation targeted for a GAL20V8 device
+ ROM_LOAD( "palce20v8h.u10", 0x0200, 0x0157, CRC(738765b4) SHA1(1357ca21112b9d6da735a1070deeaa8097cf2a6e) ) // this is actually a recreation targeted for a GAL20V8 device
+ ROM_LOAD( "peel18cv8b.u12", 0x0400, 0x0155, CRC(e1ee3a45) SHA1(983918d504c16b20ae185679ed489b167c993609) ) // this is actually a recreation
+ ROM_LOAD( "palce16v8h.u13", 0x0600, 0x0117, CRC(611c95a9) SHA1(b138041dd99af0bed37f178d2733764309279ee6) ) // probably actual dump
+ ROM_LOAD( "palce16v8h.u14", 0x0800, 0x0117, CRC(82d9c905) SHA1(70c16fb86a16319246eae02d9e5439bc65453174) ) // probably actual dump
+ ROM_LOAD( "palce20v8h.u16", 0x0a00, 0x0157, CRC(3593d7e8) SHA1(47094c6469fed5f10bea9f0f993b0257fc39e12f) ) // this is actually a recreation targeted for a GAL20V8 device
+ ROM_LOAD( "palce20v8h.u17", 0x0c00, 0x0157, CRC(f58539ae) SHA1(c5105f0dd9c7d0f966b84444c17fe798cfcdcdc1) ) // this is actually a recreation targeted for a GAL20V8 device
+ ROM_LOAD( "palce20v8h.u18", 0x0e00, 0x0157, CRC(97d8652f) SHA1(6bff3088fed8253cfd2b57a101e91e0a0e66bcff) ) // this is actually a recreation targeted for a GAL20V8 device
+ ROM_LOAD( "palce20v8h.u19", 0x1000, 0x0157, CRC(2e42ed8f) SHA1(51f461756668a51e4f9b800168412dab26cd5ca9) ) // this is actually a recreation targeted for a GAL20V8 device
+ROM_END
+
+
+void sns_pro_fighter_x_device::device_start()
+{
+}
+
+void sns_pro_fighter_x_device::device_reset()
+{
+
+}
+
+const tiny_rom_entry *sns_pro_fighter_x_device::device_rom_region() const
+{
+ return ROM_NAME( profghtx );
+}
+
+void sns_pro_fighter_x_device::device_add_mconfig(machine_config &config)
+{
+ WD37C65C(config, "fdc", 16_MHz_XTAL); // actually GM82C765B
+ FLOPPY_CONNECTOR(config, "fdc:0", profght_floppies, "35dd", floppy_image_device::default_pc_floppy_formats).enable_sound(true);
+
+ SNS_CART_SLOT(config, "cartslot", 0, snes_cart, nullptr);
+}
diff --git a/src/devices/bus/snes/profighter.h b/src/devices/bus/snes/profighter.h
new file mode 100644
index 00000000000..164ddce5b99
--- /dev/null
+++ b/src/devices/bus/snes/profighter.h
@@ -0,0 +1,70 @@
+// license:BSD-3-Clause
+// copyright-holders:
+
+#ifndef MAME_BUS_SNES_PROFIGHTER_H
+#define MAME_BUS_SNES_PROFIGHTER_H
+
+#pragma once
+
+#include "snes_slot.h"
+
+
+class sns_pro_fighter_q_device : public device_t,
+ public device_sns_cart_interface
+{
+public:
+ sns_pro_fighter_q_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+};
+
+class sns_pro_fighter_qa_device : public device_t,
+ public device_sns_cart_interface
+{
+public:
+ sns_pro_fighter_qa_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+};
+
+class sns_pro_fighter_qb_device : public device_t,
+ public device_sns_cart_interface
+{
+public:
+ sns_pro_fighter_qb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+};
+
+class sns_pro_fighter_x_device : public device_t,
+ public device_sns_cart_interface
+{
+public:
+ sns_pro_fighter_x_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+};
+
+
+DECLARE_DEVICE_TYPE(SNS_PRO_FIGHTER_Q, sns_pro_fighter_q_device);
+DECLARE_DEVICE_TYPE(SNS_PRO_FIGHTER_QA, sns_pro_fighter_qa_device);
+DECLARE_DEVICE_TYPE(SNS_PRO_FIGHTER_QB, sns_pro_fighter_qb_device);
+DECLARE_DEVICE_TYPE(SNS_PRO_FIGHTER_X, sns_pro_fighter_x_device);
+
+#endif // MAME_BUS_SNES_PROFIGHTER_H
diff --git a/src/devices/bus/snes/sfx.cpp b/src/devices/bus/snes/sfx.cpp
index 8051fe9c8f8..88405e67feb 100644
--- a/src/devices/bus/snes/sfx.cpp
+++ b/src/devices/bus/snes/sfx.cpp
@@ -90,7 +90,7 @@ void sns_rom_superfx_device::sfx_map(address_map &map)
}
-WRITE_LINE_MEMBER(sns_rom_superfx_device::snes_extern_irq_w)
+void sns_rom_superfx_device::snes_extern_irq_w(int state)
{
write_irq(state);
}
diff --git a/src/devices/bus/snes/sfx.h b/src/devices/bus/snes/sfx.h
index 54df5a8018b..b46ca0c639d 100644
--- a/src/devices/bus/snes/sfx.h
+++ b/src/devices/bus/snes/sfx.h
@@ -20,7 +20,7 @@ protected:
virtual void device_start() override;
virtual void device_reset() override;
- virtual DECLARE_WRITE_LINE_MEMBER(snes_extern_irq_w);
+ virtual void snes_extern_irq_w(int state);
// additional reading and writing
virtual uint8_t read_l(offs_t offset) override;
diff --git a/src/devices/bus/snes/sgb.cpp b/src/devices/bus/snes/sgb.cpp
index 6c790a1c773..8ce9ebfab65 100644
--- a/src/devices/bus/snes/sgb.cpp
+++ b/src/devices/bus/snes/sgb.cpp
@@ -15,6 +15,9 @@
#include "emu.h"
#include "sgb.h"
+#include "bus/gameboy/carts.h"
+
+
//-------------------------------------------------
// sns_rom_sgb_device - constructor
//-------------------------------------------------
@@ -23,13 +26,15 @@ DEFINE_DEVICE_TYPE(SNS_LOROM_SUPERGB, sns_rom_sgb1_device, "sns_rom_sgb", "SNE
DEFINE_DEVICE_TYPE(SNS_LOROM_SUPERGB2, sns_rom_sgb2_device, "sns_rom_sgb2", "SNES Super Game Boy 2 Cart")
-sns_rom_sgb_device::sns_rom_sgb_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
- : sns_rom_device(mconfig, type, tag, owner, clock),
+sns_rom_sgb_device::sns_rom_sgb_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
+ sns_rom_device(mconfig, type, tag, owner, clock),
m_sgb_cpu(*this, "sgb_cpu"),
m_sgb_apu(*this, "sgb_apu"),
m_sgb_ppu(*this, "sgb_ppu"),
m_cartslot(*this, "gb_slot"),
- m_region_bios(*this, "sgb_cpu"),
+ m_region_bootstrap(*this, "sgb_cpu"),
+ m_view_bootstrap(*this, "sgb_boot"),
+ m_bootstrap_installed(false),
m_sgb_ly(0),
m_sgb_row(0),
m_vram(0),
@@ -40,8 +45,7 @@ sns_rom_sgb_device::sns_rom_sgb_device(const machine_config &mconfig, device_typ
m_joy4(0),
m_vram_offs(0),
m_lcd_row(0),
- m_packetsize(0),
- m_bios_disabled(false)
+ m_packetsize(0)
{
}
@@ -60,10 +64,19 @@ sns_rom_sgb2_device::sns_rom_sgb2_device(const machine_config& mconfig, const ch
void sns_rom_sgb_device::device_start()
{
+ m_bootstrap_installed = false;
}
void sns_rom_sgb_device::device_reset()
{
+ // need to install the bootstrap view over the top of the cartridge, which installs *after* start
+ if (!m_bootstrap_installed)
+ {
+ m_sgb_cpu->space(AS_PROGRAM).install_view(0x0000, 0x00ff, m_view_bootstrap);
+ m_view_bootstrap[0].install_rom(0x0000, 0x00ff, &m_region_bootstrap[0]);
+ m_bootstrap_installed = true;
+ }
+ m_view_bootstrap.select(0);
}
@@ -74,40 +87,6 @@ void sns_rom_sgb_device::device_reset()
// ADDRESS_MAP( supergb_map )
//-------------------------------------------------
-uint8_t sns_rom_sgb_device::gb_cart_r(offs_t offset)
-{
- if (offset < 0x100 && !m_bios_disabled)
- {
- return m_region_bios->base()[offset];
- }
- return m_cartslot->read_rom(offset);
-}
-
-void sns_rom_sgb_device::gb_bank_w(offs_t offset, uint8_t data)
-{
- m_cartslot->write_bank(offset, data);
-}
-
-uint8_t sns_rom_sgb_device::gb_ram_r(offs_t offset)
-{
- return m_cartslot->read_ram(offset);
-}
-
-void sns_rom_sgb_device::gb_ram_w(offs_t offset, uint8_t data)
-{
- m_cartslot->write_ram(offset, data);
-}
-
-uint8_t sns_rom_sgb_device::gb_echo_r(offs_t offset)
-{
- return m_sgb_cpu->space(AS_PROGRAM).read_byte(0xc000 + offset);
-}
-
-void sns_rom_sgb_device::gb_echo_w(offs_t offset, uint8_t data)
-{
- return m_sgb_cpu->space(AS_PROGRAM).write_byte(0xc000 + offset, data);
-}
-
uint8_t sns_rom_sgb_device::gb_io_r(offs_t offset)
{
return 0;
@@ -132,19 +111,18 @@ void sns_rom_sgb_device::gb_ie_w(offs_t offset, uint8_t data)
void sns_rom_sgb_device::supergb_map(address_map &map)
{
map.unmap_value_high();
- map(0x0000, 0x7fff).rw(FUNC(sns_rom_sgb_device::gb_cart_r), FUNC(sns_rom_sgb_device::gb_bank_w));
- map(0x8000, 0x9fff).rw("sgb_ppu", FUNC(sgb_ppu_device::vram_r), FUNC(sgb_ppu_device::vram_w)); /* 8k VRAM */
- map(0xa000, 0xbfff).rw(FUNC(sns_rom_sgb_device::gb_ram_r), FUNC(sns_rom_sgb_device::gb_ram_w)); /* 8k switched RAM bank (cartridge) */
- map(0xc000, 0xdfff).ram(); /* 8k low RAM */
- map(0xe000, 0xfdff).rw(FUNC(sns_rom_sgb_device::gb_echo_r), FUNC(sns_rom_sgb_device::gb_echo_w));
- map(0xfe00, 0xfeff).rw("sgb_ppu", FUNC(sgb_ppu_device::oam_r), FUNC(sgb_ppu_device::oam_w)); /* OAM RAM */
- map(0xff00, 0xff0f).rw(FUNC(sns_rom_sgb_device::gb_io_r), FUNC(sns_rom_sgb_device::gb_io_w)); /* I/O */
- map(0xff10, 0xff26).rw("sgb_apu", FUNC(gameboy_sound_device::sound_r), FUNC(gameboy_sound_device::sound_w)); /* sound registers */
- map(0xff27, 0xff2f).noprw(); /* unused */
- map(0xff30, 0xff3f).rw("sgb_apu", FUNC(gameboy_sound_device::wave_r), FUNC(gameboy_sound_device::wave_w)); /* Wave RAM */
- map(0xff40, 0xff7f).rw("sgb_ppu", FUNC(sgb_ppu_device::video_r), FUNC(sgb_ppu_device::video_w)); /* also disable bios?? */ /* Video controller & BIOS flip-flop */
- map(0xff80, 0xfffe).ram(); /* High RAM */
- map(0xffff, 0xffff).rw(FUNC(sns_rom_sgb_device::gb_ie_r), FUNC(sns_rom_sgb_device::gb_ie_w)); /* Interrupt enable register */
+ // cartridge ROM and memory controller goes here
+ map(0x8000, 0x9fff).rw(m_sgb_ppu, FUNC(sgb_ppu_device::vram_r), FUNC(sgb_ppu_device::vram_w)); // 8k VRAM
+ // cartridge RAM and/or I/O goes here
+ map(0xc000, 0xdfff).mirror(0x2000).ram(); // 8k low RAM
+ map(0xfe00, 0xfeff).rw(m_sgb_ppu, FUNC(sgb_ppu_device::oam_r), FUNC(sgb_ppu_device::oam_w)); // OAM RAM
+ map(0xff00, 0xff0f).rw(FUNC(sns_rom_sgb_device::gb_io_r), FUNC(sns_rom_sgb_device::gb_io_w)); // I/O
+ map(0xff10, 0xff26).rw(m_sgb_apu, FUNC(gameboy_sound_device::sound_r), FUNC(gameboy_sound_device::sound_w)); /* sound registers */
+ map(0xff27, 0xff2f).noprw(); // unused
+ map(0xff30, 0xff3f).rw(m_sgb_apu, FUNC(gameboy_sound_device::wave_r), FUNC(gameboy_sound_device::wave_w)); /* Wave RAM */
+ map(0xff40, 0xff7f).rw(m_sgb_ppu, FUNC(sgb_ppu_device::video_r), FUNC(sgb_ppu_device::video_w)); // also disable bios??
+ map(0xff80, 0xfffe).ram(); // High RAM
+ map(0xffff, 0xffff).rw(FUNC(sns_rom_sgb_device::gb_ie_r), FUNC(sns_rom_sgb_device::gb_ie_w)); // Interrupt enable register
}
@@ -154,13 +132,6 @@ void sns_rom_sgb_device::gb_timer_callback(uint8_t data)
}
-static void supergb_cart(device_slot_interface &device)
-{
- device.option_add_internal("rom", GB_STD_ROM);
- device.option_add_internal("rom_mbc1", GB_ROM_MBC1);
-}
-
-
void sns_rom_sgb1_device::device_add_mconfig(machine_config &config)
{
LR35902(config, m_sgb_cpu, 4295454); /* 4.295454 MHz */
@@ -172,7 +143,8 @@ void sns_rom_sgb1_device::device_add_mconfig(machine_config &config)
DMG_APU(config, m_sgb_apu, 4295454);
- GB_CART_SLOT(config, m_cartslot, supergb_cart, nullptr);
+ GB_CART_SLOT(config, m_cartslot, gameboy_cartridges, nullptr);
+ m_cartslot->set_space(m_sgb_cpu, AS_PROGRAM);
}
@@ -199,7 +171,8 @@ void sns_rom_sgb2_device::device_add_mconfig(machine_config &config)
DMG_APU(config, m_sgb_apu, XTAL(4'194'304));
- GB_CART_SLOT(config, m_cartslot, supergb_cart, nullptr);
+ GB_CART_SLOT(config, m_cartslot, gameboy_cartridges, nullptr);
+ m_cartslot->set_space(m_sgb_cpu, AS_PROGRAM);
}
@@ -355,5 +328,4 @@ void sns_rom_sgb_device::chip_write(offs_t offset, uint8_t data)
m_joy4 = data;
return;
}
-
}
diff --git a/src/devices/bus/snes/sgb.h b/src/devices/bus/snes/sgb.h
index db6782ddb98..46d600a704b 100644
--- a/src/devices/bus/snes/sgb.h
+++ b/src/devices/bus/snes/sgb.h
@@ -9,9 +9,7 @@
#include "rom.h"
#include "cpu/lr35902/lr35902.h"
-#include "bus/gameboy/gb_slot.h"
-#include "bus/gameboy/rom.h"
-#include "bus/gameboy/mbc.h"
+#include "bus/gameboy/gbslot.h"
#include "video/gb_lcd.h"
#include "sound/gb.h"
@@ -37,12 +35,6 @@ protected:
virtual uint8_t chip_read(offs_t offset) override;
virtual void chip_write(offs_t offset, uint8_t data) override;
- uint8_t gb_cart_r(offs_t offset);
- void gb_bank_w(offs_t offset, uint8_t data);
- uint8_t gb_ram_r(offs_t offset);
- void gb_ram_w(offs_t offset, uint8_t data);
- uint8_t gb_echo_r(offs_t offset);
- void gb_echo_w(offs_t offset, uint8_t data);
uint8_t gb_io_r(offs_t offset);
void gb_io_w(offs_t offset, uint8_t data);
uint8_t gb_ie_r(offs_t offset);
@@ -56,10 +48,12 @@ protected:
required_device<gb_cart_slot_device> m_cartslot;
private:
- required_memory_region m_region_bios;
-
void lcd_render(uint32_t *source);
+ required_region_ptr<u8> m_region_bootstrap;
+ memory_view m_view_bootstrap;
+ bool m_bootstrap_installed;
+
// ICD2 regs
uint8_t m_sgb_ly;
uint8_t m_sgb_row;
@@ -76,8 +70,6 @@ private:
// input bits
int m_packetsize;
uint8_t m_packet_data[64][16];
-
- bool m_bios_disabled;
};
diff --git a/src/devices/bus/snes/snes_carts.cpp b/src/devices/bus/snes/snes_carts.cpp
index bbe6c628c06..228c340fac4 100644
--- a/src/devices/bus/snes/snes_carts.cpp
+++ b/src/devices/bus/snes/snes_carts.cpp
@@ -7,11 +7,14 @@
**********************************************************************/
#include "emu.h"
+
#include "snes_carts.h"
+#include "bsx.h"
+#include "event.h"
#include "rom.h"
#include "rom21.h"
-#include "bsx.h"
+#include "profighter.h"
#include "sa1.h"
#include "sdd1.h"
#include "sfx.h"
@@ -19,7 +22,6 @@
#include "spc7110.h"
#include "sufami.h"
#include "upd.h"
-#include "event.h"
void snes_cart(device_slot_interface &device)
@@ -66,4 +68,9 @@ void snes_cart(device_slot_interface &device)
device.option_add_internal("hirom_dsp1leg", SNS_HIROM_NECDSP1_LEG);
device.option_add_internal("lorom_st10leg", SNS_LOROM_SETA10_LEG);
device.option_add_internal("lorom_st11leg", SNS_LOROM_SETA11_LEG);
+ // copiers
+ device.option_add("profighterq", SNS_PRO_FIGHTER_Q);
+ device.option_add("profighterqa", SNS_PRO_FIGHTER_QA);
+ device.option_add("profighterqb", SNS_PRO_FIGHTER_QB);
+ device.option_add("profighterx", SNS_PRO_FIGHTER_X);
}
diff --git a/src/devices/bus/snes/snes_slot.cpp b/src/devices/bus/snes/snes_slot.cpp
index b6764119233..d447c390bd2 100644
--- a/src/devices/bus/snes/snes_slot.cpp
+++ b/src/devices/bus/snes/snes_slot.cpp
@@ -88,11 +88,11 @@ device_sns_cart_interface::~device_sns_cart_interface()
// rom_alloc - alloc the space for the cart
//-------------------------------------------------
-void device_sns_cart_interface::rom_alloc(uint32_t size, const char *tag)
+void device_sns_cart_interface::rom_alloc(uint32_t size)
{
if (m_rom == nullptr)
{
- m_rom = device().machine().memory().region_alloc(std::string(tag).append(SNSSLOT_ROM_REGION_TAG).c_str(), size, 1, ENDIANNESS_LITTLE)->base();
+ m_rom = device().machine().memory().region_alloc(device().subtag("^cart:rom"), size, 1, ENDIANNESS_LITTLE)->base();
m_rom_size = size;
}
}
@@ -170,7 +170,7 @@ void device_sns_cart_interface::rom_map_setup(uint32_t size)
// write_irq - set the cart IRQ output
//-------------------------------------------------
-WRITE_LINE_MEMBER(device_sns_cart_interface::write_irq)
+void device_sns_cart_interface::write_irq(int state)
{
if (m_slot != nullptr)
m_slot->write_irq(state);
@@ -227,7 +227,7 @@ base_sns_cart_slot_device::base_sns_cart_slot_device(const machine_config &mconf
m_type(SNES_MODE20),
m_cart(nullptr),
m_irq_callback(*this),
- m_open_bus_callback(*this)
+ m_open_bus_callback(*this, 0xff)
{
}
@@ -263,9 +263,6 @@ void base_sns_cart_slot_device::device_start()
m_cart = dynamic_cast<device_sns_cart_interface *>(get_card_device());
if (m_cart != nullptr)
m_cart->m_slot = this;
-
- m_irq_callback.resolve_safe();
- m_open_bus_callback.resolve_safe(0xff);
}
@@ -649,15 +646,12 @@ static int snes_find_addon_chip(const uint8_t *buffer, uint32_t start_offs, uint
-------------------------------------------------*/
-image_init_result base_sns_cart_slot_device::call_load()
+std::pair<std::error_condition, std::string> base_sns_cart_slot_device::call_load()
{
if (m_cart)
{
- uint8_t *ROM;
- uint32_t len, offset = 0;
- const char *slot_name;
-
- /* Check for a header (512 bytes), and skip it if found */
+ // Check for a header (512 bytes), and skip it if found
+ uint32_t offset = 0;
if (!loaded_through_softlist())
{
uint32_t tmplen = length();
@@ -667,10 +661,10 @@ image_init_result base_sns_cart_slot_device::call_load()
fseek(offset, SEEK_SET);
}
- len = !loaded_through_softlist() ? (length() - offset) : get_software_region_length("rom");
+ uint32_t const len = !loaded_through_softlist() ? (length() - offset) : get_software_region_length("rom");
- m_cart->rom_alloc(len, tag());
- ROM = m_cart->get_rom_base();
+ m_cart->rom_alloc(len);
+ uint8_t *const ROM = m_cart->get_rom_base();
if (!loaded_through_softlist())
fread(ROM, len);
else
@@ -693,13 +687,14 @@ image_init_result base_sns_cart_slot_device::call_load()
get_cart_type_addon(ROM, len, m_type, m_addon);
else
{
+ const char *slot_name;
if ((slot_name = get_feature("slot")) == nullptr)
m_type = SNES_MODE20;
else
m_type = sns_get_pcb_id(slot_name);
if (m_type == SNES_DSP && len > 0x100000)
- m_type = SNES_DSP_2MB;
+ m_type = SNES_DSP_2MB;
}
if (!loaded_through_softlist())
@@ -725,11 +720,9 @@ image_init_result base_sns_cart_slot_device::call_load()
//printf("Type %d\n", m_type);
internal_header_logging(ROM, len);
-
- return image_init_result::PASS;
}
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
@@ -851,37 +844,37 @@ void base_sns_cart_slot_device::setup_addon_from_fullpath()
switch (m_addon)
{
case ADDON_DSP1:
- ROM = machine().root_device().memregion(region.c_str())->base();
+ ROM = machine().root_device().memregion(region)->base();
m_cart->addon_bios_alloc(0x2800);
memcpy(m_cart->get_addon_bios_base(), ROM, 0x2800);
break;
case ADDON_DSP1B:
- ROM = machine().root_device().memregion(region.c_str())->base();
+ ROM = machine().root_device().memregion(region)->base();
m_cart->addon_bios_alloc(0x2800);
memcpy(m_cart->get_addon_bios_base(), ROM, 0x2800);
break;
case ADDON_DSP2:
- ROM = machine().root_device().memregion(region.c_str())->base();
+ ROM = machine().root_device().memregion(region)->base();
m_cart->addon_bios_alloc(0x2800);
memcpy(m_cart->get_addon_bios_base(), ROM, 0x2800);
break;
case ADDON_DSP3:
- ROM = machine().root_device().memregion(region.c_str())->base();
+ ROM = machine().root_device().memregion(region)->base();
m_cart->addon_bios_alloc(0x2800);
memcpy(m_cart->get_addon_bios_base(), ROM, 0x2800);
break;
case ADDON_DSP4:
- ROM = machine().root_device().memregion(region.c_str())->base();
+ ROM = machine().root_device().memregion(region)->base();
m_cart->addon_bios_alloc(0x2800);
memcpy(m_cart->get_addon_bios_base(), ROM, 0x2800);
break;
case ADDON_ST010:
- ROM = machine().root_device().memregion(region.c_str())->base();
+ ROM = machine().root_device().memregion(region)->base();
m_cart->addon_bios_alloc(0x11000);
memcpy(m_cart->get_addon_bios_base(), ROM, 0x11000);
break;
case ADDON_ST011:
- ROM = machine().root_device().memregion(region.c_str())->base();
+ ROM = machine().root_device().memregion(region)->base();
m_cart->addon_bios_alloc(0x11000);
memcpy(m_cart->get_addon_bios_base(), ROM, 0x11000);
break;
@@ -1051,8 +1044,7 @@ std::string base_sns_cart_slot_device::get_default_card_software(get_default_car
std::vector<uint8_t> rom(len);
int type = 0, addon = 0;
- size_t actual;
- hook.image_file()->read(&rom[0], len, actual); // FIXME: check for error result or read returning short
+ /*auto const [err, actual] =*/ read(*hook.image_file(), &rom[0], len); // FIXME: check for error result or read returning short
offset = snes_skip_header(&rom[0], len);
@@ -1371,7 +1363,7 @@ void base_sns_cart_slot_device::internal_header_logging(uint8_t *ROM, uint32_t l
logerror( "HEADER DETAILS\n" );
logerror( "==============\n\n" );
logerror( "\tName: %.21s\n", title );
- logerror( "\tSpeed: %s [%d]\n", (ROM[hilo_mode + 0x15] & 0xf0) ? "FastROM" : "SlowROM", (ROM[hilo_mode + 0x15] & 0xf0) >> 4);
+ logerror( "\tSpeed: %s [%d]\n", (ROM[hilo_mode + 0x15] & 0x10) ? "FastROM" : "SlowROM", (ROM[hilo_mode + 0x15] & 0xf0) >> 4);
logerror( "\tBank size: %s [%d]\n", (ROM[hilo_mode + 0x15] & 0xf) ? "HiROM" : "LoROM", ROM[hilo_mode + 0x15] & 0xf);
logerror( "\tType: %s", cart_types[type]);
diff --git a/src/devices/bus/snes/snes_slot.h b/src/devices/bus/snes/snes_slot.h
index cb90c41d64f..43ea1aeab8e 100644
--- a/src/devices/bus/snes/snes_slot.h
+++ b/src/devices/bus/snes/snes_slot.h
@@ -123,7 +123,7 @@ public:
virtual void chip_write(offs_t offset, uint8_t data) { }
virtual void speedup_addon_bios_access() {}
- void rom_alloc(uint32_t size, const char *tag);
+ void rom_alloc(uint32_t size);
void nvram_alloc(uint32_t size);
void rtc_ram_alloc(uint32_t size);
void addon_bios_alloc(uint32_t size);
@@ -143,7 +143,7 @@ public:
protected:
device_sns_cart_interface(const machine_config &mconfig, device_t &device);
- DECLARE_WRITE_LINE_MEMBER(write_irq);
+ void write_irq(int state);
uint8_t read_open_bus();
int scanlines_r();
offs_t address_r();
@@ -177,13 +177,13 @@ public:
void set_scanlines(int scanlines) { m_scanlines = scanlines; }
void set_address(offs_t address) { m_address = address; }
- // image-level overrides
- virtual image_init_result call_load() override;
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
virtual void call_unload() override;
virtual bool is_reset_on_load() const noexcept override { return true; }
- // slot interface overrides
+ // device_slot_interface implementation
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
void get_cart_type_addon(const uint8_t *ROM, uint32_t len, int &type, int &addon) const;
@@ -212,7 +212,7 @@ public:
uint8_t chip_read(offs_t offset);
void chip_write(offs_t offset, uint8_t data);
- DECLARE_WRITE_LINE_MEMBER(write_irq) { m_irq_callback(state); }
+ void write_irq(int state) { m_irq_callback(state); }
uint8_t read_open_bus() { return m_open_bus_callback(); }
int scanlines_r() { return m_scanlines; }
offs_t address_r() { return m_address; }
@@ -236,7 +236,7 @@ public:
protected:
base_sns_cart_slot_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
private:
@@ -312,12 +312,4 @@ DECLARE_DEVICE_TYPE(SNS_CART_SLOT, sns_cart_slot_device)
DECLARE_DEVICE_TYPE(SNS_SUFAMI_CART_SLOT, sns_sufami_cart_slot_device)
DECLARE_DEVICE_TYPE(SNS_BSX_CART_SLOT, sns_bsx_cart_slot_device)
-
-/***************************************************************************
- DEVICE CONFIGURATION MACROS
- ***************************************************************************/
-
-#define SNSSLOT_ROM_REGION_TAG ":cart:rom"
-
-
#endif // MAME_BUS_SNES_SNES_SLOT_H
diff --git a/src/devices/bus/snes_ctrl/ctrl.cpp b/src/devices/bus/snes_ctrl/ctrl.cpp
index 68e69ee0a8b..69fe2554725 100644
--- a/src/devices/bus/snes_ctrl/ctrl.cpp
+++ b/src/devices/bus/snes_ctrl/ctrl.cpp
@@ -85,8 +85,8 @@ snes_control_port_device::~snes_control_port_device()
void snes_control_port_device::device_start()
{
m_device = get_card_device();
- m_onscreen_cb.resolve();
- m_gunlatch_cb.resolve();
+ m_onscreen_cb.resolve_safe(true);
+ m_gunlatch_cb.resolve_safe();
}
diff --git a/src/devices/bus/snes_ctrl/ctrl.h b/src/devices/bus/snes_ctrl/ctrl.h
index b6e6ddc869e..30169d8a7dd 100644
--- a/src/devices/bus/snes_ctrl/ctrl.h
+++ b/src/devices/bus/snes_ctrl/ctrl.h
@@ -71,8 +71,8 @@ public:
void write_strobe(uint8_t data);
void port_poll();
- bool onscreen_cb(int16_t x, int16_t y) { return m_onscreen_cb.isnull() ? true : m_onscreen_cb(x, y); }
- void gunlatch_cb(int16_t x, int16_t y) { if (!m_gunlatch_cb.isnull()) m_gunlatch_cb(x, y); }
+ bool onscreen_cb(int16_t x, int16_t y) { return m_onscreen_cb(x, y); }
+ void gunlatch_cb(int16_t x, int16_t y) { m_gunlatch_cb(x, y); }
protected:
// device-level overrides
diff --git a/src/devices/bus/spc1000/vdp.cpp b/src/devices/bus/spc1000/vdp.cpp
index f85a64f59b9..5380ac9c061 100644
--- a/src/devices/bus/spc1000/vdp.cpp
+++ b/src/devices/bus/spc1000/vdp.cpp
@@ -14,7 +14,7 @@
IMPLEMENTATION
***************************************************************************/
-WRITE_LINE_MEMBER(spc1000_vdp_exp_device::vdp_interrupt)
+void spc1000_vdp_exp_device::vdp_interrupt(int state)
{
// nothing here?
}
diff --git a/src/devices/bus/spc1000/vdp.h b/src/devices/bus/spc1000/vdp.h
index 989b25d5a90..3f7bdf31dfe 100644
--- a/src/devices/bus/spc1000/vdp.h
+++ b/src/devices/bus/spc1000/vdp.h
@@ -30,7 +30,7 @@ protected:
virtual uint8_t read(offs_t offset) override;
virtual void write(offs_t offset, uint8_t data) override;
- DECLARE_WRITE_LINE_MEMBER(vdp_interrupt);
+ void vdp_interrupt(int state);
private:
// internal state
diff --git a/src/devices/bus/spectrum/beta.cpp b/src/devices/bus/spectrum/beta.cpp
index 8578cf46b3d..c159b625df7 100644
--- a/src/devices/bus/spectrum/beta.cpp
+++ b/src/devices/bus/spectrum/beta.cpp
@@ -96,6 +96,8 @@
#include "emu.h"
#include "beta.h"
+#include "formats/trd_dsk.h"
+
/***************************************************************************
DEVICE DEFINITIONS
@@ -475,9 +477,9 @@ void spectrum_betav2_device::device_reset()
// IMPLEMENTATION
//**************************************************************************
-READ_LINE_MEMBER(spectrum_betav2_device::romcs)
+bool spectrum_betav2_device::romcs()
{
- return m_romcs | m_exp->romcs();
+ return m_romcs || m_exp->romcs();
}
void spectrum_betav2_device::fetch(offs_t offset)
diff --git a/src/devices/bus/spectrum/beta.h b/src/devices/bus/spectrum/beta.h
index 1827c741355..3dac22f95d3 100644
--- a/src/devices/bus/spectrum/beta.h
+++ b/src/devices/bus/spectrum/beta.h
@@ -15,7 +15,6 @@
#include "machine/wd_fdc.h"
#include "machine/i8255.h"
#include "machine/6850acia.h"
-#include "formats/trd_dsk.h"
//**************************************************************************
// TYPE DEFINITIONS
@@ -48,7 +47,7 @@ protected:
virtual uint8_t mreq_r(offs_t offset) override;
virtual uint8_t iorq_r(offs_t offset) override;
virtual void iorq_w(offs_t offset, uint8_t data) override;
- virtual DECLARE_READ_LINE_MEMBER(romcs) override;
+ virtual bool romcs() override;
// passthru
virtual void post_opcode_fetch(offs_t offset) override { m_exp->post_opcode_fetch(offset); }
@@ -60,7 +59,7 @@ protected:
required_device_array<floppy_connector, 4> m_floppy;
required_device<spectrum_expansion_slot_device> m_exp;
- int m_romcs;
+ bool m_romcs;
u8 m_masterdisable;
u8 m_control;
bool m_motor_active;
@@ -154,7 +153,7 @@ protected:
virtual const tiny_rom_entry *device_rom_region() const override;
virtual uint8_t iorq_r(offs_t offset) override;
virtual void iorq_w(offs_t offset, uint8_t data) override;
- virtual DECLARE_READ_LINE_MEMBER(romcs) override { return 1; }
+ virtual bool romcs() override { return 1; }
required_device<i8255_device> m_ppi;
required_device<acia6850_device> m_acia;
diff --git a/src/devices/bus/spectrum/beta128.cpp b/src/devices/bus/spectrum/beta128.cpp
index 09b95763a27..b97159c46fc 100644
--- a/src/devices/bus/spectrum/beta128.cpp
+++ b/src/devices/bus/spectrum/beta128.cpp
@@ -21,6 +21,8 @@
#include "emu.h"
#include "beta128.h"
+#include "formats/trd_dsk.h"
+
/***************************************************************************
DEVICE DEFINITIONS
@@ -175,9 +177,9 @@ void spectrum_beta128_device::device_reset()
// IMPLEMENTATION
//**************************************************************************
-READ_LINE_MEMBER(spectrum_beta128_device::romcs)
+bool spectrum_beta128_device::romcs()
{
- return m_romcs | m_exp->romcs();
+ return m_romcs || m_exp->romcs();
}
diff --git a/src/devices/bus/spectrum/beta128.h b/src/devices/bus/spectrum/beta128.h
index bcbc889c94d..3201e9ecf6e 100644
--- a/src/devices/bus/spectrum/beta128.h
+++ b/src/devices/bus/spectrum/beta128.h
@@ -12,7 +12,6 @@
#include "softlist.h"
#include "imagedev/floppy.h"
#include "machine/wd_fdc.h"
-#include "formats/trd_dsk.h"
//**************************************************************************
// TYPE DEFINITIONS
@@ -44,7 +43,7 @@ protected:
virtual uint8_t mreq_r(offs_t offset) override;
virtual uint8_t iorq_r(offs_t offset) override;
virtual void iorq_w(offs_t offset, uint8_t data) override;
- virtual DECLARE_READ_LINE_MEMBER(romcs) override;
+ virtual bool romcs() override;
// passthru
virtual void post_opcode_fetch(offs_t offset) override { m_exp->post_opcode_fetch(offset); }
@@ -58,7 +57,7 @@ protected:
required_device<spectrum_expansion_slot_device> m_exp;
required_ioport m_switch;
- int m_romcs;
+ bool m_romcs;
u8 m_control;
bool m_motor_active;
bool m_128rom_bit;
diff --git a/src/devices/bus/spectrum/d40.cpp b/src/devices/bus/spectrum/d40.cpp
index 9a7811b7936..f7c5f5c28ed 100644
--- a/src/devices/bus/spectrum/d40.cpp
+++ b/src/devices/bus/spectrum/d40.cpp
@@ -211,7 +211,7 @@ void spectrum_d40base_device::device_reset()
// IMPLEMENTATION spectrum_d40base_device
//**************************************************************************
-READ_LINE_MEMBER(spectrum_d40base_device::romcs)
+bool spectrum_d40base_device::romcs()
{
return m_romcs;
}
diff --git a/src/devices/bus/spectrum/d40.h b/src/devices/bus/spectrum/d40.h
index 250b2feccd8..b3f3b856217 100644
--- a/src/devices/bus/spectrum/d40.h
+++ b/src/devices/bus/spectrum/d40.h
@@ -17,7 +17,6 @@
#include "machine/wd_fdc.h"
#include "machine/upd765.h"
#include "machine/i8255.h"
-#include "formats/pc_dsk.h"
//**************************************************************************
// TYPE DEFINITIONS
@@ -43,7 +42,7 @@ protected:
virtual void mreq_w(offs_t offset, uint8_t data) override;
virtual uint8_t iorq_r(offs_t offset) override;
virtual void iorq_w(offs_t offset, uint8_t data) override;
- virtual DECLARE_READ_LINE_MEMBER(romcs) override;
+ virtual bool romcs() override;
virtual uint8_t fdc0_r(offs_t offset) { return 0xff; }
virtual uint8_t fdc1_r(offs_t offset) { return 0xff; }
@@ -55,7 +54,7 @@ protected:
required_device<i8255_device> m_ppi;
required_ioport m_snap;
- int m_romcs;
+ bool m_romcs;
uint8_t m_ram[2 * 1024];
int m_snap_flag;
int m_8255_reset;
diff --git a/src/devices/bus/spectrum/exp.cpp b/src/devices/bus/spectrum/exp.cpp
index a0c79eeaec8..90015c8c72a 100644
--- a/src/devices/bus/spectrum/exp.cpp
+++ b/src/devices/bus/spectrum/exp.cpp
@@ -46,7 +46,7 @@ spectrum_expansion_slot_device::spectrum_expansion_slot_device(const machine_con
m_card(nullptr),
m_irq_handler(*this),
m_nmi_handler(*this),
- m_fb_r_handler(*this)
+ m_fb_r_handler(*this, 0xff)
{
}
@@ -58,18 +58,13 @@ spectrum_expansion_slot_device::spectrum_expansion_slot_device(const machine_con
void spectrum_expansion_slot_device::device_start()
{
m_card = get_card_device();
-
- // resolve callbacks
- m_irq_handler.resolve_safe();
- m_nmi_handler.resolve_safe();
- m_fb_r_handler.resolve_safe(0xff);
}
//-------------------------------------------------
// romcs
//-------------------------------------------------
-READ_LINE_MEMBER(spectrum_expansion_slot_device::romcs)
+bool spectrum_expansion_slot_device::romcs()
{
if (m_card)
return m_card->romcs();
@@ -183,6 +178,7 @@ void spectrum_expansion_slot_device::mreq_w(offs_t offset, uint8_t data)
#include "uslot.h"
#include "usource.h"
#include "uspeech.h"
+#include "vtx5000.h"
#include "wafa.h"
void spectrum_expansion_devices(device_slot_interface &device)
@@ -233,6 +229,7 @@ void spectrum_expansion_devices(device_slot_interface &device)
device.option_add("uslot", SPECTRUM_USLOT);
device.option_add("usource", SPECTRUM_USOURCE);
device.option_add("uspeech", SPECTRUM_USPEECH);
+ device.option_add("vtx5000", SPECTRUM_VTX5000);
device.option_add("wafadrive", SPECTRUM_WAFA);
}
diff --git a/src/devices/bus/spectrum/exp.h b/src/devices/bus/spectrum/exp.h
index 04e3e942889..677d23d6f9e 100644
--- a/src/devices/bus/spectrum/exp.h
+++ b/src/devices/bus/spectrum/exp.h
@@ -87,10 +87,10 @@ public:
void mreq_w(offs_t offset, uint8_t data);
uint8_t iorq_r(offs_t offset);
void iorq_w(offs_t offset, uint8_t data);
- DECLARE_READ_LINE_MEMBER( romcs );
+ bool romcs();
- DECLARE_WRITE_LINE_MEMBER( irq_w ) { m_irq_handler(state); }
- DECLARE_WRITE_LINE_MEMBER( nmi_w ) { m_nmi_handler(state); }
+ void irq_w(int state) { m_irq_handler(state); }
+ void nmi_w(int state) { m_nmi_handler(state); }
uint8_t fb_r() { return m_fb_r_handler(); }
protected:
@@ -120,7 +120,7 @@ public:
virtual void mreq_w(offs_t offset, uint8_t data) { }
virtual uint8_t iorq_r(offs_t offset) { return offset & 1 ? m_slot->fb_r() : 0xff; }
virtual void iorq_w(offs_t offset, uint8_t data) { }
- virtual DECLARE_READ_LINE_MEMBER(romcs) { return 0; }
+ virtual bool romcs() { return 0; }
protected:
// construction/destruction
diff --git a/src/devices/bus/spectrum/floppyone.cpp b/src/devices/bus/spectrum/floppyone.cpp
index 4291199501d..063864764f1 100644
--- a/src/devices/bus/spectrum/floppyone.cpp
+++ b/src/devices/bus/spectrum/floppyone.cpp
@@ -33,6 +33,8 @@
#include "emu.h"
#include "floppyone.h"
+#include "formats/fl1_dsk.h"
+
/***************************************************************************
DEVICE DEFINITIONS
@@ -193,9 +195,9 @@ void spectrum_flpone_device::device_reset()
// IMPLEMENTATION
//**************************************************************************
-READ_LINE_MEMBER(spectrum_flpone_device::romcs)
+bool spectrum_flpone_device::romcs()
{
- return m_romcs | m_exp->romcs();
+ return m_romcs || m_exp->romcs();
}
void spectrum_flpone_device::post_opcode_fetch(offs_t offset)
diff --git a/src/devices/bus/spectrum/floppyone.h b/src/devices/bus/spectrum/floppyone.h
index 8eeea6bad0f..1020dac7518 100644
--- a/src/devices/bus/spectrum/floppyone.h
+++ b/src/devices/bus/spectrum/floppyone.h
@@ -10,12 +10,10 @@
#define MAME_BUS_SPECTRUM_FLPONE_H
#include "exp.h"
-#include "softlist.h"
#include "imagedev/floppy.h"
#include "machine/wd_fdc.h"
#include "bus/centronics/ctronics.h"
#include "bus/rs232/rs232.h"
-#include "formats/fl1_dsk.h"
//**************************************************************************
// TYPE DEFINITIONS
@@ -47,7 +45,7 @@ protected:
virtual void post_opcode_fetch(offs_t offset) override;
virtual uint8_t mreq_r(offs_t offset) override;
virtual void mreq_w(offs_t offset, uint8_t data) override;
- virtual DECLARE_READ_LINE_MEMBER(romcs) override;
+ virtual bool romcs() override;
// passthru
virtual void pre_opcode_fetch(offs_t offset) override { m_exp->pre_opcode_fetch(offset); }
@@ -56,7 +54,7 @@ protected:
virtual uint8_t iorq_r(offs_t offset) override { return m_exp->iorq_r(offset); }
virtual void iorq_w(offs_t offset, uint8_t data) override { m_exp->iorq_w(offset, data); }
- DECLARE_WRITE_LINE_MEMBER(busy_w) { m_busy = state; }
+ void busy_w(int state) { m_busy = state; }
required_memory_region m_rom;
required_memory_region m_prom;
@@ -68,7 +66,7 @@ protected:
required_ioport m_sw1;
required_ioport m_sw2;
- int m_romcs, m_if1cs;
+ bool m_romcs, m_if1cs;
u8 m_ram[0x1000];
int m_busy;
uint8_t m_shifter;
diff --git a/src/devices/bus/spectrum/fuller.h b/src/devices/bus/spectrum/fuller.h
index fa16ec01579..70c776a81a2 100644
--- a/src/devices/bus/spectrum/fuller.h
+++ b/src/devices/bus/spectrum/fuller.h
@@ -47,7 +47,7 @@ protected:
virtual void post_data_fetch(offs_t offset) override { m_exp->post_data_fetch(offset); }
virtual uint8_t mreq_r(offs_t offset) override { return m_exp->romcs() ? m_exp->mreq_r(offset) : 0xff; }
virtual void mreq_w(offs_t offset, uint8_t data) override { if (m_exp->romcs()) m_exp->mreq_w(offset, data); }
- virtual DECLARE_READ_LINE_MEMBER(romcs) override { return m_exp->romcs(); }
+ virtual bool romcs() override { return m_exp->romcs(); }
private:
required_device<spectrum_expansion_slot_device> m_exp;
diff --git a/src/devices/bus/spectrum/intf1.cpp b/src/devices/bus/spectrum/intf1.cpp
index df40de1f9d6..f80a02723ef 100644
--- a/src/devices/bus/spectrum/intf1.cpp
+++ b/src/devices/bus/spectrum/intf1.cpp
@@ -105,9 +105,9 @@ void spectrum_intf1_device::device_reset()
// IMPLEMENTATION
//**************************************************************************
-READ_LINE_MEMBER(spectrum_intf1_device::romcs)
+bool spectrum_intf1_device::romcs()
{
- return m_romcs | m_exp->romcs();
+ return m_romcs || m_exp->romcs();
}
// the Interface 1 looks for specific bus conditions to enable / disable the expansion overlay ROM
diff --git a/src/devices/bus/spectrum/intf1.h b/src/devices/bus/spectrum/intf1.h
index 787c64b843d..bd40d12f25b 100644
--- a/src/devices/bus/spectrum/intf1.h
+++ b/src/devices/bus/spectrum/intf1.h
@@ -42,7 +42,7 @@ protected:
virtual uint8_t mreq_r(offs_t offset) override;
virtual uint8_t iorq_r(offs_t offset) override;
virtual void iorq_w(offs_t offset, uint8_t data) override;
- virtual DECLARE_READ_LINE_MEMBER(romcs) override;
+ virtual bool romcs() override;
// passthru
virtual void pre_data_fetch(offs_t offset) override { m_exp->pre_data_fetch(offset); }
@@ -56,7 +56,7 @@ private:
required_device<microdrive_image_device> m_mdv2;
required_memory_region m_rom;
- int m_romcs;
+ bool m_romcs;
};
diff --git a/src/devices/bus/spectrum/intf2.cpp b/src/devices/bus/spectrum/intf2.cpp
index 5b407d88df3..514a7e42151 100644
--- a/src/devices/bus/spectrum/intf2.cpp
+++ b/src/devices/bus/spectrum/intf2.cpp
@@ -96,21 +96,18 @@ void spectrum_intf2_device::device_start()
DEVICE_IMAGE_LOAD_MEMBER(spectrum_intf2_device::cart_load)
{
- uint32_t size = m_cart->common_get_size("rom");
+ uint32_t const size = m_cart->common_get_size("rom");
if (size != 0x4000)
- {
- image.seterror(image_error::INVALIDIMAGE, "Unsupported cartridge size");
- return image_init_result::FAIL;
- }
+ return std::make_pair(image_error::INVALIDLENGTH, "Unsupported cartridge size (only 16K supported)");
m_cart->rom_alloc(size, GENERIC_ROM8_WIDTH, ENDIANNESS_LITTLE);
m_cart->common_load_rom(m_cart->get_rom_base(), size, "rom");
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
-READ_LINE_MEMBER(spectrum_intf2_device::romcs)
+bool spectrum_intf2_device::romcs()
{
if (m_cart && m_cart->exists())
return 1;
diff --git a/src/devices/bus/spectrum/intf2.h b/src/devices/bus/spectrum/intf2.h
index 4faecbae93a..cbb2a18ca45 100644
--- a/src/devices/bus/spectrum/intf2.h
+++ b/src/devices/bus/spectrum/intf2.h
@@ -34,12 +34,12 @@ protected:
virtual void device_add_mconfig(machine_config &config) override;
virtual ioport_constructor device_input_ports() const override;
- virtual DECLARE_READ_LINE_MEMBER(romcs) override;
+ virtual bool romcs() override;
virtual uint8_t mreq_r(offs_t offset) override;
virtual uint8_t iorq_r(offs_t offset) override;
private:
- image_init_result load_cart(device_image_interface &image, generic_slot_device *slot);
+ std::error_condition load_cart(device_image_interface &image, generic_slot_device *slot);
DECLARE_DEVICE_IMAGE_LOAD_MEMBER(cart_load);
required_device<generic_slot_device> m_cart;
diff --git a/src/devices/bus/spectrum/kempdisc.cpp b/src/devices/bus/spectrum/kempdisc.cpp
index 32573ebf969..059403959fa 100644
--- a/src/devices/bus/spectrum/kempdisc.cpp
+++ b/src/devices/bus/spectrum/kempdisc.cpp
@@ -162,9 +162,9 @@ void spectrum_kempdisc_device::device_reset()
// IMPLEMENTATION
//**************************************************************************
-READ_LINE_MEMBER(spectrum_kempdisc_device::romcs)
+bool spectrum_kempdisc_device::romcs()
{
- return m_romcs | m_exp->romcs();
+ return m_romcs || m_exp->romcs();
}
diff --git a/src/devices/bus/spectrum/kempdisc.h b/src/devices/bus/spectrum/kempdisc.h
index 3a3b5118402..9737da16887 100644
--- a/src/devices/bus/spectrum/kempdisc.h
+++ b/src/devices/bus/spectrum/kempdisc.h
@@ -12,7 +12,6 @@
#include "softlist.h"
#include "imagedev/floppy.h"
#include "machine/wd_fdc.h"
-#include "formats/dsk_dsk.h"
//**************************************************************************
// TYPE DEFINITIONS
@@ -42,7 +41,7 @@ protected:
virtual uint8_t mreq_r(offs_t offset) override;
virtual uint8_t iorq_r(offs_t offset) override;
virtual void iorq_w(offs_t offset, uint8_t data) override;
- virtual DECLARE_READ_LINE_MEMBER(romcs) override;
+ virtual bool romcs() override;
// passthru
virtual void pre_opcode_fetch(offs_t offset) override { m_exp->pre_opcode_fetch(offset); }
@@ -56,7 +55,7 @@ protected:
required_device_array<floppy_connector, 4> m_floppy;
required_device<spectrum_expansion_slot_device> m_exp;
- int m_romcs;
+ bool m_romcs;
// u8 m_control;
};
diff --git a/src/devices/bus/spectrum/logitek.cpp b/src/devices/bus/spectrum/logitek.cpp
index 6406231ce47..cc93252fc55 100644
--- a/src/devices/bus/spectrum/logitek.cpp
+++ b/src/devices/bus/spectrum/logitek.cpp
@@ -127,7 +127,7 @@ void spectrum_proceed_device::device_reset()
// IMPLEMENTATION
//**************************************************************************
-READ_LINE_MEMBER(spectrum_proceed_device::romcs)
+bool spectrum_proceed_device::romcs()
{
return m_romcs;
}
diff --git a/src/devices/bus/spectrum/logitek.h b/src/devices/bus/spectrum/logitek.h
index a6d807d7236..01236da2dde 100644
--- a/src/devices/bus/spectrum/logitek.h
+++ b/src/devices/bus/spectrum/logitek.h
@@ -50,7 +50,7 @@ protected:
virtual uint8_t mreq_r(offs_t offset) override;
virtual uint8_t iorq_r(offs_t offset) override;
virtual void iorq_w(offs_t offset, uint8_t data) override;
- virtual DECLARE_READ_LINE_MEMBER(romcs) override;
+ virtual bool romcs() override;
required_memory_region m_rom;
required_device<z80pio_device> m_z80pio;
@@ -61,7 +61,7 @@ protected:
void piob_w(uint8_t data);
uint8_t piob_r();
- int m_romcs;
+ bool m_romcs;
int m_romen;
};
diff --git a/src/devices/bus/spectrum/lprint.cpp b/src/devices/bus/spectrum/lprint.cpp
index 912c26d6c74..92b1e8d533e 100644
--- a/src/devices/bus/spectrum/lprint.cpp
+++ b/src/devices/bus/spectrum/lprint.cpp
@@ -251,7 +251,7 @@ void spectrum_kempcentre_device::device_reset()
// IMPLEMENTATION (lprint)
//**************************************************************************
-READ_LINE_MEMBER(spectrum_lprint_device::romcs)
+bool spectrum_lprint_device::romcs()
{
return m_romcs;
}
@@ -315,9 +315,9 @@ void spectrum_lprint_device::iorq_w(offs_t offset, uint8_t data)
// IMPLEMENTATION (lprint3)
//**************************************************************************
-READ_LINE_MEMBER(spectrum_lprint3_device::romcs)
+bool spectrum_lprint3_device::romcs()
{
- return m_romcs | m_exp->romcs();
+ return m_romcs || m_exp->romcs();
}
uint8_t spectrum_lprint3_device::iorq_r(offs_t offset)
@@ -414,7 +414,7 @@ void spectrum_kempcentrs_device::iorq_w(offs_t offset, uint8_t data)
// IMPLEMENTATION (kempcentre)
//**************************************************************************
-READ_LINE_MEMBER(spectrum_kempcentre_device::romcs)
+bool spectrum_kempcentre_device::romcs()
{
return m_romcs;
}
diff --git a/src/devices/bus/spectrum/lprint.h b/src/devices/bus/spectrum/lprint.h
index d58793607c6..f8a1f135096 100644
--- a/src/devices/bus/spectrum/lprint.h
+++ b/src/devices/bus/spectrum/lprint.h
@@ -39,14 +39,14 @@ protected:
virtual uint8_t mreq_r(offs_t offset) override;
virtual uint8_t iorq_r(offs_t offset) override;
virtual void iorq_w(offs_t offset, uint8_t data) override;
- virtual DECLARE_READ_LINE_MEMBER(romcs) override;
+ virtual bool romcs() override;
- DECLARE_WRITE_LINE_MEMBER(busy_w) { m_busy = state; }
+ void busy_w(int state) { m_busy = state; }
required_memory_region m_rom;
required_device<centronics_device> m_centronics;
- int m_romcs;
+ bool m_romcs;
int m_busy;
};
@@ -71,7 +71,7 @@ protected:
virtual uint8_t mreq_r(offs_t offset) override;
virtual uint8_t iorq_r(offs_t offset) override;
virtual void iorq_w(offs_t offset, uint8_t data) override;
- virtual DECLARE_READ_LINE_MEMBER(romcs) override;
+ virtual bool romcs() override;
// passthru
virtual void pre_opcode_fetch(offs_t offset) override { m_exp->pre_opcode_fetch(offset); }
@@ -80,14 +80,14 @@ protected:
virtual void post_data_fetch(offs_t offset) override { m_exp->post_data_fetch(offset); }
virtual void mreq_w(offs_t offset, uint8_t data) override { if (m_exp->romcs()) m_exp->mreq_w(offset, data); }
- DECLARE_WRITE_LINE_MEMBER(busy_w) { m_busy = state; }
+ void busy_w(int state) { m_busy = state; }
required_memory_region m_rom;
required_device<centronics_device> m_centronics;
required_device<rs232_port_device> m_rs232;
required_device<spectrum_expansion_slot_device> m_exp;
- int m_romcs;
+ bool m_romcs;
int m_busy;
};
@@ -111,7 +111,7 @@ protected:
virtual uint8_t iorq_r(offs_t offset) override;
virtual void iorq_w(offs_t offset, uint8_t data) override;
- DECLARE_WRITE_LINE_MEMBER(busy_w) { m_busy = state; }
+ void busy_w(int state) { m_busy = state; }
required_device<centronics_device> m_centronics;
@@ -143,15 +143,15 @@ protected:
virtual uint8_t mreq_r(offs_t offset) override;
virtual uint8_t iorq_r(offs_t offset) override;
virtual void iorq_w(offs_t offset, uint8_t data) override;
- virtual DECLARE_READ_LINE_MEMBER(romcs) override;
+ virtual bool romcs() override;
- DECLARE_WRITE_LINE_MEMBER(busy_w) { m_busy = state; }
+ void busy_w(int state) { m_busy = state; }
required_memory_region m_rom;
required_device<centronics_device> m_centronics;
int m_active;
- int m_romcs;
+ bool m_romcs;
int m_busy;
};
diff --git a/src/devices/bus/spectrum/melodik.h b/src/devices/bus/spectrum/melodik.h
index 6c0d4f6b3fd..b5775e6438f 100644
--- a/src/devices/bus/spectrum/melodik.h
+++ b/src/devices/bus/spectrum/melodik.h
@@ -46,7 +46,7 @@ protected:
virtual void post_data_fetch(offs_t offset) override { m_exp->post_data_fetch(offset); }
virtual uint8_t mreq_r(offs_t offset) override { return m_exp->romcs() ? m_exp->mreq_r(offset) : 0xff; }
virtual void mreq_w(offs_t offset, uint8_t data) override { if (m_exp->romcs()) m_exp->mreq_w(offset, data); }
- virtual DECLARE_READ_LINE_MEMBER(romcs) override { return m_exp->romcs(); }
+ virtual bool romcs() override { return m_exp->romcs(); }
private:
required_device<spectrum_expansion_slot_device> m_exp;
diff --git a/src/devices/bus/spectrum/mface.cpp b/src/devices/bus/spectrum/mface.cpp
index 693b3eb4fcf..1c79316bcc9 100644
--- a/src/devices/bus/spectrum/mface.cpp
+++ b/src/devices/bus/spectrum/mface.cpp
@@ -50,7 +50,7 @@
This isn't enough to stop the clash so perhaps schematic is for some non-Beta-supporting version or has an error.
Assume for now the entire joystick is disabled as that's the only way Beta can work.
Beta support seems limited to Beta v3/plus (TR-DOS 3/4.xx) models, beta128 (TR-DOS 5.xx) doesn't work.
- Bios rom "mu21e7" has issues with Betaplus, doesn't work with betav3,beta128,betacbi, perhaps it's for some other interface entirely...?
+ BIOS rom "mu21e7" has issues with Betaplus, doesn't work with betav3,beta128,betacbi, perhaps it's for some other interface entirely...?
The enable/disable switch became necessary on later versions as games had started including checks to detect presence of the interface.
eg. Renegade ("The Hit Squad" re-release) whilst loading, reads from 0x9f specifically to cause the MF (if present) to page in and crash the machine.
@@ -509,9 +509,9 @@ void spectrum_mprint_device::device_reset()
// IMPLEMENTATION
//**************************************************************************
-READ_LINE_MEMBER(spectrum_mface_base_device::romcs)
+bool spectrum_mface_base_device::romcs()
{
- return m_romcs | m_exp->romcs();
+ return m_romcs || m_exp->romcs();
}
void spectrum_mface_base_device::pre_opcode_fetch(offs_t offset)
diff --git a/src/devices/bus/spectrum/mface.h b/src/devices/bus/spectrum/mface.h
index 7b3fbf03e72..c4c73f3d931 100644
--- a/src/devices/bus/spectrum/mface.h
+++ b/src/devices/bus/spectrum/mface.h
@@ -39,7 +39,7 @@ protected:
virtual void pre_opcode_fetch(offs_t offset) override;
virtual uint8_t mreq_r(offs_t offset) override;
virtual void mreq_w(offs_t offset, uint8_t data) override;
- virtual DECLARE_READ_LINE_MEMBER(romcs) override;
+ virtual bool romcs() override;
// passthru
virtual void post_opcode_fetch(offs_t offset) override { m_exp->post_opcode_fetch(offset); }
@@ -53,7 +53,7 @@ protected:
required_memory_region m_rom;
required_device<spectrum_expansion_slot_device> m_exp;
- int m_romcs;
+ bool m_romcs;
int m_nmi_pending;
std::unique_ptr<uint8_t[]> m_ram;
};
@@ -223,7 +223,7 @@ protected:
virtual void iorq_w(offs_t offset, uint8_t data) override;
private:
- DECLARE_WRITE_LINE_MEMBER(busy_w) { m_busy = state; }
+ void busy_w(int state) { m_busy = state; }
required_device<centronics_device> m_centronics;
diff --git a/src/devices/bus/spectrum/mgt.cpp b/src/devices/bus/spectrum/mgt.cpp
index 581a748dcea..265db2d7301 100644
--- a/src/devices/bus/spectrum/mgt.cpp
+++ b/src/devices/bus/spectrum/mgt.cpp
@@ -151,11 +151,12 @@
**********************************************************************/
-
#include "emu.h"
#include "mgt.h"
#include "softlist_dev.h"
+#include "formats/coupedsk.h"
+
//**************************************************************************
// DEVICE DEFINITIONS
@@ -403,7 +404,7 @@ void spectrum_disciple_device::device_reset()
// IMPLEMENTATION spectrum_plusd_device
//**************************************************************************
-READ_LINE_MEMBER(spectrum_plusd_device::romcs)
+bool spectrum_plusd_device::romcs()
{
return m_romcs;
}
@@ -530,7 +531,7 @@ INPUT_CHANGED_MEMBER(spectrum_plusd_device::snapshot_button)
}
}
-WRITE_LINE_MEMBER(spectrum_plusd_device::busy_w)
+void spectrum_plusd_device::busy_w(int state)
{
m_centronics_busy = state;
}
@@ -539,9 +540,9 @@ WRITE_LINE_MEMBER(spectrum_plusd_device::busy_w)
// IMPLEMENTATION spectrum_disciple_device
//**************************************************************************
-READ_LINE_MEMBER(spectrum_disciple_device::romcs)
+bool spectrum_disciple_device::romcs()
{
- return m_romcs | m_exp->romcs();
+ return m_romcs || m_exp->romcs();
}
void spectrum_disciple_device::pre_opcode_fetch(offs_t offset)
diff --git a/src/devices/bus/spectrum/mgt.h b/src/devices/bus/spectrum/mgt.h
index 35d168b10ae..b40b18c5711 100644
--- a/src/devices/bus/spectrum/mgt.h
+++ b/src/devices/bus/spectrum/mgt.h
@@ -19,7 +19,6 @@
#include "imagedev/floppy.h"
#include "machine/wd_fdc.h"
#include "bus/centronics/ctronics.h"
-#include "formats/coupedsk.h"
//**************************************************************************
// TYPE DEFINITIONS
@@ -51,16 +50,16 @@ protected:
virtual void mreq_w(offs_t offset, uint8_t data) override;
virtual uint8_t iorq_r(offs_t offset) override;
virtual void iorq_w(offs_t offset, uint8_t data) override;
- virtual DECLARE_READ_LINE_MEMBER(romcs) override;
+ virtual bool romcs() override;
- DECLARE_WRITE_LINE_MEMBER(busy_w);
+ void busy_w(int state);
required_memory_region m_rom;
required_device<wd_fdc_device_base> m_fdc;
required_device_array<floppy_connector, 2> m_floppy;
required_device<centronics_device> m_centronics;
- int m_romcs;
+ bool m_romcs;
uint8_t m_ram[8 * 1024];
bool m_centronics_busy;
};
@@ -88,7 +87,7 @@ protected:
virtual void mreq_w(offs_t offset, uint8_t data) override;
virtual uint8_t iorq_r(offs_t offset) override;
virtual void iorq_w(offs_t offset, uint8_t data) override;
- virtual DECLARE_READ_LINE_MEMBER(romcs) override;
+ virtual bool romcs() override;
TIMER_CALLBACK_MEMBER(reset_tick);
diff --git a/src/devices/bus/spectrum/mikroplus.cpp b/src/devices/bus/spectrum/mikroplus.cpp
index 9f46bc1b7db..76681e372f9 100644
--- a/src/devices/bus/spectrum/mikroplus.cpp
+++ b/src/devices/bus/spectrum/mikroplus.cpp
@@ -100,7 +100,7 @@ uint8_t spectrum_mikroplus_device::iorq_r(offs_t offset)
return data;
}
-READ_LINE_MEMBER(spectrum_mikroplus_device::romcs)
+bool spectrum_mikroplus_device::romcs()
{
return 1;
}
diff --git a/src/devices/bus/spectrum/mikroplus.h b/src/devices/bus/spectrum/mikroplus.h
index e06cb38bb2c..2ac3bb08fb1 100644
--- a/src/devices/bus/spectrum/mikroplus.h
+++ b/src/devices/bus/spectrum/mikroplus.h
@@ -36,7 +36,7 @@ protected:
virtual const tiny_rom_entry *device_rom_region() const override;
virtual ioport_constructor device_input_ports() const override;
- virtual DECLARE_READ_LINE_MEMBER(romcs) override;
+ virtual bool romcs() override;
virtual uint8_t mreq_r(offs_t offset) override;
virtual uint8_t iorq_r(offs_t offset) override;
diff --git a/src/devices/bus/spectrum/mpoker.cpp b/src/devices/bus/spectrum/mpoker.cpp
index c2d84d13c1b..99be5b63f55 100644
--- a/src/devices/bus/spectrum/mpoker.cpp
+++ b/src/devices/bus/spectrum/mpoker.cpp
@@ -129,7 +129,7 @@ void spectrum_mpoker_device::device_reset()
// IMPLEMENTATION
//**************************************************************************
-READ_LINE_MEMBER(spectrum_mpoker_device::romcs)
+bool spectrum_mpoker_device::romcs()
{
return m_romcs;
}
diff --git a/src/devices/bus/spectrum/mpoker.h b/src/devices/bus/spectrum/mpoker.h
index 27f7cef19b0..12e72154d5e 100644
--- a/src/devices/bus/spectrum/mpoker.h
+++ b/src/devices/bus/spectrum/mpoker.h
@@ -36,11 +36,11 @@ protected:
virtual uint8_t mreq_r(offs_t offset) override;
virtual void iorq_w(offs_t offset, uint8_t data) override;
- virtual DECLARE_READ_LINE_MEMBER(romcs) override;
+ virtual bool romcs() override;
required_memory_region m_rom;
- int m_romcs;
+ bool m_romcs;
};
// device type definition
diff --git a/src/devices/bus/spectrum/nemoide.cpp b/src/devices/bus/spectrum/nemoide.cpp
new file mode 100644
index 00000000000..dd1797ec374
--- /dev/null
+++ b/src/devices/bus/spectrum/nemoide.cpp
@@ -0,0 +1,85 @@
+// license:BSD-3-Clause
+// copyright-holders:Andrei I. Holub
+
+#include "emu.h"
+#include "nemoide.h"
+
+#include "bus/ata/ataintf.h"
+#include "bus/ata/atapicdr.h"
+#include "bus/ata/hdd.h"
+
+namespace bus::spectrum::zxbus {
+
+namespace {
+
+class nemoide_device : public device_t, public device_zxbus_card_interface
+{
+public:
+ nemoide_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, ZXBUS_NEMOIDE, tag, owner, clock)
+ , device_zxbus_card_interface(mconfig, *this)
+ , m_ata(*this, "ata")
+ { }
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_start() override;
+
+private:
+ void map_io(address_map &map);
+
+ u8 ata_r(offs_t offset);
+ void ata_w(offs_t offset, u8 data);
+
+ required_device<ata_interface_device> m_ata;
+
+ u8 m_ata_data_latch;
+};
+
+u8 nemoide_device::ata_r(offs_t offset)
+{
+ const u16 data = m_ata->cs0_r((offset >> 5) & 7);
+ if (!machine().side_effects_disabled())
+ m_ata_data_latch = data >> 8;
+
+ return data & 0xff;
+}
+
+void nemoide_device::ata_w(offs_t offset, u8 data)
+{
+ const u16 ata_data = (m_ata_data_latch << 8) | data;
+ m_ata->cs0_w((offset >> 5) & 7, ata_data);
+}
+
+void nemoide_device::map_io(address_map &map)
+{
+ map(0x00011, 0x00011).mirror(0xff00).lrw8(NAME([this]() { return m_ata_data_latch; })
+ , NAME([this](offs_t offset, u8 data) { m_ata_data_latch = data; }));
+ map(0x00010, 0x00010).select(0xffe0).rw(FUNC(nemoide_device::ata_r), FUNC(nemoide_device::ata_w));
+ map(0x000c8, 0x000c8).mirror(0xff00).lrw8(NAME([this]() { return m_ata->cs1_r(6); })
+ , NAME([this](offs_t offset, u8 data) { m_ata->cs1_w(6, data); }));
+}
+
+static void nemoide_ata_devices(device_slot_interface &device)
+{
+ device.option_add("hdd", IDE_HARDDISK);
+ device.option_add("cdrom", ATAPI_CDROM);
+}
+
+void nemoide_device::device_add_mconfig(machine_config &config)
+{
+ ATA_INTERFACE(config, m_ata).options(nemoide_ata_devices, "hdd", "hdd", false);
+}
+
+void nemoide_device::device_start()
+{
+ save_item(NAME(m_ata_data_latch));
+
+ m_zxbus->install_device(0x00000, 0x1ffff, *this, &nemoide_device::map_io);
+}
+
+} // anonymous namespace
+
+} // namespace bus::spectrum::zxbus
+
+DEFINE_DEVICE_TYPE_PRIVATE(ZXBUS_NEMOIDE, device_zxbus_card_interface, bus::spectrum::zxbus::nemoide_device, "zxbus_nemoide", "Nemo IDE Controller")
diff --git a/src/devices/bus/spectrum/nemoide.h b/src/devices/bus/spectrum/nemoide.h
new file mode 100644
index 00000000000..441f3c9514a
--- /dev/null
+++ b/src/devices/bus/spectrum/nemoide.h
@@ -0,0 +1,14 @@
+// license:BSD-3-Clause
+// copyright-holders:Andrei I. Holub
+
+#ifndef MAME_SINCLAIR_NEMOIDE_H
+#define MAME_SINCLAIR_NEMOIDE_H
+
+#pragma once
+
+#include "zxbus.h"
+
+
+DECLARE_DEVICE_TYPE(ZXBUS_NEMOIDE, device_zxbus_card_interface)
+
+#endif // MAME_SINCLAIR_NEMOIDE_H
diff --git a/src/devices/bus/spectrum/neogs.cpp b/src/devices/bus/spectrum/neogs.cpp
new file mode 100644
index 00000000000..e9d011a7aef
--- /dev/null
+++ b/src/devices/bus/spectrum/neogs.cpp
@@ -0,0 +1,484 @@
+// license:BSD-3-Clause
+// copyright-holders:Andrei I. Holub
+/*******************************************************************************************
+
+ Sound card NeoGS appropriate for playing trackers (MOD) and compressed (MP3) music on
+Spectrum-compatible computers with ZXBUS slot.
+
+Hardware:
+- Compatible with General Sound (GS);
+- Flexible scheme, based on fpga (Altera EP1K30);
+- 4Mb RAM, 512Kb flash-ROM;
+- Extended techniques of memory addressing: 2 memory windows in visible area, exclude ROM
+ from visible area;
+- Z80 frequency modes (10, 12, 20 and 24 Mhz);
+- Support up to 8 sound channels (for MOD);
+- SPI mp3-decoder (like VS1011);
+- SD-card SPI interface;
+- DMA to NeoGS memory (transfer data from ZX to NeoGS by instructions LDI, LDIR and similar);
+- Parallel working (NeoGS play music independently from ZX).
+
+Refs:
+ http://nedopc.com/gs/ngs_eng.php
+ https://github.com/psbhlw/gs-firmware
+ https://8bit.yarek.pl/interface/zx.generalsound/index.html
+
+TODO:
+- DMA
+- MP3
+
+*******************************************************************************************/
+
+#include "emu.h"
+#include "neogs.h"
+
+#include "cpu/z80/z80.h"
+#include "machine/ram.h"
+#include "machine/spi_sdcard.h"
+#include "sound/dac.h"
+#include "speaker.h"
+
+
+#define LOG_STATUS (1U << 1)
+#define LOG_WARN (1U << 2)
+
+#define VERBOSE ( /*LOG_GENERAL | LOG_STATUS |*/ LOG_WARN )
+#include "logmacro.h"
+
+#define LOGSTATUS(...) LOGMASKED(LOG_STATUS, __VA_ARGS__)
+#define LOGWARN(...) LOGMASKED(LOG_WARN, __VA_ARGS__)
+
+namespace bus::spectrum::zxbus {
+
+namespace {
+
+#define TIMINGS_PERFECT 1
+
+ROM_START( neogs )
+ ROM_REGION(0x80000, "maincpu", 0)
+ ROM_DEFAULT_BIOS("v1.10.2")
+
+ ROM_SYSTEM_BIOS(0, "v1.10.2", "v1.10 fix2")
+ ROMX_LOAD( "neogs110_fix2.rom", 0x0000, 0x80000, CRC(641a4976) SHA1(6409c111a8ca3314a52bdcfc3ba944b73c300987), ROM_BIOS(0))
+ ROM_SYSTEM_BIOS(1, "v1.08", "v1.08")
+ ROMX_LOAD( "neogs108.rom", 0x0000, 0x80000, CRC(8e261323) SHA1(b500b4aa8dea7506d26ad9e50593d9d3bee11ae1), ROM_BIOS(1))
+
+ ROM_SYSTEM_BIOS(2, "test_muchkin", "Test ROM (Muchkin)")
+ ROMX_LOAD( "testrom_muchkin.rom", 0x0000, 0x80000, CRC(8ab10a88) SHA1(cff3ca96489e517568146a00412107259360d01e), ROM_BIOS(2))
+ROM_END
+
+class neogs_device : public device_t, public device_zxbus_card_interface
+{
+public:
+ neogs_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, ZXBUS_NEOGS, tag, owner, clock)
+ , device_zxbus_card_interface(mconfig, *this)
+ , m_maincpu(*this, "maincpu")
+ , m_ram(*this, RAM_TAG)
+ , m_rom(*this, "maincpu")
+ , m_bank_rom(*this, "bank_rom")
+ , m_bank_ram(*this, "bank_ram")
+ , m_view(*this, "view")
+ , m_dac(*this, "dac%u", 0U)
+ , m_sdcard(*this, "sdcard")
+ , m_neogs_led(*this, "neogs_led")
+ { }
+
+protected:
+ // device_t implementation
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override;
+
+ void neogsmap(address_map &map);
+
+ INTERRUPT_GEN_MEMBER(irq0_line_assert);
+
+ void map_memory(address_map &map);
+ void map_io(address_map &map);
+ void update_config();
+
+ required_device<z80_device> m_maincpu;
+ required_device<ram_device> m_ram;
+ required_region_ptr<u8> m_rom;
+ memory_bank_creator m_bank_rom;
+ memory_bank_creator m_bank_ram;
+ memory_view m_view;
+ required_device_array<dac_word_interface, 2> m_dac;
+ required_device<spi_sdcard_sdhc_device> m_sdcard;
+ output_finder<> m_neogs_led;
+
+private:
+ TIMER_CALLBACK_MEMBER(spi_clock);
+
+ template <u8 Bank> u8 ram_bank_r(offs_t offset);
+ template <u8 Bank> void ram_bank_w(offs_t offset, u8 data);
+
+ u8 neogs_status_r();
+ void neogs_command_w(u8 data);
+ u8 neogs_data_r();
+ void neogs_data_w(u8 data);
+ void neogs_ctrl_w(u8 data);
+
+ void status_reset();
+ u8 data_r();
+ void data_w(u8 data);
+
+ void dac_flush();
+
+ void spi_ctrl_w(u8 data);
+ u8 sd_r();
+ void sd_w(u8 data);
+
+ u8 m_data_in;
+ u8 m_data_out;
+ u8 m_command_in;
+ u8 m_status;
+
+ u8 m_spi_ctrl;
+ u8 m_spi_data_out;
+ u8 m_spi_data_in_latch;
+
+ emu_timer *m_spi_clock;
+ int m_spi_clock_cycles;
+ bool m_spi_clock_state;
+
+ u8 m_mpag;
+ u8 m_mpagx;
+ u8 m_gscfg0;
+ u8 m_vol[8];
+ u8 m_sample[8];
+};
+
+void neogs_device::update_config()
+{
+ if (m_gscfg0 & 4) // EXPAG
+ ;
+
+ if (m_gscfg0 & 1) // NOROM
+ {
+ m_bank_ram->set_entry(m_mpag % (m_ram->size() / 0x8000));
+ m_view.select(BIT(m_gscfg0, 1)); // RAMRO
+ }
+ else
+ {
+ m_bank_rom->set_entry(m_mpag % (m_rom.bytes() / 0x8000));
+ m_view.disable();
+ }
+
+ const double cpu_scale = (BIT(m_gscfg0, 5) ? 1 : 1.2) * (1 << BIT(~m_gscfg0, 4));
+ m_maincpu->set_clock_scale(cpu_scale);
+}
+
+u8 neogs_device::neogs_status_r()
+{
+ if (!machine().side_effects_disabled())
+ LOGSTATUS(" read STAT & %02X\n", m_status);
+ return m_status | 0x7e;
+}
+
+void neogs_device::neogs_command_w(u8 data)
+{
+ m_status |= 0x01;
+ LOGSTATUS("write CMD & %02X, status: %02X\n", data, m_status);
+ m_command_in = data;
+}
+
+u8 neogs_device::neogs_data_r()
+{
+ if (!machine().side_effects_disabled())
+ {
+ m_status &= ~0x80;
+ LOGSTATUS(" read DATA & %02X, status: %02X\n", m_data_out, m_status);
+ }
+ return m_data_out;
+}
+
+void neogs_device::neogs_data_w(u8 data)
+{
+ m_status |= 0x80;
+ LOGSTATUS("write: DATA & %02X, status: %02X\n", data, m_status);
+ m_data_in = data;
+}
+
+void neogs_device::neogs_ctrl_w(u8 data)
+{
+ if (data & 0x80)
+ {
+ LOG("Reset Request\n");
+ reset();
+ }
+ if (data & 0x40)
+ {
+ LOG("NMI Request\n");
+ m_maincpu->pulse_input_line(INPUT_LINE_NMI, attotime::zero);
+ }
+ m_neogs_led = BIT(data, 5);
+}
+
+template <u8 Bank> u8 neogs_device::ram_bank_r(offs_t offset)
+{
+ return m_ram->read((0xc000 * Bank) + offset);
+}
+
+template <u8 Bank> void neogs_device::ram_bank_w(offs_t offset, u8 data)
+{
+ m_ram->write((0xc000 * Bank) + offset, data);
+}
+
+void neogs_device::status_reset()
+{
+ if (!machine().side_effects_disabled())
+ {
+ m_status &= ~0x01;
+ LOGSTATUS(" read: 05, status: %02X\n", m_status);
+ }
+}
+
+u8 neogs_device::data_r()
+{
+ if (!machine().side_effects_disabled())
+ {
+ m_status &= ~0x80;
+ LOGSTATUS(" read: 02 & %02X, status: %02X\n", m_data_in, m_status);
+ }
+ return m_data_in;
+}
+
+void neogs_device::data_w(u8 data)
+{
+ m_status |= 0x80;
+ LOGSTATUS("write: 03 & %02X, status: %02X\n", data, m_status);
+ m_data_out = data;
+}
+
+void neogs_device::spi_ctrl_w(u8 data)
+{
+ if (BIT(data, 7))
+ m_spi_ctrl |= (data & 0x0f);
+ else
+ m_spi_ctrl &= (~data & 0x0f);
+}
+
+u8 neogs_device::sd_r()
+{
+ u8 din = m_spi_data_in_latch;
+ if (!machine().side_effects_disabled())
+ sd_w(0xff);
+
+ return din;
+}
+
+void neogs_device::sd_w(u8 data)
+{
+ m_spi_data_out = data;
+#if TIMINGS_PERFECT
+ m_spi_clock_cycles = 8;
+ m_spi_clock->adjust(m_maincpu->clocks_to_attotime(1) / 4, 0, m_maincpu->clocks_to_attotime(1) / 4);
+#else
+ m_sdcard->spi_ss_w(BIT(~m_spi_ctrl, 0));
+ for (u8 m = 0x80; m; m >>= 1)
+ {
+ m_sdcard->spi_mosi_w(m_spi_data_out & m ? 1 : 0);
+ m_sdcard->spi_clock_w(CLEAR_LINE);
+ m_sdcard->spi_clock_w(ASSERT_LINE);
+ }
+#endif
+}
+
+void neogs_device::dac_flush()
+{
+ s16 left = 0;
+ s16 right = 0;
+ for (auto ch = 0; ch < 8; ch++)
+ {
+ const bool leftright = BIT(~ch, 1);
+ const u8 sample = m_sample[ch] ^ (m_gscfg0 & 0x80); // INV7B
+ const s16 out = (sample - 0x80) * m_vol[ch];
+ if (leftright)
+ left += out;
+ else
+ right += out;
+
+ if (BIT(m_gscfg0, 2) && BIT(m_gscfg0, 6)) // PAN4CH
+ ;
+ }
+ m_dac[0]->data_w(left);
+ m_dac[1]->data_w(right);
+}
+
+TIMER_CALLBACK_MEMBER(neogs_device::spi_clock)
+{
+ if (m_spi_clock_cycles > 0)
+ {
+ m_sdcard->spi_ss_w(BIT(~m_spi_ctrl, 0));
+
+ if (m_spi_clock_state)
+ {
+ m_sdcard->spi_clock_w(ASSERT_LINE);
+ m_spi_clock_cycles--;
+ }
+ else
+ {
+ m_sdcard->spi_mosi_w(BIT(m_spi_data_out, m_spi_clock_cycles - 1));
+ m_sdcard->spi_clock_w(CLEAR_LINE);
+ }
+
+ m_spi_clock_state = !m_spi_clock_state;
+ }
+ else
+ {
+ m_spi_clock_state = false;
+ m_spi_clock->adjust(attotime::never);
+ }
+}
+
+INTERRUPT_GEN_MEMBER(neogs_device::irq0_line_assert)
+{
+ dac_flush();
+ m_maincpu->pulse_input_line(INPUT_LINE_IRQ0, attotime::from_ticks(32, m_maincpu->clock()));
+}
+
+void neogs_device::map_memory(address_map &map)
+{
+ map(0x0000, 0x3fff).rom().region("maincpu", 0x0000);
+ map(0x4000, 0x7fff).rw(FUNC(neogs_device::ram_bank_r<1>), FUNC(neogs_device::ram_bank_w<1>));
+ map(0x8000, 0xffff).bankr(m_bank_rom);
+
+ map(0x0000, 0xffff).view(m_view);
+ m_view[0](0x0000, 0x3fff).rw(FUNC(neogs_device::ram_bank_r<0>), FUNC(neogs_device::ram_bank_w<0>));
+ m_view[0](0x8000, 0xffff).bankrw(m_bank_ram);
+ m_view[1](0x0000, 0x3fff).r(FUNC(neogs_device::ram_bank_r<0>));
+ m_view[1](0x8000, 0xffff).bankrw(m_bank_ram);
+}
+
+void neogs_device::map_io(address_map &map)
+{
+ map(0x0000, 0x0000).mirror(0xff00).lw8(
+ NAME([this](offs_t offset, u8 data) { m_mpag = data; update_config(); }));
+ map(0x0001, 0x0001).mirror(0xff00).lr8(
+ NAME([this](offs_t offset) { return m_command_in; }));
+ map(0x0002, 0x0002).mirror(0xff00).r(FUNC(neogs_device::data_r));
+ map(0x0003, 0x0003).mirror(0xff00).w(FUNC(neogs_device::data_w));
+ map(0x0004, 0x0004).mirror(0xff00).lr8(
+ NAME([this](offs_t offset) { return m_status; }));
+ map(0x0005, 0x0005).mirror(0xff00).lrw8(
+ NAME([this](offs_t offset) { status_reset(); return ~0; }),
+ NAME([this](offs_t offset, u8 data) { m_status &= ~0x01; LOGSTATUS("write: 05, status: %02X\n", m_status); }));
+ map(0x0006, 0x0009).mirror(0xff00).lw8(
+ NAME([this](offs_t offset, u8 data) { m_vol[offset] = data & 0x3f; }));
+ map(0x0016, 0x0019).mirror(0xff00).lw8(
+ NAME([this](offs_t offset, u8 data) { m_vol[4 + offset] = data & 0x3f; }));
+ map(0x0010, 0x0010).mirror(0xff00).lw8(
+ NAME([this](offs_t offset, u8 data) { m_mpagx = data; update_config(); }));
+ map(0x000a, 0x000a).mirror(0xff00).lrw8(
+ NAME([this](offs_t offset) { if (!machine().side_effects_disabled()) { m_status = (m_status & 0x7f) | (m_mpag << 7); } return ~0; }),
+ NAME([this](offs_t offset, u8 data) { m_status = (m_status & 0x7f) | (m_mpag << 7); }));
+ map(0x000b, 0x000b).mirror(0xff00).lrw8(
+ NAME([this](offs_t offset) { if (!machine().side_effects_disabled()) { m_status = (m_status & 0xfe) | (m_vol[0] >> 5); } return ~0; }),
+ NAME([this](offs_t offset, u8 data) { m_status = (m_status & 0xfe) | ((m_vol[0] >> 5) & 1); }));
+
+ map(0x000f, 0x000f).mirror(0xff00).lrw8(
+ NAME([this](offs_t offset) { return m_gscfg0; }),
+ NAME([this](offs_t offset, u8 data) { m_gscfg0 = data & 0x3f; update_config(); }));
+
+ map(0x0011, 0x0011).mirror(0xff00).lr8(
+ NAME([this]() { return m_spi_ctrl; })).w(FUNC(neogs_device::spi_ctrl_w));
+ map(0x0012, 0x0012).mirror(0xff00).lr8(
+ NAME([this](offs_t offset) { return (m_sdcard->get_card_present() << 1) | 0x05; })); // SSTAT
+
+ //SPI
+ map(0x0013, 0x0013).mirror(0xff00).lr8(
+ NAME([this]() { return m_spi_data_in_latch; })).w(FUNC(neogs_device::sd_w));
+ map(0x0014, 0x0014).mirror(0xff00).r(FUNC(neogs_device::sd_r));
+
+ // MP3
+ //map(0x0014, 0x0014).mirror(0xff00).nopw();
+ map(0x0015, 0x0015).mirror(0xff00).lrw8(
+ NAME([](offs_t offset) { return 0xff; }),
+ NAME([](offs_t offset, u8 data) { ;/* TODO */ }));
+}
+
+void neogs_device::device_add_mconfig(machine_config &config)
+{
+ RAM(config, m_ram).set_default_size("4M").set_default_value(0xff);
+
+ Z80(config, m_maincpu, 10_MHz_XTAL);
+ m_maincpu->set_memory_map(&neogs_device::map_memory);
+ m_maincpu->set_io_map(&neogs_device::map_io);
+ m_maincpu->set_periodic_int(FUNC(neogs_device::irq0_line_assert), attotime::from_hz(37.5_kHz_XTAL));
+ m_maincpu->irqack_cb().set_inputline(m_maincpu, INPUT_LINE_IRQ0, CLEAR_LINE);
+
+ SPI_SDCARD(config, m_sdcard, 0);
+ m_sdcard->spi_miso_callback().set([this](int state) { m_spi_data_in_latch <<= 1; m_spi_data_in_latch |= state; });
+
+ SPEAKER(config, "lspeaker").front_left();
+ SPEAKER(config, "rspeaker").front_right();
+
+ DAC_16BIT_R2R_TWOS_COMPLEMENT(config, m_dac[0], 0).add_route(ALL_OUTPUTS, "lspeaker", 0.75); // TDA1543
+ DAC_16BIT_R2R_TWOS_COMPLEMENT(config, m_dac[1], 0).add_route(ALL_OUTPUTS, "rspeaker", 0.75);
+}
+
+const tiny_rom_entry *neogs_device::device_rom_region() const
+{
+ return ROM_NAME( neogs );
+}
+
+void neogs_device::neogsmap(address_map &map)
+{
+ map(0x000bb, 0x000bb).mirror(0xff00).rw(FUNC(neogs_device::neogs_status_r), FUNC(neogs_device::neogs_command_w));
+ map(0x000b3, 0x000b3).mirror(0xff00).rw(FUNC(neogs_device::neogs_data_r), FUNC(neogs_device::neogs_data_w));
+ map(0x00033, 0x00033).mirror(0xff00).w(FUNC(neogs_device::neogs_ctrl_w));
+}
+
+void neogs_device::device_start()
+{
+ if (!m_ram->started())
+ throw device_missing_dependencies();
+
+ m_spi_clock = timer_alloc(FUNC(neogs_device::spi_clock), this);
+
+ m_bank_rom->configure_entries(0, m_rom.bytes() / 0x8000, &m_rom[0], 0x8000);
+ m_bank_ram->configure_entries(0, m_ram->size() / 0x8000, m_ram->pointer(), 0x8000);
+
+ m_maincpu->space(AS_PROGRAM).install_read_tap(0x6000, 0x7fff, "dac_w",
+ [this](offs_t offset, u8 &data, u8 mem_mask)
+ {
+ if (!machine().side_effects_disabled())
+ {
+ const u8 chanel = BIT(offset, 8, BIT(m_gscfg0, 2) ? 3 : 2); // 8CHANS
+ m_sample[chanel] = data;
+ }
+ });
+
+ m_zxbus->install_device(0x0000, 0xffff, *this, &neogs_device::neogsmap);
+
+ m_neogs_led.resolve();
+}
+
+void neogs_device::device_reset()
+{
+ m_spi_clock->adjust(attotime::never);
+ m_spi_clock_cycles = 0;
+ m_spi_clock_state = false;
+ m_spi_ctrl = 0x07;
+
+ u8 vol[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+ std::copy(std::begin(vol), std::end(vol), std::begin(m_vol));
+
+ m_spi_data_in_latch = 0xff;
+ m_spi_data_out = 0xff;
+
+ m_status = 0;
+ m_mpag = 0;
+ m_gscfg0 = 0x30;
+ update_config();
+}
+
+} // anonymous namespace
+
+} // namespace bus::spectrum::zxbus
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(ZXBUS_NEOGS, device_zxbus_card_interface, bus::spectrum::zxbus::neogs_device, "zxbus_neogs", "NeoGS / General Sound")
diff --git a/src/devices/bus/spectrum/neogs.h b/src/devices/bus/spectrum/neogs.h
new file mode 100644
index 00000000000..79170356690
--- /dev/null
+++ b/src/devices/bus/spectrum/neogs.h
@@ -0,0 +1,14 @@
+// license:BSD-3-Clause
+// copyright-holders:Andrei I. Holub
+
+#ifndef MAME_SINCLAIR_NEOGS_H
+#define MAME_SINCLAIR_NEOGS_H
+
+#pragma once
+
+#include "zxbus.h"
+
+
+DECLARE_DEVICE_TYPE(ZXBUS_NEOGS, device_zxbus_card_interface)
+
+#endif // MAME_SINCLAIR_NEOGS_H
diff --git a/src/devices/bus/spectrum/opus.cpp b/src/devices/bus/spectrum/opus.cpp
index 37eff23bce6..fef2107cb72 100644
--- a/src/devices/bus/spectrum/opus.cpp
+++ b/src/devices/bus/spectrum/opus.cpp
@@ -6,11 +6,12 @@
**********************************************************************/
-
#include "emu.h"
#include "opus.h"
#include "softlist_dev.h"
+#include "formats/opd_dsk.h"
+
//**************************************************************************
// DEVICE DEFINITIONS
@@ -82,8 +83,8 @@ void spectrum_opus_device::device_add_mconfig(machine_config &config)
WD1770(config, m_fdc, 16_MHz_XTAL / 2);
m_fdc->drq_wr_callback().set(DEVICE_SELF_OWNER, FUNC(spectrum_expansion_slot_device::nmi_w));
- FLOPPY_CONNECTOR(config, "fdc:0", spectrum_floppies, "35dd", spectrum_opus_device::floppy_formats).enable_sound(true);
- FLOPPY_CONNECTOR(config, "fdc:1", spectrum_floppies, "35dd", spectrum_opus_device::floppy_formats).enable_sound(true);
+ for (auto &floppy : m_floppy)
+ FLOPPY_CONNECTOR(config, floppy, spectrum_floppies, "35dd", spectrum_opus_device::floppy_formats).enable_sound(true);
/* parallel printer port */
CENTRONICS(config, m_centronics, centronics_devices, "printer");
@@ -91,7 +92,7 @@ void spectrum_opus_device::device_add_mconfig(machine_config &config)
m_centronics->busy_handler().set(FUNC(spectrum_opus_device::busy_w));
/* pia */
- PIA6821(config, m_pia, 0);
+ PIA6821(config, m_pia);
m_pia->writepa_handler().set(FUNC(spectrum_opus_device::pia_out_a));
m_pia->writepb_handler().set(FUNC(spectrum_opus_device::pia_out_b));
m_pia->cb2_handler().set("centronics", FUNC(centronics_device::write_strobe));
@@ -126,8 +127,7 @@ spectrum_opus_device::spectrum_opus_device(const machine_config &mconfig, const
, m_rom(*this, "rom")
, m_pia(*this, "pia")
, m_fdc(*this, "fdc")
- , m_floppy0(*this, "fdc:0")
- , m_floppy1(*this, "fdc:1")
+ , m_floppy(*this, "fdc:%u", 0U)
, m_centronics(*this, "centronics")
, m_exp(*this, "exp")
{
@@ -159,9 +159,9 @@ void spectrum_opus_device::device_reset()
// IMPLEMENTATION
//**************************************************************************
-READ_LINE_MEMBER(spectrum_opus_device::romcs)
+bool spectrum_opus_device::romcs()
{
- return m_romcs | m_exp->romcs();
+ return m_romcs || m_exp->romcs();
}
void spectrum_opus_device::post_opcode_fetch(offs_t offset)
@@ -256,8 +256,8 @@ void spectrum_opus_device::pia_out_a(uint8_t data)
floppy_image_device *floppy = nullptr;
// bit 0, 1: drive select
- if (!BIT(data, 0)) floppy = m_floppy1->get_device();
- if (!BIT(data, 1)) floppy = m_floppy0->get_device();
+ if (!BIT(data, 0)) floppy = m_floppy[1]->get_device();
+ if (!BIT(data, 1)) floppy = m_floppy[0]->get_device();
m_fdc->set_floppy(floppy);
// bit 4: side select
@@ -280,7 +280,7 @@ void spectrum_opus_device::pia_out_b(uint8_t data)
m_centronics->write_data7(BIT(data, 7));
}
-WRITE_LINE_MEMBER(spectrum_opus_device::busy_w)
+void spectrum_opus_device::busy_w(int state)
{
m_pia->set_a_input(state << 6);
}
diff --git a/src/devices/bus/spectrum/opus.h b/src/devices/bus/spectrum/opus.h
index 2c175621820..1bdf7ad26fa 100644
--- a/src/devices/bus/spectrum/opus.h
+++ b/src/devices/bus/spectrum/opus.h
@@ -15,7 +15,6 @@
#include "machine/wd_fdc.h"
#include "machine/6821pia.h"
#include "bus/centronics/ctronics.h"
-#include "formats/opd_dsk.h"
//**************************************************************************
// TYPE DEFINITIONS
@@ -46,7 +45,7 @@ protected:
virtual uint8_t mreq_r(offs_t offset) override;
virtual void mreq_w(offs_t offset, uint8_t data) override;
virtual uint8_t iorq_r(offs_t offset) override;
- virtual DECLARE_READ_LINE_MEMBER(romcs) override;
+ virtual bool romcs() override;
// passthru
virtual void pre_opcode_fetch(offs_t offset) override { m_exp->pre_opcode_fetch(offset); }
@@ -57,18 +56,17 @@ protected:
private:
void pia_out_a(uint8_t data);
void pia_out_b(uint8_t data);
- DECLARE_WRITE_LINE_MEMBER(busy_w);
+ void busy_w(int state);
required_ioport m_joy;
required_memory_region m_rom;
required_device<pia6821_device> m_pia;
required_device<wd_fdc_device_base> m_fdc;
- required_device<floppy_connector> m_floppy0;
- required_device<floppy_connector> m_floppy1;
+ required_device_array<floppy_connector, 2> m_floppy;
required_device<centronics_device> m_centronics;
required_device<spectrum_expansion_slot_device> m_exp;
- int m_romcs;
+ bool m_romcs;
uint8_t m_ram[4 * 1024];
};
diff --git a/src/devices/bus/spectrum/plus2test.cpp b/src/devices/bus/spectrum/plus2test.cpp
index 3d90ed4dee3..1f6e81246a5 100644
--- a/src/devices/bus/spectrum/plus2test.cpp
+++ b/src/devices/bus/spectrum/plus2test.cpp
@@ -63,7 +63,7 @@ void spectrum_plus2test_device::device_start()
// IMPLEMENTATION
//**************************************************************************
-READ_LINE_MEMBER(spectrum_plus2test_device::romcs)
+bool spectrum_plus2test_device::romcs()
{
return 1;
}
diff --git a/src/devices/bus/spectrum/plus2test.h b/src/devices/bus/spectrum/plus2test.h
index f8caad2fa26..34a7e014e41 100644
--- a/src/devices/bus/spectrum/plus2test.h
+++ b/src/devices/bus/spectrum/plus2test.h
@@ -35,7 +35,7 @@ protected:
// optional information overrides
virtual const tiny_rom_entry *device_rom_region() const override;
- virtual DECLARE_READ_LINE_MEMBER(romcs) override;
+ virtual bool romcs() override;
virtual uint8_t mreq_r(offs_t offset) override;
private:
diff --git a/src/devices/bus/spectrum/sdi.cpp b/src/devices/bus/spectrum/sdi.cpp
index ab8becb80f8..fc5e1de2406 100644
--- a/src/devices/bus/spectrum/sdi.cpp
+++ b/src/devices/bus/spectrum/sdi.cpp
@@ -98,7 +98,7 @@ void spectrum_sdi_device::device_reset()
// IMPLEMENTATION
//**************************************************************************
-READ_LINE_MEMBER(spectrum_sdi_device::romcs)
+bool spectrum_sdi_device::romcs()
{
return m_romcs;
}
diff --git a/src/devices/bus/spectrum/sdi.h b/src/devices/bus/spectrum/sdi.h
index 619ec52f44f..539ca55eb6b 100644
--- a/src/devices/bus/spectrum/sdi.h
+++ b/src/devices/bus/spectrum/sdi.h
@@ -41,7 +41,7 @@ protected:
virtual uint8_t mreq_r(offs_t offset) override;
virtual uint8_t iorq_r(offs_t offset) override;
virtual void iorq_w(offs_t offset, uint8_t data) override;
- virtual DECLARE_READ_LINE_MEMBER(romcs) override;
+ virtual bool romcs() override;
required_memory_region m_rom;
required_device<i8255_device> m_ppi;
@@ -50,7 +50,7 @@ protected:
void ppic_w(uint8_t data);
uint8_t ppic_r();
- int m_romcs;
+ bool m_romcs;
};
diff --git a/src/devices/bus/spectrum/sixword.cpp b/src/devices/bus/spectrum/sixword.cpp
index c85a9347dc9..81c3ad842a4 100644
--- a/src/devices/bus/spectrum/sixword.cpp
+++ b/src/devices/bus/spectrum/sixword.cpp
@@ -45,6 +45,8 @@
#include "emu.h"
#include "sixword.h"
+#include "formats/swd_dsk.h"
+
/***************************************************************************
DEVICE DEFINITIONS
@@ -266,9 +268,9 @@ void spectrum_swiftdisc2_device::device_reset()
// IMPLEMENTATION (swiftdisc)
//**************************************************************************
-READ_LINE_MEMBER(spectrum_swiftdisc_device::romcs)
+bool spectrum_swiftdisc_device::romcs()
{
- return m_romcs | m_exp->romcs();
+ return m_romcs || m_exp->romcs();
}
void spectrum_swiftdisc_device::post_opcode_fetch(offs_t offset)
diff --git a/src/devices/bus/spectrum/sixword.h b/src/devices/bus/spectrum/sixword.h
index c11108454f6..2c35304a391 100644
--- a/src/devices/bus/spectrum/sixword.h
+++ b/src/devices/bus/spectrum/sixword.h
@@ -14,7 +14,6 @@
#include "machine/wd_fdc.h"
#include "bus/centronics/ctronics.h"
#include "bus/rs232/rs232.h"
-#include "formats/swd_dsk.h"
//**************************************************************************
// TYPE DEFINITIONS
@@ -49,7 +48,7 @@ protected:
virtual uint8_t mreq_r(offs_t offset) override;
virtual void mreq_w(offs_t offset, uint8_t data) override;
virtual uint8_t iorq_r(offs_t offset) override;
- virtual DECLARE_READ_LINE_MEMBER(romcs) override;
+ virtual bool romcs() override;
// passthru
virtual void pre_opcode_fetch(offs_t offset) override { m_exp->pre_opcode_fetch(offset); }
@@ -64,7 +63,7 @@ protected:
required_device<rs232_port_device> m_rs232;
required_ioport m_joy;
- int m_romcs;
+ bool m_romcs;
u8 m_ram[0x2000];
u16 m_rombank;
u8 m_control;
@@ -92,7 +91,7 @@ protected:
virtual void mreq_w(offs_t offset, uint8_t data) override;
virtual uint8_t iorq_r(offs_t offset) override;
virtual void iorq_w(offs_t offset, uint8_t data) override;
- DECLARE_WRITE_LINE_MEMBER(busy_w) { m_busy = state; }
+ void busy_w(int state) { m_busy = state; }
required_device<centronics_device> m_centronics;
required_ioport m_conf;
diff --git a/src/devices/bus/spectrum/smuc.cpp b/src/devices/bus/spectrum/smuc.cpp
new file mode 100644
index 00000000000..ba2aba269f4
--- /dev/null
+++ b/src/devices/bus/spectrum/smuc.cpp
@@ -0,0 +1,140 @@
+// license:BSD-3-Clause
+// copyright-holders:Andrei I. Holub
+
+#include "emu.h"
+#include "smuc.h"
+
+#include "bus/ata/ataintf.h"
+#include "bus/ata/atapicdr.h"
+#include "bus/ata/hdd.h"
+#include "machine/ds17x85.h"
+#include "machine/i2cmem.h"
+
+namespace bus::spectrum::zxbus {
+
+namespace {
+
+class smuc_device : public device_t, public device_zxbus_card_interface
+{
+public:
+ smuc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, ZXBUS_SMUC, tag, owner, clock)
+ , device_zxbus_card_interface(mconfig, *this)
+ , m_rtc(*this, "rtc")
+ , m_eeprom(*this, "eeprom")
+ , m_ata(*this, "ata")
+ { }
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+private:
+ void map_io(address_map &map);
+
+ void port_ffba_w(offs_t offset, u8 data);
+ u8 ata_r(offs_t offset);
+ void ata_w(offs_t offset, u8 data);
+
+ required_device<ds17x85_device> m_rtc; //cmos
+ required_device<i2cmem_device> m_eeprom; //nvram
+ required_device<ata_interface_device> m_ata;
+
+ u8 m_port_ffba_data;
+ u8 m_port_7fba_data;
+ u8 m_ide_hi;
+};
+
+void smuc_device::port_ffba_w(offs_t offset, u8 data)
+{
+ if (!BIT(data, 0))
+ m_ata->reset();
+
+ m_eeprom->write_sda(BIT(data, 4));
+ m_eeprom->write_wc(BIT(data, 5));
+ m_eeprom->write_scl(BIT(data, 6));
+
+ m_port_ffba_data = data;
+}
+
+u8 smuc_device::ata_r(offs_t offset)
+{
+ const u8 ata_offset = BIT(offset, 8, 3);
+ const u16 data = BIT(m_port_ffba_data, 7)
+ ? m_ata->cs1_r(ata_offset)
+ : m_ata->cs0_r(ata_offset);
+
+ if (!machine().side_effects_disabled())
+ m_ide_hi = data >> 8;
+
+ return data & 0xff;
+}
+
+void smuc_device::ata_w(offs_t offset, u8 data)
+{
+ const u8 ata_offset = BIT(offset, 8, 3);
+ const u16 ata_data = (m_ide_hi << 8) | data;
+ if (BIT(m_port_ffba_data, 7))
+ m_ata->cs1_w(ata_offset, ata_data);
+ else
+ m_ata->cs0_w(ata_offset, ata_data);
+}
+
+
+void smuc_device::map_io(address_map &map)
+{
+ map(0x118a2, 0x118a2).mirror(0x4718) // 5fba | 0x011xxx101xx010 | Version: 2
+ .lr8(NAME([]() { return 0x40; }));
+ map(0x118a6, 0x118a6).mirror(0x4718) // 5fbe | 0x011xxx101xx110 | Revision: 0
+ .lr8(NAME([]() { return 0x28; }));
+ map(0x138a2, 0x138a2).mirror(0x4718) // 7fba | 0x111xxx101xx010 | VirtualFDD
+ .lrw8(NAME([this]() { return m_port_7fba_data | 0x37; })
+ , NAME([this](u8 data) { m_port_7fba_data = data; }));
+ map(0x138a6, 0x138a6).mirror(0x4718) // 7[ef]be | 0x111xxN101xx110 | i8259 - absent in 2.0
+ .lr8(NAME([]() { return 0x57; })).nopw();
+ map(0x198a2, 0x198a2).mirror(0x4718) // dfba | 1x011xxx101xx010 | DS1685RTC
+ .lrw8(NAME([this]() { return m_rtc->data_r(); })
+ , NAME([this](u8 data) { if (BIT(m_port_ffba_data, 7)) m_rtc->data_w(data); else m_rtc->address_w(data); }));
+ map(0x198a6, 0x198a6).mirror(0x4718) // d8be | 1x011xxx101xx110 | IDE-Hi
+ .lrw8(NAME([this]() { return m_ide_hi; }), NAME([this](u8 data) { m_ide_hi = data; }));
+ map(0x1b8a2, 0x1b8a2).mirror(0x4718) // ffba | 1x111xxx101xx010 | SYS
+ .lr8(NAME([this]() { return m_eeprom->read_sda() ? 0xff : 0xbf; })).w(FUNC(smuc_device::port_ffba_w));
+ map(0x1b8a6, 0x1b8a6).select(0x4718) // f[8-f]be | 1x111NNN101xx110 | IDE#1Fx/#3F6
+ .rw(FUNC(smuc_device::ata_r), FUNC(smuc_device::ata_w));
+}
+
+static void smuc_ata_devices(device_slot_interface &device)
+{
+ device.option_add("hdd", IDE_HARDDISK);
+ device.option_add("cdrom", ATAPI_CDROM);
+}
+
+void smuc_device::device_add_mconfig(machine_config &config)
+{
+ DS1685(config, m_rtc, XTAL(32'768));
+ I2C_24C16(config, m_eeprom);
+ ATA_INTERFACE(config, m_ata).options(smuc_ata_devices, "hdd", "hdd", false);
+}
+
+void smuc_device::device_start()
+{
+ m_port_7fba_data = 0;
+
+ save_item(NAME(m_port_7fba_data));
+ save_item(NAME(m_port_ffba_data));
+ save_item(NAME(m_ide_hi));
+
+ m_zxbus->install_device(0x00000, 0x1ffff, *this, &smuc_device::map_io);
+}
+
+void smuc_device::device_reset()
+{
+ m_port_ffba_data = 0;
+}
+
+} // anonymous namespace
+
+} // namespace bus::spectrum::zxbus
+
+DEFINE_DEVICE_TYPE_PRIVATE(ZXBUS_SMUC, device_zxbus_card_interface, bus::spectrum::zxbus::smuc_device, "zxbus_smuc", "SMUC")
diff --git a/src/devices/bus/spectrum/smuc.h b/src/devices/bus/spectrum/smuc.h
new file mode 100644
index 00000000000..87de5539783
--- /dev/null
+++ b/src/devices/bus/spectrum/smuc.h
@@ -0,0 +1,14 @@
+// license:BSD-3-Clause
+// copyright-holders:Andrei I. Holub
+
+#ifndef MAME_SINCLAIR_SMUC_H
+#define MAME_SINCLAIR_SMUC_H
+
+#pragma once
+
+#include "zxbus.h"
+
+
+DECLARE_DEVICE_TYPE(ZXBUS_SMUC, device_zxbus_card_interface)
+
+#endif // MAME_SINCLAIR_SMUC_H
diff --git a/src/devices/bus/spectrum/speccydos.cpp b/src/devices/bus/spectrum/speccydos.cpp
index 1afbb52da26..4512da94d05 100644
--- a/src/devices/bus/spectrum/speccydos.cpp
+++ b/src/devices/bus/spectrum/speccydos.cpp
@@ -30,6 +30,8 @@
#include "emu.h"
#include "speccydos.h"
+#include "formats/sdd_dsk.h"
+
/***************************************************************************
DEVICE DEFINITIONS
@@ -168,9 +170,9 @@ void spectrum_speccydos_device::device_reset()
// IMPLEMENTATION
//**************************************************************************
-READ_LINE_MEMBER(spectrum_speccydos_device::romcs)
+bool spectrum_speccydos_device::romcs()
{
- return m_romcs | m_exp->romcs();
+ return m_romcs || m_exp->romcs();
}
void spectrum_speccydos_device::pre_opcode_fetch(offs_t offset)
diff --git a/src/devices/bus/spectrum/speccydos.h b/src/devices/bus/spectrum/speccydos.h
index 3cdb29b7b38..6c5ade77630 100644
--- a/src/devices/bus/spectrum/speccydos.h
+++ b/src/devices/bus/spectrum/speccydos.h
@@ -12,7 +12,6 @@
#include "softlist.h"
#include "imagedev/floppy.h"
#include "machine/wd_fdc.h"
-#include "formats/sdd_dsk.h"
//**************************************************************************
// TYPE DEFINITIONS
@@ -44,7 +43,7 @@ protected:
virtual void pre_opcode_fetch(offs_t offset) override;
virtual uint8_t mreq_r(offs_t offset) override;
virtual void mreq_w(offs_t offset, uint8_t data) override;
- virtual DECLARE_READ_LINE_MEMBER(romcs) override;
+ virtual bool romcs() override;
// passthru
virtual void post_opcode_fetch(offs_t offset) override { m_exp->post_opcode_fetch(offset); }
@@ -58,7 +57,7 @@ protected:
required_device_array<floppy_connector, 4> m_floppy;
required_device<spectrum_expansion_slot_device> m_exp;
- int m_romcs;
+ bool m_romcs;
u8 m_control;
u8 m_ram[0x400];
};
diff --git a/src/devices/bus/spectrum/specmate.cpp b/src/devices/bus/spectrum/specmate.cpp
index 4177a74f814..4b090cf2c17 100644
--- a/src/devices/bus/spectrum/specmate.cpp
+++ b/src/devices/bus/spectrum/specmate.cpp
@@ -151,9 +151,9 @@ void spectrum_specmate_device::device_reset()
// IMPLEMENTATION
//**************************************************************************
-READ_LINE_MEMBER(spectrum_specmate_device::romcs)
+bool spectrum_specmate_device::romcs()
{
- return m_romcs | m_exp->romcs();
+ return m_romcs || m_exp->romcs();
}
void spectrum_specmate_device::pre_opcode_fetch(offs_t offset)
diff --git a/src/devices/bus/spectrum/specmate.h b/src/devices/bus/spectrum/specmate.h
index cc361b49171..2c0951a119b 100644
--- a/src/devices/bus/spectrum/specmate.h
+++ b/src/devices/bus/spectrum/specmate.h
@@ -37,7 +37,7 @@ protected:
virtual void pre_opcode_fetch(offs_t offset) override;
virtual uint8_t mreq_r(offs_t offset) override;
- virtual DECLARE_READ_LINE_MEMBER(romcs) override;
+ virtual bool romcs() override;
// passthru
virtual void post_opcode_fetch(offs_t offset) override { m_exp->post_opcode_fetch(offset); }
@@ -50,7 +50,7 @@ protected:
required_memory_region m_rom;
required_device<spectrum_expansion_slot_device> m_exp;
- int m_romcs;
+ bool m_romcs;
};
// device type definition
diff --git a/src/devices/bus/spectrum/uslot.cpp b/src/devices/bus/spectrum/uslot.cpp
index eeef849a8fe..d3955ec50d5 100644
--- a/src/devices/bus/spectrum/uslot.cpp
+++ b/src/devices/bus/spectrum/uslot.cpp
@@ -71,9 +71,9 @@ void spectrum_uslot_device::device_reset()
// IMPLEMENTATION
//**************************************************************************
-READ_LINE_MEMBER(spectrum_uslot_device::romcs)
+bool spectrum_uslot_device::romcs()
{
- return m_exp1->romcs() | m_exp2->romcs();
+ return m_exp1->romcs() || m_exp2->romcs();
}
void spectrum_uslot_device::pre_opcode_fetch(offs_t offset)
diff --git a/src/devices/bus/spectrum/uslot.h b/src/devices/bus/spectrum/uslot.h
index 0764d014147..7cda022c3d9 100644
--- a/src/devices/bus/spectrum/uslot.h
+++ b/src/devices/bus/spectrum/uslot.h
@@ -44,7 +44,7 @@ protected:
virtual void mreq_w(offs_t offset, uint8_t data) override;
virtual uint8_t iorq_r(offs_t offset) override;
virtual void iorq_w(offs_t offset, uint8_t data) override;
- virtual DECLARE_READ_LINE_MEMBER(romcs) override;
+ virtual bool romcs() override;
private:
required_device<spectrum_expansion_slot_device> m_exp1;
diff --git a/src/devices/bus/spectrum/usource.cpp b/src/devices/bus/spectrum/usource.cpp
index 3c368297fef..6b9ffbbfbc0 100644
--- a/src/devices/bus/spectrum/usource.cpp
+++ b/src/devices/bus/spectrum/usource.cpp
@@ -78,7 +78,7 @@ void spectrum_usource_device::device_reset()
// IMPLEMENTATION
//**************************************************************************
-READ_LINE_MEMBER(spectrum_usource_device::romcs)
+bool spectrum_usource_device::romcs()
{
return m_romcs;
}
diff --git a/src/devices/bus/spectrum/usource.h b/src/devices/bus/spectrum/usource.h
index 1f0d7d44e58..b30aadb7eec 100644
--- a/src/devices/bus/spectrum/usource.h
+++ b/src/devices/bus/spectrum/usource.h
@@ -39,13 +39,13 @@ protected:
virtual const tiny_rom_entry *device_rom_region() const override;
virtual void pre_opcode_fetch(offs_t offset) override;
- virtual DECLARE_READ_LINE_MEMBER(romcs) override;
+ virtual bool romcs() override;
virtual uint8_t mreq_r(offs_t offset) override;
private:
required_memory_region m_rom;
- int m_romcs;
+ bool m_romcs;
};
diff --git a/src/devices/bus/spectrum/uspeech.cpp b/src/devices/bus/spectrum/uspeech.cpp
index 06e48dca0fd..fd013dabacc 100644
--- a/src/devices/bus/spectrum/uspeech.cpp
+++ b/src/devices/bus/spectrum/uspeech.cpp
@@ -94,7 +94,7 @@ void spectrum_uspeech_device::device_reset()
// IMPLEMENTATION
//**************************************************************************
-READ_LINE_MEMBER(spectrum_uspeech_device::romcs)
+bool spectrum_uspeech_device::romcs()
{
return m_romcs;
}
diff --git a/src/devices/bus/spectrum/uspeech.h b/src/devices/bus/spectrum/uspeech.h
index 078e33599af..d1ec459c8d3 100644
--- a/src/devices/bus/spectrum/uspeech.h
+++ b/src/devices/bus/spectrum/uspeech.h
@@ -41,7 +41,7 @@ protected:
virtual void device_add_mconfig(machine_config &config) override;
virtual void pre_opcode_fetch(offs_t offset) override;
- virtual DECLARE_READ_LINE_MEMBER(romcs) override;
+ virtual bool romcs() override;
virtual uint8_t mreq_r(offs_t offset) override;
virtual void mreq_w(offs_t offset, uint8_t data) override;
virtual uint8_t iorq_r(offs_t offset) override;
@@ -50,7 +50,7 @@ private:
required_device<sp0256_device> m_nsp;
required_memory_region m_rom;
- int m_romcs;
+ bool m_romcs;
};
diff --git a/src/devices/bus/spectrum/vtx5000.cpp b/src/devices/bus/spectrum/vtx5000.cpp
new file mode 100644
index 00000000000..b028f198266
--- /dev/null
+++ b/src/devices/bus/spectrum/vtx5000.cpp
@@ -0,0 +1,170 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Prism VTX 5000 Modem
+
+**********************************************************************/
+
+#include "emu.h"
+#include "vtx5000.h"
+#include "machine/clock.h"
+#include "machine/i8251.h"
+#include "bus/rs232/rs232.h"
+
+
+namespace {
+
+class spectrum_vtx5000_device : public device_t, public device_spectrum_expansion_interface
+{
+public:
+ spectrum_vtx5000_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, SPECTRUM_VTX5000, tag, owner, clock)
+ , device_spectrum_expansion_interface(mconfig, *this)
+ , m_exp(*this, "exp")
+ , m_usart(*this, "i8251")
+ , m_rom(*this, "rom")
+ {
+ }
+
+protected:
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+ virtual uint8_t mreq_r(offs_t offset) override;
+ virtual uint8_t iorq_r(offs_t offset) override;
+ virtual void iorq_w(offs_t offset, uint8_t data) override;
+ virtual bool romcs() override;
+
+ // passthru
+ virtual void pre_opcode_fetch(offs_t offset) override { m_exp->pre_opcode_fetch(offset); }
+ virtual void post_opcode_fetch(offs_t offset) override { m_exp->post_opcode_fetch(offset); }
+ virtual void pre_data_fetch(offs_t offset) override { m_exp->pre_data_fetch(offset); }
+ virtual void post_data_fetch(offs_t offset) override { m_exp->post_data_fetch(offset); }
+ virtual void mreq_w(offs_t offset, uint8_t data) override { if (m_exp->romcs()) m_exp->mreq_w(offset, data); }
+
+private:
+ required_device<spectrum_expansion_slot_device> m_exp;
+ required_device<i8251_device> m_usart;
+ required_memory_region m_rom;
+
+ bool m_romcs;
+};
+
+
+ROM_START(vtx5000)
+ ROM_REGION( 0x2000, "rom", 0 )
+ ROM_SYSTEM_BIOS(0, "v31mnet", "V3.1 Micronet")
+ ROMX_LOAD("vtx5000-3-1.rom", 0x0000, 0x2000, CRC(1431505c) SHA1(42ae2b47c44d8c0d6a6c6a2b39a4a25a6d3a4bda), ROM_BIOS(0))
+
+ ROM_SYSTEM_BIOS(1, "v31hlink", "V3.1 Homelink")
+ ROMX_LOAD("homelink.rom", 0x0000, 0x2000, CRC(527d7f32) SHA1(4490186845b198ca9191dd711bd38274cba6f04b), ROM_BIOS(1))
+ROM_END
+
+
+const tiny_rom_entry *spectrum_vtx5000_device::device_rom_region() const
+{
+ return ROM_NAME(vtx5000);
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void spectrum_vtx5000_device::device_add_mconfig(machine_config &config)
+{
+ I8251(config, m_usart, 2.4576_MHz_XTAL);
+ m_usart->txd_handler().set("modem", FUNC(rs232_port_device::write_txd));
+ m_usart->dtr_handler().set("modem", FUNC(rs232_port_device::write_dtr));
+ m_usart->rts_handler().set([this](int state) { m_romcs = state; });
+
+ clock_device &rx_clock(CLOCK(config, "rx_clock", 2.4576_MHz_XTAL / 16 / 2)); // 1200 baud
+ rx_clock.signal_handler().set(m_usart, FUNC(i8251_device::write_rxc));
+
+ clock_device &tx_clock(CLOCK(config, "tx_clock", 2.4576_MHz_XTAL / 16 / 32)); // 75 baud
+ tx_clock.signal_handler().set(m_usart, FUNC(i8251_device::write_txc));
+
+ rs232_port_device &rs232(RS232_PORT(config, "modem", default_rs232_devices, nullptr)); // TCM3101 (internal modem)
+ rs232.rxd_handler().set(m_usart, FUNC(i8251_device::write_rxd));
+ rs232.dcd_handler().set(m_usart, FUNC(i8251_device::write_dsr)).invert();
+
+ // passthru
+ SPECTRUM_EXPANSION_SLOT(config, m_exp, spectrum_expansion_devices, nullptr);
+ m_exp->irq_handler().set(DEVICE_SELF_OWNER, FUNC(spectrum_expansion_slot_device::irq_w));
+ m_exp->nmi_handler().set(DEVICE_SELF_OWNER, FUNC(spectrum_expansion_slot_device::nmi_w));
+ m_exp->fb_r_handler().set(DEVICE_SELF_OWNER, FUNC(spectrum_expansion_slot_device::fb_r));
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void spectrum_vtx5000_device::device_start()
+{
+ // CTS grounded
+ m_usart->write_cts(0);
+
+ save_item(NAME(m_romcs));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void spectrum_vtx5000_device::device_reset()
+{
+ m_romcs = 1;
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+bool spectrum_vtx5000_device::romcs()
+{
+ return m_romcs || m_exp->romcs();
+}
+
+
+uint8_t spectrum_vtx5000_device::mreq_r(offs_t offset)
+{
+ uint8_t data = 0xff;
+
+ if (m_romcs)
+ data = m_rom->base()[offset & 0x1fff];
+
+ if (m_exp->romcs())
+ data &= m_exp->mreq_r(offset);
+
+ return data;
+}
+
+
+uint8_t spectrum_vtx5000_device::iorq_r(offs_t offset)
+{
+ uint8_t data = m_exp->iorq_r(offset);
+
+ if ((offset & 0x7f) == 0x7f)
+ data = m_usart->read(BIT(offset, 7));
+
+ return data;
+}
+
+void spectrum_vtx5000_device::iorq_w(offs_t offset, uint8_t data)
+{
+ if ((offset & 0x7f) == 0x7f)
+ m_usart->write(BIT(offset, 7), data);
+
+ m_exp->iorq_w(offset, data);
+}
+
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(SPECTRUM_VTX5000, device_spectrum_expansion_interface, spectrum_vtx5000_device, "spectrum_vtx5000", "Prism VTX 5000 Modem")
diff --git a/src/devices/bus/spectrum/vtx5000.h b/src/devices/bus/spectrum/vtx5000.h
new file mode 100644
index 00000000000..2ecd3f113cf
--- /dev/null
+++ b/src/devices/bus/spectrum/vtx5000.h
@@ -0,0 +1,11 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+#ifndef MAME_BUS_SPECTRUM_VTX5000_H
+#define MAME_BUS_SPECTRUM_VTX5000_H
+
+#include "exp.h"
+
+
+DECLARE_DEVICE_TYPE(SPECTRUM_VTX5000, device_spectrum_expansion_interface)
+
+#endif // MAME_BUS_SPECTRUM_VTX5000_H
diff --git a/src/devices/bus/spectrum/wafa.cpp b/src/devices/bus/spectrum/wafa.cpp
index c5af195289c..f1f722715b3 100644
--- a/src/devices/bus/spectrum/wafa.cpp
+++ b/src/devices/bus/spectrum/wafa.cpp
@@ -103,9 +103,9 @@ void spectrum_wafa_device::device_reset()
// IMPLEMENTATION
//**************************************************************************
-READ_LINE_MEMBER(spectrum_wafa_device::romcs)
+bool spectrum_wafa_device::romcs()
{
- return m_romcs | m_exp->romcs();
+ return m_romcs || m_exp->romcs();
}
void spectrum_wafa_device::pre_opcode_fetch(offs_t offset)
diff --git a/src/devices/bus/spectrum/wafa.h b/src/devices/bus/spectrum/wafa.h
index 6ca1f4d256a..39ce95e2a76 100644
--- a/src/devices/bus/spectrum/wafa.h
+++ b/src/devices/bus/spectrum/wafa.h
@@ -44,7 +44,7 @@ protected:
virtual uint8_t mreq_r(offs_t offset) override;
virtual uint8_t iorq_r(offs_t offset) override;
virtual void iorq_w(offs_t offset, uint8_t data) override;
- virtual DECLARE_READ_LINE_MEMBER(romcs) override;
+ virtual bool romcs() override;
// passthru
virtual void pre_data_fetch(offs_t offset) override { m_exp->pre_data_fetch(offset); }
@@ -57,7 +57,7 @@ private:
required_device<wafadrive_image_device> m_wafa1;
required_device<wafadrive_image_device> m_wafa2;
- int m_romcs;
+ bool m_romcs;
};
diff --git a/src/devices/bus/spectrum/zxbus.cpp b/src/devices/bus/spectrum/zxbus.cpp
new file mode 100644
index 00000000000..24546353cf7
--- /dev/null
+++ b/src/devices/bus/spectrum/zxbus.cpp
@@ -0,0 +1,78 @@
+// license:BSD-3-Clause
+// copyright-holders:Andrei I. Holub
+/*******************************************************************************************
+
+ ZXBUS device
+
+*******************************************************************************************/
+
+#include "emu.h"
+#include "zxbus.h"
+
+DEFINE_DEVICE_TYPE(ZXBUS_SLOT, zxbus_slot_device, "zxbus_slot", "ZXBUS slot")
+
+zxbus_slot_device::zxbus_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : zxbus_slot_device(mconfig, ZXBUS_SLOT, tag, owner, clock)
+{
+}
+
+zxbus_slot_device::zxbus_slot_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, type, tag, owner, clock)
+ , device_single_card_slot_interface<device_zxbus_card_interface>(mconfig, *this)
+ , m_zxbus_bus(*this, finder_base::DUMMY_TAG)
+{
+}
+
+void zxbus_slot_device::device_start()
+{
+ device_zxbus_card_interface *const card(get_card_device());
+ if (card) card->set_zxbusbus(*m_zxbus_bus);
+
+ m_zxbus_bus->add_slot(*this);
+}
+
+DEFINE_DEVICE_TYPE(ZXBUS, zxbus_device, "zxbus", "ZXBUS bus")
+
+zxbus_device::zxbus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : zxbus_device(mconfig, ZXBUS, tag, owner, clock)
+{
+}
+
+zxbus_device::zxbus_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, type, tag, owner, clock)
+ , m_iospace(*this, finder_base::DUMMY_TAG, -1)
+{
+}
+
+void zxbus_device::device_start()
+{
+}
+
+void zxbus_device::add_slot(zxbus_slot_device &slot)
+{
+ m_slot_list.push_front(&slot);
+}
+
+device_zxbus_card_interface::device_zxbus_card_interface(const machine_config &mconfig, device_t &device)
+ : device_interface(device, "zxbus")
+ , m_zxbus(nullptr)
+{
+}
+
+void device_zxbus_card_interface::interface_pre_start()
+{
+ if (!m_zxbus)
+ throw device_missing_dependencies();
+}
+
+
+#include "nemoide.h"
+#include "neogs.h"
+#include "smuc.h"
+
+void zxbus_cards(device_slot_interface &device)
+{
+ device.option_add("nemoide", ZXBUS_NEMOIDE);
+ device.option_add("neogs", ZXBUS_NEOGS);
+ device.option_add("smuc", ZXBUS_SMUC);
+}
diff --git a/src/devices/bus/spectrum/zxbus.h b/src/devices/bus/spectrum/zxbus.h
new file mode 100644
index 00000000000..09aeec5abad
--- /dev/null
+++ b/src/devices/bus/spectrum/zxbus.h
@@ -0,0 +1,128 @@
+// license:BSD-3-Clause
+// copyright-holders:Andrei I. Holub
+/*******************************************************************************************
+
+ ZXBUS device
+
+ ┌──┬───┬──┐
+ │ B│ │ A│
+ │ │ │ │
+ *5 A15 │ 1│ │ 1│ A14 *4
+ *3 A13 │ 2│ │ 2│ A12 *2
+ *13 D7 │ 3│ │ 3│ +5V (guaranteed +5V only here ! )
+ BLK (CSDS) │ 4│ │ 4│ DOS (DCDOS)
+ -not-used- │ 5│ │ 5│ KAY = 14Mhz / SCORPION = +12V
+ *14 D0 │ 6│ │ 6│ GND
+ *15 D1 │ 7│ │ 7│ GND
+ *12 D2 │ 8│ │ 8│ CLK Z80 (SCORPION aka /RAS 3.5Mhz ONLY ! )
+ *10 D6 │ 9│ │ 9│ A0 *30
+ *9 D5 │10│ │10│ A1 *31
+ *8 D3 │11│ │11│ A2
+ *7 D4 │12│ │12│ A3
+ - │13│ │13│ IOGE (IORQCE)
+ *17 NMI │14│ │14│ GND
+ - │15│ │15│ RDR(RDROM) (CSROMCE)
+ *19 MREQ │16│ │16│ RS (BIT_4 OF #7FFD)
+ *20 IORQ │17│ │17│ -not-used-
+ *21 RD │18│ │18│ -not-used-
+ *22 WR │19│ │19│ BUSRQ
+ -not-used- │20│ │20│ RES *26
+ *24 WAIT │21│ │21│ A7 *37
+ -not-used- │22│ │22│ A6 *36
+ -not-used- │23│ │23│ A5 *35
+ *27 M1 │24│ │24│ A4
+ RFRSH │25│ │25│ CSR (CSROM)
+ *38 A8 │26│ │26│ BUSAK
+ *40 A10 │27│ │27│ A9 *39
+ KAY=+5V n.u. │28│ │28│ A11 *1
+ KAY=+12V n.u. │29│ │29│ n.u. KAY=+5V
+ GND │30│ │30│ GND
+ │ │ │ │
+ │ B│ │A │
+ └──┴───┴──┘
+ '-' - not used
+ '*' - Z80 CPU out
+
+*******************************************************************************************/
+
+#ifndef MAME_BUS_SPECTRUM_ZXBUS_H
+#define MAME_BUS_SPECTRUM_ZXBUS_H
+
+#pragma once
+
+class zxbus_device;
+class device_zxbus_card_interface;
+
+class zxbus_slot_device : public device_t, public device_single_card_slot_interface<device_zxbus_card_interface>
+{
+public:
+ zxbus_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+ template <typename T, typename U>
+ zxbus_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock, T &&zxbus_tag, U &&slot_options, const char *dflt)
+ : zxbus_slot_device(mconfig, tag, owner, clock)
+ {
+ option_reset();
+ slot_options(*this);
+ set_default_option(dflt);
+ set_fixed(false);
+ m_zxbus_bus.set_tag(std::forward<T>(zxbus_tag));
+ }
+
+protected:
+ zxbus_slot_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
+ virtual void device_start() override;
+
+ required_device<zxbus_device> m_zxbus_bus;
+};
+
+DECLARE_DEVICE_TYPE(ZXBUS_SLOT, zxbus_slot_device)
+
+
+class zxbus_device : public device_t
+{
+public:
+ zxbus_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ template <typename T> void set_iospace(T &&tag, int spacenum) { m_iospace.set_tag(std::forward<T>(tag), spacenum); }
+ template<typename T> void install_device(offs_t addrstart, offs_t addrend, T &device, void (T::*map)(class address_map &map), u64 unitmask = ~u64(0))
+ {
+ m_iospace->install_device(addrstart, addrend, device, map, unitmask);
+ }
+
+ void add_slot(zxbus_slot_device &slot);
+
+protected:
+ zxbus_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
+ virtual void device_start() override;
+
+private:
+ required_address_space m_iospace;
+
+ std::forward_list<zxbus_slot_device *> m_slot_list;
+};
+
+DECLARE_DEVICE_TYPE(ZXBUS, zxbus_device)
+
+
+class device_zxbus_card_interface : public device_interface
+{
+ friend class zxbus_slot_device;
+
+protected:
+ device_zxbus_card_interface(const machine_config &mconfig, device_t &device);
+
+ virtual void interface_pre_start() override;
+
+ void set_zxbusbus(zxbus_device &zxbus) { assert(!device().started()); m_zxbus = &zxbus; }
+
+ zxbus_device *m_zxbus;
+};
+
+
+void zxbus_cards(device_slot_interface &device);
+
+
+#endif // MAME_BUS_SPECTRUM_ZXBUS_H
diff --git a/src/devices/bus/ss50/dc5.cpp b/src/devices/bus/ss50/dc5.cpp
index 90b7f40d4d1..3b077403255 100644
--- a/src/devices/bus/ss50/dc5.cpp
+++ b/src/devices/bus/ss50/dc5.cpp
@@ -32,6 +32,7 @@
#include "machine/wd_fdc.h"
#include "imagedev/floppy.h"
#include "formats/cp68_dsk.h"
+#include "formats/fdos_dsk.h"
#include "formats/flex_dsk.h"
#include "formats/os9_dsk.h"
#include "formats/uniflex_dsk.h"
@@ -43,10 +44,7 @@ public:
: device_t(mconfig, SS50_DC5, tag, owner, clock)
, ss50_card_interface(mconfig, *this)
, m_fdc(*this, "fdc")
- , m_floppy0(*this, "fdc:0")
- , m_floppy1(*this, "fdc:1")
- , m_floppy2(*this, "fdc:2")
- , m_floppy3(*this, "fdc:3")
+ , m_floppy(*this, "fdc:%u", 0U)
, m_interrupt_select(*this, "INTERRUPT_SELECT")
, m_address_mode(*this, "ADDRESS_MODE")
, m_two_control_regs(*this, "TWO_CONTROL_REGS")
@@ -73,9 +71,9 @@ protected:
virtual void register_write(offs_t offset, uint8_t data) override;
private:
- DECLARE_WRITE_LINE_MEMBER( fdc_intrq_w );
- DECLARE_WRITE_LINE_MEMBER( fdc_drq_w );
- DECLARE_WRITE_LINE_MEMBER( fdc_sso_w );
+ void fdc_intrq_w(int state);
+ void fdc_drq_w(int state);
+ void fdc_sso_w(int state);
static void floppy_formats(format_registration &fr);
uint8_t m_fdc_status; // for floppy controller
@@ -97,10 +95,7 @@ private:
uint8_t validate_fdc_sector_size(uint8_t cmd);
required_device<wd2797_device> m_fdc;
- required_device<floppy_connector> m_floppy0;
- required_device<floppy_connector> m_floppy1;
- required_device<floppy_connector> m_floppy2;
- required_device<floppy_connector> m_floppy3;
+ required_device_array<floppy_connector, 4> m_floppy;
required_ioport m_interrupt_select;
required_ioport m_address_mode;
required_ioport m_two_control_regs;
@@ -242,6 +237,7 @@ void ss50_dc5_device::floppy_formats(format_registration &fr)
fr.add_mfm_containers();
fr.add(FLOPPY_FLEX_FORMAT);
fr.add(FLOPPY_CP68_FORMAT);
+ fr.add(FLOPPY_FDOS_FORMAT);
fr.add(FLOPPY_OS9_FORMAT);
fr.add(FLOPPY_UNIFLEX_FORMAT);
}
@@ -266,10 +262,8 @@ static void flex_floppies(device_slot_interface &device)
void ss50_dc5_device::device_add_mconfig(machine_config &config)
{
WD2797(config, m_fdc, 12_MHz_XTAL / 12); // divider is selectable
- FLOPPY_CONNECTOR(config, "fdc:0", flex_floppies, "sssd35", ss50_dc5_device::floppy_formats).enable_sound(true);
- FLOPPY_CONNECTOR(config, "fdc:1", flex_floppies, "sssd35", ss50_dc5_device::floppy_formats).enable_sound(true);
- FLOPPY_CONNECTOR(config, "fdc:2", flex_floppies, "sssd35", ss50_dc5_device::floppy_formats).enable_sound(true);
- FLOPPY_CONNECTOR(config, "fdc:3", flex_floppies, "sssd35", ss50_dc5_device::floppy_formats).enable_sound(true);
+ for (auto &floppy : m_floppy)
+ FLOPPY_CONNECTOR(config, floppy, flex_floppies, "sssd35", ss50_dc5_device::floppy_formats).enable_sound(true);
m_fdc->intrq_wr_callback().set(FUNC(ss50_dc5_device::fdc_intrq_w));
m_fdc->drq_wr_callback().set(FUNC(ss50_dc5_device::fdc_drq_w));
@@ -501,7 +495,7 @@ uint8_t ss50_dc5_device::validate_fdc_sector_size(uint8_t cmd)
return cmd;
}
-WRITE_LINE_MEMBER( ss50_dc5_device::fdc_intrq_w )
+void ss50_dc5_device::fdc_intrq_w(int state)
{
if (state)
m_fdc_status |= 0x40;
@@ -516,7 +510,7 @@ WRITE_LINE_MEMBER( ss50_dc5_device::fdc_intrq_w )
write_firq(state);
}
-WRITE_LINE_MEMBER( ss50_dc5_device::fdc_drq_w )
+void ss50_dc5_device::fdc_drq_w(int state)
{
if (state)
m_fdc_status |= 0x80;
@@ -524,7 +518,7 @@ WRITE_LINE_MEMBER( ss50_dc5_device::fdc_drq_w )
m_fdc_status &= 0x7f;
}
-WRITE_LINE_MEMBER( ss50_dc5_device::fdc_sso_w )
+void ss50_dc5_device::fdc_sso_w(int state)
{
// The DC4 and DC5 invert the SSO output and wire it to the DDEN input
// to allow selection of single or double density.
@@ -603,10 +597,12 @@ void ss50_dc5_device::control_register_update()
// The floppy drives do not gate the motor based on the select input,
// so the motors run, or not, irrespective of the drive selection.
uint8_t motor = m_motor_timer_out ? CLEAR_LINE : ASSERT_LINE;
- m_floppy0->get_device()->mon_w(motor);
- m_floppy1->get_device()->mon_w(motor);
- m_floppy2->get_device()->mon_w(motor);
- m_floppy3->get_device()->mon_w(motor);
+ for (auto &floppy : m_floppy)
+ {
+ floppy_image_device *fd = floppy->get_device();
+ if (fd)
+ fd->mon_w(motor);
+ }
// The DC2, DC3, DC4, DC5 have a drive inhibit feature controlled by
// bit 7, and the drives are de-selected if the motor timer has timed
@@ -620,13 +616,7 @@ void ss50_dc5_device::control_register_update()
floppy_image_device *floppy = nullptr;
if ((bit7_side_select || !inhibit) && m_motor_timer_out)
- {
- uint8_t drive = m_control_register & 3;
- if (drive == 0) floppy = m_floppy0->get_device();
- if (drive == 1) floppy = m_floppy1->get_device();
- if (drive == 2) floppy = m_floppy2->get_device();
- if (drive == 3) floppy = m_floppy3->get_device();
- }
+ floppy = m_floppy[m_control_register & 3]->get_device();
if (floppy != m_fdc_selected_floppy)
{
diff --git a/src/devices/bus/ss50/interface.cpp b/src/devices/bus/ss50/interface.cpp
index a3100585a76..af39817693b 100644
--- a/src/devices/bus/ss50/interface.cpp
+++ b/src/devices/bus/ss50/interface.cpp
@@ -120,9 +120,6 @@ ss50_interface_port_device::ss50_interface_port_device(const machine_config &mco
void ss50_interface_port_device::device_resolve_objects()
{
- m_irq_cb.resolve_safe();
- m_firq_cb.resolve_safe();
-
m_card = get_card_device();
if (m_card != nullptr)
m_card->m_slot = this;
@@ -171,31 +168,31 @@ void ss50_interface_port_device::write(offs_t offset, u8 data)
// fN_w - baud rate clocks for serial interfaces
//-------------------------------------------------
-WRITE_LINE_MEMBER(ss50_interface_port_device::f110_w)
+void ss50_interface_port_device::f110_w(int state)
{
if (m_card != nullptr)
m_card->f110_w(state);
}
-WRITE_LINE_MEMBER(ss50_interface_port_device::f150_9600_w)
+void ss50_interface_port_device::f150_9600_w(int state)
{
if (m_card != nullptr)
m_card->f150_9600_w(state);
}
-WRITE_LINE_MEMBER(ss50_interface_port_device::f300_w)
+void ss50_interface_port_device::f300_w(int state)
{
if (m_card != nullptr)
m_card->f300_w(state);
}
-WRITE_LINE_MEMBER(ss50_interface_port_device::f600_4800_w)
+void ss50_interface_port_device::f600_4800_w(int state)
{
if (m_card != nullptr)
m_card->f600_4800_w(state);
}
-WRITE_LINE_MEMBER(ss50_interface_port_device::f600_1200_w)
+void ss50_interface_port_device::f600_1200_w(int state)
{
if (m_card != nullptr)
m_card->f600_1200_w(state);
diff --git a/src/devices/bus/ss50/interface.h b/src/devices/bus/ss50/interface.h
index 28e8f82c8c9..ead1754ba00 100644
--- a/src/devices/bus/ss50/interface.h
+++ b/src/devices/bus/ss50/interface.h
@@ -48,11 +48,11 @@ public:
void write(offs_t offset, u8 data);
// baud rates
- DECLARE_WRITE_LINE_MEMBER(f110_w);
- DECLARE_WRITE_LINE_MEMBER(f150_9600_w);
- DECLARE_WRITE_LINE_MEMBER(f300_w);
- DECLARE_WRITE_LINE_MEMBER(f600_4800_w);
- DECLARE_WRITE_LINE_MEMBER(f600_1200_w);
+ void f110_w(int state);
+ void f150_9600_w(int state);
+ void f300_w(int state);
+ void f600_4800_w(int state);
+ void f600_1200_w(int state);
protected:
// device-specific overrides
@@ -83,15 +83,15 @@ protected:
virtual void register_write(offs_t offset, u8 data) = 0;
// optional overrides
- virtual DECLARE_WRITE_LINE_MEMBER(f110_w) { }
- virtual DECLARE_WRITE_LINE_MEMBER(f150_9600_w) { }
- virtual DECLARE_WRITE_LINE_MEMBER(f300_w) { }
- virtual DECLARE_WRITE_LINE_MEMBER(f600_4800_w) { }
- virtual DECLARE_WRITE_LINE_MEMBER(f600_1200_w) { }
+ virtual void f110_w(int state) { }
+ virtual void f150_9600_w(int state) { }
+ virtual void f300_w(int state) { }
+ virtual void f600_4800_w(int state) { }
+ virtual void f600_1200_w(int state) { }
// IRQ/FIRQ/NMI outputs
- DECLARE_WRITE_LINE_MEMBER(write_irq) { m_slot->m_irq_cb(state); }
- DECLARE_WRITE_LINE_MEMBER(write_firq) { m_slot->m_firq_cb(state); }
+ void write_irq(int state) { m_slot->m_irq_cb(state); }
+ void write_firq(int state) { m_slot->m_firq_cb(state); }
private:
virtual void interface_pre_start() override;
diff --git a/src/devices/bus/ss50/mpc.cpp b/src/devices/bus/ss50/mpc.cpp
index 99c476684b3..947e2d80144 100644
--- a/src/devices/bus/ss50/mpc.cpp
+++ b/src/devices/bus/ss50/mpc.cpp
@@ -44,14 +44,14 @@ protected:
// interface-specific overrides
virtual u8 register_read(offs_t offset) override;
virtual void register_write(offs_t offset, u8 data) override;
- virtual DECLARE_WRITE_LINE_MEMBER(f110_w) override;
- virtual DECLARE_WRITE_LINE_MEMBER(f300_w) override;
+ virtual void f110_w(int state) override;
+ virtual void f300_w(int state) override;
private:
- DECLARE_WRITE_LINE_MEMBER(serial_input_w);
- DECLARE_WRITE_LINE_MEMBER(reader_control_w);
- DECLARE_READ_LINE_MEMBER(count_r);
- DECLARE_WRITE_LINE_MEMBER(count_select_w);
+ void serial_input_w(int state);
+ void reader_control_w(int state);
+ int count_r();
+ void count_select_w(int state);
required_device<pia6821_device> m_pia;
required_device<input_merger_device> m_loopback;
@@ -101,7 +101,7 @@ DEVICE_INPUT_DEFAULTS_END
void ss50_mpc_device::device_add_mconfig(machine_config &config)
{
- PIA6821(config, m_pia, 0); // actually MC6820
+ PIA6821(config, m_pia); // actually MC6820
m_pia->writepa_handler().set("outgate", FUNC(input_merger_device::in_w<0>)).bit(0);
m_pia->cb2_handler().set(FUNC(ss50_mpc_device::reader_control_w));
m_pia->readpb_handler().set_ioport("STOP").mask(0x01).lshift(6);
@@ -133,24 +133,24 @@ void ss50_mpc_device::device_start()
save_item(NAME(m_count_select));
}
-WRITE_LINE_MEMBER(ss50_mpc_device::serial_input_w)
+void ss50_mpc_device::serial_input_w(int state)
{
m_pia->write_porta_line(7, state);
m_loopback->in_w<0>(state);
}
-WRITE_LINE_MEMBER(ss50_mpc_device::reader_control_w)
+void ss50_mpc_device::reader_control_w(int state)
{
m_loopback->in_w<1>(state);
}
-READ_LINE_MEMBER(ss50_mpc_device::count_r)
+int ss50_mpc_device::count_r()
{
return BIT(m_counter->count(), m_count_select ? 4 : 3);
}
-WRITE_LINE_MEMBER(ss50_mpc_device::count_select_w)
+void ss50_mpc_device::count_select_w(int state)
{
m_count_select = bool(state);
}
@@ -174,13 +174,13 @@ void ss50_mpc_device::register_write(offs_t offset, u8 data)
m_pia->write(offset & 3, data);
}
-WRITE_LINE_MEMBER(ss50_mpc_device::f110_w)
+void ss50_mpc_device::f110_w(int state)
{
if (m_baud_jumper->read())
m_counter->clock_w(state);
}
-WRITE_LINE_MEMBER(ss50_mpc_device::f300_w)
+void ss50_mpc_device::f300_w(int state)
{
if (!m_baud_jumper->read())
m_counter->clock_w(state);
diff --git a/src/devices/bus/ss50/mps.cpp b/src/devices/bus/ss50/mps.cpp
index b79d1dddbc0..5275c84350d 100644
--- a/src/devices/bus/ss50/mps.cpp
+++ b/src/devices/bus/ss50/mps.cpp
@@ -43,15 +43,15 @@ protected:
// interface-specific overrides
virtual u8 register_read(offs_t offset) override;
virtual void register_write(offs_t offset, u8 data) override;
- virtual DECLARE_WRITE_LINE_MEMBER(f110_w) override;
- virtual DECLARE_WRITE_LINE_MEMBER(f150_9600_w) override;
- virtual DECLARE_WRITE_LINE_MEMBER(f300_w) override;
- virtual DECLARE_WRITE_LINE_MEMBER(f600_4800_w) override;
- virtual DECLARE_WRITE_LINE_MEMBER(f600_1200_w) override;
+ virtual void f110_w(int state) override;
+ virtual void f150_9600_w(int state) override;
+ virtual void f300_w(int state) override;
+ virtual void f600_4800_w(int state) override;
+ virtual void f600_1200_w(int state) override;
private:
- DECLARE_WRITE_LINE_MEMBER(acia_irq_w);
- DECLARE_WRITE_LINE_MEMBER(route_cts);
+ void acia_irq_w(int state);
+ void route_cts(int state);
required_device<acia6850_device> m_acia;
required_ioport m_irq_jumper;
@@ -143,7 +143,7 @@ void ss50_mps_device::register_write(offs_t offset, u8 data)
m_acia->write(offset & 1, data);
}
-WRITE_LINE_MEMBER(ss50_mps_device::f110_w)
+void ss50_mps_device::f110_w(int state)
{
if (!BIT(m_rate_jumper->read(), 0))
{
@@ -152,7 +152,7 @@ WRITE_LINE_MEMBER(ss50_mps_device::f110_w)
}
}
-WRITE_LINE_MEMBER(ss50_mps_device::f150_9600_w)
+void ss50_mps_device::f150_9600_w(int state)
{
if (!BIT(m_rate_jumper->read(), 1))
{
@@ -161,7 +161,7 @@ WRITE_LINE_MEMBER(ss50_mps_device::f150_9600_w)
}
}
-WRITE_LINE_MEMBER(ss50_mps_device::f300_w)
+void ss50_mps_device::f300_w(int state)
{
if (!BIT(m_rate_jumper->read(), 2))
{
@@ -170,7 +170,7 @@ WRITE_LINE_MEMBER(ss50_mps_device::f300_w)
}
}
-WRITE_LINE_MEMBER(ss50_mps_device::f600_4800_w)
+void ss50_mps_device::f600_4800_w(int state)
{
if (!BIT(m_rate_jumper->read(), 3))
{
@@ -179,7 +179,7 @@ WRITE_LINE_MEMBER(ss50_mps_device::f600_4800_w)
}
}
-WRITE_LINE_MEMBER(ss50_mps_device::f600_1200_w)
+void ss50_mps_device::f600_1200_w(int state)
{
if (!BIT(m_rate_jumper->read(), 4))
{
@@ -188,13 +188,13 @@ WRITE_LINE_MEMBER(ss50_mps_device::f600_1200_w)
}
}
-WRITE_LINE_MEMBER(ss50_mps_device::acia_irq_w)
+void ss50_mps_device::acia_irq_w(int state)
{
if (!m_irq_jumper->read())
write_irq(state);
}
-WRITE_LINE_MEMBER(ss50_mps_device::route_cts)
+void ss50_mps_device::route_cts(int state)
{
if (m_cts_route->read())
m_acia->write_cts(state);
diff --git a/src/devices/bus/ss50/mps2.cpp b/src/devices/bus/ss50/mps2.cpp
index f0d9350bfb8..9d8b8990ac1 100644
--- a/src/devices/bus/ss50/mps2.cpp
+++ b/src/devices/bus/ss50/mps2.cpp
@@ -45,11 +45,11 @@ protected:
// interface-specific overrides
virtual u8 register_read(offs_t offset) override;
virtual void register_write(offs_t offset, u8 data) override;
- virtual DECLARE_WRITE_LINE_MEMBER(f110_w) override;
- virtual DECLARE_WRITE_LINE_MEMBER(f150_9600_w) override;
- virtual DECLARE_WRITE_LINE_MEMBER(f300_w) override;
- virtual DECLARE_WRITE_LINE_MEMBER(f600_4800_w) override;
- virtual DECLARE_WRITE_LINE_MEMBER(f600_1200_w) override;
+ virtual void f110_w(int state) override;
+ virtual void f150_9600_w(int state) override;
+ virtual void f300_w(int state) override;
+ virtual void f600_4800_w(int state) override;
+ virtual void f600_1200_w(int state) override;
private:
required_device<acia6850_device> m_acia_upper;
@@ -195,7 +195,7 @@ void ss50_mps2_device::register_write(offs_t offset, u8 data)
m_acia_lower->write((offset - 4) & 1, data);
}
-WRITE_LINE_MEMBER(ss50_mps2_device::f110_w)
+void ss50_mps2_device::f110_w(int state)
{
if (!BIT(m_tx_rate_upper_jumper->read(), 0))
m_acia_upper->write_txc(state);
@@ -207,7 +207,7 @@ WRITE_LINE_MEMBER(ss50_mps2_device::f110_w)
m_acia_lower->write_rxc(state);
}
-WRITE_LINE_MEMBER(ss50_mps2_device::f150_9600_w)
+void ss50_mps2_device::f150_9600_w(int state)
{
if (!BIT(m_tx_rate_upper_jumper->read(), 1))
m_acia_upper->write_txc(state);
@@ -219,7 +219,7 @@ WRITE_LINE_MEMBER(ss50_mps2_device::f150_9600_w)
m_acia_lower->write_rxc(state);
}
-WRITE_LINE_MEMBER(ss50_mps2_device::f300_w)
+void ss50_mps2_device::f300_w(int state)
{
if (!BIT(m_tx_rate_upper_jumper->read(), 2))
m_acia_upper->write_txc(state);
@@ -231,7 +231,7 @@ WRITE_LINE_MEMBER(ss50_mps2_device::f300_w)
m_acia_lower->write_rxc(state);
}
-WRITE_LINE_MEMBER(ss50_mps2_device::f600_4800_w)
+void ss50_mps2_device::f600_4800_w(int state)
{
if (!BIT(m_tx_rate_upper_jumper->read(), 3))
m_acia_upper->write_txc(state);
@@ -243,7 +243,7 @@ WRITE_LINE_MEMBER(ss50_mps2_device::f600_4800_w)
m_acia_lower->write_rxc(state);
}
-WRITE_LINE_MEMBER(ss50_mps2_device::f600_1200_w)
+void ss50_mps2_device::f600_1200_w(int state)
{
if (!BIT(m_tx_rate_upper_jumper->read(), 4))
m_acia_upper->write_txc(state);
diff --git a/src/devices/bus/ss50/mpt.cpp b/src/devices/bus/ss50/mpt.cpp
index f9078aee4ac..b6763c88961 100644
--- a/src/devices/bus/ss50/mpt.cpp
+++ b/src/devices/bus/ss50/mpt.cpp
@@ -36,10 +36,10 @@ protected:
private:
void pia_b_w(uint8_t data);
- DECLARE_WRITE_LINE_MEMBER(pia_irq_b);
+ void pia_irq_b(int state);
TIMER_CALLBACK_MEMBER(mpt_timer_callback);
- DECLARE_WRITE_LINE_MEMBER(pia_irqa_w);
- DECLARE_WRITE_LINE_MEMBER(pia_irqb_w);
+ void pia_irqa_w(int state);
+ void pia_irqb_w(int state);
required_device<pia6821_device> m_pia;
required_ioport m_irqa_jumper;
@@ -80,7 +80,7 @@ ioport_constructor ss50_mpt_device::device_input_ports() const
void ss50_mpt_device::device_add_mconfig(machine_config &config)
{
- PIA6821(config, m_pia, 0);
+ PIA6821(config, m_pia);
m_pia->writepb_handler().set(FUNC(ss50_mpt_device::pia_b_w));
m_pia->cb1_w(0);
m_pia->irqa_handler().set(FUNC(ss50_mpt_device::pia_irqa_w));
@@ -178,13 +178,13 @@ TIMER_CALLBACK_MEMBER(ss50_mpt_device::mpt_timer_callback)
m_mpt_timer->enable(true);
}
-WRITE_LINE_MEMBER(ss50_mpt_device::pia_irqa_w)
+void ss50_mpt_device::pia_irqa_w(int state)
{
if (m_irqa_jumper->read())
write_irq(state);
}
-WRITE_LINE_MEMBER(ss50_mpt_device::pia_irqb_w)
+void ss50_mpt_device::pia_irqb_w(int state)
{
if (m_irqb_jumper->read())
write_irq(state);
diff --git a/src/devices/bus/ss50/piaide.cpp b/src/devices/bus/ss50/piaide.cpp
index a8ac76efdf6..9ab93593c38 100644
--- a/src/devices/bus/ss50/piaide.cpp
+++ b/src/devices/bus/ss50/piaide.cpp
@@ -93,7 +93,7 @@ void ss50_piaide_device::device_start()
void ss50_piaide_device::device_add_mconfig(machine_config &config)
{
- PIA6821(config, m_pia, 0);
+ PIA6821(config, m_pia);
m_pia->readpa_handler().set(FUNC(ss50_piaide_device::pia_a_r));
m_pia->readpb_handler().set(FUNC(ss50_piaide_device::pia_b_r));
m_pia->writepa_handler().set(FUNC(ss50_piaide_device::pia_a_w));
diff --git a/src/devices/bus/sunkbd/hlekbd.cpp b/src/devices/bus/sunkbd/hlekbd.cpp
index db798a716fb..3a45c85569a 100644
--- a/src/devices/bus/sunkbd/hlekbd.cpp
+++ b/src/devices/bus/sunkbd/hlekbd.cpp
@@ -971,7 +971,7 @@ hle_device_base::~hle_device_base()
handle serial input line changes
--------------------------------------------------*/
-WRITE_LINE_MEMBER( hle_device_base::input_txd )
+void hle_device_base::input_txd(int state)
{
device_buffered_serial_interface::rx_w(state);
}
diff --git a/src/devices/bus/sunkbd/hlekbd.h b/src/devices/bus/sunkbd/hlekbd.h
index 3ed680b24c6..775117eb790 100644
--- a/src/devices/bus/sunkbd/hlekbd.h
+++ b/src/devices/bus/sunkbd/hlekbd.h
@@ -23,7 +23,7 @@ class hle_device_base
public:
virtual ~hle_device_base() override;
- virtual DECLARE_WRITE_LINE_MEMBER( input_txd ) override;
+ virtual void input_txd(int state) override;
protected:
// constructor/destructor
diff --git a/src/devices/bus/sunkbd/sunkbd.cpp b/src/devices/bus/sunkbd/sunkbd.cpp
index ee166b8b39f..315b9332130 100644
--- a/src/devices/bus/sunkbd/sunkbd.cpp
+++ b/src/devices/bus/sunkbd/sunkbd.cpp
@@ -132,12 +132,6 @@ void sun_keyboard_port_device::device_config_complete()
}
-void sun_keyboard_port_device::device_resolve_objects()
-{
- m_rxd_handler.resolve_safe();
-}
-
-
void sun_keyboard_port_device::device_start()
{
save_item(NAME(m_rxd));
@@ -148,7 +142,7 @@ void sun_keyboard_port_device::device_start()
}
-WRITE_LINE_MEMBER( sun_keyboard_port_device::write_txd )
+void sun_keyboard_port_device::write_txd(int state)
{
if (m_dev)
m_dev->input_txd(state);
diff --git a/src/devices/bus/sunkbd/sunkbd.h b/src/devices/bus/sunkbd/sunkbd.h
index 8a210025912..39d38b093ec 100644
--- a/src/devices/bus/sunkbd/sunkbd.h
+++ b/src/devices/bus/sunkbd/sunkbd.h
@@ -31,15 +31,14 @@ public:
// configuration helpers
auto rxd_handler() { return m_rxd_handler.bind(); }
- DECLARE_WRITE_LINE_MEMBER( write_txd );
+ void write_txd(int state);
- DECLARE_READ_LINE_MEMBER( rxd_r ) { return m_rxd; }
+ int rxd_r() { return m_rxd; }
protected:
sun_keyboard_port_device(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, uint32_t clock);
virtual void device_config_complete() override;
- virtual void device_resolve_objects() override;
virtual void device_start() override;
int m_rxd;
@@ -61,9 +60,9 @@ public:
protected:
device_sun_keyboard_port_interface(machine_config const &mconfig, device_t &device);
- virtual DECLARE_WRITE_LINE_MEMBER( input_txd ) { }
+ virtual void input_txd(int state) { }
- DECLARE_WRITE_LINE_MEMBER( output_rxd ) { m_port->m_rxd = state; m_port->m_rxd_handler(state); }
+ void output_rxd(int state) { m_port->m_rxd = state; m_port->m_rxd_handler(state); }
sun_keyboard_port_device *m_port;
diff --git a/src/devices/bus/sunmouse/hlemouse.cpp b/src/devices/bus/sunmouse/hlemouse.cpp
index 3256f171aee..07f9648d6c1 100644
--- a/src/devices/bus/sunmouse/hlemouse.cpp
+++ b/src/devices/bus/sunmouse/hlemouse.cpp
@@ -3,7 +3,6 @@
#include "emu.h"
#include "hlemouse.h"
-#define LOG_GENERAL (1U << 0)
#define LOG_BIT (1U << 1)
//#define VERBOSE (LOG_GENERAL | LOG_BIT)
diff --git a/src/devices/bus/sunmouse/sunmouse.cpp b/src/devices/bus/sunmouse/sunmouse.cpp
index 4bd80279149..15635831ed2 100644
--- a/src/devices/bus/sunmouse/sunmouse.cpp
+++ b/src/devices/bus/sunmouse/sunmouse.cpp
@@ -112,8 +112,6 @@ void sun_mouse_port_device::device_config_complete()
void sun_mouse_port_device::device_resolve_objects()
{
m_rxd = 1;
-
- m_rxd_handler.resolve_safe();
}
@@ -126,7 +124,7 @@ void sun_mouse_port_device::device_start()
}
-WRITE_LINE_MEMBER( sun_mouse_port_device::write_txd )
+void sun_mouse_port_device::write_txd(int state)
{
if (m_dev)
m_dev->input_txd(state ? 0 : 1);
diff --git a/src/devices/bus/sunmouse/sunmouse.h b/src/devices/bus/sunmouse/sunmouse.h
index e665529bdfe..4c91aac522e 100644
--- a/src/devices/bus/sunmouse/sunmouse.h
+++ b/src/devices/bus/sunmouse/sunmouse.h
@@ -31,9 +31,9 @@ public:
// configuration helpers
auto rxd_handler() { return m_rxd_handler.bind(); }
- DECLARE_WRITE_LINE_MEMBER( write_txd );
+ void write_txd(int state);
- DECLARE_READ_LINE_MEMBER( rxd_r ) { return m_rxd; }
+ int rxd_r() { return m_rxd; }
protected:
sun_mouse_port_device(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, uint32_t clock);
@@ -61,9 +61,9 @@ public:
protected:
device_sun_mouse_port_interface(machine_config const &mconfig, device_t &device);
- virtual DECLARE_WRITE_LINE_MEMBER( input_txd ) { }
+ virtual void input_txd(int state) { }
- DECLARE_WRITE_LINE_MEMBER( output_rxd ) { m_port->m_rxd_handler(m_port->m_rxd = state ? 0 : 1); }
+ void output_rxd(int state) { m_port->m_rxd_handler(m_port->m_rxd = state ? 0 : 1); }
sun_mouse_port_device *m_port;
diff --git a/src/devices/bus/svi3x8/expander/expander.cpp b/src/devices/bus/svi3x8/expander/expander.cpp
index ea1fab43f93..652e32467b5 100644
--- a/src/devices/bus/svi3x8/expander/expander.cpp
+++ b/src/devices/bus/svi3x8/expander/expander.cpp
@@ -30,14 +30,16 @@ DEFINE_DEVICE_TYPE(SVI_EXPANDER, svi_expander_device, "svi_expander", "SVI 318/3
svi_expander_device::svi_expander_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, SVI_EXPANDER, tag, owner, clock),
device_single_card_slot_interface<device_svi_expander_interface>(mconfig, *this),
+ device_mixer_interface(mconfig, *this),
m_module(nullptr),
m_int_handler(*this),
m_romdis_handler(*this),
m_ramdis_handler(*this),
m_ctrl1_handler(*this),
m_ctrl2_handler(*this),
- m_excsr_handler(*this),
- m_excsw_handler(*this)
+ m_excsr_handler(*this, 0xff),
+ m_excsw_handler(*this),
+ m_dummy(0)
{
}
@@ -58,14 +60,8 @@ void svi_expander_device::device_start()
// get inserted module
m_module = get_card_device();
- // resolve callbacks
- m_int_handler.resolve_safe();
- m_romdis_handler.resolve_safe();
- m_ramdis_handler.resolve_safe();
- m_ctrl1_handler.resolve_safe();
- m_ctrl2_handler.resolve_safe();
- m_excsr_handler.resolve_safe(0xff);
- m_excsw_handler.resolve_safe();
+ // register for save states
+ save_item(NAME(m_dummy));
}
//-------------------------------------------------
@@ -106,28 +102,28 @@ void svi_expander_device::iorq_w(offs_t offset, uint8_t data)
m_module->iorq_w(offset, data);
}
-WRITE_LINE_MEMBER( svi_expander_device::bk21_w )
+void svi_expander_device::bk21_w(int state)
{
- if (m_module)
- m_module->bk21_w(state);
+ if (m_module)
+ m_module->bk21_w(state);
}
-WRITE_LINE_MEMBER( svi_expander_device::bk22_w )
+void svi_expander_device::bk22_w(int state)
{
- if (m_module)
- m_module->bk22_w(state);
+ if (m_module)
+ m_module->bk22_w(state);
}
-WRITE_LINE_MEMBER( svi_expander_device::bk31_w )
+void svi_expander_device::bk31_w(int state)
{
- if (m_module)
- m_module->bk31_w(state);
+ if (m_module)
+ m_module->bk31_w(state);
}
-WRITE_LINE_MEMBER( svi_expander_device::bk32_w )
+void svi_expander_device::bk32_w(int state)
{
- if (m_module)
- m_module->bk32_w(state);
+ if (m_module)
+ m_module->bk32_w(state);
}
diff --git a/src/devices/bus/svi3x8/expander/expander.h b/src/devices/bus/svi3x8/expander/expander.h
index f7bba16eba3..62fc16a337c 100644
--- a/src/devices/bus/svi3x8/expander/expander.h
+++ b/src/devices/bus/svi3x8/expander/expander.h
@@ -39,16 +39,18 @@
#pragma once
+// forward declaration
+class device_svi_expander_interface;
+
//**************************************************************************
-// TYPE DEFINITIONS
+// BUS DEVICE
//**************************************************************************
-class device_svi_expander_interface;
-
-// ======================> svi_expander_device
-
-class svi_expander_device : public device_t, public device_single_card_slot_interface<device_svi_expander_interface>
+class svi_expander_device :
+ public device_t,
+ public device_single_card_slot_interface<device_svi_expander_interface>,
+ public device_mixer_interface
{
public:
// construction/destruction
@@ -75,11 +77,11 @@ public:
auto excsw_handler() { return m_excsw_handler.bind(); }
// called from cart device
- DECLARE_WRITE_LINE_MEMBER( int_w ) { m_int_handler(state); }
- DECLARE_WRITE_LINE_MEMBER( romdis_w ) { m_romdis_handler(state); }
- DECLARE_WRITE_LINE_MEMBER( ramdis_w ) { m_ramdis_handler(state); }
- DECLARE_WRITE_LINE_MEMBER( ctrl1_w ) { m_ctrl1_handler(state); }
- DECLARE_WRITE_LINE_MEMBER( ctrl2_w ) { m_ctrl2_handler(state); }
+ void int_w(int state) { m_int_handler(state); }
+ void romdis_w(int state) { m_romdis_handler(state); }
+ void ramdis_w(int state) { m_ramdis_handler(state); }
+ void ctrl1_w(int state) { m_ctrl1_handler(state); }
+ void ctrl2_w(int state) { m_ctrl2_handler(state); }
uint8_t excs_r(offs_t offset) { return m_excsr_handler(offset); }
void excs_w(offs_t offset, uint8_t data) { m_excsw_handler(offset, data); }
@@ -90,10 +92,10 @@ public:
uint8_t iorq_r(offs_t offset);
void iorq_w(offs_t offset, uint8_t data);
- DECLARE_WRITE_LINE_MEMBER( bk21_w );
- DECLARE_WRITE_LINE_MEMBER( bk22_w );
- DECLARE_WRITE_LINE_MEMBER( bk31_w );
- DECLARE_WRITE_LINE_MEMBER( bk32_w );
+ void bk21_w(int state);
+ void bk22_w(int state);
+ void bk31_w(int state);
+ void bk32_w(int state);
protected:
// device-level overrides
@@ -110,9 +112,14 @@ private:
devcb_read8 m_excsr_handler;
devcb_write8 m_excsw_handler;
+
+ uint8_t m_dummy; // needed for save-state support
};
-// ======================> device_svi_expander_interface
+
+//**************************************************************************
+// CARD INTERFACE
+//**************************************************************************
class device_svi_expander_interface : public device_interface
{
@@ -136,7 +143,7 @@ protected:
svi_expander_device *m_expander;
};
-// device type definition
+// device type declaration
DECLARE_DEVICE_TYPE(SVI_EXPANDER, svi_expander_device)
// include here so drivers don't need to
diff --git a/src/devices/bus/svi3x8/expander/sv601.cpp b/src/devices/bus/svi3x8/expander/sv601.cpp
index 662f3cb0c2e..f37c844d5ab 100644
--- a/src/devices/bus/svi3x8/expander/sv601.cpp
+++ b/src/devices/bus/svi3x8/expander/sv601.cpp
@@ -64,9 +64,9 @@ void sv601_device::device_start()
// IMPLEMENTATION
//**************************************************************************
-WRITE_LINE_MEMBER( sv601_device::int_w ) { m_expander->int_w(state); }
-WRITE_LINE_MEMBER( sv601_device::romdis_w ) { m_expander->romdis_w(state); }
-WRITE_LINE_MEMBER( sv601_device::ramdis_w ) { m_expander->ramdis_w(state); }
+void sv601_device::int_w(int state) { m_expander->int_w(state); }
+void sv601_device::romdis_w(int state) { m_expander->romdis_w(state); }
+void sv601_device::ramdis_w(int state) { m_expander->ramdis_w(state); }
uint8_t sv601_device::mreq_r(offs_t offset) { return m_slotbus->mreq_r(offset); }
void sv601_device::mreq_w(offs_t offset, uint8_t data) { m_slotbus->mreq_w(offset, data); }
diff --git a/src/devices/bus/svi3x8/expander/sv601.h b/src/devices/bus/svi3x8/expander/sv601.h
index 692191a7ea9..cd08e785aa6 100644
--- a/src/devices/bus/svi3x8/expander/sv601.h
+++ b/src/devices/bus/svi3x8/expander/sv601.h
@@ -28,9 +28,9 @@ public:
sv601_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// from slots
- WRITE_LINE_MEMBER( int_w );
- WRITE_LINE_MEMBER( romdis_w );
- WRITE_LINE_MEMBER( ramdis_w );
+ void int_w(int state);
+ void romdis_w(int state);
+ void ramdis_w(int state);
// from host
virtual uint8_t mreq_r(offs_t offset) override;
diff --git a/src/devices/bus/svi3x8/expander/sv602.cpp b/src/devices/bus/svi3x8/expander/sv602.cpp
index 1f5d0c0d352..3143d9239f1 100644
--- a/src/devices/bus/svi3x8/expander/sv602.cpp
+++ b/src/devices/bus/svi3x8/expander/sv602.cpp
@@ -58,9 +58,9 @@ void sv602_device::device_start()
// IMPLEMENTATION
//**************************************************************************
-WRITE_LINE_MEMBER( sv602_device::int_w ) { m_expander->int_w(state); }
-WRITE_LINE_MEMBER( sv602_device::romdis_w ) { m_expander->romdis_w(state); }
-WRITE_LINE_MEMBER( sv602_device::ramdis_w ) { m_expander->ramdis_w(state); }
+void sv602_device::int_w(int state) { m_expander->int_w(state); }
+void sv602_device::romdis_w(int state) { m_expander->romdis_w(state); }
+void sv602_device::ramdis_w(int state) { m_expander->ramdis_w(state); }
uint8_t sv602_device::mreq_r(offs_t offset) { return m_slotbus->mreq_r(offset); }
void sv602_device::mreq_w(offs_t offset, uint8_t data) { m_slotbus->mreq_w(offset, data); }
diff --git a/src/devices/bus/svi3x8/expander/sv602.h b/src/devices/bus/svi3x8/expander/sv602.h
index 607d1cf6c17..d90a0c0ae8e 100644
--- a/src/devices/bus/svi3x8/expander/sv602.h
+++ b/src/devices/bus/svi3x8/expander/sv602.h
@@ -44,9 +44,9 @@ protected:
private:
// from slots
- WRITE_LINE_MEMBER( int_w );
- WRITE_LINE_MEMBER( romdis_w );
- WRITE_LINE_MEMBER( ramdis_w );
+ void int_w(int state);
+ void romdis_w(int state);
+ void ramdis_w(int state);
required_device<svi_slot_bus_device> m_slotbus;
};
diff --git a/src/devices/bus/svi3x8/expander/sv603.cpp b/src/devices/bus/svi3x8/expander/sv603.cpp
index fb0fd3428f9..c52902cc69c 100644
--- a/src/devices/bus/svi3x8/expander/sv603.cpp
+++ b/src/devices/bus/svi3x8/expander/sv603.cpp
@@ -9,7 +9,6 @@
#include "emu.h"
#include "sv603.h"
#include "softlist_dev.h"
-#include "speaker.h"
//**************************************************************************
@@ -38,8 +37,8 @@ const tiny_rom_entry *sv603_device::device_rom_region() const
void sv603_device::device_add_mconfig(machine_config &config)
{
- SPEAKER(config, "mono").front_center();
- SN76489A(config, m_snd, XTAL(10'738'635) / 3).add_route(ALL_OUTPUTS, "mono", 1.00);
+ SN76489A(config, m_snd, XTAL(10'738'635) / 3);
+ m_snd->add_route(ALL_OUTPUTS, DEVICE_SELF_OWNER, 1.0);
// controller ports
COLECOVISION_CONTROL_PORT(config, m_joy[0], colecovision_control_port_devices, "hand");
@@ -50,6 +49,7 @@ void sv603_device::device_add_mconfig(machine_config &config)
// cartridge slot
COLECOVISION_CARTRIDGE_SLOT(config, m_cart, colecovision_cartridges, nullptr);
SOFTWARE_LIST(config, "cart_list").set_original("coleco");
+ SOFTWARE_LIST(config, "homebrew_list").set_original("coleco_homebrew");
}
@@ -94,7 +94,7 @@ void sv603_device::device_reset()
//**************************************************************************
template<int N>
-WRITE_LINE_MEMBER( sv603_device::joy_irq_w )
+void sv603_device::joy_irq_w(int state)
{
m_expander->int_w(state);
}
@@ -104,17 +104,17 @@ uint8_t sv603_device::mreq_r(offs_t offset)
uint8_t data = 0xff;
// ls138 (active low)
- int ccs1 = ((offset >> 13) == 0) ? 0 : 1;
- int ccs2 = ((offset >> 13) == 1) ? 0 : 1;
- int ccs3 = ((offset >> 13) == 2) ? 0 : 1;
- int ccs4 = ((offset >> 13) == 3) ? 0 : 1;
- int bios = ((offset >> 13) == 4) ? 0 : 1;
+ const int ccs1 = ((offset >> 13) == 0) ? 0 : 1;
+ const int ccs2 = ((offset >> 13) == 1) ? 0 : 1;
+ const int ccs3 = ((offset >> 13) == 2) ? 0 : 1;
+ const int ccs4 = ((offset >> 13) == 3) ? 0 : 1;
+ const int bios = ((offset >> 13) == 4) ? 0 : 1;
// 5, 6, 7: not connected
m_expander->romdis_w(0);
m_expander->ramdis_w(bios);
- data &= m_cart->bd_r(offset, data, ccs1, ccs2, ccs3, ccs4);
+ data &= m_cart->read(offset, ccs1, ccs2, ccs3, ccs4);
if (bios == 0)
data &= m_bios->as_u8(offset & 0x1fff);
@@ -124,7 +124,16 @@ uint8_t sv603_device::mreq_r(offs_t offset)
void sv603_device::mreq_w(offs_t offset, uint8_t data)
{
+ const int ccs1 = ((offset >> 13) == 0) ? 0 : 1;
+ const int ccs2 = ((offset >> 13) == 1) ? 0 : 1;
+ const int ccs3 = ((offset >> 13) == 2) ? 0 : 1;
+ const int ccs4 = ((offset >> 13) == 3) ? 0 : 1;
+ const int bios = ((offset >> 13) == 4) ? 0 : 1;
+
m_expander->romdis_w(0);
+ m_expander->ramdis_w(bios);
+
+ m_cart->write(offset, data, ccs1, ccs2, ccs3, ccs4);
}
uint8_t sv603_device::iorq_r(offs_t offset)
diff --git a/src/devices/bus/svi3x8/expander/sv603.h b/src/devices/bus/svi3x8/expander/sv603.h
index a6b3fde21b8..a0bc5297835 100644
--- a/src/devices/bus/svi3x8/expander/sv603.h
+++ b/src/devices/bus/svi3x8/expander/sv603.h
@@ -21,8 +21,6 @@
// TYPE DEFINITIONS
//**************************************************************************
-// ======================> sv603_device
-
class sv603_device : public device_t, public device_svi_expander_interface
{
public:
@@ -35,7 +33,7 @@ public:
virtual uint8_t iorq_r(offs_t offset) override;
virtual void iorq_w(offs_t offset, uint8_t data) override;
- template<int N> DECLARE_WRITE_LINE_MEMBER( joy_irq_w );
+ template<int N> void joy_irq_w(int state);
protected:
virtual const tiny_rom_entry *device_rom_region() const override;
@@ -50,7 +48,7 @@ private:
required_device<colecovision_cartridge_slot_device> m_cart;
};
-// device type definition
+// device type declaration
DECLARE_DEVICE_TYPE(SV603, sv603_device)
#endif // MAME_BUS_SVI3X8_EXPANDER_SV603_H
diff --git a/src/devices/bus/svi3x8/slot/slot.cpp b/src/devices/bus/svi3x8/slot/slot.cpp
index 705734dea4c..dddae4f445a 100644
--- a/src/devices/bus/svi3x8/slot/slot.cpp
+++ b/src/devices/bus/svi3x8/slot/slot.cpp
@@ -34,7 +34,6 @@ svi_slot_bus_device::svi_slot_bus_device(const machine_config &mconfig, const ch
svi_slot_bus_device::~svi_slot_bus_device()
{
- m_dev.detach_all();
}
//-------------------------------------------------
@@ -43,10 +42,6 @@ svi_slot_bus_device::~svi_slot_bus_device()
void svi_slot_bus_device::device_start()
{
- // resolve callbacks
- m_int_handler.resolve_safe();
- m_romdis_handler.resolve_safe();
- m_ramdis_handler.resolve_safe();
}
//-------------------------------------------------
@@ -56,7 +51,7 @@ void svi_slot_bus_device::device_start()
void svi_slot_bus_device::add_card(device_svi_slot_interface &card)
{
card.set_bus_device(*this);
- m_dev.append(card);
+ m_dev.emplace_back(card);
}
//-------------------------------------------------
@@ -65,14 +60,10 @@ void svi_slot_bus_device::add_card(device_svi_slot_interface &card)
uint8_t svi_slot_bus_device::mreq_r(offs_t offset)
{
- device_svi_slot_interface *entry = m_dev.first();
uint8_t data = 0xff;
- while (entry)
- {
- data &= entry->mreq_r(offset);
- entry = entry->next();
- }
+ for (device_svi_slot_interface &entry : m_dev)
+ data &= entry.mreq_r(offset);
return data;
}
@@ -83,13 +74,8 @@ uint8_t svi_slot_bus_device::mreq_r(offs_t offset)
void svi_slot_bus_device::mreq_w(offs_t offset, uint8_t data)
{
- device_svi_slot_interface *entry = m_dev.first();
-
- while (entry)
- {
- entry->mreq_w(offset, data);
- entry = entry->next();
- }
+ for (device_svi_slot_interface &entry : m_dev)
+ entry.mreq_w(offset, data);
}
//-------------------------------------------------
@@ -98,14 +84,10 @@ void svi_slot_bus_device::mreq_w(offs_t offset, uint8_t data)
uint8_t svi_slot_bus_device::iorq_r(offs_t offset)
{
- device_svi_slot_interface *entry = m_dev.first();
uint8_t data = 0xff;
- while (entry)
- {
- data &= entry->iorq_r(offset);
- entry = entry->next();
- }
+ for (device_svi_slot_interface &entry : m_dev)
+ data &= entry.iorq_r(offset);
return data;
}
@@ -116,73 +98,48 @@ uint8_t svi_slot_bus_device::iorq_r(offs_t offset)
void svi_slot_bus_device::iorq_w(offs_t offset, uint8_t data)
{
- device_svi_slot_interface *entry = m_dev.first();
-
- while (entry)
- {
- entry->iorq_w(offset, data);
- entry = entry->next();
- }
+ for (device_svi_slot_interface &entry : m_dev)
+ entry.iorq_w(offset, data);
}
//-------------------------------------------------
// bk21_w - signal from host to slots
//-------------------------------------------------
-WRITE_LINE_MEMBER( svi_slot_bus_device::bk21_w )
+void svi_slot_bus_device::bk21_w(int state)
{
- device_svi_slot_interface *entry = m_dev.first();
-
- while (entry)
- {
- entry->bk21_w(state);
- entry = entry->next();
- }
+ for (device_svi_slot_interface &entry : m_dev)
+ entry.bk21_w(state);
}
//-------------------------------------------------
// bk22_w - signal from host to slots
//-------------------------------------------------
-WRITE_LINE_MEMBER( svi_slot_bus_device::bk22_w )
+void svi_slot_bus_device::bk22_w(int state)
{
- device_svi_slot_interface *entry = m_dev.first();
-
- while (entry)
- {
- entry->bk22_w(state);
- entry = entry->next();
- }
+ for (device_svi_slot_interface &entry : m_dev)
+ entry.bk22_w(state);
}
//-------------------------------------------------
// bk31_w - signal from host to slots
//-------------------------------------------------
-WRITE_LINE_MEMBER( svi_slot_bus_device::bk31_w )
+void svi_slot_bus_device::bk31_w(int state)
{
- device_svi_slot_interface *entry = m_dev.first();
-
- while (entry)
- {
- entry->bk31_w(state);
- entry = entry->next();
- }
+ for (device_svi_slot_interface &entry : m_dev)
+ entry.bk31_w(state);
}
//-------------------------------------------------
// bk32_w - signal from host to slots
//-------------------------------------------------
-WRITE_LINE_MEMBER( svi_slot_bus_device::bk32_w )
+void svi_slot_bus_device::bk32_w(int state)
{
- device_svi_slot_interface *entry = m_dev.first();
-
- while (entry)
- {
- entry->bk32_w(state);
- entry = entry->next();
- }
+ for (device_svi_slot_interface &entry : m_dev)
+ entry.bk32_w(state);
}
@@ -225,8 +182,7 @@ void svi_slot_device::device_start()
device_svi_slot_interface::device_svi_slot_interface(const machine_config &mconfig, device_t &device) :
device_interface(device, "svi3x8slot"),
- m_bus(nullptr),
- m_next(nullptr)
+ m_bus(nullptr)
{
}
diff --git a/src/devices/bus/svi3x8/slot/slot.h b/src/devices/bus/svi3x8/slot/slot.h
index 11b94d07e5d..ca69257b99c 100644
--- a/src/devices/bus/svi3x8/slot/slot.h
+++ b/src/devices/bus/svi3x8/slot/slot.h
@@ -39,6 +39,9 @@
#pragma once
+#include <functional>
+#include <vector>
+
//**************************************************************************
@@ -64,9 +67,9 @@ public:
void add_card(device_svi_slot_interface &card);
// from slot
- DECLARE_WRITE_LINE_MEMBER( int_w ) { m_int_handler(state); }
- DECLARE_WRITE_LINE_MEMBER( romdis_w ) { m_romdis_handler(state); }
- DECLARE_WRITE_LINE_MEMBER( ramdis_w ) { m_ramdis_handler(state); }
+ void int_w(int state) { m_int_handler(state); }
+ void romdis_w(int state) { m_romdis_handler(state); }
+ void ramdis_w(int state) { m_ramdis_handler(state); }
// from host
uint8_t mreq_r(offs_t offset);
@@ -74,16 +77,18 @@ public:
uint8_t iorq_r(offs_t offset);
void iorq_w(offs_t offset, uint8_t data);
- DECLARE_WRITE_LINE_MEMBER( bk21_w );
- DECLARE_WRITE_LINE_MEMBER( bk22_w );
- DECLARE_WRITE_LINE_MEMBER( bk31_w );
- DECLARE_WRITE_LINE_MEMBER( bk32_w );
+ void bk21_w(int state);
+ void bk22_w(int state);
+ void bk31_w(int state);
+ void bk32_w(int state);
private:
- // device-level overrides
+ using card_vector = std::vector<std::reference_wrapper<device_svi_slot_interface> >;
+
+ // device_t implementation
virtual void device_start() override;
- simple_list<device_svi_slot_interface> m_dev;
+ card_vector m_dev;
devcb_write_line m_int_handler;
devcb_write_line m_romdis_handler;
@@ -115,7 +120,7 @@ public:
template <typename T> void set_bus(T &&tag) { m_bus.set_tag(std::forward<T>(tag)); }
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
// configuration
@@ -129,32 +134,26 @@ DECLARE_DEVICE_TYPE(SVI_SLOT, svi_slot_device)
class device_svi_slot_interface : public device_interface
{
- template <class ElementType> friend class simple_list;
public:
// construction/destruction
virtual ~device_svi_slot_interface();
void set_bus_device(svi_slot_bus_device &bus);
- device_svi_slot_interface *next() const { return m_next; }
-
virtual uint8_t mreq_r(offs_t offset) { return 0xff; }
virtual void mreq_w(offs_t offset, uint8_t data) { }
virtual uint8_t iorq_r(offs_t offset) { return 0xff; }
virtual void iorq_w(offs_t offset, uint8_t data) { }
- virtual DECLARE_WRITE_LINE_MEMBER( bk21_w ) { }
- virtual DECLARE_WRITE_LINE_MEMBER( bk22_w ) { }
- virtual DECLARE_WRITE_LINE_MEMBER( bk31_w ) { }
- virtual DECLARE_WRITE_LINE_MEMBER( bk32_w ) { }
+ virtual void bk21_w(int state) { }
+ virtual void bk22_w(int state) { }
+ virtual void bk31_w(int state) { }
+ virtual void bk32_w(int state) { }
protected:
device_svi_slot_interface(const machine_config &mconfig, device_t &device);
svi_slot_bus_device *m_bus;
-
-private:
- device_svi_slot_interface *m_next;
};
// include here so drivers don't need to
diff --git a/src/devices/bus/svi3x8/slot/sv801.cpp b/src/devices/bus/svi3x8/slot/sv801.cpp
index 5695cfd5957..514a844e3a0 100644
--- a/src/devices/bus/svi3x8/slot/sv801.cpp
+++ b/src/devices/bus/svi3x8/slot/sv801.cpp
@@ -89,12 +89,12 @@ void sv801_device::device_reset()
// IMPLEMENTATION
//**************************************************************************
-WRITE_LINE_MEMBER( sv801_device::intrq_w )
+void sv801_device::intrq_w(int state)
{
m_irq = state;
}
-WRITE_LINE_MEMBER( sv801_device::drq_w )
+void sv801_device::drq_w(int state)
{
m_drq = state;
}
diff --git a/src/devices/bus/svi3x8/slot/sv801.h b/src/devices/bus/svi3x8/slot/sv801.h
index 5651e519fb7..1369dc27972 100644
--- a/src/devices/bus/svi3x8/slot/sv801.h
+++ b/src/devices/bus/svi3x8/slot/sv801.h
@@ -39,8 +39,8 @@ protected:
private:
void motor_w(uint8_t data);
- DECLARE_WRITE_LINE_MEMBER( intrq_w );
- DECLARE_WRITE_LINE_MEMBER( drq_w );
+ void intrq_w(int state);
+ void drq_w(int state);
static void floppy_formats(format_registration &fr);
diff --git a/src/devices/bus/svi3x8/slot/sv802.cpp b/src/devices/bus/svi3x8/slot/sv802.cpp
index 909ed2fa712..cf407084a49 100644
--- a/src/devices/bus/svi3x8/slot/sv802.cpp
+++ b/src/devices/bus/svi3x8/slot/sv802.cpp
@@ -79,7 +79,7 @@ void sv802_device::iorq_w(offs_t offset, uint8_t data)
}
}
-WRITE_LINE_MEMBER( sv802_device::busy_w )
+void sv802_device::busy_w(int state)
{
m_busy = state;
}
diff --git a/src/devices/bus/svi3x8/slot/sv802.h b/src/devices/bus/svi3x8/slot/sv802.h
index aabea33bbaf..f70440fc9fd 100644
--- a/src/devices/bus/svi3x8/slot/sv802.h
+++ b/src/devices/bus/svi3x8/slot/sv802.h
@@ -36,7 +36,7 @@ protected:
virtual void device_start() override;
private:
- DECLARE_WRITE_LINE_MEMBER( busy_w );
+ void busy_w(int state);
required_device<centronics_device> m_centronics;
required_device<output_latch_device> m_cent_data_out;
diff --git a/src/devices/bus/svi3x8/slot/sv805.cpp b/src/devices/bus/svi3x8/slot/sv805.cpp
index a5ceadf3577..0e41f8b5f89 100644
--- a/src/devices/bus/svi3x8/slot/sv805.cpp
+++ b/src/devices/bus/svi3x8/slot/sv805.cpp
@@ -99,7 +99,7 @@ void sv805_device::iorq_w(offs_t offset, uint8_t data)
}
}
-WRITE_LINE_MEMBER( sv805_device::uart_intr_w )
+void sv805_device::uart_intr_w(int state)
{
m_bus->int_w(state);
}
diff --git a/src/devices/bus/svi3x8/slot/sv805.h b/src/devices/bus/svi3x8/slot/sv805.h
index 892dc23b432..317fa0fe47c 100644
--- a/src/devices/bus/svi3x8/slot/sv805.h
+++ b/src/devices/bus/svi3x8/slot/sv805.h
@@ -36,7 +36,7 @@ protected:
virtual void device_start() override;
private:
- DECLARE_WRITE_LINE_MEMBER( uart_intr_w );
+ void uart_intr_w(int state);
required_device<ins8250_device> m_uart;
required_device<rs232_port_device> m_rs232;
diff --git a/src/devices/bus/tanbus/etirtc.cpp b/src/devices/bus/tanbus/etirtc.cpp
new file mode 100644
index 00000000000..9875858bd44
--- /dev/null
+++ b/src/devices/bus/tanbus/etirtc.cpp
@@ -0,0 +1,88 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ ETI Real Time Clock/Calendar
+
+ http://www.microtan.ukpc.net/pageProducts.html#CLOCK
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "etirtc.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(TANBUS_ETIRTC, tanbus_etirtc_device, "tanbus_etirtc", "Microtan ETI Real Time Clock")
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void tanbus_etirtc_device::device_add_mconfig(machine_config &config)
+{
+ MM58174(config, "rtc", 32.768_kHz_XTAL);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// tanbus_etirtc_device - constructor
+//-------------------------------------------------
+
+tanbus_etirtc_device::tanbus_etirtc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, TANBUS_ETIRTC, tag, owner, clock)
+ , device_tanbus_interface(mconfig, *this)
+ , m_rtc(*this, "rtc")
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void tanbus_etirtc_device::device_start()
+{
+}
+
+
+//-------------------------------------------------
+// read - card read
+//-------------------------------------------------
+
+uint8_t tanbus_etirtc_device::read(offs_t offset, int inhrom, int inhram, int be)
+{
+ uint8_t data = 0xff;
+
+ switch (offset & 0xfff0)
+ {
+ case 0xbc00:
+ data = m_rtc->read(offset);
+ break;
+ }
+
+ return data;
+}
+
+
+//-------------------------------------------------
+// write - card write
+//-------------------------------------------------
+
+void tanbus_etirtc_device::write(offs_t offset, uint8_t data, int inhrom, int inhram, int be)
+{
+ switch (offset & 0xfff0)
+ {
+ case 0xbc00:
+ m_rtc->write(offset, data);
+ break;
+ }
+}
diff --git a/src/devices/bus/tanbus/etirtc.h b/src/devices/bus/tanbus/etirtc.h
new file mode 100644
index 00000000000..7f7c51eeaea
--- /dev/null
+++ b/src/devices/bus/tanbus/etirtc.h
@@ -0,0 +1,47 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ ETI Real Time Clock/Calendar
+
+**********************************************************************/
+
+
+#ifndef MAME_BUS_TANBUS_ETIRTC_H
+#define MAME_BUS_TANBUS_ETIRTC_H
+
+#pragma once
+
+#include "tanbus.h"
+#include "machine/mm58174.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class tanbus_etirtc_device : public device_t, public device_tanbus_interface
+{
+public:
+ // construction/destruction
+ tanbus_etirtc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+
+ virtual uint8_t read(offs_t offset, int inhrom, int inhram, int be) override;
+ virtual void write(offs_t offset, uint8_t data, int inhrom, int inhram, int be) override;
+
+private:
+ required_device<mm58174_device> m_rtc;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(TANBUS_ETIRTC, tanbus_etirtc_device)
+
+
+#endif // MAME_BUS_TANBUS_ETIRTC_H
diff --git a/src/devices/bus/tanbus/etisnd.cpp b/src/devices/bus/tanbus/etisnd.cpp
new file mode 100644
index 00000000000..7ae5b20a5a7
--- /dev/null
+++ b/src/devices/bus/tanbus/etisnd.cpp
@@ -0,0 +1,153 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ ETI Sound Card
+
+ http://www.microtan.ukpc.net/pageProducts.html#SOUND
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "etisnd.h"
+#include "speaker.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(TANBUS_ETISND, tanbus_etisnd_device, "tanbus_etisnd", "Microtan ETI Sound Card")
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void tanbus_etisnd_device::device_add_mconfig(machine_config &config)
+{
+ PIA6821(config, m_pia[0]);
+ m_pia[0]->writepa_handler().set("dac1", FUNC(dac_byte_interface::data_w));
+ m_pia[0]->writepb_handler().set("dac2", FUNC(dac_byte_interface::data_w));
+
+ PIA6821(config, m_pia[1]);
+ m_pia[1]->writepa_handler().set("dac3", FUNC(dac_byte_interface::data_w));
+ m_pia[1]->writepb_handler().set("dac4", FUNC(dac_byte_interface::data_w));
+
+ PIA6821(config, m_pia[2]);
+ m_pia[2]->writepa_handler().set("dac5", FUNC(dac_byte_interface::data_w));
+ m_pia[2]->writepb_handler().set("dac6", FUNC(dac_byte_interface::data_w));
+
+ PIA6821(config, m_pia[3]);
+ m_pia[2]->writepb_handler().set(FUNC(tanbus_etisnd_device::pia_pb_w));
+
+ SPEAKER(config, "speaker").front_center();
+ DAC0800(config, "dac1").add_route(ALL_OUTPUTS, "speaker", 1.0);
+ DAC0800(config, "dac2").add_route(ALL_OUTPUTS, "speaker", 1.0);
+ DAC0800(config, "dac3").add_route(ALL_OUTPUTS, "speaker", 1.0);
+ DAC0800(config, "dac4").add_route(ALL_OUTPUTS, "speaker", 1.0);
+ DAC0800(config, "dac5").add_route(ALL_OUTPUTS, "speaker", 1.0);
+ DAC0800(config, "dac6").add_route(ALL_OUTPUTS, "speaker", 1.0);
+
+ AY8910(config, m_ay8910, DERIVED_CLOCK(1, 4)).add_route(ALL_OUTPUTS, "speaker", 0.5);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// tanbus_etisnd_device - constructor
+//-------------------------------------------------
+
+tanbus_etisnd_device::tanbus_etisnd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, TANBUS_ETISND, tag, owner, clock)
+ , device_tanbus_interface(mconfig, *this)
+ , m_pia(*this, "pia%u", 0)
+ , m_ay8910(*this, "ay8910")
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void tanbus_etisnd_device::device_start()
+{
+}
+
+
+//-------------------------------------------------
+// read - card read
+//-------------------------------------------------
+
+uint8_t tanbus_etisnd_device::read(offs_t offset, int inhrom, int inhram, int be)
+{
+ uint8_t data = 0xff;
+
+ switch (offset & 0xfffc)
+ {
+ case 0xbc00:
+ data = m_pia[0]->read(offset & 3);
+ break;
+ case 0xbc04:
+ data = m_pia[1]->read(offset & 3);
+ break;
+ case 0xbc08:
+ data = m_pia[2]->read(offset & 3);
+ break;
+ case 0xbc0c:
+ data = m_pia[3]->read(offset & 3);
+ break;
+ }
+
+ return data;
+}
+
+
+//-------------------------------------------------
+// write - card write
+//-------------------------------------------------
+
+void tanbus_etisnd_device::write(offs_t offset, uint8_t data, int inhrom, int inhram, int be)
+{
+ switch (offset & 0xfffc)
+ {
+ case 0xbc00:
+ m_pia[0]->write(offset & 3, data);
+ break;
+ case 0xbc04:
+ m_pia[1]->write(offset & 3, data);
+ break;
+ case 0xbc08:
+ m_pia[2]->write(offset & 3, data);
+ break;
+ case 0xbc0c:
+ m_pia[3]->write(offset & 3, data);
+ break;
+ }
+}
+
+void tanbus_etisnd_device::pia_pb_w(uint8_t data)
+{
+ // PB0 -> BC1
+ // PB1 -> BDIR
+ // +5v -> BC2
+ switch (data & 3)
+ {
+ case 0:
+ m_pia[3]->porta_w(0xff);
+ break;
+ case 1:
+ m_pia[3]->porta_w(m_ay8910->data_r());
+ break;
+ case 2:
+ m_ay8910->data_w(m_pia[3]->a_output());
+ break;
+ case 3:
+ m_ay8910->address_w(m_pia[3]->a_output());
+ break;
+ }
+}
diff --git a/src/devices/bus/tanbus/etisnd.h b/src/devices/bus/tanbus/etisnd.h
new file mode 100644
index 00000000000..6bc8bead361
--- /dev/null
+++ b/src/devices/bus/tanbus/etisnd.h
@@ -0,0 +1,53 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ ETI Sound Card
+
+**********************************************************************/
+
+
+#ifndef MAME_BUS_TANBUS_ETISND_H
+#define MAME_BUS_TANBUS_ETISND_H
+
+#pragma once
+
+#include "tanbus.h"
+#include "machine/6821pia.h"
+#include "sound/ay8910.h"
+#include "sound/dac.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class tanbus_etisnd_device : public device_t, public device_tanbus_interface
+{
+public:
+ // construction/destruction
+ tanbus_etisnd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+
+ virtual uint8_t read(offs_t offset, int inhrom, int inhram, int be) override;
+ virtual void write(offs_t offset, uint8_t data, int inhrom, int inhram, int be) override;
+
+private:
+ required_device_array<pia6821_device, 4> m_pia;
+ required_device<ay8910_device> m_ay8910;
+
+ void pia_pb_w(uint8_t data);
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(TANBUS_ETISND, tanbus_etisnd_device)
+
+
+#endif // MAME_BUS_TANBUS_ETISND_H
diff --git a/src/devices/bus/tanbus/keyboard/keyboard.cpp b/src/devices/bus/tanbus/keyboard/keyboard.cpp
new file mode 100644
index 00000000000..183b0890765
--- /dev/null
+++ b/src/devices/bus/tanbus/keyboard/keyboard.cpp
@@ -0,0 +1,104 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Microtan Keyboard Interface
+
+**********************************************************************/
+
+#include "emu.h"
+#include "keyboard.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(MICROTAN_KBD_SLOT, microtan_kbd_slot_device, "microtan_kbd_slot", "Microtan Keyboard Interface")
+
+
+
+//**************************************************************************
+// DEVICE MICROTAN_KBD PORT INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// device_microtan_kbd_interface - constructor
+//-------------------------------------------------
+
+device_microtan_kbd_interface::device_microtan_kbd_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "microtankbd")
+{
+ m_slot = dynamic_cast<microtan_kbd_slot_device *>(device.owner());
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// microtan_kbd_slot_device - constructor
+//-------------------------------------------------
+
+microtan_kbd_slot_device::microtan_kbd_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MICROTAN_KBD_SLOT, tag, owner, clock)
+ , device_single_card_slot_interface<device_microtan_kbd_interface>(mconfig, *this)
+ , m_kbd(nullptr)
+ , m_strobe_handler(*this)
+ , m_reset_handler(*this)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void microtan_kbd_slot_device::device_start()
+{
+ m_kbd = get_card_device();
+}
+
+
+//-------------------------------------------------
+// kbd_in
+//-------------------------------------------------
+
+u8 microtan_kbd_slot_device::read()
+{
+ if (m_kbd)
+ return m_kbd->read() & 0x7f;
+ else
+ return 0x7f;
+}
+
+//-------------------------------------------------
+// write
+//-------------------------------------------------
+
+void microtan_kbd_slot_device::write(uint8_t data)
+{
+ if (m_kbd)
+ m_kbd->write(data);
+}
+
+//-------------------------------------------------
+// SLOT_INTERFACE( microtan_kbd_devices )
+//-------------------------------------------------
+
+
+// slot devices
+#include "mt006.h"
+#include "mt009.h"
+//#include "mt0020.h"
+#include "spinveti.h"
+
+
+void microtan_kbd_devices(device_slot_interface &device)
+{
+ device.option_add("mt006", MICROTAN_KBD_MT006);
+ device.option_add("mt009", MICROTAN_KBD_MT009);
+ //device.option_add("mt0020", MICROTAN_KBD_MT0020);
+ device.option_add("spinveti", MICROTAN_KBD_SPINVETI);
+}
diff --git a/src/devices/bus/tanbus/keyboard/keyboard.h b/src/devices/bus/tanbus/keyboard/keyboard.h
new file mode 100644
index 00000000000..a9b0c5300b1
--- /dev/null
+++ b/src/devices/bus/tanbus/keyboard/keyboard.h
@@ -0,0 +1,82 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Microtan Keyboard Interface
+
+**********************************************************************/
+
+#ifndef MAME_BUS_TANBUS_KEYBOARD_H
+#define MAME_BUS_TANBUS_KEYBOARD_H
+
+#pragma once
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class device_microtan_kbd_interface;
+
+// ======================> microtan_kbd_slot_device
+
+class microtan_kbd_slot_device : public device_t, public device_single_card_slot_interface<device_microtan_kbd_interface>
+{
+public:
+ // construction/destruction
+ template <typename T>
+ microtan_kbd_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&slot_options, const char *default_option)
+ : microtan_kbd_slot_device(mconfig, tag, owner, 0)
+ {
+ option_reset();
+ slot_options(*this);
+ set_default_option(default_option);
+ set_fixed(false);
+ }
+
+ microtan_kbd_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock = 0);
+
+ // callbacks
+ auto strobe_handler() { return m_strobe_handler.bind(); }
+ auto reset_handler() { return m_reset_handler.bind(); }
+
+ virtual uint8_t read();
+ virtual void write(uint8_t data);
+
+ void strobe_w(int state) { m_strobe_handler(state); }
+ void reset_w(int state) { m_reset_handler(state); }
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+
+private:
+ device_microtan_kbd_interface *m_kbd;
+
+ devcb_write_line m_strobe_handler;
+ devcb_write_line m_reset_handler;
+};
+
+
+// ======================> device_microtan_kbd_interface
+
+class device_microtan_kbd_interface : public device_interface
+{
+public:
+ virtual uint8_t read() { return 0xff; }
+ virtual void write(uint8_t data) { }
+
+protected:
+ device_microtan_kbd_interface(const machine_config &mconfig, device_t &device);
+
+ microtan_kbd_slot_device *m_slot;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(MICROTAN_KBD_SLOT, microtan_kbd_slot_device)
+
+void microtan_kbd_devices(device_slot_interface &device);
+
+
+#endif // MAME_BUS_TANBUS_KEYBOARD_H
diff --git a/src/devices/bus/tanbus/keyboard/mt006.cpp b/src/devices/bus/tanbus/keyboard/mt006.cpp
new file mode 100644
index 00000000000..c46ed6fab76
--- /dev/null
+++ b/src/devices/bus/tanbus/keyboard/mt006.cpp
@@ -0,0 +1,118 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Microtan Keypad (MT006)
+
+ http://www.microtan.ukpc.net/pageProducts.html#KEYBOARDS
+
+*********************************************************************/
+
+#include "emu.h"
+#include "mt006.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(MICROTAN_KBD_MT006, microtan_kbd_mt006, "microtan_kbd_mt006", "Microtan Keypad (MT006)")
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+static INPUT_PORTS_START( mt006 )
+ PORT_START("KPAD0")
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("0") PORT_CODE(KEYCODE_0_PAD)
+ PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("4") PORT_CODE(KEYCODE_4_PAD)
+ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("8 P") PORT_CODE(KEYCODE_8_PAD)
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("C M") PORT_CODE(KEYCODE_C)
+ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("SHIFT") PORT_CODE(KEYCODE_LSHIFT)
+
+ PORT_START("KPAD1")
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("1") PORT_CODE(KEYCODE_1_PAD)
+ PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("5 O") PORT_CODE(KEYCODE_5_PAD)
+ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("9 ESC") PORT_CODE(KEYCODE_9_PAD)
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("D G") PORT_CODE(KEYCODE_D)
+ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("LF DEL") PORT_CODE(KEYCODE_DEL_PAD)
+
+ PORT_START("KPAD2")
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("2") PORT_CODE(KEYCODE_2_PAD)
+ PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("6 C") PORT_CODE(KEYCODE_6_PAD)
+ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("A") PORT_CODE(KEYCODE_A)
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("E S") PORT_CODE(KEYCODE_E)
+ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("CR SP") PORT_CODE(KEYCODE_ENTER_PAD)
+
+ PORT_START("KPAD3")
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("3 '") PORT_CODE(KEYCODE_3_PAD)
+ PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("7 R") PORT_CODE(KEYCODE_7_PAD)
+ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("B L") PORT_CODE(KEYCODE_B)
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("F N") PORT_CODE(KEYCODE_F)
+ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_UNUSED)
+
+ PORT_START("RESET")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("RESET") PORT_CODE(KEYCODE_F12) PORT_CHANGED_MEMBER(DEVICE_SELF, microtan_kbd_mt006, trigger_reset, 0)
+INPUT_PORTS_END
+
+INPUT_CHANGED_MEMBER(microtan_kbd_mt006::trigger_reset)
+{
+ m_slot->reset_w(newval ? CLEAR_LINE : ASSERT_LINE);
+}
+
+ioport_constructor microtan_kbd_mt006::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( mt006 );
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// microtan_kbd_mt006 - constructor
+//-------------------------------------------------
+
+microtan_kbd_mt006::microtan_kbd_mt006(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, MICROTAN_KBD_MT006, tag, owner, clock)
+ , device_microtan_kbd_interface(mconfig, *this)
+ , m_keypad(*this, "KPAD%u", 0U)
+ , m_column(0)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void microtan_kbd_mt006::device_start()
+{
+ save_item(NAME(m_column));
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+uint8_t microtan_kbd_mt006::read()
+{
+ uint8_t data = 0x00;
+
+ for (int i = 0; i < 4; i++)
+ if (BIT(m_column, i))
+ data |= m_keypad[i]->read();
+
+ return data;
+}
+
+
+void microtan_kbd_mt006::write(uint8_t data)
+{
+ m_column = data & 0x0f;
+
+ m_slot->strobe_w(BIT(data, 4));
+}
diff --git a/src/devices/bus/tanbus/keyboard/mt006.h b/src/devices/bus/tanbus/keyboard/mt006.h
new file mode 100644
index 00000000000..02315a94149
--- /dev/null
+++ b/src/devices/bus/tanbus/keyboard/mt006.h
@@ -0,0 +1,50 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Microtan Keypad (MT006)
+
+*********************************************************************/
+
+#ifndef MAME_BUS_TANBUS_KEYBOARD_MT006_H
+#define MAME_BUS_TANBUS_KEYBOARD_MT006_H
+
+#pragma once
+
+#include "keyboard.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class microtan_kbd_mt006 : public device_t, public device_microtan_kbd_interface
+{
+public:
+ // construction/destruction
+ microtan_kbd_mt006(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
+
+ DECLARE_INPUT_CHANGED_MEMBER(trigger_reset);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+
+ // optional information overrides
+ virtual ioport_constructor device_input_ports() const override;
+
+ virtual uint8_t read() override;
+ virtual void write(uint8_t data) override;
+
+private:
+ required_ioport_array<4> m_keypad;
+
+ uint8_t m_column;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(MICROTAN_KBD_MT006, microtan_kbd_mt006)
+
+
+#endif // MAME_BUS_TANBUS_KEYBOARD_MT006_H
diff --git a/src/devices/bus/tanbus/keyboard/mt009.cpp b/src/devices/bus/tanbus/keyboard/mt009.cpp
new file mode 100644
index 00000000000..50aa471cdf2
--- /dev/null
+++ b/src/devices/bus/tanbus/keyboard/mt009.cpp
@@ -0,0 +1,389 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Microtan Keyboard (MT009)
+
+ http://www.microtan.ukpc.net/pageProducts.html#KEYBOARDS
+
+ The keyboard is essentially an ordinary ASCII keyboard, with 71 keys, 8
+ TTL chips and a 2716 eprom labeled MON V1. We currently use a
+ generic keyboard because of the lack of a schematic. Unemulated keys are
+ 'SHIFT LOCK' and 'REPT'. Since all commands must be uppercase, capslock
+ is defaulted to on.
+
+ TODO:
+ - use ROM data to determine the returned ASCII code.
+
+*********************************************************************/
+
+#include "emu.h"
+#include "mt009.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(MICROTAN_KBD_MT009, microtan_kbd_mt009, "microtan_kbd_mt009", "Microtan Keyboard (MT009)")
+
+
+static const char keyboard[8][9][8] = {
+ { /* normal */
+ { 27,'1','2','3','4','5','6','7'},
+ {'8','9','0',':','-', 12,127,'^'},
+ {'q','w','e','r','t','y','u','i'},
+ {'o','p','[',']', 13, 3, 0, 0},
+ {'a','s','d','f','g','h','j','k'},
+ {'l',';','@', 92, 0,'z','x','c'},
+ {'v','b','n','m',',','.','/', 0},
+ { 10,' ','-',',', 13,'.','0','1'},
+ {'2','3','4','5','6','7','8','9'},
+ },
+ { /* Shift */
+ { 27,'!','"','#','$','%','&', 39},
+ {'(',')','~','*','=', 12,127,'_'},
+ {'Q','W','E','R','T','Y','U','I'},
+ {'O','P','{','}', 13, 3, 0, 0},
+ {'A','S','D','F','G','H','J','K'},
+ {'L','+','`','|', 0,'Z','X','C'},
+ {'V','B','N','M','<','>','?', 0},
+ { 10,' ','-',',', 13,'.','0','1'},
+ {'2','3','4','5','6','7','8','9'},
+ },
+ { /* Control */
+ { 27,'1','2','3','4','5','6','7'},
+ {'8','9','0',':','-','`',127, 30},
+ { 17, 23, 5, 18, 20, 25, 21, 9},
+ { 15, 16, 27, 29, 13, 3, 0, 0},
+ { 1, 19, 4, 6, 7, 8, 10, 11},
+ { 12,';','@', 28, 0, 26, 24, 3},
+ { 22, 2, 14, 13,',','.','/', 0},
+ { 10,' ','-',',', 13,'.','0','1'},
+ {'2','3','4','5','6','7','8','9'},
+ },
+ { /* Shift+Control */
+ { 27,'!','"','#','$','%','&', 39},
+ {'(',')','~','*','=', 12,127, 31},
+ { 17, 23, 5, 18, 20, 25, 21, 9},
+ { 15, 16, 27, 29, 13,127, 0, 0},
+ { 1, 19, 4, 6, 7, 8, 10, 11},
+ { 12,'+','`', 28, 0, 26, 24, 3},
+ { 22, 2, 14, 13,',','.','/', 0},
+ { 10,' ','-',',', 13,'.','0','1'},
+ {'2','3','4','5','6','7','8','9'},
+ },
+ { /* CapsLock */
+ { 27,'1','2','3','4','5','6','7'},
+ {'8','9','0',':','-', 12,127,'^'},
+ {'Q','W','E','R','T','Y','U','I'},
+ {'O','P','[',']', 13, 3, 0, 0},
+ {'A','S','D','F','G','H','J','K'},
+ {'L',';','@', 92, 0,'Z','X','C'},
+ {'V','B','N','M',',','.','/', 0},
+ { 10,' ','-',',', 13,'.','0','1'},
+ {'2','3','4','5','6','7','8','9'},
+ },
+ { /* Shift+CapsLock */
+ { 27,'!','"','#','$','%','&', 39},
+ {'(',')','~','*','=', 12,127,'_'},
+ {'q','w','e','r','t','y','u','i'},
+ {'o','p','{','}', 13, 3, 0, 0},
+ {'a','s','d','f','g','h','j','k'},
+ {'l','+','`','|', 0,'z','x','c'},
+ {'v','b','n','m','<','>','?', 0},
+ { 10,' ','-',',', 13,'.','0','1'},
+ {'2','3','4','5','6','7','8','9'},
+ },
+ { /* Control+CapsLock */
+ { 27,'1','2','3','4','5','6','7'},
+ {'8','9','0',':','-', 12,127, 9},
+ { 17, 23, 5, 18, 20, 25, 21, 9},
+ { 15, 16, 27, 29, 13,127, 0, 0},
+ { 1, 19, 4, 6, 7, 8, 10, 11},
+ { 12,';', 39, 28, 0, 26, 24, 3},
+ { 22, 2, 14, 13,',','.','/', 0},
+ { 10,' ','-',',', 13,'.','0','1'},
+ {'2','3','4','5','6','7','8','9'},
+ },
+ { /* Shift+Control+CapsLock */
+ { 27,'!','"','#','$','%','&', 39},
+ {'(',')','~','*','=', 12,127, 9},
+ { 17, 23, 5, 18, 20, 25, 21, 9},
+ { 15, 16, 27, 29, 13,127, 0, 0},
+ { 1, 19, 4, 6, 7, 8, 10, 11},
+ { 12,':','"', 28, 0, 26, 24, 3},
+ { 22, 2, 14, 13,',','.','/', 0},
+ { 10,' ','-',',', 13,'.','0','1'},
+ {'2','3','4','5','6','7','8','9'},
+ },
+};
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+static INPUT_PORTS_START( kbd_mt009 )
+ PORT_START("KBD0")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("ESC") PORT_CODE(KEYCODE_ESC) PORT_CHAR(27)
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!')
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('"')
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#')
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$')
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%')
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('&')
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('\'')
+
+ PORT_START("KBD1")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('(')
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR(')')
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR('~')
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_MINUS) PORT_CHAR(':') PORT_CHAR('*')
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('-') PORT_CHAR('=')
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("NEW PAGE") PORT_CODE(KEYCODE_TILDE) PORT_CHAR(12)
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("RUB OUT") PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8)
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME(u8"\u2191") PORT_CODE(KEYCODE_TAB) PORT_CHAR('^') PORT_CHAR('_') // U+2191 = ↑
+
+ PORT_START("KBD2")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Q) PORT_CHAR('Q') PORT_CHAR('q')
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_W) PORT_CHAR('W') PORT_CHAR('w')
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_E) PORT_CHAR('E') PORT_CHAR('e')
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_R) PORT_CHAR('R') PORT_CHAR('r')
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_T) PORT_CHAR('T') PORT_CHAR('t')
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Y) PORT_CHAR('Y') PORT_CHAR('y')
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_U) PORT_CHAR('U') PORT_CHAR('u')
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_I) PORT_CHAR('I') PORT_CHAR('i')
+
+ PORT_START("KBD3")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_O) PORT_CHAR('O') PORT_CHAR('o')
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_P) PORT_CHAR('P') PORT_CHAR('p')
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('[') PORT_CHAR('{')
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR(']') PORT_CHAR('}')
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("RETURN") PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13)
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("BREAK") PORT_CODE(KEYCODE_DEL) PORT_CHAR(3)
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("CTRL") PORT_CODE(KEYCODE_LCONTROL)
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("ALFA LOCK") PORT_CODE(KEYCODE_CAPSLOCK) PORT_TOGGLE
+
+ PORT_START("KBD4")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_A) PORT_CHAR('A') PORT_CHAR('a')
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_S) PORT_CHAR('S') PORT_CHAR('s')
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_D) PORT_CHAR('D') PORT_CHAR('d')
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_F) PORT_CHAR('F') PORT_CHAR('f')
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_G) PORT_CHAR('G') PORT_CHAR('g')
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_H) PORT_CHAR('H') PORT_CHAR('h')
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_J) PORT_CHAR('J') PORT_CHAR('j')
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_K) PORT_CHAR('K') PORT_CHAR('k')
+
+ PORT_START("KBD5")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_L) PORT_CHAR('L') PORT_CHAR('l')
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR('+')
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("@") PORT_CODE(KEYCODE_QUOTE) PORT_CHAR('@') PORT_CHAR('`')
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR('\\') PORT_CHAR('|')
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("SHIFT (L)") PORT_CODE(KEYCODE_LSHIFT) PORT_CHAR(UCHAR_SHIFT_1)
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Z) PORT_CHAR('Z') PORT_CHAR('z')
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_X) PORT_CHAR('X') PORT_CHAR('x')
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_C) PORT_CHAR('C') PORT_CHAR('c')
+
+ PORT_START("KBD6")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_V) PORT_CHAR('V') PORT_CHAR('v')
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_B) PORT_CHAR('B') PORT_CHAR('b')
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_N) PORT_CHAR('N') PORT_CHAR('n')
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_M) PORT_CHAR('M') PORT_CHAR('m')
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<')
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>')
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?')
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("SHIFT (R)") PORT_CODE(KEYCODE_RSHIFT)
+
+ PORT_START("KBD7")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("LINE FEED") PORT_CHAR(10)
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("SPACE") PORT_CODE(KEYCODE_SPACE) PORT_CHAR(32)
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("- (KP)") PORT_CODE(KEYCODE_MINUS_PAD)
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME(", (KP)") PORT_CODE(KEYCODE_PLUS_PAD)
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("ENTER (KP)") PORT_CODE(KEYCODE_ENTER_PAD)
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME(". (KP)") PORT_CODE(KEYCODE_DEL_PAD)
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("0 (KP)") PORT_CODE(KEYCODE_0_PAD)
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("1 (KP)") PORT_CODE(KEYCODE_1_PAD)
+
+ PORT_START("KBD8")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("2 (KP)") PORT_CODE(KEYCODE_2_PAD)
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("3 (KP)") PORT_CODE(KEYCODE_3_PAD)
+ PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("4 (KP)") PORT_CODE(KEYCODE_4_PAD)
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("5 (KP)") PORT_CODE(KEYCODE_5_PAD)
+ PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("6 (KP)") PORT_CODE(KEYCODE_6_PAD)
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("7 (KP)") PORT_CODE(KEYCODE_7_PAD)
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("8 (KP)") PORT_CODE(KEYCODE_8_PAD)
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("9 (KP)") PORT_CODE(KEYCODE_9_PAD)
+
+ PORT_START("BRK")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("RESET") PORT_CODE(KEYCODE_F12) PORT_CHAR(UCHAR_MAMEKEY(F12)) PORT_CHANGED_MEMBER(DEVICE_SELF, microtan_kbd_mt009, trigger_reset, 0)
+INPUT_PORTS_END
+
+INPUT_CHANGED_MEMBER(microtan_kbd_mt009::trigger_reset)
+{
+ m_slot->reset_w(newval ? ASSERT_LINE : CLEAR_LINE);
+}
+
+ioport_constructor microtan_kbd_mt009::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( kbd_mt009 );
+}
+
+
+//-------------------------------------------------
+// rom_region - device-specific ROM region
+//-------------------------------------------------
+
+ROM_START( kbd_mt009 )
+ ROM_REGION( 0x0800, "rom", 0 )
+ ROM_LOAD("ascii_v1.bin", 0x0000, 0x0800, CRC(17a03a82) SHA1(89dcc0712745ed9ba876a78eefd55e9a54fc4fad))
+ROM_END
+
+const tiny_rom_entry *microtan_kbd_mt009::device_rom_region() const
+{
+ return ROM_NAME( kbd_mt009 );
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// microtan_kbd_mt009 - constructor
+//-------------------------------------------------
+
+microtan_kbd_mt009::microtan_kbd_mt009(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, MICROTAN_KBD_MT009, tag, owner, clock)
+ , device_microtan_kbd_interface(mconfig, *this)
+ , m_rom(*this, "rom")
+ , m_keyboard(*this, "KBD%u", 0U)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void microtan_kbd_mt009::device_start()
+{
+ m_kbd_scan_timer = timer_alloc(FUNC(microtan_kbd_mt009::kbd_scan), this);
+
+ m_kbd_scan_timer->adjust(attotime::from_hz(45), 0, attotime::from_hz(45));
+
+ save_item(NAME(m_kbd_ascii));
+ save_item(NAME(m_keyrows));
+ save_item(NAME(m_lastrow));
+ save_item(NAME(m_mask));
+ save_item(NAME(m_key));
+ save_item(NAME(m_repeat));
+ save_item(NAME(m_repeater));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void microtan_kbd_mt009::device_reset()
+{
+ for (int i = 1; i < 10; i++)
+ m_keyrows[i] = m_keyboard[i-1]->read();
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+uint8_t microtan_kbd_mt009::read()
+{
+ return m_kbd_ascii;
+}
+
+
+void microtan_kbd_mt009::store_key(int key)
+{
+ m_kbd_ascii = key;
+ m_slot->strobe_w(ASSERT_LINE);
+}
+
+TIMER_CALLBACK_MEMBER(microtan_kbd_mt009::kbd_scan)
+{
+ int mod, row, col, chg, newvar;
+
+ if (m_repeat)
+ {
+ if (!--m_repeat)
+ m_repeater = 4;
+ }
+ else if (m_repeater)
+ m_repeat = m_repeater;
+
+ row = 9;
+ newvar = m_keyboard[8]->read();
+ chg = m_keyrows[--row] ^ newvar;
+
+ while (!chg && row > 0)
+ {
+ newvar = m_keyboard[row - 1]->read();
+ chg = m_keyrows[--row] ^ newvar;
+ }
+ if (!chg)
+ --row;
+
+ if (row >= 0)
+ {
+ m_repeater = 0x00;
+ m_mask = 0x00;
+ m_key = 0x00;
+ m_lastrow = row;
+
+ if (newvar & chg) /* key(s) pressed ? */
+ {
+ mod = 0;
+
+ /* Shift modifier */
+ if ((m_keyrows[5] & 0x10) || (m_keyrows[6] & 0x80))
+ mod |= 1;
+
+ /* Control modifier */
+ if (m_keyrows[3] & 0x40)
+ mod |= 2;
+
+ /* CapsLock modifier */
+ if (m_keyrows[3] & 0x80)
+ mod |= 4;
+
+ /* find newvar key */
+ m_mask = 0x01;
+ for (col = 0; col < 8; col++)
+ {
+ if (chg & m_mask)
+ {
+ newvar &= m_mask;
+ m_key = keyboard[mod][row][col];
+ break;
+ }
+ m_mask <<= 1;
+ }
+ if (m_key) /* normal key */
+ {
+ m_repeater = 30;
+ store_key(m_key);
+ }
+ else
+ if ((row == 0) && (chg == 0x04)) /* Ctrl-@ (NUL) */
+ store_key(0);
+ m_keyrows[row] |= newvar;
+ }
+ else
+ m_keyrows[row] = newvar;
+
+ m_repeat = m_repeater;
+ }
+ else
+ if (m_key && (m_keyrows[m_lastrow] & m_mask) && m_repeat == 0)
+ store_key(m_key);
+}
diff --git a/src/devices/bus/tanbus/keyboard/mt009.h b/src/devices/bus/tanbus/keyboard/mt009.h
new file mode 100644
index 00000000000..f9c934f551d
--- /dev/null
+++ b/src/devices/bus/tanbus/keyboard/mt009.h
@@ -0,0 +1,63 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Microtan Keyboard (MT009)
+
+*********************************************************************/
+
+#ifndef MAME_BUS_TANBUS_KEYBOARD_MT009_H
+#define MAME_BUS_TANBUS_KEYBOARD_MT009_H
+
+#pragma once
+
+#include "keyboard.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class microtan_kbd_mt009 : public device_t, public device_microtan_kbd_interface
+{
+public:
+ // construction/destruction
+ microtan_kbd_mt009(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
+
+ DECLARE_INPUT_CHANGED_MEMBER(trigger_reset);
+ TIMER_CALLBACK_MEMBER(kbd_scan);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ // optional information overrides
+ virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual ioport_constructor device_input_ports() const override;
+
+ virtual uint8_t read() override;
+
+private:
+ required_memory_region m_rom;
+ required_ioport_array<9> m_keyboard;
+
+ emu_timer *m_kbd_scan_timer = nullptr;
+
+ uint8_t m_kbd_ascii = 0;
+ uint8_t m_keyrows[10]{};
+ int m_lastrow = 0;
+ int m_mask = 0;
+ int m_key = 0;
+ int m_repeat = 0;
+ int m_repeater = 0;
+
+ void store_key(int key);
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(MICROTAN_KBD_MT009, microtan_kbd_mt009)
+
+
+#endif // MAME_BUS_TANBUS_KEYBOARD_MT009_H
diff --git a/src/devices/bus/tanbus/keyboard/spinveti.cpp b/src/devices/bus/tanbus/keyboard/spinveti.cpp
new file mode 100644
index 00000000000..143442a31bd
--- /dev/null
+++ b/src/devices/bus/tanbus/keyboard/spinveti.cpp
@@ -0,0 +1,97 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ ETI Space Invasion Key Unit
+
+*********************************************************************/
+
+#include "emu.h"
+#include "spinveti.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(MICROTAN_KBD_SPINVETI, microtan_kbd_spinveti, "microtan_kbd_spinveti", "ETI Space Invasion Key Unit")
+
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+static INPUT_PORTS_START( spinveti )
+ PORT_START("PB")
+ PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("Start") PORT_CODE(KEYCODE_ENTER)
+ PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("Right") PORT_CODE(KEYCODE_RIGHT)
+ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("Left") PORT_CODE(KEYCODE_LEFT)
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("Fire") PORT_CODE(KEYCODE_LCONTROL)
+ PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("Hold") PORT_CODE(KEYCODE_H)
+
+ PORT_START("SW")
+ PORT_CONFNAME(0x60, 0x20, "Difficulty")
+ PORT_CONFSETTING(0x00, "Easy")
+ PORT_CONFSETTING(0x20, "Normal")
+ PORT_CONFSETTING(0x40, "Hard")
+ PORT_CONFSETTING(0x60, "Hardest")
+
+ PORT_START("RS")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Reset") PORT_CODE(KEYCODE_R) PORT_CHANGED_MEMBER(DEVICE_SELF, microtan_kbd_spinveti, trigger_reset, 0)
+INPUT_PORTS_END
+
+INPUT_CHANGED_MEMBER(microtan_kbd_spinveti::trigger_reset)
+{
+ m_slot->reset_w(newval ? CLEAR_LINE : ASSERT_LINE);
+}
+
+ioport_constructor microtan_kbd_spinveti::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( spinveti );
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// microtan_kbd_spinveti - constructor
+//-------------------------------------------------
+
+microtan_kbd_spinveti::microtan_kbd_spinveti(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, MICROTAN_KBD_SPINVETI, tag, owner, clock)
+ , device_microtan_kbd_interface(mconfig, *this)
+ , m_pb(*this, "PB")
+ , m_sw(*this, "SW")
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void microtan_kbd_spinveti::device_start()
+{
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+uint8_t microtan_kbd_spinveti::read()
+{
+ return m_pb->read() | m_sw->read();
+}
+
+
+void microtan_kbd_spinveti::write(uint8_t data)
+{
+ // TODO: sound effects (heartbeat, fire, saucer, and explosion)
+ // bit 1 Heartbeat (active high)
+ // bit 2 Gun firing (active low)
+ // bit 3 Flying saucer (active high)
+ // bit 4 Explosion (active high)
+}
diff --git a/src/devices/bus/tanbus/keyboard/spinveti.h b/src/devices/bus/tanbus/keyboard/spinveti.h
new file mode 100644
index 00000000000..941581a5912
--- /dev/null
+++ b/src/devices/bus/tanbus/keyboard/spinveti.h
@@ -0,0 +1,49 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ ETI Space Invasion Key Unit
+
+*********************************************************************/
+
+#ifndef MAME_BUS_TANBUS_KEYBOARD_SPINVETI_H
+#define MAME_BUS_TANBUS_KEYBOARD_SPINVETI_H
+
+#pragma once
+
+#include "keyboard.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class microtan_kbd_spinveti : public device_t, public device_microtan_kbd_interface
+{
+public:
+ // construction/destruction
+ microtan_kbd_spinveti(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
+
+ DECLARE_INPUT_CHANGED_MEMBER(trigger_reset);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+
+ // optional information overrides
+ virtual ioport_constructor device_input_ports() const override;
+
+ virtual uint8_t read() override;
+ virtual void write(uint8_t data) override;
+
+private:
+ required_ioport m_pb;
+ required_ioport m_sw;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(MICROTAN_KBD_SPINVETI, microtan_kbd_spinveti)
+
+
+#endif // MAME_BUS_TANBUS_KEYBOARD_SPINVETI_H
diff --git a/src/devices/bus/tanbus/mpvdu.cpp b/src/devices/bus/tanbus/mpvdu.cpp
index 43c303dff4b..a74bdddedaf 100644
--- a/src/devices/bus/tanbus/mpvdu.cpp
+++ b/src/devices/bus/tanbus/mpvdu.cpp
@@ -180,7 +180,7 @@ MC6845_UPDATE_ROW(tanbus_mpvdu_device::crtc_update_row)
}
}
-WRITE_LINE_MEMBER(tanbus_mpvdu_device::vsync_changed)
+void tanbus_mpvdu_device::vsync_changed(int state)
{
m_trom->dew_w(state);
}
diff --git a/src/devices/bus/tanbus/mpvdu.h b/src/devices/bus/tanbus/mpvdu.h
index ddde01e0611..37db354574e 100644
--- a/src/devices/bus/tanbus/mpvdu.h
+++ b/src/devices/bus/tanbus/mpvdu.h
@@ -45,7 +45,7 @@ protected:
private:
uint8_t videoram_r(offs_t offset);
MC6845_UPDATE_ROW(crtc_update_row);
- DECLARE_WRITE_LINE_MEMBER(vsync_changed);
+ void vsync_changed(int state);
required_device<screen_device> m_screen;
required_device<mc6845_device> m_crtc;
diff --git a/src/devices/bus/tanbus/ra32k.cpp b/src/devices/bus/tanbus/ra32k.cpp
index 9b83afc96f0..15f3aa25e37 100644
--- a/src/devices/bus/tanbus/ra32k.cpp
+++ b/src/devices/bus/tanbus/ra32k.cpp
@@ -17,7 +17,8 @@
// DEVICE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(TANBUS_RA32K, tanbus_ra32k_device, "tanbus_ra32k", "Ralph Allen 32K EPROM-RAM Card")
+DEFINE_DEVICE_TYPE(TANBUS_RA32KRAM, tanbus_ra32kram_device, "tanbus_ra32kram", "Ralph Allen 32K EPROM-RAM Card (RAM)")
+DEFINE_DEVICE_TYPE(TANBUS_RA32KROM, tanbus_ra32krom_device, "tanbus_ra32krom", "Ralph Allen 32K EPROM-RAM Card (RALBUG)")
//-------------------------------------------------
@@ -97,10 +98,9 @@ INPUT_PORTS_START( ra32k )
PORT_DIPSETTING(0x0b, "$F000-$6FFF")
PORT_START("LNK1")
- PORT_CONFNAME(0x03, 0x00, "Block Enable")
- PORT_CONFSETTING(0x00, "RAM (permanent)")
- PORT_CONFSETTING(0x01, "RAM (page selectable)")
- PORT_CONFSETTING(0x02, "EPROM (page selectable)")
+ PORT_CONFNAME(0x01, 0x00, "Block Enable")
+ PORT_CONFSETTING(0x00, "Permanent")
+ PORT_CONFSETTING(0x01, "Page selectable")
INPUT_PORTS_END
@@ -114,20 +114,20 @@ ioport_constructor tanbus_ra32k_device::device_input_ports() const
}
//-------------------------------------------------
-// ROM( ra32k )
+// ROM( ra32krom )
//-------------------------------------------------
-ROM_START(ra32k)
+ROM_START(ra32krom)
ROM_REGION(0x8000, "rom", 0)
- ROM_LOAD("data_v1.4.rom", 0x0000, 0x0800, CRC(de61f11d) SHA1(3e6ddc5dba47d9136f58abc9475c3e73fc8cc0c2))
- ROM_LOAD("syntax_v1.4.rom", 0x0800, 0x0800, CRC(17438c4c) SHA1(46bf4e33544c19e142b380095736c5c3eb885ba0))
- ROM_LOAD("ascii_v1.4.rom", 0x1000, 0x0800, CRC(93244a81) SHA1(6149eec9904438a0d23529d2c2428a594d5b1fb9))
- ROM_LOAD("graph_v1.4.rom", 0x1800, 0x0800, CRC(159eb1f6) SHA1(5e49edda4b550506aca70d1f7e7de7a352f0359f))
+ ROM_LOAD("data_v1.4.rom", 0x2000, 0x0800, CRC(de61f11d) SHA1(3e6ddc5dba47d9136f58abc9475c3e73fc8cc0c2))
+ ROM_LOAD("syntax_v1.4.rom", 0x2800, 0x0800, CRC(17438c4c) SHA1(46bf4e33544c19e142b380095736c5c3eb885ba0))
+ ROM_LOAD("ascii_v1.4.rom", 0x3000, 0x0800, CRC(93244a81) SHA1(6149eec9904438a0d23529d2c2428a594d5b1fb9))
+ ROM_LOAD("graph_v1.4.rom", 0x3800, 0x0800, CRC(159eb1f6) SHA1(5e49edda4b550506aca70d1f7e7de7a352f0359f))
ROM_END
-const tiny_rom_entry *tanbus_ra32k_device::device_rom_region() const
+const tiny_rom_entry *tanbus_ra32krom_device::device_rom_region() const
{
- return ROM_NAME(ra32k);
+ return ROM_NAME(ra32krom);
}
//**************************************************************************
@@ -138,95 +138,50 @@ const tiny_rom_entry *tanbus_ra32k_device::device_rom_region() const
// tanbus_ra32k_device - constructor
//-------------------------------------------------
-tanbus_ra32k_device::tanbus_ra32k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, TANBUS_RA32K, tag, owner, clock)
+tanbus_ra32k_device::tanbus_ra32k_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, type, tag, owner, clock)
, device_tanbus_interface(mconfig, *this)
- , m_rom(*this, "rom")
, m_dsw(*this, "DSW%u", 1)
, m_link(*this, "LNK1")
{
}
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-
-void tanbus_ra32k_device::device_start()
+tanbus_ra32kram_device::tanbus_ra32kram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : tanbus_ra32k_device(mconfig, TANBUS_RA32KRAM, tag, owner, clock)
{
- m_ram = std::make_unique<uint8_t[]>(0x8000);
-
- save_pointer(NAME(m_ram), 0x8000);
}
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
-void tanbus_ra32k_device::device_reset()
+tanbus_ra32krom_device::tanbus_ra32krom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : tanbus_ra32k_device(mconfig, TANBUS_RA32KROM, tag, owner, clock)
+ , m_rom(*this, "rom")
{
}
//-------------------------------------------------
-// read - card read
+// device_start - device-specific startup
//-------------------------------------------------
-uint8_t tanbus_ra32k_device::read(offs_t offset, int inhrom, int inhram, int be)
+void tanbus_ra32kram_device::device_start()
{
- uint8_t data = 0xff;
+ m_ram = make_unique_clear<uint8_t[]>(0x8000);
- switch (m_link->read() & 0x02)
- {
- case 0x00:
- /* 32K dynamic RAM */
- if (block_enabled(offset, inhrom, inhram, be))
- {
- //logerror("ram read %04x\n", offset);
- data = m_ram[offset & 0x7fff];
- }
- break;
- case 0x02:
- /* ROM selected */
- if (block_enabled(offset, inhrom, inhram, be))
- {
- //logerror("rom read %04x\n", offset);
- data = m_rom->base()[(offset - m_addr_start) & 0x7fff];
- }
- break;
- }
-
- return data;
+ save_pointer(NAME(m_ram), 0x8000);
}
-//-------------------------------------------------
-// write - card write
-//-------------------------------------------------
-
-void tanbus_ra32k_device::write(offs_t offset, uint8_t data, int inhrom, int inhram, int be)
+void tanbus_ra32krom_device::device_start()
{
- switch (m_link->read() & 0x02)
- {
- case 0x00:
- /* 32K dynamic RAM */
- if (block_enabled(offset, inhrom, inhram, be))
- {
- //logerror("ram write %04x %02x\n", offset, data);
- m_ram[offset & 0x7fff] = data;
- }
- break;
- case 0x02:
- /* ROM selected */
- break;
- }
}
+
bool tanbus_ra32k_device::block_enabled(offs_t offset, int inhrom, int inhram, int be)
{
- m_addr_start = ((bitswap<4>(m_dsw[2]->read(), 1, 0, 3, 2) << 12) + 0x1000) & 0xffff;
- m_addr_end = (m_addr_start + 0x7fff) & 0xffff;
+ offs_t addr_start = ((bitswap<4>(m_dsw[2]->read(), 1, 0, 3, 2) << 12) + 0x1000) & 0xffff;
+ offs_t addr_end = (addr_start + 0x7fff) & 0xffff;
- //uint8_t block_start = (bitswap<4>(m_dsw[2]->read(), 1, 0, 3, 2) + 1) & 0x0f;
- uint8_t block = offset >> 12;
- //logerror("%04x start %04x current %04x\n", offset, block_start, block);
+ uint8_t block = (offset & 0x7800) >> 12;
+
+ if (offset < addr_start || offset > addr_end)
+ return false;
if (offset & 0x0800)
{
@@ -255,3 +210,37 @@ bool tanbus_ra32k_device::block_enabled(offs_t offset, int inhrom, int inhram, i
return true;
}
+
+//-------------------------------------------------
+// read - card read
+//-------------------------------------------------
+
+uint8_t tanbus_ra32kram_device::read(offs_t offset, int inhrom, int inhram, int be)
+{
+ if (block_enabled(offset, inhrom, inhram, be))
+ {
+ return m_ram[offset & 0x7fff];
+ }
+ return 0xff;
+}
+
+uint8_t tanbus_ra32krom_device::read(offs_t offset, int inhrom, int inhram, int be)
+{
+ if (block_enabled(offset, inhrom, inhram, be))
+ {
+ return m_rom[offset & 0x7fff];
+ }
+ return 0xff;
+}
+
+//-------------------------------------------------
+// write - card write
+//-------------------------------------------------
+
+void tanbus_ra32kram_device::write(offs_t offset, uint8_t data, int inhrom, int inhram, int be)
+{
+ if (block_enabled(offset, inhrom, inhram, be))
+ {
+ m_ram[offset & 0x7fff] = data;
+ }
+}
diff --git a/src/devices/bus/tanbus/ra32k.h b/src/devices/bus/tanbus/ra32k.h
index a67e9c859bb..e92e96452fa 100644
--- a/src/devices/bus/tanbus/ra32k.h
+++ b/src/devices/bus/tanbus/ra32k.h
@@ -19,41 +19,66 @@
// TYPE DEFINITIONS
//**************************************************************************
-class tanbus_ra32k_device :
- public device_t,
- public device_tanbus_interface
+class tanbus_ra32k_device : public device_t, public device_tanbus_interface
+{
+protected:
+ tanbus_ra32k_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ // optional information overrides
+ virtual ioport_constructor device_input_ports() const override;
+
+ required_ioport_array<3> m_dsw;
+ required_ioport m_link;
+
+ bool block_enabled(offs_t offset, int inhrom, int inhram, int be);
+};
+
+
+// ======================> tanbus_ra32kram_device
+
+class tanbus_ra32kram_device : public tanbus_ra32k_device
{
public:
// construction/destruction
- tanbus_ra32k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ tanbus_ra32kram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
// device-level overrides
virtual void device_start() override;
- virtual void device_reset() override;
-
- // optional information overrides
- virtual const tiny_rom_entry *device_rom_region() const override;
- virtual ioport_constructor device_input_ports() const override;
virtual uint8_t read(offs_t offset, int inhrom, int inhram, int be) override;
virtual void write(offs_t offset, uint8_t data, int inhrom, int inhram, int be) override;
private:
- required_memory_region m_rom;
- required_ioport_array<3> m_dsw;
- required_ioport m_link;
-
- offs_t m_addr_start;
- offs_t m_addr_end;
std::unique_ptr<uint8_t[]> m_ram;
+};
- bool block_enabled(offs_t offset, int inhrom, int inhram, int be);
+
+// ======================> tanbus_ra32krom_device
+
+class tanbus_ra32krom_device : public tanbus_ra32k_device
+{
+public:
+ // construction/destruction
+ tanbus_ra32krom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+
+ // optional information overrides
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+ virtual uint8_t read(offs_t offset, int inhrom, int inhram, int be) override;
+
+private:
+ required_region_ptr<uint8_t> m_rom;
};
// device type definition
-DECLARE_DEVICE_TYPE(TANBUS_RA32K, tanbus_ra32k_device)
+DECLARE_DEVICE_TYPE(TANBUS_RA32KRAM, tanbus_ra32kram_device)
+DECLARE_DEVICE_TYPE(TANBUS_RA32KROM, tanbus_ra32krom_device)
#endif // MAME_BUS_TANBUS_RA32K_H
diff --git a/src/devices/bus/tanbus/radisc.cpp b/src/devices/bus/tanbus/radisc.cpp
index b302e33c80d..add9a7e3945 100644
--- a/src/devices/bus/tanbus/radisc.cpp
+++ b/src/devices/bus/tanbus/radisc.cpp
@@ -11,6 +11,8 @@
#include "emu.h"
#include "radisc.h"
+#include "formats/acorn_dsk.h"
+#include "formats/flex_dsk.h"
#include "speaker.h"
@@ -31,24 +33,30 @@ static void tandos_floppies(device_slot_interface &device)
device.option_add("525qd", FLOPPY_525_QD);
}
+void tanbus_radisc_device::floppy_formats(format_registration &fr)
+{
+ fr.add_mfm_containers();
+ fr.add(FLOPPY_FLEX_FORMAT);
+ fr.add(FLOPPY_ACORN_SSD_FORMAT);
+}
+
//-------------------------------------------------
// device_add_mconfig - add device configuration
//-------------------------------------------------
void tanbus_radisc_device::device_add_mconfig(machine_config &config)
{
- INPUT_MERGER_ANY_HIGH(config, m_irq_line).output_handler().set(FUNC(tanbus_radisc_device::fdc_irq_w));
+ INPUT_MERGER_ANY_HIGH(config, m_irq_line).output_handler().set(FUNC(tanbus_radisc_device::irq_w));
FD1793(config, m_fdc, 4_MHz_XTAL / 4);
- m_fdc->intrq_wr_callback().set(m_irq_line, FUNC(input_merger_device::in_w<IRQ_FDC>));
+ m_fdc->intrq_wr_callback().set(FUNC(tanbus_radisc_device::fdc_irq_w));
m_fdc->drq_wr_callback().set(FUNC(tanbus_radisc_device::fdc_drq_w));
- m_fdc->hld_wr_callback().set(FUNC(tanbus_radisc_device::fdc_hld_w));
m_fdc->set_force_ready(true);
- FLOPPY_CONNECTOR(config, m_floppies[0], tandos_floppies, "525qd", floppy_image_device::default_mfm_floppy_formats).enable_sound(true);
- FLOPPY_CONNECTOR(config, m_floppies[1], tandos_floppies, "525qd", floppy_image_device::default_mfm_floppy_formats).enable_sound(true);
- FLOPPY_CONNECTOR(config, m_floppies[2], tandos_floppies, nullptr, floppy_image_device::default_mfm_floppy_formats).enable_sound(true);
- FLOPPY_CONNECTOR(config, m_floppies[3], tandos_floppies, nullptr, floppy_image_device::default_mfm_floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppies[0], tandos_floppies, "525qd", tanbus_radisc_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppies[1], tandos_floppies, "525qd", tanbus_radisc_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppies[2], tandos_floppies, nullptr, tanbus_radisc_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppies[3], tandos_floppies, nullptr, tanbus_radisc_device::floppy_formats).enable_sound(true);
MC146818(config, m_rtc, 32.768_kHz_XTAL);
m_rtc->irq().set(m_irq_line, FUNC(input_merger_device::in_w<IRQ_RTC>));
@@ -56,7 +64,6 @@ void tanbus_radisc_device::device_add_mconfig(machine_config &config)
MOS6522(config, m_via, 4_MHz_XTAL / 4);
m_via->irq_handler().set(m_irq_line, FUNC(input_merger_device::in_w<IRQ_VIA>));
- /* audio hardware */
SPEAKER(config, "mono").front_center();
BEEP(config, m_beeper, 1000); // TODO: unknown frequency
m_beeper->add_route(ALL_OUTPUTS, "mono", 1.0);
@@ -75,13 +82,14 @@ tanbus_radisc_device::tanbus_radisc_device(const machine_config &mconfig, const
, device_tanbus_interface(mconfig, *this)
, m_fdc(*this, "fdc")
, m_floppies(*this, "fdc:%u", 0)
- , m_floppy(nullptr)
, m_rtc(*this, "rtc")
, m_via(*this, "via")
, m_irq_line(*this, "irq_line")
, m_beeper(*this, "beeper")
, m_beeper_state(0)
- , m_drive_control(0)
+ , m_status(0)
+ , m_irq_enable(0)
+ , m_drq_enable(0)
{
}
@@ -95,14 +103,6 @@ void tanbus_radisc_device::device_start()
}
//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
-void tanbus_radisc_device::device_reset()
-{
-}
-
-//-------------------------------------------------
// read - card read
//-------------------------------------------------
@@ -119,10 +119,10 @@ uint8_t tanbus_radisc_device::read(offs_t offset, int inhrom, int inhram, int be
data = m_fdc->read(offset & 0x03);
break;
case 0xbf94:
- data = control_r();
+ data = status_r();
break;
- case 0xbf98: case 0xbf99:
- data = m_rtc->read(offset & 0x01);
+ case 0xbf99:
+ data = m_rtc->data_r();
break;
}
@@ -150,8 +150,11 @@ void tanbus_radisc_device::write(offs_t offset, uint8_t data, int inhrom, int in
m_beeper_state ^= 1;
m_beeper->set_state(m_beeper_state);
break;
- case 0xbf98: case 0xbf99:
- m_rtc->write(offset & 0x01, data);
+ case 0xbf98:
+ m_rtc->address_w(data);
+ break;
+ case 0xbf99:
+ m_rtc->data_w(data);
break;
}
}
@@ -160,54 +163,51 @@ void tanbus_radisc_device::write(offs_t offset, uint8_t data, int inhrom, int in
// IMPLEMENTATION
//**************************************************************************
-void tanbus_radisc_device::control_w(uint8_t val)
+void tanbus_radisc_device::control_w(uint8_t data)
{
- logerror("control_w %02x\n", val);
- m_drive_control = val;
+ m_status = data & 0x3e;
// bit 0: irq enable
- m_irq_enable = BIT(val, 0);
+ m_irq_enable = BIT(data, 0);
// bit 1: data select (data stream controller)
// bit 2, 3: drive select
- m_floppy = m_floppies[(val >> 2) & 0x03]->get_device();
- m_fdc->set_floppy(m_floppy);
+ floppy_image_device *floppy = m_floppies[BIT(data, 2, 2)]->get_device();
+ m_fdc->set_floppy(floppy);
// bit 4: side select
- if (m_floppy)
- m_floppy->ss_w(BIT(val, 4));
+ if (floppy)
+ floppy->ss_w(BIT(data, 4));
// bit 5: density
- m_fdc->dden_w(BIT(val, 5));
+ m_fdc->dden_w(BIT(data, 5));
- // bit 6: head load
- if (m_floppy)
- m_floppy->mon_w(BIT(val, 6));
+ // bit 6: head load timing
+ m_fdc->hlt_w(BIT(data, 6));
+ if (floppy)
+ floppy->mon_w(!BIT(data, 6));
// bit 7: drq enable
- m_drq_enable = BIT(val, 7);
+ m_drq_enable = BIT(data, 7);
}
-uint8_t tanbus_radisc_device::control_r()
+uint8_t tanbus_radisc_device::status_r()
{
- logerror("control_r %02x\n", m_drive_control);
- return m_drive_control;
+ return m_status | (m_fdc->drq_r() << 7) | (m_fdc->hld_r() << 6) | (m_fdc->intrq_r() << 0);
}
-WRITE_LINE_MEMBER(tanbus_radisc_device::fdc_drq_w)
+void tanbus_radisc_device::fdc_drq_w(int state)
{
m_tanbus->so_w((m_drq_enable && state) ? ASSERT_LINE : CLEAR_LINE);
}
-WRITE_LINE_MEMBER(tanbus_radisc_device::fdc_irq_w)
+void tanbus_radisc_device::fdc_irq_w(int state)
{
- m_tanbus->irq_w((m_irq_enable && state) ? ASSERT_LINE : CLEAR_LINE);
+ m_irq_line->in_w<IRQ_FDC>((m_irq_enable && state) ? ASSERT_LINE : CLEAR_LINE);
}
-WRITE_LINE_MEMBER(tanbus_radisc_device::fdc_hld_w)
+void tanbus_radisc_device::irq_w(int state)
{
- logerror("fdc_hld_w %d\n", state);
- if (m_floppy)
- m_floppy->mon_w(state);
+ m_tanbus->irq_w(state ? ASSERT_LINE : CLEAR_LINE);
}
diff --git a/src/devices/bus/tanbus/radisc.h b/src/devices/bus/tanbus/radisc.h
index bbcfc2298ac..86654897c8a 100644
--- a/src/devices/bus/tanbus/radisc.h
+++ b/src/devices/bus/tanbus/radisc.h
@@ -13,22 +13,22 @@
#pragma once
#include "bus/tanbus/tanbus.h"
-#include "imagedev/floppy.h"
#include "machine/wd_fdc.h"
#include "machine/mc146818.h"
#include "machine/6522via.h"
#include "machine/input_merger.h"
#include "sound/beep.h"
+#include "imagedev/floppy.h"
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
-class tanbus_radisc_device :
- public device_t,
- public device_tanbus_interface
+class tanbus_radisc_device : public device_t, public device_tanbus_interface
{
public:
+ static constexpr feature_type imperfect_features() { return feature::DISK; }
+
// construction/destruction
tanbus_radisc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
@@ -37,7 +37,6 @@ public:
protected:
// device-level overrides
virtual void device_start() override;
- virtual void device_reset() override;
// optional information overrides
virtual void device_add_mconfig(machine_config &config) override;
@@ -48,22 +47,21 @@ protected:
private:
enum { IRQ_FDC, IRQ_VIA, IRQ_RTC };
- void control_w(uint8_t val);
- uint8_t control_r();
- DECLARE_WRITE_LINE_MEMBER(fdc_irq_w);
- DECLARE_WRITE_LINE_MEMBER(fdc_drq_w);
- DECLARE_WRITE_LINE_MEMBER(fdc_hld_w);
+ void control_w(uint8_t data);
+ uint8_t status_r();
+ void fdc_irq_w(int state);
+ void fdc_drq_w(int state);
+ void irq_w(int state);
required_device<fd1793_device> m_fdc;
required_device_array<floppy_connector, 4> m_floppies;
- floppy_image_device *m_floppy;
required_device<mc146818_device> m_rtc;
required_device<via6522_device> m_via;
required_device<input_merger_device> m_irq_line;
required_device<beep_device> m_beeper;
int m_beeper_state;
- uint8_t m_drive_control;
+ uint8_t m_status;
int m_irq_enable;
int m_drq_enable;
};
diff --git a/src/devices/bus/tanbus/ravdu.cpp b/src/devices/bus/tanbus/ravdu.cpp
index 43cd6ff45ab..2a20e14cbe5 100644
--- a/src/devices/bus/tanbus/ravdu.cpp
+++ b/src/devices/bus/tanbus/ravdu.cpp
@@ -193,7 +193,7 @@ MC6845_UPDATE_ROW(tanbus_ravdu_device::crtc_update_row)
}
}
-WRITE_LINE_MEMBER(tanbus_ravdu_device::vsync_changed)
+void tanbus_ravdu_device::vsync_changed(int state)
{
m_trom->dew_w(state);
}
diff --git a/src/devices/bus/tanbus/ravdu.h b/src/devices/bus/tanbus/ravdu.h
index f21dc73c4f5..e98fe034d4f 100644
--- a/src/devices/bus/tanbus/ravdu.h
+++ b/src/devices/bus/tanbus/ravdu.h
@@ -46,7 +46,7 @@ protected:
private:
uint8_t videoram_r(offs_t offset);
MC6845_UPDATE_ROW(crtc_update_row);
- DECLARE_WRITE_LINE_MEMBER(vsync_changed);
+ void vsync_changed(int state);
required_device<screen_device> m_screen;
required_device<mc6845_device> m_crtc;
diff --git a/src/devices/bus/tanbus/tanbus.cpp b/src/devices/bus/tanbus/tanbus.cpp
index b84d625c80f..15d4ab8c976 100644
--- a/src/devices/bus/tanbus/tanbus.cpp
+++ b/src/devices/bus/tanbus/tanbus.cpp
@@ -67,11 +67,15 @@ tanbus_device::tanbus_device(const machine_config &mconfig, const char *tag, dev
{
}
+tanbus_device::~tanbus_device()
+{
+}
+
void tanbus_device::add_card(device_tanbus_interface *card, int num)
{
card->m_tanbus = this;
card->m_page = num;
- m_device_list.append(*card);
+ m_device_list.emplace_back(*card);
}
//-------------------------------------------------
@@ -80,12 +84,6 @@ void tanbus_device::add_card(device_tanbus_interface *card, int num)
void tanbus_device::device_start()
{
- // resolve callbacks
- m_out_irq_cb.resolve_safe();
- m_out_nmi_cb.resolve_safe();
- m_out_so_cb.resolve_safe();
- m_out_pgm_cb.resolve_safe();
-
save_item(NAME(m_block_register));
}
@@ -104,19 +102,11 @@ void tanbus_device::device_reset()
void tanbus_device::set_inhibit_lines(offs_t offset)
{
- // prevent debugger from changing inhibit lines
- if (machine().side_effects_disabled()) return;
-
// reset inhibit lines
m_inhram = m_inhrom = 0;
- device_tanbus_interface *card = m_device_list.first();
-
- while (card)
- {
- card->set_inhibit_lines(offset, m_inhram, m_inhrom);
- card = card->next();
- }
+ for (device_tanbus_interface &card : m_device_list)
+ card.set_inhibit_lines(offset, m_inhram, m_inhrom);
}
//-------------------------------------------------
@@ -129,19 +119,15 @@ uint8_t tanbus_device::read(offs_t offset)
set_inhibit_lines(offset);
- device_tanbus_interface *card = m_device_list.first();
-
- while (card)
+ for (device_tanbus_interface &card : m_device_list)
{
// set block enable line for current card
- if ((card->m_page == 0) || ((m_block_register >> 4) & 7) == card->m_page)
+ if (BIT(m_block_register, 4, 3) == card.m_page)
m_block_enable = 1;
else
m_block_enable = 0;
- data &= card->read(offset, m_inhrom, m_inhram, m_block_enable);
- card = card->next();
-
+ data &= card.read(offset, m_inhrom, m_inhram, m_block_enable);
}
return data;
@@ -155,7 +141,7 @@ void tanbus_device::write(offs_t offset, uint8_t data)
{
if (offset == 0xffff)
{
- logerror("write: Memory management control (read %d, write %d)\n", (data >> 4) & 7, data & 7);
+ logerror("write: Memory management control %02x (read %d, write %d)\n", data, BIT(data, 4, 3), BIT(data, 0, 3));
m_block_register = data;
}
else if (offset >= 0xf800)
@@ -165,18 +151,15 @@ void tanbus_device::write(offs_t offset, uint8_t data)
set_inhibit_lines(offset);
- device_tanbus_interface *card = m_device_list.first();
-
- while (card)
+ for (device_tanbus_interface &card : m_device_list)
{
// set block enable line for current card
- if ((card->m_page == 0) || (m_block_register & 7) == card->m_page)
+ if (BIT(m_block_register, 0,3) == card.m_page)
m_block_enable = 1;
else
m_block_enable = 0;
- card->write(offset, data, m_inhrom, m_inhram, m_block_enable);
- card = card->next();
+ card.write(offset, data, m_inhrom, m_inhram, m_block_enable);
}
}
@@ -192,7 +175,6 @@ device_tanbus_interface::device_tanbus_interface(const machine_config &mconfig,
: device_interface(device, "tanbus")
, m_tanbus(nullptr)
, m_page(0)
- , m_next(nullptr)
{
}
@@ -204,16 +186,20 @@ device_tanbus_interface::device_tanbus_interface(const machine_config &mconfig,
// slot devices
#include "bullsnd.h"
+#include "etirtc.h"
+#include "etisnd.h"
#include "mpvdu.h"
#include "ra32k.h"
#include "radisc.h"
#include "ravdu.h"
#include "tanram.h"
+#include "tanrtc.h"
#include "tandos.h"
#include "tanex.h"
#include "tanhrg.h"
#include "tug64k.h"
#include "tug8082.h"
+#include "tugcombo.h"
#include "tugpgm.h"
void tanex_devices(device_slot_interface &device)
@@ -224,19 +210,29 @@ void tanex_devices(device_slot_interface &device)
void tanbus_devices(device_slot_interface &device)
{
device.option_add("bullsnd", TANBUS_BULLSND);
+ device.option_add("etirtc", TANBUS_ETIRTC);
+ device.option_add("etisnd", TANBUS_ETISND);
+ //device.option_add("intelgraph", TANBUS_INTELGRAPH);
device.option_add("mpvdu", TANBUS_MPVDU);
device.option_add("tanram", TANBUS_TANRAM);
+ device.option_add("tanrtc", TANBUS_TANRTC);
device.option_add("tandos", TANBUS_TANDOS);
device.option_add("tanhrg", TANBUS_TANHRG);
device.option_add("tanhrgc", TANBUS_TANHRGC);
device.option_add("tug64k", TANBUS_TUG64K);
device.option_add("tug8082", TANBUS_TUG8082);
+ device.option_add("tugesc2716", TANBUS_TUGESC2716);
+ device.option_add("tugesc2732", TANBUS_TUGESC2732);
+ device.option_add("tugcombo2716", TANBUS_TUGCOMBO2716);
+ device.option_add("tugcombo2732", TANBUS_TUGCOMBO2732);
+ device.option_add("tugcombo6116", TANBUS_TUGCOMBO6116);
device.option_add("tugpgm", TANBUS_TUGPGM);
}
void tanbus6809_devices(device_slot_interface &device)
{
- device.option_add("ra32k", TANBUS_RA32K);
+ device.option_add("ra32kram", TANBUS_RA32KRAM);
+ device.option_add("ra32krom", TANBUS_RA32KROM);
device.option_add("radisc", TANBUS_RADISC);
device.option_add("ravdu", TANBUS_RAVDU);
device.option_add("tanram", TANBUS_TANRAM);
diff --git a/src/devices/bus/tanbus/tanbus.h b/src/devices/bus/tanbus/tanbus.h
index 7f5e87eb0aa..86636e834dd 100644
--- a/src/devices/bus/tanbus/tanbus.h
+++ b/src/devices/bus/tanbus/tanbus.h
@@ -11,6 +11,8 @@
#pragma once
+#include <functional>
+#include <vector>
//**************************************************************************
@@ -66,7 +68,7 @@ class tanbus_device : public device_t
public:
// construction/destruction
tanbus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- ~tanbus_device() { m_device_list.detach_all(); }
+ ~tanbus_device();
// inline configuration
auto out_irq_callback() { return m_out_irq_cb.bind(); }
@@ -81,9 +83,9 @@ public:
void set_inhibit_lines(offs_t offset);
- DECLARE_WRITE_LINE_MEMBER(irq_w) { m_out_irq_cb(state); }
- DECLARE_WRITE_LINE_MEMBER(nmi_w) { m_out_nmi_cb(state); }
- DECLARE_WRITE_LINE_MEMBER(so_w) { m_out_so_cb(state); }
+ void irq_w(int state) { m_out_irq_cb(state); }
+ void nmi_w(int state) { m_out_nmi_cb(state); }
+ void so_w(int state) { m_out_so_cb(state); }
// pgm board has additional cable to fully decode the character generator
void pgm_w(offs_t offset, uint8_t data) { m_out_pgm_cb(offset, data); }
@@ -106,7 +108,7 @@ private:
int m_inhram;
int m_block_enable;
- simple_list<device_tanbus_interface> m_device_list;
+ std::vector<std::reference_wrapper<device_tanbus_interface> > m_device_list;
};
@@ -118,11 +120,8 @@ DECLARE_DEVICE_TYPE(TANBUS, tanbus_device)
class device_tanbus_interface : public device_interface
{
friend class tanbus_device;
- template <class ElementType> friend class simple_list;
public:
- device_tanbus_interface *next() const { return m_next; }
-
// bus access
virtual uint8_t read(offs_t offset, int inhrom, int inhram, int be) { return 0xff; }
virtual void write(offs_t offset, uint8_t data, int inhrom, int inhram, int be) { }
@@ -133,9 +132,6 @@ protected:
tanbus_device *m_tanbus;
int m_page;
-
-private:
- device_tanbus_interface *m_next;
};
diff --git a/src/devices/bus/tanbus/tandos.cpp b/src/devices/bus/tanbus/tandos.cpp
index ae971913254..cefecca7cc6 100644
--- a/src/devices/bus/tanbus/tandos.cpp
+++ b/src/devices/bus/tanbus/tandos.cpp
@@ -59,6 +59,29 @@ void tanbus_tandos_device::device_add_mconfig(machine_config &config)
FLOPPY_CONNECTOR(config, m_floppies[1], tandos_floppies, "525qd", floppy_image_device::default_mfm_floppy_formats).enable_sound(true);
FLOPPY_CONNECTOR(config, m_floppies[2], tandos_floppies, nullptr, floppy_image_device::default_mfm_floppy_formats).enable_sound(true);
FLOPPY_CONNECTOR(config, m_floppies[3], tandos_floppies, nullptr, floppy_image_device::default_mfm_floppy_formats).enable_sound(true);
+
+ TMS9914(config, m_tms9914, 8_MHz_XTAL / 2);
+ m_tms9914->dio_read_cb().set(IEEE488_TAG, FUNC(ieee488_device::dio_r));
+ m_tms9914->dio_write_cb().set(IEEE488_TAG, FUNC(ieee488_device::host_dio_w));
+ m_tms9914->eoi_write_cb().set(IEEE488_TAG, FUNC(ieee488_device::host_eoi_w));
+ m_tms9914->dav_write_cb().set(IEEE488_TAG, FUNC(ieee488_device::host_dav_w));
+ m_tms9914->nrfd_write_cb().set(IEEE488_TAG, FUNC(ieee488_device::host_nrfd_w));
+ m_tms9914->ndac_write_cb().set(IEEE488_TAG, FUNC(ieee488_device::host_ndac_w));
+ m_tms9914->ifc_write_cb().set(IEEE488_TAG, FUNC(ieee488_device::host_ifc_w));
+ m_tms9914->srq_write_cb().set(IEEE488_TAG, FUNC(ieee488_device::host_srq_w));
+ m_tms9914->atn_write_cb().set(IEEE488_TAG, FUNC(ieee488_device::host_atn_w));
+ m_tms9914->ren_write_cb().set(IEEE488_TAG, FUNC(ieee488_device::host_ren_w));
+
+ IEEE488(config, m_ieee);
+ m_ieee->eoi_callback().set(m_tms9914, FUNC(tms9914_device::eoi_w));
+ m_ieee->dav_callback().set(m_tms9914, FUNC(tms9914_device::dav_w));
+ m_ieee->nrfd_callback().set(m_tms9914, FUNC(tms9914_device::nrfd_w));
+ m_ieee->ndac_callback().set(m_tms9914, FUNC(tms9914_device::ndac_w));
+ m_ieee->ifc_callback().set(m_tms9914, FUNC(tms9914_device::ifc_w));
+ m_ieee->srq_callback().set(m_tms9914, FUNC(tms9914_device::srq_w));
+ m_ieee->atn_callback().set(m_tms9914, FUNC(tms9914_device::atn_w));
+ m_ieee->ren_callback().set(m_tms9914, FUNC(tms9914_device::ren_w));
+ IEEE488_SLOT(config, "ieee_dev", 0, cbm_ieee488_devices, nullptr);
}
const tiny_rom_entry *tanbus_tandos_device::device_rom_region() const
@@ -78,10 +101,12 @@ tanbus_tandos_device::tanbus_tandos_device(const machine_config &mconfig, const
: device_t(mconfig, TANBUS_TANDOS, tag, owner, clock)
, device_tanbus_interface(mconfig, *this)
, m_dos_rom(*this, "dos_rom")
+ , m_ieee(*this, IEEE488_TAG)
+ , m_tms9914(*this, "hpib")
, m_fdc(*this, "fdc")
, m_floppies(*this, "fdc:%u", 0)
, m_floppy(nullptr)
- , m_drive_control(0)
+ , m_status(0)
{
}
@@ -138,7 +163,7 @@ uint8_t tanbus_tandos_device::read(offs_t offset, int inhrom, int inhram, int be
// GPIB PCB Switches
break;
case 0xbf98: case 0xbf99: case 0xbf9a: case 0xbf9b: case 0xbf9c: case 0xbf9d: case 0xbf9e: case 0xbf9f:
- // GPIB (9914)
+ data = m_tms9914->read(offset & 0x07);
break;
}
break;
@@ -169,7 +194,7 @@ void tanbus_tandos_device::write(offs_t offset, uint8_t data, int inhrom, int in
control_w(data);
break;
case 0xbf98: case 0xbf99: case 0xbf9a: case 0xbf9b: case 0xbf9c: case 0xbf9d: case 0xbf9e: case 0xbf9f:
- // GPIB (9914)
+ m_tms9914->write(offset & 0x07, data);
break;
}
break;
@@ -195,8 +220,7 @@ void tanbus_tandos_device::set_inhibit_lines(offs_t offset, int &inhram, int &in
void tanbus_tandos_device::control_w(uint8_t data)
{
- logerror("control_w %02x\n", data);
- m_drive_control = data;
+ m_status = data & 0x3e;
// bit 0: irq enable
m_irq_enable = BIT(data, 0);
@@ -204,7 +228,7 @@ void tanbus_tandos_device::control_w(uint8_t data)
// bit 1: data select (data stream controller)
// bit 2, 3: drive select
- m_floppy = m_floppies[(data >> 2) & 0x03]->get_device();
+ m_floppy = m_floppies[BIT(data, 2, 2)]->get_device();
m_fdc->set_floppy(m_floppy);
// bit 4: side select
@@ -225,30 +249,22 @@ void tanbus_tandos_device::control_w(uint8_t data)
uint8_t tanbus_tandos_device::status_r()
{
- uint8_t data = 0x00;
-
- data |= m_drive_control & 0x3c;
- data |= m_fdc->intrq_r() << 0;
- data |= m_fdc->hld_r() << 6;
- data |= m_fdc->drq_r() << 7;
-
- return data;
+ return m_status | (m_fdc->drq_r() << 7) | (m_fdc->hld_r() << 6) | (m_fdc->intrq_r() << 0);
}
-WRITE_LINE_MEMBER(tanbus_tandos_device::fdc_drq_w)
+void tanbus_tandos_device::fdc_drq_w(int state)
{
m_tanbus->so_w((m_drq_enable && state) ? ASSERT_LINE : CLEAR_LINE);
}
-WRITE_LINE_MEMBER(tanbus_tandos_device::fdc_irq_w)
+void tanbus_tandos_device::fdc_irq_w(int state)
{
m_tanbus->irq_w((m_irq_enable && state) ? ASSERT_LINE : CLEAR_LINE);
}
-WRITE_LINE_MEMBER(tanbus_tandos_device::fdc_hld_w)
+void tanbus_tandos_device::fdc_hld_w(int state)
{
- logerror("fdc_hld_w %d\n", state);
if (m_floppy)
m_floppy->mon_w(state);
}
diff --git a/src/devices/bus/tanbus/tandos.h b/src/devices/bus/tanbus/tandos.h
index 60a157809f8..449ea65df72 100644
--- a/src/devices/bus/tanbus/tandos.h
+++ b/src/devices/bus/tanbus/tandos.h
@@ -12,17 +12,17 @@
#pragma once
-#include "bus/tanbus/tanbus.h"
-#include "imagedev/floppy.h"
+#include "tanbus.h"
#include "machine/wd_fdc.h"
+#include "machine/tms9914.h"
+#include "bus/ieee488/ieee488.h"
+#include "imagedev/floppy.h"
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
-class tanbus_tandos_device :
- public device_t,
- public device_tanbus_interface
+class tanbus_tandos_device : public device_t, public device_tanbus_interface
{
public:
static constexpr feature_type imperfect_features() { return feature::DISK; }
@@ -46,18 +46,20 @@ protected:
virtual void set_inhibit_lines(offs_t offset, int &inhram, int &inhrom) override;
private:
- void control_w(uint8_t val);
+ void control_w(uint8_t data);
uint8_t status_r();
- DECLARE_WRITE_LINE_MEMBER(fdc_irq_w);
- DECLARE_WRITE_LINE_MEMBER(fdc_drq_w);
- DECLARE_WRITE_LINE_MEMBER(fdc_hld_w);
+ void fdc_irq_w(int state);
+ void fdc_drq_w(int state);
+ void fdc_hld_w(int state);
required_memory_region m_dos_rom;
+ required_device<ieee488_device> m_ieee;
+ required_device<tms9914_device> m_tms9914;
required_device<fd1793_device> m_fdc;
required_device_array<floppy_connector, 4> m_floppies;
floppy_image_device *m_floppy;
- uint8_t m_drive_control;
+ uint8_t m_status;
int m_irq_enable;
int m_drq_enable;
diff --git a/src/devices/bus/tanbus/tanex.cpp b/src/devices/bus/tanbus/tanex.cpp
index f99a9d6cdf4..2af60e172e5 100644
--- a/src/devices/bus/tanbus/tanex.cpp
+++ b/src/devices/bus/tanbus/tanex.cpp
@@ -366,12 +366,12 @@ TIMER_DEVICE_CALLBACK_MEMBER(tanbus_tanex_device::read_cassette)
m_via6522[0]->write_cb2(1);
}
-WRITE_LINE_MEMBER(tanbus_tanex_device::bus_so_w)
+void tanbus_tanex_device::bus_so_w(int state)
{
m_tanbus->so_w(state);
}
-WRITE_LINE_MEMBER(tanbus_tanex_device::bus_irq_w)
+void tanbus_tanex_device::bus_irq_w(int state)
{
m_tanbus->irq_w(state);
}
@@ -401,12 +401,12 @@ void tanbus_tanex_device::via_0_out_b(uint8_t data)
m_cassette->output(data & 0x80 ? +1.0 : -1.0);
}
-WRITE_LINE_MEMBER(tanbus_tanex_device::via_0_out_ca2)
+void tanbus_tanex_device::via_0_out_ca2(int state)
{
LOG("via_0_out_ca2 %d\n", state);
}
-WRITE_LINE_MEMBER(tanbus_tanex_device::via_0_out_cb2)
+void tanbus_tanex_device::via_0_out_cb2(int state)
{
LOG("via_0_out_cb2 %d\n", state);
}
@@ -425,12 +425,12 @@ void tanbus_tanex_device::via_1_out_b(uint8_t data)
LOG("via_1_out_b %02X\n", data);
}
-WRITE_LINE_MEMBER(tanbus_tanex_device::via_1_out_ca2)
+void tanbus_tanex_device::via_1_out_ca2(int state)
{
LOG("via_1_out_ca2 %d\n", state);
}
-WRITE_LINE_MEMBER(tanbus_tanex_device::via_1_out_cb2)
+void tanbus_tanex_device::via_1_out_cb2(int state)
{
LOG("via_1_out_cb2 %d\n", state);
}
diff --git a/src/devices/bus/tanbus/tanex.h b/src/devices/bus/tanbus/tanex.h
index ec3f75fb344..96afff46e2c 100644
--- a/src/devices/bus/tanbus/tanex.h
+++ b/src/devices/bus/tanbus/tanex.h
@@ -50,18 +50,18 @@ protected:
private:
enum { IRQ_VIA_0, IRQ_VIA_1, IRQ_ACIA };
- DECLARE_WRITE_LINE_MEMBER(bus_irq_w);
- DECLARE_WRITE_LINE_MEMBER(bus_so_w);
+ void bus_irq_w(int state);
+ void bus_so_w(int state);
TIMER_DEVICE_CALLBACK_MEMBER(read_cassette);
uint8_t via_0_in_a();
void via_0_out_a(uint8_t data);
void via_0_out_b(uint8_t data);
- DECLARE_WRITE_LINE_MEMBER(via_0_out_ca2);
- DECLARE_WRITE_LINE_MEMBER(via_0_out_cb2);
+ void via_0_out_ca2(int state);
+ void via_0_out_cb2(int state);
void via_1_out_a(uint8_t data);
void via_1_out_b(uint8_t data);
- DECLARE_WRITE_LINE_MEMBER(via_1_out_ca2);
- DECLARE_WRITE_LINE_MEMBER(via_1_out_cb2);
+ void via_1_out_ca2(int state);
+ void via_1_out_cb2(int state);
required_memory_region m_rom_tanex;
required_memory_region m_rom_h2;
diff --git a/src/devices/bus/tanbus/tanram.cpp b/src/devices/bus/tanbus/tanram.cpp
index 0e3dadf9d15..253c05f4f24 100644
--- a/src/devices/bus/tanbus/tanram.cpp
+++ b/src/devices/bus/tanbus/tanram.cpp
@@ -55,17 +55,11 @@ uint8_t tanbus_tanram_device::read(offs_t offset, int inhrom, int inhram, int be
if (be && !inhram)
{
- /* 32K dynamic ram */
- if ((offset >= 0x2000) && (offset < 0xa000))
+ /* 32K dynamic ram + 7K static ram */
+ if ((offset >= 0x2000) && (offset < 0xbc00))
{
data = m_ram[offset - 0x2000];
}
-
- /* 7K static ram */
- if ((offset >= 0xa000) && (offset < 0xbc00))
- {
- data = m_ram[offset - 0xa000];
- }
}
return data;
}
@@ -78,16 +72,10 @@ void tanbus_tanram_device::write(offs_t offset, uint8_t data, int inhrom, int in
{
if (be && !inhram)
{
- /* 32K dynamic ram */
- if ((offset >= 0x2000) && (offset < 0xa000))
+ /* 32K dynamic ram + 7K static ram */
+ if ((offset >= 0x2000) && (offset < 0xbc00))
{
m_ram[offset - 0x2000] = data;
}
-
- /* 7K static ram */
- if ((offset >= 0xa000) && (offset < 0xbc00))
- {
- m_ram[offset - 0xa000] = data;
- }
}
}
diff --git a/src/devices/bus/tanbus/tanrtc.cpp b/src/devices/bus/tanbus/tanrtc.cpp
new file mode 100644
index 00000000000..5583ac79c4d
--- /dev/null
+++ b/src/devices/bus/tanbus/tanrtc.cpp
@@ -0,0 +1,86 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Microtanic Real Time Clock
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "tanrtc.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(TANBUS_TANRTC, tanbus_tanrtc_device, "tanbus_tanrtc", "Microtanic Real Time Clock")
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void tanbus_tanrtc_device::device_add_mconfig(machine_config &config)
+{
+ MC146818(config, m_rtc, 32.768_kHz_XTAL);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// tanbus_tanrtc_device - constructor
+//-------------------------------------------------
+
+tanbus_tanrtc_device::tanbus_tanrtc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, TANBUS_TANRTC, tag, owner, clock)
+ , device_tanbus_interface(mconfig, *this)
+ , m_rtc(*this, "rtc")
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void tanbus_tanrtc_device::device_start()
+{
+}
+
+
+//-------------------------------------------------
+// read - card read
+//-------------------------------------------------
+
+uint8_t tanbus_tanrtc_device::read(offs_t offset, int inhrom, int inhram, int be)
+{
+ uint8_t data = 0xff;
+
+ switch (offset & 0xffc0)
+ {
+ case 0xbc00:
+ data = m_rtc->read_direct(offset);
+ break;
+ }
+
+ return data;
+}
+
+
+//-------------------------------------------------
+// write - card write
+//-------------------------------------------------
+
+void tanbus_tanrtc_device::write(offs_t offset, uint8_t data, int inhrom, int inhram, int be)
+{
+ switch (offset & 0xffc0)
+ {
+ case 0xbc00:
+ m_rtc->write_direct(offset, data);
+ break;
+ }
+}
diff --git a/src/devices/bus/tanbus/tanrtc.h b/src/devices/bus/tanbus/tanrtc.h
new file mode 100644
index 00000000000..737abf10528
--- /dev/null
+++ b/src/devices/bus/tanbus/tanrtc.h
@@ -0,0 +1,47 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Microtanic Real Time Clock
+
+**********************************************************************/
+
+
+#ifndef MAME_BUS_TANBUS_TANRTC_H
+#define MAME_BUS_TANBUS_TANRTC_H
+
+#pragma once
+
+#include "tanbus.h"
+#include "machine/mc146818.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class tanbus_tanrtc_device : public device_t, public device_tanbus_interface
+{
+public:
+ // construction/destruction
+ tanbus_tanrtc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+
+ virtual uint8_t read(offs_t offset, int inhrom, int inhram, int be) override;
+ virtual void write(offs_t offset, uint8_t data, int inhrom, int inhram, int be) override;
+
+private:
+ required_device<mc146818_device> m_rtc;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(TANBUS_TANRTC, tanbus_tanrtc_device)
+
+
+#endif // MAME_BUS_TANBUS_TANRTC_H
diff --git a/src/devices/bus/tanbus/tug8082.cpp b/src/devices/bus/tanbus/tug8082.cpp
index 582ab726c8e..86eac77b5d8 100644
--- a/src/devices/bus/tanbus/tug8082.cpp
+++ b/src/devices/bus/tanbus/tug8082.cpp
@@ -208,7 +208,7 @@ void tanbus_tug8082_device::write(offs_t offset, uint8_t data, int inhrom, int i
// IMPLEMENTATION
//**************************************************************************
-WRITE_LINE_MEMBER(tanbus_tug8082_device::bus_irq_w)
+void tanbus_tug8082_device::bus_irq_w(int state)
{
/* Manual says these DIPs are not used but schematic suggests they are */
//switch (m_dips[0]->read() >> 2)
@@ -222,7 +222,7 @@ WRITE_LINE_MEMBER(tanbus_tug8082_device::bus_irq_w)
//}
}
-WRITE_LINE_MEMBER(tanbus_tug8082_device::vdu_irq_w)
+void tanbus_tug8082_device::vdu_irq_w(int state)
{
switch (m_dips[0]->read() & 0x03)
{
diff --git a/src/devices/bus/tanbus/tug8082.h b/src/devices/bus/tanbus/tug8082.h
index 979e47180e5..aae8887a6d8 100644
--- a/src/devices/bus/tanbus/tug8082.h
+++ b/src/devices/bus/tanbus/tug8082.h
@@ -46,8 +46,8 @@ protected:
virtual void write(offs_t offset, uint8_t data, int inhrom, int inhram, int be) override;
private:
- DECLARE_WRITE_LINE_MEMBER(bus_irq_w);
- DECLARE_WRITE_LINE_MEMBER(vdu_irq_w);
+ void bus_irq_w(int state);
+ void vdu_irq_w(int state);
uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
diff --git a/src/devices/bus/tanbus/tugcombo.cpp b/src/devices/bus/tanbus/tugcombo.cpp
new file mode 100644
index 00000000000..8cee9bae33f
--- /dev/null
+++ b/src/devices/bus/tanbus/tugcombo.cpp
@@ -0,0 +1,270 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ TUG Combo Card / TUG EPROM Storage Card
+
+ http://www.microtan.ukpc.net/pageProducts.html#ROM
+
+ Usage:
+ G EFFC
+
+**********************************************************************/
+
+
+#include "emu.h"
+#include "tugcombo.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(TANBUS_TUGCOMBO2716, tanbus_tugcombo2716_device, "tanbus_tugcombo2716", "TUG Combo Card (2716)")
+DEFINE_DEVICE_TYPE(TANBUS_TUGCOMBO2732, tanbus_tugcombo2732_device, "tanbus_tugcombo2732", "TUG Combo Card (2732)")
+DEFINE_DEVICE_TYPE(TANBUS_TUGCOMBO6116, tanbus_tugcombo6116_device, "tanbus_tugcombo6116", "TUG Combo Card (6116)")
+DEFINE_DEVICE_TYPE(TANBUS_TUGESC2716, tanbus_tugesc2716_device, "tanbus_tugesc2716", "TUG EPROM Storage Card (2716)")
+DEFINE_DEVICE_TYPE(TANBUS_TUGESC2732, tanbus_tugesc2732_device, "tanbus_tugesc2732", "TUG EPROM Storage Card (2732)")
+
+
+//-------------------------------------------------
+// INPUT_PORTS( tugcombo )
+//-------------------------------------------------
+
+INPUT_PORTS_START(tugcombo)
+ PORT_START("LINKS")
+ PORT_DIPNAME(0x88, 0x00, "I/O Address")
+ PORT_DIPSETTING(0x00, "$BD00 - $BD07")
+ PORT_DIPSETTING(0x08, "$BD08 - $BD0F")
+ PORT_DIPSETTING(0x80, "$BD80 - $BD87")
+ PORT_DIPSETTING(0x88, "$BD88 - $BD8F")
+INPUT_PORTS_END
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor tanbus_tugcombo_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(tugcombo);
+}
+
+
+void tanbus_tugcombo2716_device::mem_map(address_map &map)
+{
+ map(0x0000, 0x07ff).mirror(0x8000).r(m_rom[0], FUNC(generic_slot_device::read_rom));
+ map(0x0800, 0x0fff).mirror(0x8000).r(m_rom[1], FUNC(generic_slot_device::read_rom));
+ map(0x1000, 0x17ff).mirror(0x8000).r(m_rom[2], FUNC(generic_slot_device::read_rom));
+ map(0x1800, 0x1fff).mirror(0x8000).r(m_rom[3], FUNC(generic_slot_device::read_rom));
+ map(0x2000, 0x27ff).mirror(0x8000).r(m_rom[4], FUNC(generic_slot_device::read_rom));
+ map(0x2800, 0x2fff).mirror(0x8000).r(m_rom[5], FUNC(generic_slot_device::read_rom));
+ map(0x3000, 0x37ff).mirror(0x8000).r(m_rom[6], FUNC(generic_slot_device::read_rom));
+ map(0x3800, 0x3fff).mirror(0x8000).r(m_rom[7], FUNC(generic_slot_device::read_rom));
+ map(0x4000, 0x47ff).mirror(0x8000).r(m_rom[8], FUNC(generic_slot_device::read_rom));
+ map(0x4800, 0x4fff).mirror(0x8000).r(m_rom[9], FUNC(generic_slot_device::read_rom));
+ map(0x5000, 0x57ff).mirror(0x8000).r(m_rom[10], FUNC(generic_slot_device::read_rom));
+ map(0x5800, 0x5fff).mirror(0x8000).r(m_rom[11], FUNC(generic_slot_device::read_rom));
+ map(0x6000, 0x67ff).mirror(0x8000).r(m_rom[12], FUNC(generic_slot_device::read_rom));
+ map(0x6800, 0x6fff).mirror(0x8000).r(m_rom[13], FUNC(generic_slot_device::read_rom));
+ map(0x7000, 0x77ff).mirror(0x8000).r(m_rom[14], FUNC(generic_slot_device::read_rom));
+ map(0x7800, 0x7fff).mirror(0x8000).r(m_rom[15], FUNC(generic_slot_device::read_rom));
+}
+
+void tanbus_tugcombo2732_device::mem_map(address_map &map)
+{
+ map(0x0000, 0x0fff).r(m_rom[0], FUNC(generic_slot_device::read_rom));
+ map(0x1000, 0x1fff).r(m_rom[1], FUNC(generic_slot_device::read_rom));
+ map(0x2000, 0x2fff).r(m_rom[2], FUNC(generic_slot_device::read_rom));
+ map(0x3000, 0x3fff).r(m_rom[3], FUNC(generic_slot_device::read_rom));
+ map(0x4000, 0x4fff).r(m_rom[4], FUNC(generic_slot_device::read_rom));
+ map(0x5000, 0x5fff).r(m_rom[5], FUNC(generic_slot_device::read_rom));
+ map(0x6000, 0x6fff).r(m_rom[6], FUNC(generic_slot_device::read_rom));
+ map(0x7000, 0x7fff).r(m_rom[7], FUNC(generic_slot_device::read_rom));
+ map(0x8000, 0x8fff).r(m_rom[8], FUNC(generic_slot_device::read_rom));
+ map(0x9000, 0x9fff).r(m_rom[9], FUNC(generic_slot_device::read_rom));
+ map(0xa000, 0xafff).r(m_rom[10], FUNC(generic_slot_device::read_rom));
+ map(0xb000, 0xbfff).r(m_rom[11], FUNC(generic_slot_device::read_rom));
+ map(0xc000, 0xcfff).r(m_rom[12], FUNC(generic_slot_device::read_rom));
+ map(0xd000, 0xdfff).r(m_rom[13], FUNC(generic_slot_device::read_rom));
+ map(0xe000, 0xefff).r(m_rom[14], FUNC(generic_slot_device::read_rom));
+ map(0xf000, 0xffff).r(m_rom[15], FUNC(generic_slot_device::read_rom));
+}
+
+void tanbus_tugcombo6116_device::mem_map(address_map &map)
+{
+ map(0x0000, 0x7fff).mirror(0x8000).ram().share("nvram");
+}
+
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void tanbus_tugcombo_device::device_add_mconfig(machine_config &config)
+{
+ PIA6821(config, m_pia[0]);
+ m_pia[0]->writepa_handler().set([this](uint8_t data) { m_addr = (m_addr & 0xff00) | data; });
+ m_pia[0]->writepb_handler().set([this](uint8_t data) { m_addr = (m_addr & 0x00ff) | (data << 8); });
+
+ PIA6821(config, m_pia[1]);
+ m_pia[1]->readpb_handler().set([this]() { return m_space->read_byte(m_addr); });
+ m_pia[1]->writepb_handler().set([this](uint8_t data) { m_space->write_byte(m_addr, data); });
+}
+
+void tanbus_tugcombo2716_device::device_add_mconfig(machine_config &config)
+{
+ tanbus_tugcombo_device::device_add_mconfig(config);
+
+ for (int i = 0; i < 16; i++)
+ GENERIC_SOCKET(config, m_rom[i], generic_linear_slot, "rom_esc2716", "bin,rom");
+}
+
+void tanbus_tugcombo2732_device::device_add_mconfig(machine_config &config)
+{
+ tanbus_tugcombo_device::device_add_mconfig(config);
+
+ for (int i = 0; i < 16; i++)
+ GENERIC_SOCKET(config, m_rom[i], generic_linear_slot, "rom_esc2732", "bin,rom");
+}
+
+void tanbus_tugcombo6116_device::device_add_mconfig(machine_config &config)
+{
+ tanbus_tugcombo_device::device_add_mconfig(config);
+
+ NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// tanbus_tugcombo_device - constructor
+//-------------------------------------------------
+
+tanbus_tugcombo_device::tanbus_tugcombo_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, type, tag, owner, clock)
+ , device_memory_interface(mconfig, *this)
+ , device_tanbus_interface(mconfig, *this)
+ , m_space(nullptr)
+ , m_links(*this, "LINKS")
+ , m_pia(*this, "pia%u", 0)
+ , m_addr(0)
+{
+}
+
+
+tanbus_tugcombo2716_device::tanbus_tugcombo2716_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : tanbus_tugcombo_device(mconfig, type, tag, owner, clock)
+ , m_rom(*this, "rom%u", 0)
+{
+ m_space_config = address_space_config("memory", ENDIANNESS_LITTLE, 8, 16, 0, address_map_constructor(FUNC(tanbus_tugcombo2716_device::mem_map), this));
+}
+
+tanbus_tugcombo2716_device::tanbus_tugcombo2716_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : tanbus_tugcombo2716_device(mconfig, TANBUS_TUGCOMBO2716, tag, owner, clock)
+{
+}
+
+tanbus_tugesc2716_device::tanbus_tugesc2716_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : tanbus_tugcombo2716_device(mconfig, TANBUS_TUGESC2716, tag, owner, clock)
+{
+}
+
+
+tanbus_tugcombo2732_device::tanbus_tugcombo2732_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : tanbus_tugcombo_device(mconfig, type, tag, owner, clock)
+ , m_rom(*this, "rom%u", 0)
+{
+ m_space_config = address_space_config("memory", ENDIANNESS_LITTLE, 8, 16, 0, address_map_constructor(FUNC(tanbus_tugcombo2732_device::mem_map), this));
+}
+
+tanbus_tugcombo2732_device::tanbus_tugcombo2732_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : tanbus_tugcombo2732_device(mconfig, TANBUS_TUGCOMBO2732, tag, owner, clock)
+{
+}
+
+tanbus_tugesc2732_device::tanbus_tugesc2732_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : tanbus_tugcombo2732_device(mconfig, TANBUS_TUGESC2732, tag, owner, clock)
+{
+}
+
+
+tanbus_tugcombo6116_device::tanbus_tugcombo6116_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : tanbus_tugcombo_device(mconfig, type, tag, owner, clock)
+{
+}
+
+tanbus_tugcombo6116_device::tanbus_tugcombo6116_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : tanbus_tugcombo6116_device(mconfig, TANBUS_TUGCOMBO6116, tag, owner, clock)
+{
+ m_space_config = address_space_config("memory", ENDIANNESS_LITTLE, 8, 16, 0, address_map_constructor(FUNC(tanbus_tugcombo6116_device::mem_map), this));
+}
+
+
+device_memory_interface::space_config_vector tanbus_tugcombo_device::memory_space_config() const
+{
+ return space_config_vector{ std::make_pair(0, &m_space_config) };
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void tanbus_tugcombo_device::device_start()
+{
+ m_space = &space(0);
+
+ save_item(NAME(m_addr));
+}
+
+
+//-------------------------------------------------
+// read - card read
+//-------------------------------------------------
+
+uint8_t tanbus_tugcombo_device::read(offs_t offset, int inhrom, int inhram, int be)
+{
+ uint8_t data = 0xff;
+
+ offs_t addr = 0xbd00 | m_links->read();
+
+ if (addr == (offset & 0xfff8))
+ {
+ switch (offset & 0x04)
+ {
+ case 0x00:
+ data = m_pia[0]->read(offset & 3);
+ break;
+ case 0x04:
+ data = m_pia[1]->read(offset & 3);
+ break;
+ }
+ }
+
+ return data;
+}
+
+//-------------------------------------------------
+// write - card write
+//-------------------------------------------------
+
+void tanbus_tugcombo_device::write(offs_t offset, uint8_t data, int inhrom, int inhram, int be)
+{
+ offs_t addr = 0xbd00 | m_links->read();
+
+ if (addr == (offset & 0xfff8))
+ {
+ switch (offset & 0x04)
+ {
+ case 0x00:
+ m_pia[0]->write(offset & 3, data);
+ break;
+ case 0x04:
+ m_pia[1]->write(offset & 3, data);
+ break;
+ }
+ }
+}
diff --git a/src/devices/bus/tanbus/tugcombo.h b/src/devices/bus/tanbus/tugcombo.h
new file mode 100644
index 00000000000..66dcfc9e90e
--- /dev/null
+++ b/src/devices/bus/tanbus/tugcombo.h
@@ -0,0 +1,142 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ TUG Combo Card / TUG EPROM Storage Card
+
+**********************************************************************/
+
+
+#ifndef MAME_BUS_TANBUS_TUGCOMBO_H
+#define MAME_BUS_TANBUS_TUGCOMBO_H
+
+#pragma once
+
+#include "tanbus.h"
+#include "machine/6821pia.h"
+#include "machine/nvram.h"
+#include "bus/generic/slot.h"
+#include "bus/generic/carts.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class tanbus_tugcombo_device
+ : public device_t
+ , public device_memory_interface
+ , public device_tanbus_interface
+{
+protected:
+ tanbus_tugcombo_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ // device-level overrides
+ virtual void device_start() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual ioport_constructor device_input_ports() const override;
+
+ // device_memory_interface overrides
+ virtual space_config_vector memory_space_config() const override;
+
+ virtual uint8_t read(offs_t offset, int inhrom, int inhram, int be) override;
+ virtual void write(offs_t offset, uint8_t data, int inhrom, int inhram, int be) override;
+
+ address_space_config m_space_config;
+ address_space *m_space;
+
+private:
+ required_ioport m_links;
+ required_device_array<pia6821_device, 2> m_pia;
+
+ uint16_t m_addr;
+};
+
+
+// ======================> tanbus_tugcombo2716_device
+
+class tanbus_tugcombo2716_device : public tanbus_tugcombo_device
+{
+public:
+ tanbus_tugcombo2716_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ tanbus_tugcombo2716_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+
+private:
+ required_device_array<generic_slot_device, 16> m_rom;
+
+ void mem_map(address_map &map);
+};
+
+
+// ======================> tanbus_tugcombo2732_device
+
+class tanbus_tugcombo2732_device : public tanbus_tugcombo_device
+{
+public:
+ tanbus_tugcombo2732_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ tanbus_tugcombo2732_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+
+private:
+ required_device_array<generic_slot_device, 16> m_rom;
+
+ void mem_map(address_map &map);
+};
+
+
+// ======================> tanbus_tugcombo6116_device
+
+class tanbus_tugcombo6116_device : public tanbus_tugcombo_device
+{
+public:
+ tanbus_tugcombo6116_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ tanbus_tugcombo6116_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+
+private:
+ void mem_map(address_map &map);
+};
+
+
+// ======================> tanbus_tugesc2716_device
+
+class tanbus_tugesc2716_device : public tanbus_tugcombo2716_device
+{
+public:
+ tanbus_tugesc2716_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+};
+
+
+// ======================> tanbus_tugesc2732_device
+
+class tanbus_tugesc2732_device : public tanbus_tugcombo2732_device
+{
+public:
+ tanbus_tugesc2732_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(TANBUS_TUGCOMBO2716, tanbus_tugcombo2716_device)
+DECLARE_DEVICE_TYPE(TANBUS_TUGCOMBO2732, tanbus_tugcombo2732_device)
+DECLARE_DEVICE_TYPE(TANBUS_TUGCOMBO6116, tanbus_tugcombo6116_device)
+DECLARE_DEVICE_TYPE(TANBUS_TUGESC2716, tanbus_tugesc2716_device)
+DECLARE_DEVICE_TYPE(TANBUS_TUGESC2732, tanbus_tugesc2732_device)
+
+
+#endif // MAME_BUS_TANBUS_TUGCOMBO_H
diff --git a/src/devices/bus/thomson/cc90_232.cpp b/src/devices/bus/thomson/cc90_232.cpp
new file mode 100644
index 00000000000..7b5a80e47b3
--- /dev/null
+++ b/src/devices/bus/thomson/cc90_232.cpp
@@ -0,0 +1,135 @@
+// license:BSD-3-Clause
+// copyright-holders:Antoine Mine
+
+#include "emu.h"
+#include "cc90_232.h"
+
+#include "bus/centronics/ctronics.h"
+#include "machine/input_merger.h"
+#include "machine/output_latch.h"
+
+#define VERBOSE 0
+#include "logmacro.h"
+
+/* ------------ CC 90-232 I/O extension ------------ */
+
+/* Features:
+ - 6821 PIA
+ - serial RS232: bit-banging?
+ - parallel CENTRONICS: a printer (-prin) is emulated
+ - usable on TO7(/70), MO5(E), MO5NR
+ (TO8, TO9, MO6 normally use their built-in parallel printer interfaces instead)
+
+ Note: it seems impossible to connect both a serial & a parallel device
+ because the Data Transmit Ready bit is shared in an incompatible way!
+*/
+
+// device type definition
+DEFINE_DEVICE_TYPE(CC90_232, cc90_232_device, "cc90_232", "Thomson CC 90-232 Communication Interface")
+
+//-------------------------------------------------
+// cc90_232_device - constructor
+//-------------------------------------------------
+
+cc90_232_device::cc90_232_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, CC90_232, tag, owner, clock),
+ thomson_extension_interface(mconfig, *this),
+ m_pia_io(*this, "pia"),
+ m_rs232(*this, "rs232"),
+ m_last_low(0)
+{
+}
+
+void cc90_232_device::rom_map(address_map &map)
+{
+}
+
+void cc90_232_device::io_map(address_map &map)
+{
+ map(0x20, 0x23).rw(m_pia_io, FUNC(pia6821_device::read_alt), FUNC(pia6821_device::write_alt));
+}
+
+void cc90_232_device::device_add_mconfig(machine_config &config)
+{
+ PIA6821(config, m_pia_io);
+ m_pia_io->readpa_handler().set(FUNC(cc90_232_device::porta_in));
+ m_pia_io->writepa_handler().set(FUNC(cc90_232_device::porta_out));
+ m_pia_io->writepb_handler().set("cent_data_out", FUNC(output_latch_device::write));
+ m_pia_io->cb2_handler().set("centronics", FUNC(centronics_device::write_strobe));
+ m_pia_io->irqa_handler().set("piairq", FUNC(input_merger_device::in_w<0>));
+ m_pia_io->irqb_handler().set("piairq", FUNC(input_merger_device::in_w<1>));
+
+ INPUT_MERGER_ANY_HIGH(config, "piairq").output_handler().set(FUNC(cc90_232_device::firq_w));
+
+ RS232_PORT(config, m_rs232, default_rs232_devices, nullptr);
+ m_rs232->rxd_handler().set(FUNC(cc90_232_device::write_rxd));
+ m_rs232->cts_handler().set(FUNC(cc90_232_device::write_cts));
+ m_rs232->dsr_handler().set(FUNC(cc90_232_device::write_dsr));
+
+ centronics_device &centronics(CENTRONICS(config, "centronics", centronics_devices, "printer"));
+ centronics.ack_handler().set(m_pia_io, FUNC(pia6821_device::cb1_w));
+ centronics.busy_handler().set(FUNC(cc90_232_device::write_centronics_busy));
+
+ output_latch_device &cent_data_out(OUTPUT_LATCH(config, "cent_data_out"));
+ centronics.set_output_latch(cent_data_out);
+}
+
+
+void cc90_232_device::device_start()
+{
+ m_rs232->write_dtr(0);
+}
+
+void cc90_232_device::porta_out(uint8_t data)
+{
+ int txd = (data >> 0) & 1;
+ int rts = (data >> 1) & 1;
+
+ LOG( "%s %f porta_out: txd=%i, rts=%i\n", machine().describe_context(), machine().time().as_double(), txd, rts );
+
+ m_rs232->write_txd(txd);
+ m_rs232->write_rts(rts);
+}
+
+
+
+void cc90_232_device::write_rxd(int state)
+{
+ m_rxd = state;
+}
+
+void cc90_232_device::write_dsr(int state)
+{
+ if (!state) m_last_low = 0;
+
+ m_dsr = state;
+}
+
+void cc90_232_device::write_cts(int state)
+{
+ m_pia_io->ca1_w(state);
+ m_cts = state;
+}
+
+void cc90_232_device::write_centronics_busy(int state)
+{
+ if (!state) m_last_low = 1;
+
+ m_centronics_busy = state;
+}
+
+
+uint8_t cc90_232_device::porta_in()
+{
+ LOG( "%s %f porta_in: select=%i cts=%i, dsr=%i, rd=%i\n", machine().describe_context(), machine().time().as_double(), m_centronics_busy, m_cts, m_dsr, m_rxd );
+
+ /// HACK: without high impedance we can't tell whether a device is driving a line high or if it's being pulled up.
+ /// so assume the last device to drive it low is active.
+ int dsr;
+ if (m_last_low == 0)
+ dsr = m_dsr;
+ else
+ dsr = !m_centronics_busy;
+
+ return (0x1f /* not required when converted to write_pa */) | (m_cts << 5) | (dsr << 6) | (m_rxd << 7);
+}
diff --git a/src/devices/bus/thomson/cc90_232.h b/src/devices/bus/thomson/cc90_232.h
new file mode 100644
index 00000000000..910f8a3bacc
--- /dev/null
+++ b/src/devices/bus/thomson/cc90_232.h
@@ -0,0 +1,48 @@
+// license:BSD-3-Clause
+// copyright-holders:Antoine Mine
+
+#ifndef MAME_BUS_THOMSON_CC90_232_H
+#define MAME_BUS_THOMSON_CC90_232_H
+
+#include "extension.h"
+#include "bus/rs232/rs232.h"
+#include "machine/6821pia.h"
+
+class cc90_232_device : public device_t, public thomson_extension_interface
+{
+public:
+ cc90_232_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void rom_map(address_map &map) override;
+ virtual void io_map(address_map &map) override;
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_start() override;
+
+private:
+ // read data register
+ uint8_t porta_in();
+
+ // write data register
+ void porta_out(uint8_t data);
+
+ void write_rxd(int state);
+ void write_cts(int state);
+ void write_dsr(int state);
+ void write_centronics_busy(int state);
+
+ required_device<pia6821_device> m_pia_io;
+ required_device<rs232_port_device> m_rs232;
+
+ int m_last_low = 0;
+ int m_centronics_busy = 0;
+ int m_rxd = 0;
+ int m_cts = 0;
+ int m_dsr = 0;
+};
+
+// device type declaration
+DECLARE_DEVICE_TYPE(CC90_232, cc90_232_device)
+
+#endif // MAME_BUS_THOMSON_CC90_232_H
diff --git a/src/devices/bus/thomson/cd90_015.cpp b/src/devices/bus/thomson/cd90_015.cpp
index 6f9b2822647..86e132301d4 100644
--- a/src/devices/bus/thomson/cd90_015.cpp
+++ b/src/devices/bus/thomson/cd90_015.cpp
@@ -1,15 +1,16 @@
// license:BSD-3-Clause
// copyright-holders:Olivier Galibert
-// CD 90-015 - Floppy drive selectler built from a wd1770
+// CD 90-015 - Floppy disk interface built from a MC6843 single-density controller
//
-// Handles up to two 5.25 dual-sided drives (DD 90-320)
+// Handles up to four 5.25 single-sided drives (UD 90-070). Formatted capacity is 80 KB.
+// The lack of a track zero sensor is confirmed from schematics.
#include "emu.h"
#include "cd90_015.h"
#include "formats/thom_dsk.h"
-DEFINE_DEVICE_TYPE(CD90_015, cd90_015_device, "cd90_015", "Thomson CD90-015 floppy drive selectler")
+DEFINE_DEVICE_TYPE(CD90_015, cd90_015_device, "cd90_015", "Thomson CD 90-015 floppy drive controller")
cd90_015_device::cd90_015_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, CD90_015, tag, owner, clock),
@@ -32,8 +33,8 @@ void cd90_015_device::rom_map(address_map &map)
void cd90_015_device::io_map(address_map &map)
{
- map(0, 7).m(m_fdc, FUNC(mc6843_device::map));
- map(8, 9).rw(FUNC(cd90_015_device::motor_r), FUNC(cd90_015_device::select_w));
+ map(0x10, 0x17).m(m_fdc, FUNC(mc6843_device::map));
+ map(0x18, 0x19).rw(FUNC(cd90_015_device::motor_r), FUNC(cd90_015_device::select_w));
}
const tiny_rom_entry *cd90_015_device::device_rom_region() const
@@ -41,9 +42,37 @@ const tiny_rom_entry *cd90_015_device::device_rom_region() const
return ROM_NAME(cd90_015);
}
+class ud90_070_device : public floppy_image_device {
+public:
+ ud90_070_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual const char *image_interface() const noexcept override { return "floppy_5_25"; }
+
+protected:
+ virtual void setup_characteristics() override;
+};
+
+DEFINE_DEVICE_TYPE(UD90_070, ud90_070_device, "ud90_070", "Thomson UD 90-070 5.25\" single-sided disk drive")
+
+ud90_070_device::ud90_070_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ floppy_image_device(mconfig, UD90_070, tag, owner, clock)
+{
+}
+
+void ud90_070_device::setup_characteristics()
+{
+ m_form_factor = floppy_image::FF_525;
+ m_tracks = 40;
+ m_sides = 1;
+ m_has_trk00_sensor = false;
+ set_rpm(300);
+
+ m_variants.push_back(floppy_image::SSSD);
+}
+
void cd90_015_device::floppy_drives(device_slot_interface &device)
{
- device.option_add("dd90_015", FLOPPY_525_SD);
+ device.option_add("ud90_070", UD90_070);
}
void cd90_015_device::floppy_formats(format_registration &fr)
@@ -53,9 +82,9 @@ void cd90_015_device::floppy_formats(format_registration &fr)
void cd90_015_device::device_add_mconfig(machine_config &config)
{
- MC6843(config, m_fdc, 16_MHz_XTAL / 32); // Comes from the main board
+ MC6843(config, m_fdc, DERIVED_CLOCK(1, 2)); // Comes from the main board
m_fdc->force_ready();
- FLOPPY_CONNECTOR(config, m_floppy[0], floppy_drives, "dd90_015", floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[0], floppy_drives, "ud90_070", floppy_formats).enable_sound(true);
FLOPPY_CONNECTOR(config, m_floppy[1], floppy_drives, nullptr, floppy_formats).enable_sound(true);
FLOPPY_CONNECTOR(config, m_floppy[2], floppy_drives, nullptr, floppy_formats).enable_sound(true);
FLOPPY_CONNECTOR(config, m_floppy[3], floppy_drives, nullptr, floppy_formats).enable_sound(true);
diff --git a/src/devices/bus/thomson/cd90_015.h b/src/devices/bus/thomson/cd90_015.h
index b2a4069e8cc..9af21d04a4c 100644
--- a/src/devices/bus/thomson/cd90_015.h
+++ b/src/devices/bus/thomson/cd90_015.h
@@ -15,7 +15,7 @@
class cd90_015_device : public device_t, public thomson_extension_interface
{
public:
- cd90_015_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
+ cd90_015_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual ~cd90_015_device() = default;
virtual void rom_map(address_map &map) override;
diff --git a/src/devices/bus/thomson/cd90_351.cpp b/src/devices/bus/thomson/cd90_351.cpp
index 44962c00115..d4a610c1f3f 100644
--- a/src/devices/bus/thomson/cd90_351.cpp
+++ b/src/devices/bus/thomson/cd90_351.cpp
@@ -12,7 +12,7 @@
#include "cd90_351.h"
#include "formats/thom_dsk.h"
-DEFINE_DEVICE_TYPE(CD90_351, cd90_351_device, "cd90_351", "Thomson CD90-351 floppy drive controller")
+DEFINE_DEVICE_TYPE(CD90_351, cd90_351_device, "cd90_351", "Thomson CD 90-351 Diskette Controller")
cd90_351_device::cd90_351_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, CD90_351, tag, owner, 16000000),
@@ -41,15 +41,15 @@ void cd90_351_device::rom_map(address_map &map)
void cd90_351_device::io_map(address_map &map)
{
- map(0, 0).rw(FUNC(cd90_351_device::stat0_r), FUNC(cd90_351_device::cmd0_w));
- map(1, 1).rw(FUNC(cd90_351_device::stat1_r), FUNC(cd90_351_device::cmd1_w));
- map(2, 2).w(FUNC(cd90_351_device::cmd2_w));
- map(3, 3).rw(FUNC(cd90_351_device::rdata_r), FUNC(cd90_351_device::wdata_w));
- map(4, 4).w(FUNC(cd90_351_device::wclk_w));
- map(5, 5).w(FUNC(cd90_351_device::wsect_w));
- map(6, 6).w(FUNC(cd90_351_device::wtrck_w));
- map(7, 7).w(FUNC(cd90_351_device::wcell_w));
- map(8, 8).w(FUNC(cd90_351_device::bank_w));
+ map(0x10, 0x10).rw(FUNC(cd90_351_device::stat0_r), FUNC(cd90_351_device::cmd0_w));
+ map(0x11, 0x11).rw(FUNC(cd90_351_device::stat1_r), FUNC(cd90_351_device::cmd1_w));
+ map(0x12, 0x12).w(FUNC(cd90_351_device::cmd2_w));
+ map(0x13, 0x13).rw(FUNC(cd90_351_device::rdata_r), FUNC(cd90_351_device::wdata_w));
+ map(0x14, 0x14).w(FUNC(cd90_351_device::wclk_w));
+ map(0x15, 0x15).w(FUNC(cd90_351_device::wsect_w));
+ map(0x16, 0x16).w(FUNC(cd90_351_device::wtrck_w));
+ map(0x17, 0x17).w(FUNC(cd90_351_device::wcell_w));
+ map(0x18, 0x18).w(FUNC(cd90_351_device::bank_w));
}
const tiny_rom_entry *cd90_351_device::device_rom_region() const
diff --git a/src/devices/bus/thomson/cd90_640.cpp b/src/devices/bus/thomson/cd90_640.cpp
index 4cae4efb97a..86453d795be 100644
--- a/src/devices/bus/thomson/cd90_640.cpp
+++ b/src/devices/bus/thomson/cd90_640.cpp
@@ -9,7 +9,7 @@
#include "cd90_640.h"
#include "formats/thom_dsk.h"
-DEFINE_DEVICE_TYPE(CD90_640, cd90_640_device, "cd90_640", "Thomson CD90-640 floppy drive controller")
+DEFINE_DEVICE_TYPE(CD90_640, cd90_640_device, "cd90_640", "Thomson CD 90-640 floppy drive controller")
cd90_640_device::cd90_640_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, CD90_640, tag, owner, clock),
@@ -32,8 +32,8 @@ void cd90_640_device::rom_map(address_map &map)
void cd90_640_device::io_map(address_map &map)
{
- map(0, 3).rw(m_fdc, FUNC(wd1770_device::read), FUNC(wd1770_device::write));
- map(8, 8).rw(FUNC(cd90_640_device::control_r), FUNC(cd90_640_device::control_w));
+ map(0x10, 0x13).rw(m_fdc, FUNC(wd1770_device::read), FUNC(wd1770_device::write));
+ map(0x18, 0x18).rw(FUNC(cd90_640_device::control_r), FUNC(cd90_640_device::control_w));
}
const tiny_rom_entry *cd90_640_device::device_rom_region() const
diff --git a/src/devices/bus/thomson/cd90_640.h b/src/devices/bus/thomson/cd90_640.h
index 5598a71546d..184ca9a59e6 100644
--- a/src/devices/bus/thomson/cd90_640.h
+++ b/src/devices/bus/thomson/cd90_640.h
@@ -15,7 +15,7 @@
class cd90_640_device : public device_t, public thomson_extension_interface
{
public:
- cd90_640_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
+ cd90_640_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual ~cd90_640_device() = default;
virtual void rom_map(address_map &map) override;
diff --git a/src/devices/bus/thomson/cq90_028.cpp b/src/devices/bus/thomson/cq90_028.cpp
index fd14c5302f7..8d0ce518b19 100644
--- a/src/devices/bus/thomson/cq90_028.cpp
+++ b/src/devices/bus/thomson/cq90_028.cpp
@@ -11,7 +11,7 @@
#include "emu.h"
#include "cq90_028.h"
-DEFINE_DEVICE_TYPE(CQ90_028, cq90_028_device, "cq90_028", "Thomson CQ90-028 QDD controller")
+DEFINE_DEVICE_TYPE(CQ90_028, cq90_028_device, "cq90_028", "Thomson CQ 90-028 QDD controller")
cq90_028_device::cq90_028_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, CQ90_028, tag, owner, clock),
@@ -33,9 +33,9 @@ void cq90_028_device::rom_map(address_map &map)
void cq90_028_device::io_map(address_map &map)
{
- map(0x0, 0x1).rw(m_serial, FUNC(mc6852_device::read), FUNC(mc6852_device::write));
- map(0x8, 0x8).rw(FUNC(cq90_028_device::status_r), FUNC(cq90_028_device::drive_w));
- map(0xc, 0xc).w(FUNC(cq90_028_device::motor_w));
+ map(0x10, 0x11).rw(m_serial, FUNC(mc6852_device::read), FUNC(mc6852_device::write));
+ map(0x18, 0x18).rw(FUNC(cq90_028_device::status_r), FUNC(cq90_028_device::drive_w));
+ map(0x1c, 0x1c).w(FUNC(cq90_028_device::motor_w));
}
const tiny_rom_entry *cq90_028_device::device_rom_region() const
@@ -45,7 +45,7 @@ const tiny_rom_entry *cq90_028_device::device_rom_region() const
void cq90_028_device::device_add_mconfig(machine_config &config)
{
- MC6852(config, m_serial, 16_MHz_XTAL / 16); // Comes from the main board
+ MC6852(config, m_serial, DERIVED_CLOCK(1, 1)); // Comes from the main board
// Base tx/rx clock is 101564Hz
// There's probably a pll in the gate array
}
diff --git a/src/devices/bus/thomson/cq90_028.h b/src/devices/bus/thomson/cq90_028.h
index d0a44448e38..a31a022405d 100644
--- a/src/devices/bus/thomson/cq90_028.h
+++ b/src/devices/bus/thomson/cq90_028.h
@@ -14,7 +14,7 @@
class cq90_028_device : public device_t, public thomson_extension_interface
{
public:
- cq90_028_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
+ cq90_028_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual ~cq90_028_device() = default;
static constexpr feature_type unemulated_features() { return feature::DISK; }
diff --git a/src/devices/bus/thomson/extension.cpp b/src/devices/bus/thomson/extension.cpp
index 12462b9898a..4fb2cfbb7ce 100644
--- a/src/devices/bus/thomson/extension.cpp
+++ b/src/devices/bus/thomson/extension.cpp
@@ -11,7 +11,9 @@ DEFINE_DEVICE_TYPE(THOMSON_EXTENSION, thomson_extension_device, "thomson_extensi
thomson_extension_device::thomson_extension_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, THOMSON_EXTENSION, tag, owner, clock),
- device_single_card_slot_interface<thomson_extension_interface>(mconfig, *this)
+ device_single_card_slot_interface<thomson_extension_interface>(mconfig, *this),
+ m_firq_callback(*this),
+ m_irq_callback(*this)
{
}
@@ -34,7 +36,19 @@ void thomson_extension_device::device_start()
}
thomson_extension_interface::thomson_extension_interface(const machine_config &mconfig, device_t &device) :
- device_interface(device, "extension")
+ device_interface(device, "extension"),
+ m_ext(dynamic_cast<thomson_extension_device *>(device.owner()))
{
}
+void thomson_extension_interface::firq_w(int state)
+{
+ if(m_ext)
+ m_ext->m_firq_callback(state);
+}
+
+void thomson_extension_interface::irq_w(int state)
+{
+ if(m_ext)
+ m_ext->m_irq_callback(state);
+}
diff --git a/src/devices/bus/thomson/extension.h b/src/devices/bus/thomson/extension.h
index bbe9db92915..d17b5d22536 100644
--- a/src/devices/bus/thomson/extension.h
+++ b/src/devices/bus/thomson/extension.h
@@ -6,6 +6,8 @@
#ifndef MAME_BUS_THOMSON_EXTENSION_H
#define MAME_BUS_THOMSON_EXTENSION_H
+class thomson_extension_device;
+
class thomson_extension_interface : public device_interface
{
public:
@@ -15,23 +17,37 @@ public:
// 0x7c0 window at e000 on TO* and a000 on MO*
virtual void rom_map(address_map &map) = 0;
- // 0x10 window at e7d0 on TO* and a7e0 on MO*
+ // 0x40 window at e7c0 on TO* and a7c0 on MO*
virtual void io_map(address_map &map) = 0;
-};
+protected:
+ void firq_w(int state);
+ void irq_w(int state);
+
+private:
+ thomson_extension_device *const m_ext;
+};
class thomson_extension_device : public device_t, public device_single_card_slot_interface<thomson_extension_interface>
{
+ friend class thomson_extension_interface;
+
public:
- thomson_extension_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
+ thomson_extension_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual ~thomson_extension_device() = default;
+ auto firq_callback() { return m_firq_callback.bind(); }
+ auto irq_callback() { return m_irq_callback.bind(); }
+
void rom_map(address_space_installer &space, offs_t start, offs_t end);
void io_map(address_space_installer &space, offs_t start, offs_t end);
protected:
virtual void device_start() override;
+
+ devcb_write_line m_firq_callback;
+ devcb_write_line m_irq_callback;
};
DECLARE_DEVICE_TYPE(THOMSON_EXTENSION, thomson_extension_device)
diff --git a/src/devices/bus/thomson/md90_120.cpp b/src/devices/bus/thomson/md90_120.cpp
new file mode 100644
index 00000000000..d59767a0322
--- /dev/null
+++ b/src/devices/bus/thomson/md90_120.cpp
@@ -0,0 +1,94 @@
+// license:BSD-3-Clause
+// copyright-holders:Antoine Mine
+
+#include "emu.h"
+#include "md90_120.h"
+
+#include "machine/6821pia.h"
+#include "machine/clock.h"
+
+#define VERBOSE 0
+#include "logmacro.h"
+
+/* ------------ MD 90-120 MODEM extension (not functional) ------------ */
+
+/* Features:
+ - 6850 ACIA
+ - 6821 PIA
+ - asymetric 1200/ 75 bauds (reversable)
+
+ TODO!
+ */
+
+// device type definition
+DEFINE_DEVICE_TYPE(MD90_120, md90_120_device, "md90_120", "Thomson MD 90-120 Modem")
+
+//-------------------------------------------------
+// md90_120_device - constructor
+//-------------------------------------------------
+
+md90_120_device::md90_120_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, MD90_120, tag, owner, clock),
+ thomson_extension_interface(mconfig, *this),
+ m_acia(*this, "acia")
+{
+}
+
+void md90_120_device::rom_map(address_map &map)
+{
+}
+
+void md90_120_device::io_map(address_map &map)
+{
+ map(0x38, 0x3b).rw("pia", FUNC(pia6821_device::read_alt), FUNC(pia6821_device::write_alt));
+ map(0x3e, 0x3f).rw(m_acia, FUNC(acia6850_device::read), FUNC(acia6850_device::write));
+}
+
+void md90_120_device::device_add_mconfig(machine_config &config)
+{
+ PIA6821(config, "pia");
+
+ ACIA6850(config, m_acia);
+ m_acia->txd_handler().set(FUNC(md90_120_device::modem_tx_w));
+ m_acia->irq_handler().set(FUNC(md90_120_device::modem_cb));
+
+ clock_device &acia_clock(CLOCK(config, "acia_clock", 1200)); /* 1200 bauds, might be divided by 16 */
+ acia_clock.signal_handler().set(FUNC(md90_120_device::write_acia_clock));
+}
+
+
+void md90_120_device::modem_cb(int state)
+{
+ LOG( "modem_cb: called %i\n", state );
+}
+
+
+
+void md90_120_device::modem_tx_w(int state)
+{
+ m_modem_tx = state;
+}
+
+
+void md90_120_device::write_acia_clock(int state)
+{
+ m_acia->write_txc(state);
+ m_acia->write_rxc(state);
+}
+
+void md90_120_device::device_reset()
+{
+ m_acia->write_rxd(0);
+ m_modem_tx = 0;
+ /* pia_reset() is called in machine_reset */
+ /* acia_6850 has no reset (?) */
+}
+
+
+
+void md90_120_device::device_start()
+{
+ LOG ( " MODEM not implemented!\n" );
+ save_item(NAME(m_modem_tx));
+}
+
diff --git a/src/devices/bus/thomson/md90_120.h b/src/devices/bus/thomson/md90_120.h
new file mode 100644
index 00000000000..e8d13ff1292
--- /dev/null
+++ b/src/devices/bus/thomson/md90_120.h
@@ -0,0 +1,38 @@
+// license:BSD-3-Clause
+// copyright-holders:Antoine Mine
+
+#ifndef MAME_BUS_THOMSON_MD90_120_H
+#define MAME_BUS_THOMSON_MD90_120_H
+
+#include "extension.h"
+#include "machine/6850acia.h"
+
+class md90_120_device : public device_t, public thomson_extension_interface
+{
+public:
+ md90_120_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ static constexpr feature_type unemulated_features() { return feature::COMMS; }
+
+ virtual void rom_map(address_map &map) override;
+ virtual void io_map(address_map &map) override;
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+private:
+ void modem_cb(int state);
+ void modem_tx_w(int state);
+ void write_acia_clock(int state);
+
+ required_device<acia6850_device> m_acia;
+
+ uint8_t m_modem_tx = 0;
+};
+
+// device type declaration
+DECLARE_DEVICE_TYPE(MD90_120, md90_120_device)
+
+#endif // MAME_BUS_THOMSON_MD90_120_H
diff --git a/src/devices/bus/thomson/midipak.cpp b/src/devices/bus/thomson/midipak.cpp
new file mode 100644
index 00000000000..ad1ec4198c7
--- /dev/null
+++ b/src/devices/bus/thomson/midipak.cpp
@@ -0,0 +1,61 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/***************************************************************************
+
+ Logimus Midipak
+
+ This MIDI extension interface basically consists of a EF68B50P plus
+ some glue logic. An onboard jumper (JP1) can connect the 6850's IRQ
+ output to either IRQ or FIRQ; currently only the IRQ connection is
+ supported.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "midipak.h"
+
+#include "bus/midi/midi.h"
+#include "machine/6850acia.h"
+#include "machine/clock.h"
+
+// device type definition
+DEFINE_DEVICE_TYPE(LOGIMUS_MIDIPAK, logimus_midipak_device, "logimus_midipak", "Logimus Midipak")
+
+//-------------------------------------------------
+// logimus_midipak_device - constructor
+//-------------------------------------------------
+
+logimus_midipak_device::logimus_midipak_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, LOGIMUS_MIDIPAK, tag, owner, clock)
+ , thomson_extension_interface(mconfig, *this)
+{
+}
+
+void logimus_midipak_device::rom_map(address_map &map)
+{
+}
+
+void logimus_midipak_device::io_map(address_map &map)
+{
+ map(0x32, 0x33).rw("acia", FUNC(acia6850_device::read), FUNC(acia6850_device::write));
+}
+
+void logimus_midipak_device::device_add_mconfig(machine_config &config)
+{
+ acia6850_device &acia(ACIA6850(config, "acia"));
+ acia.txd_handler().set("mdout", FUNC(midi_port_device::write_txd));
+ acia.irq_handler().set(FUNC(logimus_midipak_device::irq_w));
+ acia.write_cts(0);
+ acia.write_dcd(0);
+
+ clock_device &midiclock(CLOCK(config, "midiclock", DERIVED_CLOCK(1, 1)));
+ midiclock.signal_handler().set("acia", FUNC(acia6850_device::write_rxc));
+ midiclock.signal_handler().append("acia", FUNC(acia6850_device::write_txc));
+
+ MIDI_PORT(config, "mdin", midiin_slot, "midiin").rxd_handler().set("acia", FUNC(acia6850_device::write_rxd));
+ MIDI_PORT(config, "mdout", midiout_slot, "midiout");
+}
+
+void logimus_midipak_device::device_start()
+{
+}
diff --git a/src/devices/bus/thomson/midipak.h b/src/devices/bus/thomson/midipak.h
new file mode 100644
index 00000000000..b6a1135cd3f
--- /dev/null
+++ b/src/devices/bus/thomson/midipak.h
@@ -0,0 +1,25 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+
+#ifndef MAME_BUS_THOMSON_MIDIPAK_H
+#define MAME_BUS_THOMSON_MIDIPAK_H
+
+#include "extension.h"
+
+class logimus_midipak_device : public device_t, public thomson_extension_interface
+{
+public:
+ logimus_midipak_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void rom_map(address_map &map) override;
+ virtual void io_map(address_map &map) override;
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_start() override;
+};
+
+// device type declaration
+DECLARE_DEVICE_TYPE(LOGIMUS_MIDIPAK, logimus_midipak_device)
+
+#endif // MAME_BUS_THOMSON_MIDIPAK_H
diff --git a/src/devices/bus/thomson/nanoreseau.cpp b/src/devices/bus/thomson/nanoreseau.cpp
index 418d9ce59e5..4275fe4fb59 100644
--- a/src/devices/bus/thomson/nanoreseau.cpp
+++ b/src/devices/bus/thomson/nanoreseau.cpp
@@ -85,9 +85,9 @@ void nanoreseau_device::rom_map(address_map &map)
void nanoreseau_device::io_map(address_map &map)
{
- map(0, 3).rw(m_mc6854, FUNC(mc6854_device::read), FUNC(mc6854_device::write));
+ map(0x10, 0x13).rw(m_mc6854, FUNC(mc6854_device::read), FUNC(mc6854_device::write));
if (!m_no_id)
- map(8, 8).r(FUNC(nanoreseau_device::id_r));
+ map(0x18, 0x18).r(FUNC(nanoreseau_device::id_r));
}
const tiny_rom_entry *nanoreseau_to_device::device_rom_region() const
diff --git a/src/devices/bus/thomson/rf57_932.cpp b/src/devices/bus/thomson/rf57_932.cpp
new file mode 100644
index 00000000000..aae78237a4e
--- /dev/null
+++ b/src/devices/bus/thomson/rf57_932.cpp
@@ -0,0 +1,55 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/***************************************************************************
+
+ Thomson RF 57-932 RS-232-C extension interface
+
+***************************************************************************/
+
+#include "emu.h"
+#include "rf57_932.h"
+
+#include "bus/rs232/rs232.h"
+#include "machine/mos6551.h"
+
+// device type definition
+DEFINE_DEVICE_TYPE(RF57_932, rf57_932_device, "rf57_932", "Thomson RF 57-932 RS-232-C Interface")
+
+//-------------------------------------------------
+// rf57_932_device - constructor
+//-------------------------------------------------
+
+rf57_932_device::rf57_932_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, RF57_932, tag, owner, clock)
+ , thomson_extension_interface(mconfig, *this)
+{
+}
+
+void rf57_932_device::rom_map(address_map &map)
+{
+}
+
+void rf57_932_device::io_map(address_map &map)
+{
+ map(0x28, 0x2b).rw("acia", FUNC(mos6551_device::read), FUNC(mos6551_device::write));
+}
+
+void rf57_932_device::device_add_mconfig(machine_config &config)
+{
+ mos6551_device &acia(MOS6551(config, "acia", DERIVED_CLOCK(1, 1)));
+ acia.set_xtal(1.8432_MHz_XTAL);
+ acia.txd_handler().set("rs232", FUNC(rs232_port_device::write_txd));
+ acia.rts_handler().set("rs232", FUNC(rs232_port_device::write_rts));
+ acia.irq_handler().set(FUNC(rf57_932_device::irq_w));
+ acia.write_dcd(0);
+
+ rs232_port_device &rs232(RS232_PORT(config, "rs232", default_rs232_devices, nullptr));
+ rs232.rxd_handler().set("acia", FUNC(mos6551_device::write_rxd));
+ rs232.dsr_handler().set("acia", FUNC(mos6551_device::write_dsr));
+ rs232.cts_handler().set("acia", FUNC(mos6551_device::write_cts));
+ rs232.rxc_handler().set("acia", FUNC(mos6551_device::write_rxc));
+}
+
+void rf57_932_device::device_start()
+{
+}
diff --git a/src/devices/bus/thomson/rf57_932.h b/src/devices/bus/thomson/rf57_932.h
new file mode 100644
index 00000000000..9023403f528
--- /dev/null
+++ b/src/devices/bus/thomson/rf57_932.h
@@ -0,0 +1,25 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+
+#ifndef MAME_BUS_THOMSON_RF57_932_H
+#define MAME_BUS_THOMSON_RF57_932_H
+
+#include "extension.h"
+
+class rf57_932_device : public device_t, public thomson_extension_interface
+{
+public:
+ rf57_932_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void rom_map(address_map &map) override;
+ virtual void io_map(address_map &map) override;
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_start() override;
+};
+
+// device type declaration
+DECLARE_DEVICE_TYPE(RF57_932, rf57_932_device)
+
+#endif // MAME_BUS_THOMSON_RF57_932_H
diff --git a/src/devices/bus/thomson/speech.cpp b/src/devices/bus/thomson/speech.cpp
new file mode 100644
index 00000000000..0c14b0d6d9e
--- /dev/null
+++ b/src/devices/bus/thomson/speech.cpp
@@ -0,0 +1,43 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+
+#include "emu.h"
+#include "speech.h"
+
+#include "sound/mea8000.h"
+#include "speaker.h"
+
+// device type definition
+DEFINE_DEVICE_TYPE(THOMSON_SPEECH, thomson_speech_device, "thomson_speech", "Cedic-Nathan Speech Synthesizer")
+
+//-------------------------------------------------
+// thomson_speech_device - constructor
+//-------------------------------------------------
+
+thomson_speech_device::thomson_speech_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, THOMSON_SPEECH, tag, owner, clock)
+ , thomson_extension_interface(mconfig, *this)
+{
+}
+
+void thomson_speech_device::rom_map(address_map &map)
+{
+}
+
+void thomson_speech_device::io_map(address_map &map)
+{
+ map(0x3e, 0x3f).rw("mea8000", FUNC(mea8000_device::read), FUNC(mea8000_device::write));
+}
+
+void thomson_speech_device::device_add_mconfig(machine_config &config)
+{
+ mea8000_device &mea8000(MEA8000(config, "mea8000", 4_MHz_XTAL));
+ mea8000.add_route(ALL_OUTPUTS, "speaker", 1.0);
+
+ // FIXME: actually drives main speaker through the sound line on the bus
+ SPEAKER(config, "speaker").front_center();
+}
+
+void thomson_speech_device::device_start()
+{
+}
diff --git a/src/devices/bus/thomson/speech.h b/src/devices/bus/thomson/speech.h
new file mode 100644
index 00000000000..c4e6f227edf
--- /dev/null
+++ b/src/devices/bus/thomson/speech.h
@@ -0,0 +1,25 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+
+#ifndef MAME_BUS_THOMSON_SPEECH_H
+#define MAME_BUS_THOMSON_SPEECH_H
+
+#include "extension.h"
+
+class thomson_speech_device : public device_t, public thomson_extension_interface
+{
+public:
+ thomson_speech_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual void rom_map(address_map &map) override;
+ virtual void io_map(address_map &map) override;
+
+protected:
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_start() override;
+};
+
+// device type declaration
+DECLARE_DEVICE_TYPE(THOMSON_SPEECH, thomson_speech_device)
+
+#endif // MAME_BUS_THOMSON_SPEECH_H
diff --git a/src/devices/bus/ti8x/bitsocket.cpp b/src/devices/bus/ti8x/bitsocket.cpp
index 1c4feb4ed4f..df14d58292d 100644
--- a/src/devices/bus/ti8x/bitsocket.cpp
+++ b/src/devices/bus/ti8x/bitsocket.cpp
@@ -29,8 +29,8 @@ protected:
virtual void device_add_mconfig(machine_config &config) override;
virtual void device_start() override;
- virtual DECLARE_WRITE_LINE_MEMBER(input_tip) override;
- virtual DECLARE_WRITE_LINE_MEMBER(input_ring) override;
+ virtual void input_tip(int state) override;
+ virtual void input_ring(int state) override;
TIMER_CALLBACK_MEMBER(poll_tick);
@@ -86,14 +86,14 @@ TIMER_CALLBACK_MEMBER(bit_socket_device::poll_tick)
}
-WRITE_LINE_MEMBER(bit_socket_device::input_tip)
+void bit_socket_device::input_tip(int state)
{
m_tip_in = bool(state);
m_stream->output((m_tip_in ? 0x01 : 0x00) | 0x02);
}
-WRITE_LINE_MEMBER(bit_socket_device::input_ring)
+void bit_socket_device::input_ring(int state)
{
m_ring_in = bool(state);
m_stream->output((m_ring_in ? 0x01 : 0x00) | 0x04);
diff --git a/src/devices/bus/ti8x/teeconn.cpp b/src/devices/bus/ti8x/teeconn.cpp
index b0774684dc7..8a873c4c72d 100644
--- a/src/devices/bus/ti8x/teeconn.cpp
+++ b/src/devices/bus/ti8x/teeconn.cpp
@@ -19,13 +19,13 @@ protected:
virtual void device_add_mconfig(machine_config &config) override;
virtual void device_start() override;
- virtual DECLARE_WRITE_LINE_MEMBER(input_tip) override;
- virtual DECLARE_WRITE_LINE_MEMBER(input_ring) override;
+ virtual void input_tip(int state) override;
+ virtual void input_ring(int state) override;
- DECLARE_WRITE_LINE_MEMBER(tip_a_w);
- DECLARE_WRITE_LINE_MEMBER(ring_a_w);
- DECLARE_WRITE_LINE_MEMBER(tip_b_w);
- DECLARE_WRITE_LINE_MEMBER(ring_b_w);
+ void tip_a_w(int state);
+ void ring_a_w(int state);
+ void tip_b_w(int state);
+ void ring_b_w(int state);
required_device<ti8x_link_port_device> m_port_a;
required_device<ti8x_link_port_device> m_port_b;
@@ -54,7 +54,7 @@ tee_connector_device::tee_connector_device(
}
-WRITE_LINE_MEMBER(tee_connector_device::tip_a_w)
+void tee_connector_device::tip_a_w(int state)
{
m_tip_a = bool(state);
output_tip((m_tip_a && m_tip_b) ? 1 : 0);
@@ -62,7 +62,7 @@ WRITE_LINE_MEMBER(tee_connector_device::tip_a_w)
}
-WRITE_LINE_MEMBER(tee_connector_device::ring_a_w)
+void tee_connector_device::ring_a_w(int state)
{
m_ring_a = bool(state);
output_ring((m_ring_a && m_ring_b) ? 1 : 0);
@@ -70,7 +70,7 @@ WRITE_LINE_MEMBER(tee_connector_device::ring_a_w)
}
-WRITE_LINE_MEMBER(tee_connector_device::tip_b_w)
+void tee_connector_device::tip_b_w(int state)
{
m_tip_b = bool(state);
output_tip((m_tip_a && m_tip_b) ? 1 : 0);
@@ -78,7 +78,7 @@ WRITE_LINE_MEMBER(tee_connector_device::tip_b_w)
}
-WRITE_LINE_MEMBER(tee_connector_device::ring_b_w)
+void tee_connector_device::ring_b_w(int state)
{
m_ring_b = bool(state);
output_ring((m_ring_a && m_ring_b) ? 1 : 0);
@@ -112,7 +112,7 @@ void tee_connector_device::device_start()
}
-WRITE_LINE_MEMBER(tee_connector_device::input_tip)
+void tee_connector_device::input_tip(int state)
{
m_tip_host = bool(state);
m_port_a->tip_w((m_tip_host && m_tip_b) ? 1 : 0);
@@ -120,7 +120,7 @@ WRITE_LINE_MEMBER(tee_connector_device::input_tip)
}
-WRITE_LINE_MEMBER(tee_connector_device::input_ring)
+void tee_connector_device::input_ring(int state)
{
m_ring_host = bool(state);
m_port_a->ring_w((m_ring_host && m_ring_b) ? 1 : 0);
diff --git a/src/devices/bus/ti8x/ti8x.cpp b/src/devices/bus/ti8x/ti8x.cpp
index c9274a6f340..4c89147d996 100644
--- a/src/devices/bus/ti8x/ti8x.cpp
+++ b/src/devices/bus/ti8x/ti8x.cpp
@@ -4,9 +4,8 @@
#include "emu.h"
#include "ti8x.h"
-#define LOG_GENERAL (1U << 0)
-#define LOG_BITPROTO (1U << 1)
-#define LOG_BYTEPROTO (1U << 2)
+#define LOG_BITPROTO (1U << 1)
+#define LOG_BYTEPROTO (1U << 2)
//#define VERBOSE (LOG_GENERAL | LOG_BITPROTO | LOG_BYTEPROTO)
#define LOG_OUTPUT_FUNC device().logerror
@@ -49,7 +48,7 @@ ti8x_link_port_device::ti8x_link_port_device(
}
-WRITE_LINE_MEMBER(ti8x_link_port_device::tip_w)
+void ti8x_link_port_device::tip_w(int state)
{
if (bool(state) != m_tip_out)
{
@@ -60,7 +59,7 @@ WRITE_LINE_MEMBER(ti8x_link_port_device::tip_w)
}
-WRITE_LINE_MEMBER(ti8x_link_port_device::ring_w)
+void ti8x_link_port_device::ring_w(int state)
{
if (bool(state) != m_ring_out)
{
@@ -73,9 +72,6 @@ WRITE_LINE_MEMBER(ti8x_link_port_device::ring_w)
void ti8x_link_port_device::device_start()
{
- m_tip_handler.resolve_safe();
- m_ring_handler.resolve_safe();
-
save_item(NAME(m_tip_in));
save_item(NAME(m_tip_out));
save_item(NAME(m_ring_in));
@@ -229,7 +225,7 @@ void device_ti8x_link_port_bit_interface::accept_bit()
}
-WRITE_LINE_MEMBER(device_ti8x_link_port_bit_interface::input_tip)
+void device_ti8x_link_port_bit_interface::input_tip(int state)
{
m_tip_in = bool(state);
switch (m_bit_phase)
@@ -314,7 +310,7 @@ WRITE_LINE_MEMBER(device_ti8x_link_port_bit_interface::input_tip)
}
-WRITE_LINE_MEMBER(device_ti8x_link_port_bit_interface::input_ring)
+void device_ti8x_link_port_bit_interface::input_ring(int state)
{
m_ring_in = bool(state);
switch (m_bit_phase)
diff --git a/src/devices/bus/ti8x/ti8x.h b/src/devices/bus/ti8x/ti8x.h
index 759b3523eb1..a757a999ba0 100644
--- a/src/devices/bus/ti8x/ti8x.h
+++ b/src/devices/bus/ti8x/ti8x.h
@@ -63,11 +63,11 @@ public:
auto tip_handler() { return m_tip_handler.bind(); }
auto ring_handler() { return m_ring_handler.bind(); }
- DECLARE_WRITE_LINE_MEMBER(tip_w);
- DECLARE_WRITE_LINE_MEMBER(ring_w);
+ void tip_w(int state);
+ void ring_w(int state);
- DECLARE_READ_LINE_MEMBER(tip_r) { return m_tip_in ? 1 : 0; }
- DECLARE_READ_LINE_MEMBER(ring_r) { return m_ring_in ? 1 : 0; }
+ int tip_r() { return m_tip_in ? 1 : 0; }
+ int ring_r() { return m_ring_in ? 1 : 0; }
protected:
ti8x_link_port_device(
@@ -95,9 +95,9 @@ private:
class device_ti8x_link_port_interface : public device_interface
{
public:
- DECLARE_WRITE_LINE_MEMBER(output_tip)
+ void output_tip(int state)
{ if (bool(state) != m_port->m_tip_in) m_port->m_tip_handler((m_port->m_tip_in = bool(state)) ? 1 : 0); }
- DECLARE_WRITE_LINE_MEMBER(output_ring)
+ void output_ring(int state)
{ if (bool(state) != m_port->m_ring_in) m_port->m_ring_handler((m_port->m_ring_in = bool(state)) ? 1 : 0); }
protected:
@@ -106,8 +106,8 @@ protected:
ti8x_link_port_device &port() { return *m_port; }
private:
- virtual DECLARE_WRITE_LINE_MEMBER(input_tip) = 0;
- virtual DECLARE_WRITE_LINE_MEMBER(input_ring) = 0;
+ virtual void input_tip(int state) = 0;
+ virtual void input_ring(int state) = 0;
friend class ti8x_link_port_device;
@@ -149,8 +149,8 @@ private:
PENDING_1
};
- virtual DECLARE_WRITE_LINE_MEMBER(input_tip) override;
- virtual DECLARE_WRITE_LINE_MEMBER(input_ring) override;
+ virtual void input_tip(int state) override;
+ virtual void input_ring(int state) override;
virtual void bit_collision() = 0;
virtual void bit_send_timeout() = 0;
diff --git a/src/devices/bus/ti8x/tispeaker.cpp b/src/devices/bus/ti8x/tispeaker.cpp
index 2aa5afdcf7d..36ab34caae9 100644
--- a/src/devices/bus/ti8x/tispeaker.cpp
+++ b/src/devices/bus/ti8x/tispeaker.cpp
@@ -42,12 +42,12 @@ protected:
}
- virtual DECLARE_WRITE_LINE_MEMBER(input_tip) override
+ virtual void input_tip(int state) override
{
m_left_speaker->level_w(state);
}
- virtual DECLARE_WRITE_LINE_MEMBER(input_ring) override
+ virtual void input_ring(int state) override
{
m_right_speaker->level_w(state);
}
@@ -91,13 +91,13 @@ protected:
}
- virtual DECLARE_WRITE_LINE_MEMBER(input_tip) override
+ virtual void input_tip(int state) override
{
m_tip_state = bool(state);
m_speaker->level_w((m_tip_state || m_ring_state) ? 1 : 0);
}
- virtual DECLARE_WRITE_LINE_MEMBER(input_ring) override
+ virtual void input_ring(int state) override
{
m_ring_state = bool(state);
m_speaker->level_w((m_tip_state || m_ring_state) ? 1 : 0);
diff --git a/src/devices/bus/ti99/colorbus/busmouse.cpp b/src/devices/bus/ti99/colorbus/busmouse.cpp
index ccaf9c66f25..a84e7e22ef0 100644
--- a/src/devices/bus/ti99/colorbus/busmouse.cpp
+++ b/src/devices/bus/ti99/colorbus/busmouse.cpp
@@ -16,11 +16,11 @@
#include "emu.h"
#include "busmouse.h"
-#define LOG_BUTTON (1U<<1) // Buttons
-#define LOG_MOVEX (1U<<2) // x movement
-#define LOG_MOVEY (1U<<3) // y movement
+#define LOG_BUTTON (1U << 1) // Buttons
+#define LOG_MOVEX (1U << 2) // x movement
+#define LOG_MOVEY (1U << 3) // y movement
-#define VERBOSE ( LOG_GENERAL )
+#define VERBOSE (LOG_GENERAL)
#include "logmacro.h"
DEFINE_DEVICE_TYPE(V9938_BUSMOUSE, bus::ti99::colorbus::v9938_busmouse_device, "v9938_busmouse", "V9938 Bus Mouse")
diff --git a/src/devices/bus/ti99/colorbus/colorbus.cpp b/src/devices/bus/ti99/colorbus/colorbus.cpp
index e3decb6ba61..d3f26da93f1 100644
--- a/src/devices/bus/ti99/colorbus/colorbus.cpp
+++ b/src/devices/bus/ti99/colorbus/colorbus.cpp
@@ -25,11 +25,11 @@ DEFINE_DEVICE_TYPE(V9938_COLORBUS, bus::ti99::colorbus::v9938_colorbus_device, "
namespace bus::ti99::colorbus {
-v9938_colorbus_device::v9938_colorbus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, V9938_COLORBUS, tag, owner, clock),
- device_single_card_slot_interface<device_v9938_colorbus_interface>(mconfig, *this),
- m_v9938(*owner, TIGEN_V9938_TAG),
- m_extra_button(*this)
+v9938_colorbus_device::v9938_colorbus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, V9938_COLORBUS, tag, owner, clock),
+ device_single_card_slot_interface<device_v9938_colorbus_interface>(mconfig, *this),
+ m_v9938(*owner, TIGEN_V9938_TAG),
+ m_extra_button(*this)
{
}
@@ -51,14 +51,13 @@ void v9938_colorbus_device::buttons(int bstate)
void v9938_colorbus_device::device_start()
{
- m_extra_button.resolve_safe();
}
/*****************************************************************************/
-device_v9938_colorbus_interface::device_v9938_colorbus_interface(const machine_config &mconfig, device_t &device)
- : device_interface(device, "v9938colorbus"),
- m_colorbus(nullptr)
+device_v9938_colorbus_interface::device_v9938_colorbus_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "v9938colorbus"),
+ m_colorbus(nullptr)
{
}
diff --git a/src/devices/bus/ti99/gromport/cartridges.cpp b/src/devices/bus/ti99/gromport/cartridges.cpp
index 6ed6d19366f..e54f82e42ec 100644
--- a/src/devices/bus/ti99/gromport/cartridges.cpp
+++ b/src/devices/bus/ti99/gromport/cartridges.cpp
@@ -20,17 +20,17 @@
#include "corestr.h"
#include "formats/rpk.h"
-#define LOG_WARN (1U<<1) // Warnings
-#define LOG_CONFIG (1U<<2) // Configuration
-#define LOG_CHANGE (1U<<3) // Cart change
-#define LOG_BANKSWITCH (1U<<4) // Bank switch operation
-#define LOG_CRU (1U<<5) // CRU access
-#define LOG_READ (1U<<6) // Read operation
-#define LOG_WRITE (1U<<7) // Write operation
-#define LOG_RPK (1U<<8) // RPK handler
-#define LOG_WARNW (1U<<9) // Warn when writing to cartridge space
-
-#define VERBOSE ( LOG_GENERAL | LOG_WARN | LOG_CONFIG )
+#define LOG_WARN (1U << 1) // Warnings
+#define LOG_CONFIG (1U << 2) // Configuration
+#define LOG_CHANGE (1U << 3) // Cart change
+#define LOG_BANKSWITCH (1U << 4) // Bank switch operation
+#define LOG_CRU (1U << 5) // CRU access
+#define LOG_READ (1U << 6) // Read operation
+#define LOG_WRITE (1U << 7) // Write operation
+#define LOG_RPK (1U << 8) // RPK handler
+#define LOG_WARNW (1U << 9) // Warn when writing to cartridge space
+
+#define VERBOSE (LOG_GENERAL | LOG_WARN | LOG_CONFIG | LOG_CHANGE)
#include "logmacro.h"
DEFINE_DEVICE_TYPE(TI99_CART, bus::ti99::gromport::ti99_cartridge_device, "ti99cart", "TI-99 cartridge")
@@ -94,7 +94,6 @@ ti99_cartridge_device::ti99_cartridge_device(const machine_config &mconfig, cons
: device_t(mconfig, TI99_CART, tag, owner, clock),
device_cartrom_image_interface(mconfig, *this),
m_pcbtype(0),
- m_slot(0),
m_pcb(nullptr),
m_connector(nullptr)
{
@@ -271,11 +270,11 @@ int ti99_cartridge_device::get_index_from_tagname()
return atoi(mytag+i+1)-1;
}
-image_init_result ti99_cartridge_device::call_load()
+std::pair<std::error_condition, std::string> ti99_cartridge_device::call_load()
{
// File name is in m_basename
- // return true = error
- LOGMASKED(LOG_CHANGE, "Loading %s in slot %s\n", basename());
+ int slot = get_index_from_tagname() + 1;
+ LOGMASKED(LOG_CHANGE, "Loading %s in slot %d\n", basename(), slot);
if (loaded_through_softlist())
{
@@ -304,8 +303,7 @@ image_init_result ti99_cartridge_device::call_load()
{
LOGMASKED(LOG_WARN, "Failed to load cartridge '%s': %s\n", basename(), err.message().c_str());
m_rpk.reset();
- m_err = image_error::INVALIDIMAGE;
- return image_init_result::FAIL;
+ return std::make_pair(err, std::string());
}
m_pcbtype = m_rpk->get_type();
}
@@ -365,9 +363,8 @@ image_init_result ti99_cartridge_device::call_load()
prepare_cartridge();
m_pcb->set_cartridge(this);
m_pcb->set_tag(tag());
- m_slot = get_index_from_tagname();
- m_connector->insert(m_slot, this);
- return image_init_result::PASS;
+ m_connector->insert();
+ return std::make_pair(std::error_condition(), std::string());
}
void ti99_cartridge_device::call_unload()
@@ -389,13 +386,21 @@ void ti99_cartridge_device::call_unload()
}
}
- m_pcb = nullptr;
- m_connector->remove(m_slot);
-}
+ // If we don't clear this, swapping cartridges may make old contents reappear
+ if (memregion("grom"))
+ machine().memory().region_free(memregion("grom")->name());
-void ti99_cartridge_device::set_slot(int i)
-{
- m_slot = i;
+ if (memregion("rom"))
+ machine().memory().region_free(memregion("rom")->name());
+
+ if (memregion("nvram"))
+ machine().memory().region_free(memregion("nvram")->name());
+
+ if (memregion("ram"))
+ machine().memory().region_free(memregion("ram")->name());
+
+ m_pcb = nullptr;
+ m_connector->remove();
}
void ti99_cartridge_device::readz(offs_t offset, uint8_t *value)
@@ -420,12 +425,12 @@ void ti99_cartridge_device::cruwrite(offs_t offset, uint8_t data)
if (m_pcb != nullptr) m_pcb->cruwrite(offset, data);
}
-WRITE_LINE_MEMBER( ti99_cartridge_device::ready_line )
+void ti99_cartridge_device::ready_line(int state)
{
m_connector->ready_line(state);
}
-WRITE_LINE_MEMBER( ti99_cartridge_device::romgq_line )
+void ti99_cartridge_device::romgq_line(int state)
{
if (m_pcb != nullptr)
{
@@ -442,7 +447,7 @@ void ti99_cartridge_device::set_gromlines(line_state mline, line_state moline, l
if (m_pcb != nullptr) m_pcb->set_gromlines(mline, moline, gsq);
}
-WRITE_LINE_MEMBER(ti99_cartridge_device::gclock_in)
+void ti99_cartridge_device::gclock_in(int state)
{
if (m_pcb != nullptr) m_pcb->gclock_in(state);
}
@@ -452,11 +457,6 @@ bool ti99_cartridge_device::is_grom_idle()
return (m_pcb != nullptr)? m_pcb->is_grom_idle() : false;
}
-void ti99_cartridge_device::device_config_complete()
-{
- m_connector = static_cast<cartridge_connector_device*>(owner());
-}
-
/*
5 GROMs that may be contained in a cartridge
*/
@@ -611,7 +611,7 @@ void ti99_cartridge_pcb::set_grom_pointer(int number, device_t *dev)
}
-WRITE_LINE_MEMBER( ti99_cartridge_pcb::romgq_line )
+void ti99_cartridge_pcb::romgq_line(int state)
{
m_romspace_selected = (state==ASSERT_LINE);
}
@@ -633,7 +633,7 @@ void ti99_cartridge_pcb::set_gromlines(line_state mline, line_state moline, line
}
}
-WRITE_LINE_MEMBER(ti99_cartridge_pcb::gclock_in)
+void ti99_cartridge_pcb::gclock_in(int state)
{
for (auto& elem : m_grom)
{
diff --git a/src/devices/bus/ti99/gromport/cartridges.h b/src/devices/bus/ti99/gromport/cartridges.h
index 68593bf1ac8..6402d4cf38c 100644
--- a/src/devices/bus/ti99/gromport/cartridges.h
+++ b/src/devices/bus/ti99/gromport/cartridges.h
@@ -12,19 +12,25 @@
#include "imagedev/cartrom.h"
#include "machine/tmc0430.h"
-#include "formats/rpk.h"
#include "emuopts.h"
#include "utilfwd.h"
+// declared in formats/rpk.h
+class rpk_socket;
+
namespace bus::ti99::gromport {
class ti99_cartridge_pcb;
class ti99_cartridge_device : public device_t, public device_cartrom_image_interface
{
+ friend class ti99_single_cart_conn_device;
+ friend class ti99_multi_cart_conn_device;
+ friend class ti99_gkracker_device;
+
public:
ti99_cartridge_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
@@ -33,25 +39,23 @@ public:
void crureadz(offs_t offset, uint8_t *value);
void cruwrite(offs_t offset, uint8_t data);
- DECLARE_WRITE_LINE_MEMBER(ready_line);
- DECLARE_WRITE_LINE_MEMBER(romgq_line);
+ void ready_line(int state);
+ void romgq_line(int state);
void set_gromlines(line_state mline, line_state moline, line_state gsq);
- DECLARE_WRITE_LINE_MEMBER(gclock_in);
+ void gclock_in(int state);
bool is_available() { return m_pcb != nullptr; }
- void set_slot(int i);
bool is_grom_idle();
protected:
virtual void device_start() override { }
- virtual void device_config_complete() override;
virtual void device_add_mconfig(machine_config &config) override;
virtual const tiny_rom_entry* device_rom_region() const override;
// Image handling: implementation of methods which are abstract in the parent
- image_init_result call_load() override;
+ std::pair<std::error_condition, std::string> call_load() override;
void call_unload() override;
void prepare_cartridge();
@@ -61,6 +65,8 @@ protected:
const char *image_interface() const noexcept override { return "ti99_cart"; }
const char *file_extensions() const noexcept override { return "rpk"; }
+ void set_connector(cartridge_connector_device* conn) { m_connector = conn; }
+
private:
class ti99_rpk_socket;
@@ -114,7 +120,6 @@ private:
bool m_readrom;
int m_pcbtype;
- int m_slot;
int get_index_from_tagname();
std::unique_ptr<ti99_cartridge_pcb> m_pcb; // inbound
@@ -144,9 +149,9 @@ protected:
virtual void crureadz(offs_t offset, uint8_t *value);
virtual void cruwrite(offs_t offset, uint8_t data);
- DECLARE_WRITE_LINE_MEMBER(romgq_line);
+ void romgq_line(int state);
virtual void set_gromlines(line_state mline, line_state moline, line_state gsq);
- DECLARE_WRITE_LINE_MEMBER(gclock_in);
+ void gclock_in(int state);
void gromreadz(uint8_t* value);
void gromwrite(uint8_t data);
diff --git a/src/devices/bus/ti99/gromport/gkracker.cpp b/src/devices/bus/ti99/gromport/gkracker.cpp
index 212207665e2..c39a3cae806 100644
--- a/src/devices/bus/ti99/gromport/gkracker.cpp
+++ b/src/devices/bus/ti99/gromport/gkracker.cpp
@@ -97,11 +97,11 @@
#include "emu.h"
#include "gkracker.h"
-#define LOG_WARN (1U<<1) // Warnings
-#define LOG_CHANGE (1U<<2) // Cartridge change
-#define LOG_GKRACKER (1U<<3) // Gram Kracker operation
+#define LOG_WARN (1U << 1) // Warnings
+#define LOG_CHANGE (1U << 2) // Cartridge change
+#define LOG_GKRACKER (1U << 3) // Gram Kracker operation
-#define VERBOSE ( LOG_WARN )
+#define VERBOSE (LOG_GENERAL | LOG_WARN)
#include "logmacro.h"
DEFINE_DEVICE_TYPE(TI99_GROMPORT_GK, bus::ti99::gromport::ti99_gkracker_device, "ti99_gkracker", "Miller's Graphics GRAM Kracker")
@@ -141,15 +141,15 @@ ti99_gkracker_device::ti99_gkracker_device(const machine_config &mconfig, const
m_ram_ptr(nullptr),
m_grom_ptr(nullptr),
m_waddr_LSB(false),
- m_cartridge(nullptr)
+ m_cartridge(*this, "cartridge")
{
}
-WRITE_LINE_MEMBER(ti99_gkracker_device::romgq_line)
+void ti99_gkracker_device::romgq_line(int state)
{
m_romspace_selected = (state==ASSERT_LINE);
- // Propagate to the guest
- if (m_cartridge != nullptr) m_cartridge->romgq_line(state);
+ // Propagate to the guest (if available)
+ m_cartridge->romgq_line(state);
}
/*
@@ -158,12 +158,12 @@ WRITE_LINE_MEMBER(ti99_gkracker_device::romgq_line)
void ti99_gkracker_device::set_gromlines(line_state mline, line_state moline, line_state gsq)
{
m_grom_selected = (gsq==ASSERT_LINE);
- if (m_cartridge != nullptr) m_cartridge->set_gromlines(mline, moline, gsq);
+ m_cartridge->set_gromlines(mline, moline, gsq);
}
-WRITE_LINE_MEMBER(ti99_gkracker_device::gclock_in)
+void ti99_gkracker_device::gclock_in(int state)
{
- if (m_cartridge != nullptr) m_cartridge->gclock_in(state);
+ m_cartridge->gclock_in(state);
}
/*
@@ -171,7 +171,7 @@ WRITE_LINE_MEMBER(ti99_gkracker_device::gclock_in)
*/
bool ti99_gkracker_device::is_grom_idle()
{
- return (m_cartridge != nullptr)? m_cartridge->is_grom_idle() : false;
+ return m_cartridge->is_grom_idle();
}
void ti99_gkracker_device::readz(offs_t offset, uint8_t *value)
@@ -221,25 +221,19 @@ void ti99_gkracker_device::readz(offs_t offset, uint8_t *value)
}
// If the guest has GROMs or ROMs they will override the GK contents
- if (m_cartridge != nullptr)
- {
- // For debugging
- uint8_t val1 = *value;
+ // For debugging
+ uint8_t val1 = *value;
- // Read from the guest cartridge.
- m_cartridge->readz(offset, value);
- if (val1 != *value)
- LOGMASKED(LOG_GKRACKER, "Read (from guest) %04x -> %02x\n", offset, *value);
- }
+ // Read from the guest cartridge.
+ m_cartridge->readz(offset, value);
+ if (val1 != *value)
+ LOGMASKED(LOG_GKRACKER, "Read (from guest) %04x -> %02x\n", offset, *value);
}
void ti99_gkracker_device::write(offs_t offset, uint8_t data)
{
// write to the guest cartridge if present
- if (m_cartridge != nullptr)
- {
- m_cartridge->write(offset, data);
- }
+ m_cartridge->write(offset, data);
if (m_grom_selected)
{
@@ -307,12 +301,12 @@ void ti99_gkracker_device::write(offs_t offset, uint8_t data)
void ti99_gkracker_device::crureadz(offs_t offset, uint8_t *value)
{
- if (m_cartridge != nullptr) m_cartridge->crureadz(offset, value);
+ m_cartridge->crureadz(offset, value);
}
void ti99_gkracker_device::cruwrite(offs_t offset, uint8_t data)
{
- if (m_cartridge != nullptr) m_cartridge->cruwrite(offset, data);
+ m_cartridge->cruwrite(offset, data);
}
INPUT_CHANGED_MEMBER( ti99_gkracker_device::gk_changed )
@@ -321,21 +315,6 @@ INPUT_CHANGED_MEMBER( ti99_gkracker_device::gk_changed )
m_gk_switch[param & 0x07] = newval;
}
-void ti99_gkracker_device::insert(int index, ti99_cartridge_device* cart)
-{
- LOGMASKED(LOG_CHANGE, "Insert cartridge\n");
- m_cartridge = cart;
- // Switch 1 has a third location for resetting. We do the reset by default
- // here. It can be turned off in the configuration.
- m_gromport->cartridge_inserted();
-}
-
-void ti99_gkracker_device::remove(int index)
-{
- LOGMASKED(LOG_CHANGE, "Remove cartridge\n");
- m_cartridge = nullptr;
-}
-
void ti99_gkracker_device::gk_install_menu(const char* menutext, int len, int ptr, int next, int start)
{
const int base = 0x0000;
@@ -378,8 +357,8 @@ void ti99_gkracker_device::nvram_default()
bool ti99_gkracker_device::nvram_read(util::read_stream &file)
{
- size_t readsize;
- if (file.read(m_ram_ptr, 81920, readsize))
+ auto const [err, readsize] = util::read(file, m_ram_ptr, 81920);
+ if (err)
return false;
LOGMASKED(LOG_GKRACKER, "Reading NVRAM\n");
// If we increased the size, fill the remaining parts with 0
@@ -393,15 +372,16 @@ bool ti99_gkracker_device::nvram_read(util::read_stream &file)
bool ti99_gkracker_device::nvram_write(util::write_stream &file)
{
LOGMASKED(LOG_GKRACKER, "Writing NVRAM\n");
- size_t writesize;
- return !file.write(m_ram_ptr, 81920, writesize) && writesize == 81920;
+ auto const [err, writesize] = util::write(file, m_ram_ptr, 81920);
+ return !err;
}
void ti99_gkracker_device::device_start()
{
m_ram_ptr = memregion(GKRACKER_NVRAM_TAG)->base();
m_grom_ptr = memregion(GKRACKER_ROM_TAG)->base();
- m_cartridge = nullptr;
+ m_cartridge->set_connector(this);
+
for (int i=1; i < 6; i++) m_gk_switch[i] = 0;
save_pointer(NAME(m_gk_switch),6);
save_item(NAME(m_romspace_selected));
@@ -439,7 +419,7 @@ const tiny_rom_entry *ti99_gkracker_device::device_rom_region() const
void ti99_gkracker_device::device_add_mconfig(machine_config &config)
{
- TI99_CART(config, "cartridge", 0);
+ TI99_CART(config, m_cartridge, 0);
}
INPUT_PORTS_START(gkracker)
diff --git a/src/devices/bus/ti99/gromport/gkracker.h b/src/devices/bus/ti99/gromport/gkracker.h
index 76bc457a11e..79efe94544c 100644
--- a/src/devices/bus/ti99/gromport/gkracker.h
+++ b/src/devices/bus/ti99/gromport/gkracker.h
@@ -21,13 +21,11 @@ public:
void write(offs_t offset, uint8_t data) override;
void crureadz(offs_t offset, uint8_t *value) override;
void cruwrite(offs_t offset, uint8_t data) override;
- DECLARE_WRITE_LINE_MEMBER(romgq_line) override;
+ void romgq_line(int state) override;
void set_gromlines(line_state mline, line_state moline, line_state gsq) override;
- DECLARE_WRITE_LINE_MEMBER(gclock_in) override;
+ void gclock_in(int state) override;
- void insert(int index, ti99_cartridge_device* cart) override;
- void remove(int index) override;
DECLARE_INPUT_CHANGED_MEMBER( gk_changed );
// We may have a cartridge plugged into the GK
@@ -57,7 +55,7 @@ private:
bool m_waddr_LSB;
- ti99_cartridge_device *m_cartridge; // guest cartridge
+ required_device<ti99_cartridge_device> m_cartridge;
// Just for proper initialization
void gk_install_menu(const char* menutext, int len, int ptr, int next, int start);
diff --git a/src/devices/bus/ti99/gromport/gromport.cpp b/src/devices/bus/ti99/gromport/gromport.cpp
index 1a53362416c..6204c9b5af1 100644
--- a/src/devices/bus/ti99/gromport/gromport.cpp
+++ b/src/devices/bus/ti99/gromport/gromport.cpp
@@ -114,11 +114,11 @@
#include "multiconn.h"
#include "gkracker.h"
-#define LOG_WARN (1U<<1) // Warnings
-#define LOG_READ (1U<<2) // Reading
-#define LOG_WRITE (1U<<3) // Writing
+#define LOG_WARN (1U << 1) // Warnings
+#define LOG_READ (1U << 2) // Reading
+#define LOG_WRITE (1U << 3) // Writing
-#define VERBOSE ( LOG_WARN )
+#define VERBOSE (LOG_WARN)
#include "logmacro.h"
DEFINE_DEVICE_TYPE(TI99_GROMPORT, bus::ti99::gromport::gromport_device, "gromport", "TI-99 Cartridge port")
@@ -127,7 +127,7 @@ namespace bus::ti99::gromport {
gromport_device::gromport_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, TI99_GROMPORT, tag, owner, clock),
- device_slot_interface(mconfig, *this),
+ device_single_card_slot_interface<cartridge_connector_device>(mconfig, *this),
m_connector(nullptr),
m_reset_on_insert(true),
m_console_ready(*this),
@@ -173,7 +173,7 @@ void gromport_device::cruwrite(offs_t offset, uint8_t data)
m_connector->cruwrite(offset, data);
}
-WRITE_LINE_MEMBER(gromport_device::ready_line)
+void gromport_device::ready_line(int state)
{
m_console_ready(state);
}
@@ -181,14 +181,14 @@ WRITE_LINE_MEMBER(gromport_device::ready_line)
/*
Asserted when the console addresses cartridge rom.
*/
-WRITE_LINE_MEMBER(gromport_device::romgq_line)
+void gromport_device::romgq_line(int state)
{
m_romgq = state;
if (m_connector != nullptr)
m_connector->romgq_line(state);
}
-WRITE_LINE_MEMBER(gromport_device::gclock_in)
+void gromport_device::gclock_in(int state)
{
if (m_connector != nullptr)
m_connector->gclock_in(state);
@@ -205,10 +205,9 @@ void gromport_device::set_gromlines(line_state mline, line_state moline, line_st
void gromport_device::device_start()
{
- m_console_ready.resolve();
- m_console_reset.resolve();
-
save_item(NAME(m_romgq));
+ if (m_connector != nullptr)
+ m_connector->set_port(this);
}
void gromport_device::device_reset()
@@ -246,7 +245,7 @@ bool gromport_device::is_grom_idle()
void gromport_device::device_config_complete()
{
- m_connector = downcast<cartridge_connector_device*>(subdevices().first());
+ m_connector = get_card_device();
}
INPUT_PORTS_START(gromport)
@@ -278,16 +277,11 @@ cartridge_connector_device::cartridge_connector_device(const machine_config &mco
{
}
-WRITE_LINE_MEMBER( cartridge_connector_device::ready_line )
+void cartridge_connector_device::ready_line(int state)
{
m_gromport->ready_line(state);
}
-void cartridge_connector_device::device_config_complete()
-{
- m_gromport = static_cast<gromport_device*>(owner());
-}
-
} // end namespace bus::ti99::gromport
void ti99_gromport_options(device_slot_interface &device)
diff --git a/src/devices/bus/ti99/gromport/gromport.h b/src/devices/bus/ti99/gromport/gromport.h
index 74c844d7ed7..10c339e9128 100644
--- a/src/devices/bus/ti99/gromport/gromport.h
+++ b/src/devices/bus/ti99/gromport/gromport.h
@@ -25,7 +25,7 @@ struct pcb_type
class ti99_cartridge_device;
class cartridge_connector_device;
-class gromport_device : public device_t, public device_slot_interface
+class gromport_device : public device_t, public device_single_card_slot_interface<cartridge_connector_device>
{
public:
template <typename U>
@@ -44,10 +44,10 @@ public:
void write(offs_t offset, uint8_t data);
void crureadz(offs_t offset, uint8_t *value);
void cruwrite(offs_t offset, uint8_t data);
- DECLARE_WRITE_LINE_MEMBER(ready_line);
- DECLARE_WRITE_LINE_MEMBER(romgq_line);
+ void ready_line(int state);
+ void romgq_line(int state);
void set_gromlines(line_state mline, line_state moline, line_state gsq);
- DECLARE_WRITE_LINE_MEMBER(gclock_in);
+ void gclock_in(int state);
void cartridge_inserted();
bool is_grom_idle();
@@ -59,10 +59,10 @@ public:
gromport_device& extend() { m_mask = 0x3fff; return *this; }
protected:
- void device_start() override;
- void device_reset() override;
- void device_config_complete() override;
- ioport_constructor device_input_ports() const override;
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void device_config_complete() override;
+ virtual ioport_constructor device_input_ports() const override;
private:
cartridge_connector_device* m_connector;
@@ -75,6 +75,8 @@ private:
class cartridge_connector_device : public device_t
{
+ friend class gromport_device;
+
public:
virtual void readz(offs_t offset, uint8_t *value) = 0;
virtual void write(offs_t offset, uint8_t data) = 0;
@@ -83,23 +85,24 @@ public:
virtual void crureadz(offs_t offset, uint8_t *value) = 0;
virtual void cruwrite(offs_t offset, uint8_t data) = 0;
- virtual DECLARE_WRITE_LINE_MEMBER(romgq_line) = 0;
+ virtual void romgq_line(int state) = 0;
virtual void set_gromlines(line_state mline, line_state moline, line_state gsq) =0;
- virtual DECLARE_WRITE_LINE_MEMBER(gclock_in) = 0;
+ virtual void gclock_in(int state) = 0;
- DECLARE_WRITE_LINE_MEMBER(ready_line);
+ void ready_line(int state);
- virtual void insert(int index, bus::ti99::gromport::ti99_cartridge_device* cart) { m_gromport->cartridge_inserted(); }
- virtual void remove(int index) { }
+ virtual void insert() { m_gromport->cartridge_inserted(); }
+ virtual void remove() { }
virtual bool is_grom_idle() = 0;
protected:
cartridge_connector_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
- virtual void device_config_complete() override;
gromport_device* m_gromport;
bool m_grom_selected;
+
+ void set_port(gromport_device* gromport) { m_gromport = gromport; }
};
} // end namespace bus::ti99::gromport
diff --git a/src/devices/bus/ti99/gromport/multiconn.cpp b/src/devices/bus/ti99/gromport/multiconn.cpp
index 595a6ab1a29..415fc7c3873 100644
--- a/src/devices/bus/ti99/gromport/multiconn.cpp
+++ b/src/devices/bus/ti99/gromport/multiconn.cpp
@@ -43,9 +43,9 @@
#include "emu.h"
#include "multiconn.h"
-#define LOG_WARN (1U<<1)
-#define LOG_CHANGE (1U<<2)
-#define VERBOSE ( LOG_WARN )
+#define LOG_WARN (1U << 1)
+#define LOG_CHANGE (1U << 2)
+#define VERBOSE (LOG_GENERAL | LOG_WARN)
#include "logmacro.h"
@@ -59,7 +59,8 @@ ti99_multi_cart_conn_device::ti99_multi_cart_conn_device(const machine_config &m
: cartridge_connector_device(mconfig, TI99_GROMPORT_MULTI, tag, owner, clock),
m_active_slot(0),
m_fixed_slot(0),
- m_next_free_slot(0)
+ m_next_free_slot(0),
+ m_cart(*this, "%u", 1)
{
}
@@ -124,31 +125,13 @@ int ti99_multi_cart_conn_device::get_active_slot(bool changebase, offs_t offset)
return slot;
}
-void ti99_multi_cart_conn_device::insert(int index, ti99_cartridge_device* cart)
-{
- LOGMASKED(LOG_CHANGE, "Insert slot %d\n", index);
- m_cartridge[index] = cart;
- m_gromport->cartridge_inserted();
-}
-
-void ti99_multi_cart_conn_device::remove(int index)
-{
- LOGMASKED(LOG_CHANGE, "Remove slot %d\n", index);
- m_cartridge[index] = nullptr;
-}
-
-WRITE_LINE_MEMBER(ti99_multi_cart_conn_device::romgq_line)
+void ti99_multi_cart_conn_device::romgq_line(int state)
{
m_readrom = state;
// Propagate to all slots
- for (int i=0; i < NUMBER_OF_CARTRIDGE_SLOTS; i++)
- {
- if (m_cartridge[i] != nullptr)
- {
- m_cartridge[i]->romgq_line(state);
- }
- }
+ for (auto &cart : m_cart)
+ cart->romgq_line(state);
}
/*
@@ -159,26 +142,14 @@ void ti99_multi_cart_conn_device::set_gromlines(line_state mline, line_state mol
// GROM selected?
m_grom_selected = (gsq == ASSERT_LINE);
- // Propagate to all slots
- for (int i=0; i < NUMBER_OF_CARTRIDGE_SLOTS; i++)
- {
- if (m_cartridge[i] != nullptr)
- {
- m_cartridge[i]->set_gromlines(mline, moline, gsq);
- }
- }
+ for (auto &cart : m_cart)
+ cart->set_gromlines(mline, moline, gsq);
}
-WRITE_LINE_MEMBER(ti99_multi_cart_conn_device::gclock_in)
+void ti99_multi_cart_conn_device::gclock_in(int state)
{
- // Propagate to all slots
- for (int i=0; i < NUMBER_OF_CARTRIDGE_SLOTS; i++)
- {
- if (m_cartridge[i] != nullptr)
- {
- m_cartridge[i]->gclock_in(state);
- }
- }
+ for (auto &cart : m_cart)
+ cart->gclock_in(state);
}
void ti99_multi_cart_conn_device::readz(offs_t offset, uint8_t *value)
@@ -192,23 +163,16 @@ void ti99_multi_cart_conn_device::readz(offs_t offset, uint8_t *value)
{
for (int i=0; i < NUMBER_OF_CARTRIDGE_SLOTS; i++)
{
- if (m_cartridge[i] != nullptr)
- {
- uint8_t newval = *value;
- m_cartridge[i]->readz(offset, &newval);
- if (i==slot)
- {
- *value = newval;
- }
- }
+ uint8_t newval = *value;
+ m_cart[i]->readz(offset, &newval);
+ if (i==slot)
+ *value = newval;
}
}
else
{
- if (slot < NUMBER_OF_CARTRIDGE_SLOTS && m_cartridge[slot] != nullptr)
- {
- m_cartridge[slot]->readz(offset, value);
- }
+ if (slot < NUMBER_OF_CARTRIDGE_SLOTS)
+ m_cart[slot]->readz(offset, value);
}
}
@@ -218,50 +182,32 @@ void ti99_multi_cart_conn_device::write(offs_t offset, uint8_t data)
// We don't have GRAM cartridges, anyway, so it's just used for setting the address.
if (m_grom_selected)
{
- for (auto & elem : m_cartridge)
- {
- if (elem != nullptr)
- {
- elem->write(offset, data);
- }
- }
+ for (auto &cart : m_cart)
+ cart->write(offset, data);
}
else
{
int slot = get_active_slot(true, offset);
- if (slot < NUMBER_OF_CARTRIDGE_SLOTS && m_cartridge[slot] != nullptr)
- {
+ if (slot < NUMBER_OF_CARTRIDGE_SLOTS)
// logerror("writing %04x (slot %d) <- %02x\n", offset, slot, data);
- m_cartridge[slot]->write(offset, data);
- }
+ m_cart[slot]->write(offset, data);
}
}
void ti99_multi_cart_conn_device::crureadz(offs_t offset, uint8_t *value)
{
int slot = get_active_slot(false, offset);
- /* Sanity check. Higher slots are always empty. */
- if (slot >= NUMBER_OF_CARTRIDGE_SLOTS)
- return;
-
- if (m_cartridge[slot] != nullptr)
- {
- m_cartridge[slot]->crureadz(offset, value);
- }
+ // Sanity check. Higher slots are always empty.
+ if (slot < NUMBER_OF_CARTRIDGE_SLOTS)
+ m_cart[slot]->crureadz(offset, value);
}
void ti99_multi_cart_conn_device::cruwrite(offs_t offset, uint8_t data)
{
- int slot = get_active_slot(true, offset);
-
- /* Sanity check. Higher slots are always empty. */
- if (slot >= NUMBER_OF_CARTRIDGE_SLOTS)
- return;
+ int slot = get_active_slot(false, offset);
- if (m_cartridge[slot] != nullptr)
- {
- m_cartridge[slot]->cruwrite(offset, data);
- }
+ if (slot < NUMBER_OF_CARTRIDGE_SLOTS)
+ m_cart[slot]->cruwrite(offset, data);
}
/*
@@ -270,12 +216,9 @@ void ti99_multi_cart_conn_device::cruwrite(offs_t offset, uint8_t data)
*/
bool ti99_multi_cart_conn_device::is_grom_idle()
{
- /* Sanity check. Higher slots are always empty. */
- if (m_active_slot >= NUMBER_OF_CARTRIDGE_SLOTS)
- return false;
-
- if (m_cartridge[m_active_slot] != nullptr)
- return m_cartridge[m_active_slot]->is_grom_idle();
+ // Sanity check. Higher slots are always empty.
+ if (m_active_slot < NUMBER_OF_CARTRIDGE_SLOTS)
+ return m_cart[m_active_slot]->is_grom_idle();
return false;
}
@@ -284,14 +227,14 @@ void ti99_multi_cart_conn_device::device_start()
{
m_next_free_slot = 0;
m_active_slot = 0;
- for (auto & elem : m_cartridge)
- {
- elem = nullptr;
- }
+
save_item(NAME(m_readrom));
save_item(NAME(m_active_slot));
save_item(NAME(m_fixed_slot));
save_item(NAME(m_next_free_slot));
+
+ for (auto &cart : m_cart)
+ cart->set_connector(this);
}
void ti99_multi_cart_conn_device::device_reset(void)
@@ -303,10 +246,8 @@ void ti99_multi_cart_conn_device::device_reset(void)
void ti99_multi_cart_conn_device::device_add_mconfig(machine_config &config)
{
- TI99_CART(config, "cartridge1", 0);
- TI99_CART(config, "cartridge2", 0);
- TI99_CART(config, "cartridge3", 0);
- TI99_CART(config, "cartridge4", 0);
+ for (int i=0; i < NUMBER_OF_CARTRIDGE_SLOTS; i++)
+ TI99_CART(config, m_cart[i], 0);
}
INPUT_CHANGED_MEMBER( ti99_multi_cart_conn_device::switch_changed )
diff --git a/src/devices/bus/ti99/gromport/multiconn.h b/src/devices/bus/ti99/gromport/multiconn.h
index 517224eff14..1767461b82f 100644
--- a/src/devices/bus/ti99/gromport/multiconn.h
+++ b/src/devices/bus/ti99/gromport/multiconn.h
@@ -26,30 +26,28 @@ public:
void write(offs_t offset, uint8_t data) override;
void crureadz(offs_t offset, uint8_t *value) override;
void cruwrite(offs_t offset, uint8_t data) override;
- DECLARE_WRITE_LINE_MEMBER(romgq_line) override;
+ void romgq_line(int state) override;
void set_gromlines(line_state mline, line_state moline, line_state gsq) override;
- DECLARE_WRITE_LINE_MEMBER(gclock_in) override;
+ void gclock_in(int state) override;
- void insert(int index, ti99_cartridge_device* cart) override;
- void remove(int index) override;
DECLARE_INPUT_CHANGED_MEMBER( switch_changed );
bool is_grom_idle() override;
protected:
- static constexpr unsigned NUMBER_OF_CARTRIDGE_SLOTS = 4;
-
virtual void device_start() override;
virtual void device_reset() override;
virtual void device_add_mconfig(machine_config &config) override;
virtual ioport_constructor device_input_ports() const override;
private:
+ static constexpr unsigned NUMBER_OF_CARTRIDGE_SLOTS = 4;
bool m_readrom;
int m_active_slot;
int m_fixed_slot;
int m_next_free_slot;
- ti99_cartridge_device* m_cartridge[NUMBER_OF_CARTRIDGE_SLOTS];
+
+ required_device_array<ti99_cartridge_device,NUMBER_OF_CARTRIDGE_SLOTS> m_cart;
void set_slot(int slotnumber);
int get_active_slot(bool changebase, offs_t offset);
diff --git a/src/devices/bus/ti99/gromport/singleconn.cpp b/src/devices/bus/ti99/gromport/singleconn.cpp
index e24a3ba416a..d5b1b8a897e 100644
--- a/src/devices/bus/ti99/gromport/singleconn.cpp
+++ b/src/devices/bus/ti99/gromport/singleconn.cpp
@@ -15,7 +15,7 @@ namespace bus::ti99::gromport {
ti99_single_cart_conn_device::ti99_single_cart_conn_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: cartridge_connector_device(mconfig, TI99_GROMPORT_SINGLE, tag, owner, clock),
- m_cartridge(nullptr)
+ m_cartridge(*this, "cartridge")
{
}
@@ -43,7 +43,7 @@ void ti99_single_cart_conn_device::cruwrite(offs_t offset, uint8_t data)
m_cartridge->cruwrite(offset, data);
}
-WRITE_LINE_MEMBER(ti99_single_cart_conn_device::romgq_line)
+void ti99_single_cart_conn_device::romgq_line(int state)
{
// Pass through
m_cartridge->romgq_line(state);
@@ -59,7 +59,7 @@ void ti99_single_cart_conn_device::set_gromlines(line_state mline, line_state mo
}
-WRITE_LINE_MEMBER(ti99_single_cart_conn_device::gclock_in)
+void ti99_single_cart_conn_device::gclock_in(int state)
{
// Pass through
m_cartridge->gclock_in(state);
@@ -73,19 +73,10 @@ bool ti99_single_cart_conn_device::is_grom_idle()
return m_cartridge->is_grom_idle();
}
-void ti99_single_cart_conn_device::device_start()
-{
- m_cartridge = static_cast<ti99_cartridge_device*>(subdevices().first());
-}
-
-void ti99_single_cart_conn_device::device_reset()
-{
- m_cartridge->set_slot(0);
-}
-
void ti99_single_cart_conn_device::device_add_mconfig(machine_config &config)
{
- TI99_CART(config, "cartridge", 0);
+ TI99_CART(config, m_cartridge, 0);
+ m_cartridge->set_connector(this);
}
} // end namespace bus::ti99::gromport
diff --git a/src/devices/bus/ti99/gromport/singleconn.h b/src/devices/bus/ti99/gromport/singleconn.h
index 40627a07867..c368e37683c 100644
--- a/src/devices/bus/ti99/gromport/singleconn.h
+++ b/src/devices/bus/ti99/gromport/singleconn.h
@@ -22,19 +22,18 @@ public:
void write(offs_t offset, uint8_t data) override;
void crureadz(offs_t offset, uint8_t *value) override;
void cruwrite(offs_t offset, uint8_t data) override;
- DECLARE_WRITE_LINE_MEMBER(romgq_line) override;
+ void romgq_line(int state) override;
void set_gromlines(line_state mline, line_state moline, line_state gsq) override;
- DECLARE_WRITE_LINE_MEMBER(gclock_in) override;
+ void gclock_in(int state) override;
bool is_grom_idle() override;
protected:
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override { };
virtual void device_add_mconfig(machine_config &config) override;
private:
- ti99_cartridge_device *m_cartridge;
+ required_device<ti99_cartridge_device> m_cartridge;
};
} // end namespace bus::ti99::gromport
diff --git a/src/devices/bus/ti99/internal/992board.cpp b/src/devices/bus/ti99/internal/992board.cpp
index 7dae38759ee..23274d08291 100644
--- a/src/devices/bus/ti99/internal/992board.cpp
+++ b/src/devices/bus/ti99/internal/992board.cpp
@@ -19,13 +19,13 @@
#include "emu.h"
#include "992board.h"
-#define LOG_WARN (1U<<1) // Warnings
-#define LOG_CRU (1U<<2) // CRU logging
-#define LOG_CASSETTE (1U<<3) // Cassette logging
-#define LOG_HEXBUS (1U<<4) // Hexbus logging
-#define LOG_BANK (1U<<5) // Change ROM banks
-#define LOG_KEYBOARD (1U<<6) // Keyboard operation
-#define LOG_EXPRAM (1U<<7) // Expansion RAM
+#define LOG_WARN (1U << 1) // Warnings
+#define LOG_CRU (1U << 2) // CRU logging
+#define LOG_CASSETTE (1U << 3) // Cassette logging
+#define LOG_HEXBUS (1U << 4) // Hexbus logging
+#define LOG_BANK (1U << 5) // Change ROM banks
+#define LOG_KEYBOARD (1U << 6) // Keyboard operation
+#define LOG_EXPRAM (1U << 7) // Expansion RAM
#define VERBOSE (LOG_GENERAL | LOG_WARN)
@@ -139,13 +139,13 @@ DEFINE_DEVICE_TYPE(TI992_RAM32K, bus::ti99::internal::ti992_expram_device, "ti99
namespace bus::ti99::internal {
-video992_device::video992_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, type, tag, owner, clock),
- device_video_interface(mconfig, *this),
- m_mem_read_cb(*this),
- m_hold_cb(*this),
- m_int_cb(*this),
- m_videna(true)
+video992_device::video992_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, type, tag, owner, clock),
+ device_video_interface(mconfig, *this),
+ m_mem_read_cb(*this, 0),
+ m_hold_cb(*this),
+ m_int_cb(*this),
+ m_videna(true)
{
}
@@ -161,24 +161,11 @@ video992_32_device::video992_32_device(const machine_config &mconfig, const char
m_beol = 0x7f;
}
-std::string video992_device::tts(attotime t)
-{
- char buf[256];
- const char *sign = "";
- if (t.seconds() < 0) {
- t = attotime::zero - t;
- sign = "-";
- }
- int nsec = t.attoseconds() / ATTOSECONDS_PER_NANOSECOND;
- sprintf(buf, "%s%04d.%03d,%03d,%03d", sign, int(t.seconds()), nsec / 1000000, (nsec / 1000) % 1000, nsec % 1000);
- return buf;
-}
-
TIMER_CALLBACK_MEMBER(video992_device::hold_cpu)
{
int raw_vpos = screen().vpos();
- // logerror("release time: %s, diff: %s\n", tts(machine().time()), tts(machine().time()-m_hold_time));
+ LOG("release time: %s, diff: %s\n", machine().time().to_string(), (machine().time()-m_hold_time).to_string());
// We're holding the CPU; release it until the next start
m_hold_cb(CLEAR_LINE);
m_free_timer->adjust(screen().time_until_pos((raw_vpos+1) % screen().height(), HORZ_DISPLAY_START));
@@ -188,7 +175,7 @@ TIMER_CALLBACK_MEMBER(video992_device::free_cpu)
{
int raw_vpos = screen().vpos();
- // logerror("hold time: %s\n", tts(machine().time()));
+ LOG("hold time: %s\n", machine().time().to_string());
if (m_videna)
{
// Hold the CPU
@@ -207,7 +194,7 @@ TIMER_CALLBACK_MEMBER(video992_device::free_cpu)
int linelength = 0;
- // logerror("draw line %d\n", vpos);
+ LOG("draw line %d\n", vpos);
// Get control byte
uint8_t control = m_mem_read_cb(0xef00);
bool text_white = BIT(control, 2);
@@ -277,7 +264,7 @@ TIMER_CALLBACK_MEMBER(video992_device::free_cpu)
}
// +1 for the minimum hold time
- // logerror("line length: %d\n", linelength);
+ LOG("line length: %d\n", linelength);
m_hold_timer->adjust(screen().time_until_pos(raw_vpos, HORZ_DISPLAY_START + linelength * 8 + 1));
}
@@ -291,7 +278,7 @@ uint32_t video992_device::screen_update(screen_device &screen, bitmap_rgb32 &bit
/*
VIDENA pin, positive logic
*/
-WRITE_LINE_MEMBER(video992_device::videna)
+void video992_device::videna(int state)
{
m_videna = state;
}
@@ -308,10 +295,6 @@ void video992_device::device_start()
m_border_color = rgb_t::black();
m_background_color = rgb_t::white();
m_text_color = rgb_t::black();
-
- m_mem_read_cb.resolve();
- m_hold_cb.resolve();
- m_int_cb.resolve();
}
void video992_device::device_reset()
@@ -457,8 +440,6 @@ void io992_device::device_start()
// Establish callback for inbound propagations
m_hexbus_outbound->set_chain_element(this);
-
- m_set_rom_bank.resolve();
}
uint8_t io992_device::cruread(offs_t offset)
@@ -610,7 +591,7 @@ ioport_constructor io992_device::device_input_ports() const
ti992_expport_device::ti992_expport_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, TI992_EXPPORT, tag, owner, clock),
- device_slot_interface(mconfig, *this),
+ device_single_card_slot_interface<ti992_expport_attached_device>(mconfig, *this),
m_connected(nullptr)
{
}
@@ -629,7 +610,7 @@ void ti992_expport_device::write(offs_t offset, uint8_t data)
void ti992_expport_device::device_config_complete()
{
- m_connected = static_cast<ti992_expport_attached_device*>(subdevices().first());
+ m_connected = get_card_device();
}
/*
diff --git a/src/devices/bus/ti99/internal/992board.h b/src/devices/bus/ti99/internal/992board.h
index 5a6ab8b5a8f..41c198a8e5d 100644
--- a/src/devices/bus/ti99/internal/992board.h
+++ b/src/devices/bus/ti99/internal/992board.h
@@ -46,7 +46,7 @@ public:
uint32_t screen_update( screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect );
// Video enable
- DECLARE_WRITE_LINE_MEMBER( videna );
+ void videna(int state);
// Callbacks
auto readmem_cb() { return m_mem_read_cb.bind(); }
@@ -64,7 +64,6 @@ protected:
TIMER_CALLBACK_MEMBER(free_cpu);
private:
- std::string tts(attotime t);
devcb_read8 m_mem_read_cb; // Callback to read memory
devcb_write_line m_hold_cb;
devcb_write_line m_int_cb;
@@ -175,10 +174,8 @@ public:
virtual void write(offs_t offset, uint8_t data) { }
};
-class ti992_expport_device : public device_t, public device_slot_interface
+class ti992_expport_device : public device_t, public device_single_card_slot_interface<ti992_expport_attached_device>
{
- friend class expport_attached_device;
-
public:
template <typename U>
ti992_expport_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, U &&opts, const char *dflt)
diff --git a/src/devices/bus/ti99/internal/998board.cpp b/src/devices/bus/ti99/internal/998board.cpp
index bebd7762ec4..684c531895d 100644
--- a/src/devices/bus/ti99/internal/998board.cpp
+++ b/src/devices/bus/ti99/internal/998board.cpp
@@ -107,24 +107,24 @@
#include "998board.h"
#include "cpu/tms9900/tms99com.h"
-#define LOG_DETAIL (1U<<1) // More detail
-#define LOG_CRU (1U<<2) // CRU logging
-#define LOG_ADDRESS (1U<<3) // Address bus
-#define LOG_MEM (1U<<4) // Memory access
-#define LOG_MAP (1U<<5) // Mapper
-#define LOG_READY (1U<<6) // READY line
-#define LOG_CLOCK (1U<<7) // CLKOUT
-#define LOG_MOFETTA (1U<<8) // Mofetta operation
-#define LOG_AMIGO (1U<<9) // Amigo operation
-#define LOG_OSO (1U<<10) // Oso operation
-#define LOG_HEXBUS (1U<<11) // Hexbus operation
-#define LOG_WS (1U<<12) // Wait states
-#define LOG_CPURY (1U<<13) // Combined ready line
-#define LOG_GROM (1U<<14) // GROM operation
-#define LOG_PUNMAP (1U<<15) // Unmapped physical addresss
-#define LOG_WARN (1U<<31) // Warnings
-
-#define VERBOSE ( LOG_WARN )
+#define LOG_DETAIL (1U << 1) // More detail
+#define LOG_CRU (1U << 2) // CRU logging
+#define LOG_ADDRESS (1U << 3) // Address bus
+#define LOG_MEM (1U << 4) // Memory access
+#define LOG_MAP (1U << 5) // Mapper
+#define LOG_READY (1U << 6) // READY line
+#define LOG_CLOCK (1U << 7) // CLKOUT
+#define LOG_MOFETTA (1U << 8) // Mofetta operation
+#define LOG_AMIGO (1U << 9) // Amigo operation
+#define LOG_OSO (1U << 10) // Oso operation
+#define LOG_HEXBUS (1U << 11) // Hexbus operation
+#define LOG_WS (1U << 12) // Wait states
+#define LOG_CPURY (1U << 13) // Combined ready line
+#define LOG_GROM (1U << 14) // GROM operation
+#define LOG_PUNMAP (1U << 15) // Unmapped physical addresss
+#define LOG_WARN (1U << 31) // Warnings
+
+#define VERBOSE (LOG_WARN)
#include "logmacro.h"
@@ -414,12 +414,12 @@ void mainboard8_device::setaddress(offs_t offset, uint8_t busctrl)
m_ready(m_amigo->cpury_out());
}
-WRITE_LINE_MEMBER( mainboard8_device::reset_console )
+void mainboard8_device::reset_console(int state)
{
m_console_reset(state);
}
-WRITE_LINE_MEMBER( mainboard8_device::hold_cpu )
+void mainboard8_device::hold_cpu(int state)
{
m_hold_line(state);
}
@@ -427,7 +427,7 @@ WRITE_LINE_MEMBER( mainboard8_device::hold_cpu )
/*
HOLD Acknowledge from the CPU
*/
-WRITE_LINE_MEMBER( mainboard8_device::holda_line )
+void mainboard8_device::holda_line(int state)
{
m_amigo->holda_in(state);
}
@@ -435,7 +435,7 @@ WRITE_LINE_MEMBER( mainboard8_device::holda_line )
/*
Clock line from the CPU. Forward to the custom chips.
*/
-WRITE_LINE_MEMBER( mainboard8_device::clock_in )
+void mainboard8_device::clock_in(int state)
{
LOGMASKED(LOG_CLOCK, "CLKOUT = %d\n", state);
@@ -686,7 +686,7 @@ void mainboard8_device::set_paddress(int address)
m_ioport->setaddress_dbin(address, m_dbin_level);
}
-WRITE_LINE_MEMBER( mainboard8_device::msast_in )
+void mainboard8_device::msast_in(int state)
{
LOGMASKED(LOG_DETAIL, "msast = %d\n", state);
@@ -960,7 +960,7 @@ void mainboard8_device::write(offs_t offset, uint8_t data)
/*
Set 99/4A compatibility mode (CRUS=1)
*/
-WRITE_LINE_MEMBER( mainboard8_device::crus_in )
+void mainboard8_device::crus_in(int state)
{
LOGMASKED(LOG_CRU, "%s CRUS\n", (state==1)? "Assert" : "Clear");
m_vaquerro->crus_in(state);
@@ -972,7 +972,7 @@ WRITE_LINE_MEMBER( mainboard8_device::crus_in )
Set mapper /PTGEN line ("Pascal and Text-to-speech GROMs enable").
Note that PTGEN is negative logic.
*/
-WRITE_LINE_MEMBER( mainboard8_device::ptgen_in )
+void mainboard8_device::ptgen_in(int state)
{
LOGMASKED(LOG_CRU, "%s PTGEN*\n", (state==0)? "Assert" : "Clear");
m_vaquerro->crusgl_in((state==0)? ASSERT_LINE : CLEAR_LINE);
@@ -982,54 +982,49 @@ WRITE_LINE_MEMBER( mainboard8_device::ptgen_in )
/*
READY lines, to be combined
*/
-WRITE_LINE_MEMBER( mainboard8_device::system_grom_ready )
+void mainboard8_device::system_grom_ready(int state)
{
m_vaquerro->sgmry(state);
}
-WRITE_LINE_MEMBER( mainboard8_device::ptts_grom_ready )
+void mainboard8_device::ptts_grom_ready(int state)
{
m_vaquerro->tsgry(state);
}
-WRITE_LINE_MEMBER( mainboard8_device::p8_grom_ready )
+void mainboard8_device::p8_grom_ready(int state)
{
m_vaquerro->p8gry(state);
}
-WRITE_LINE_MEMBER( mainboard8_device::p3_grom_ready )
+void mainboard8_device::p3_grom_ready(int state)
{
m_vaquerro->p3gry(state);
}
-WRITE_LINE_MEMBER( mainboard8_device::sound_ready )
+void mainboard8_device::sound_ready(int state)
{
m_sound_ready = state;
}
-WRITE_LINE_MEMBER( mainboard8_device::speech_ready )
+void mainboard8_device::speech_ready(int state)
{
// The TMS5200 implementation uses true/false, not ASSERT/CLEAR semantics
m_speech_ready = (state==false)? ASSERT_LINE : CLEAR_LINE;
}
-WRITE_LINE_MEMBER( mainboard8_device::pbox_ready )
+void mainboard8_device::pbox_ready(int state)
{
m_pbox_ready = state;
}
-WRITE_LINE_MEMBER( mainboard8_device::ggrdy_in )
+void mainboard8_device::ggrdy_in(int state)
{
m_amigo->srdy_in((state==ASSERT_LINE && m_speech_ready && m_sound_ready && m_pbox_ready)? ASSERT_LINE : CLEAR_LINE);
}
void mainboard8_device::device_start()
{
- // Lines going to the main driver class, then to the CPU
- m_ready.resolve_safe(); // READY
- m_console_reset.resolve_safe(); // RESET
- m_hold_line.resolve_safe(); // HOLD
-
m_rom0 = machine().root_device().memregion(TI998_ROM0_REG)->base();
m_rom1 = machine().root_device().memregion(TI998_ROM1_REG)->base();
m_pascalrom = machine().root_device().memregion(TI998_PASCAL_REG)->base();
@@ -1254,17 +1249,17 @@ void vaquerro_device::set_address(offs_t offset, int state)
}
}
-WRITE_LINE_MEMBER( vaquerro_device::crusgl_in )
+void vaquerro_device::crusgl_in(int state)
{
m_crugl = (state==ASSERT_LINE);
}
-WRITE_LINE_MEMBER( vaquerro_device::crus_in )
+void vaquerro_device::crus_in(int state)
{
m_crus = (line_state)state;
}
-WRITE_LINE_MEMBER( vaquerro_device::memen_in )
+void vaquerro_device::memen_in(int state)
{
m_memen = (state==ASSERT_LINE);
}
@@ -1272,7 +1267,7 @@ WRITE_LINE_MEMBER( vaquerro_device::memen_in )
/*
Called by Mofetta
*/
-READ_LINE_MEMBER( vaquerro_device::lascsq_out )
+int vaquerro_device::lascsq_out()
{
return (m_lasreq && m_memen)? ASSERT_LINE : CLEAR_LINE;
}
@@ -1280,25 +1275,25 @@ READ_LINE_MEMBER( vaquerro_device::lascsq_out )
/*
Incoming ready lines from the GROM library
*/
-WRITE_LINE_MEMBER( vaquerro_device::sgmry )
+void vaquerro_device::sgmry(int state)
{
LOGMASKED(LOG_READY, "Incoming SGMRY = %d\n", state);
m_sgmws.ready_in((line_state)state);
}
-WRITE_LINE_MEMBER( vaquerro_device::tsgry )
+void vaquerro_device::tsgry(int state)
{
LOGMASKED(LOG_READY, "Incoming TSGRY = %d\n", state);
m_tsgws.ready_in((line_state)state);
}
-WRITE_LINE_MEMBER( vaquerro_device::p8gry )
+void vaquerro_device::p8gry(int state)
{
LOGMASKED(LOG_READY, "Incoming 8GRY = %d\n", state);
m_p8gws.ready_in((line_state)state);
}
-WRITE_LINE_MEMBER( vaquerro_device::p3gry )
+void vaquerro_device::p3gry(int state)
{
LOGMASKED(LOG_READY, "Incoming P3GRY = %d\n", state);
m_p3gws.ready_in((line_state)state);
@@ -1307,7 +1302,7 @@ WRITE_LINE_MEMBER( vaquerro_device::p3gry )
/*
Outgoing READY
*/
-READ_LINE_MEMBER( vaquerro_device::ggrdy_out )
+int vaquerro_device::ggrdy_out()
{
LOGMASKED(LOG_READY, "GGRDY out = %d\n", m_ggrdy);
return m_ggrdy;
@@ -1326,32 +1321,32 @@ int vaquerro_device::gromcs_out()
// =========================
-READ_LINE_MEMBER( vaquerro_device::vdprd_out )
+int vaquerro_device::vdprd_out()
{
return (m_vdprd && m_memen)? ASSERT_LINE : CLEAR_LINE;
}
-READ_LINE_MEMBER( vaquerro_device::vdpwt_out )
+int vaquerro_device::vdpwt_out()
{
return (m_vdpwt && m_memen)? ASSERT_LINE : CLEAR_LINE;
}
-READ_LINE_MEMBER( vaquerro_device::sprd_out )
+int vaquerro_device::sprd_out()
{
return (m_sprd && m_memen)? ASSERT_LINE : CLEAR_LINE;
}
-READ_LINE_MEMBER( vaquerro_device::spwt_out )
+int vaquerro_device::spwt_out()
{
return (m_spwt && m_memen)? ASSERT_LINE : CLEAR_LINE;
}
-READ_LINE_MEMBER( vaquerro_device::sromcs_out )
+int vaquerro_device::sromcs_out()
{
return (m_sromcs && m_memen)? ASSERT_LINE : CLEAR_LINE;
}
-READ_LINE_MEMBER( vaquerro_device::sccs_out )
+int vaquerro_device::sccs_out()
{
return (m_sccs && m_memen)? ASSERT_LINE : CLEAR_LINE;
}
@@ -1366,7 +1361,7 @@ READ_LINE_MEMBER( vaquerro_device::sccs_out )
access occurs, the system READY line will be cleared, triggering wait
states in the CPU.
*/
-WRITE_LINE_MEMBER( vaquerro_device::clock_in )
+void vaquerro_device::clock_in(int state)
{
line_state level = (line_state)state;
@@ -1662,7 +1657,7 @@ void mofetta_device::set_address(offs_t offset, int state)
Mofetta delivers the GROMCLK. In the 99/4A, this clock is produced by the VDP.
Apart from that, Mofetta does not need the CLKOUT.
*/
-WRITE_LINE_MEMBER( mofetta_device::clock_in )
+void mofetta_device::clock_in(int state)
{
if (state == CLEAR_LINE) // TODO: Correct edge?
{
@@ -1675,37 +1670,37 @@ WRITE_LINE_MEMBER( mofetta_device::clock_in )
}
}
-READ_LINE_MEMBER( mofetta_device::alccs_out )
+int mofetta_device::alccs_out()
{
return (m_alccs && m_pmemen)? ASSERT_LINE : CLEAR_LINE;
}
-READ_LINE_MEMBER( mofetta_device::gromclk_out )
+int mofetta_device::gromclk_out()
{
return m_gromclk_up? ASSERT_LINE : CLEAR_LINE;
}
-READ_LINE_MEMBER( mofetta_device::rom1cs_out )
+int mofetta_device::rom1cs_out()
{
return (m_rom1cs && m_pmemen)? ASSERT_LINE : CLEAR_LINE;
}
-READ_LINE_MEMBER( mofetta_device::rom1am_out )
+int mofetta_device::rom1am_out()
{
return (m_rom1am && m_pmemen)? ASSERT_LINE : CLEAR_LINE;
}
-READ_LINE_MEMBER( mofetta_device::rom1al_out )
+int mofetta_device::rom1al_out()
{
return (m_rom1al && m_pmemen)? ASSERT_LINE : CLEAR_LINE;
}
-READ_LINE_MEMBER( mofetta_device::prcs_out )
+int mofetta_device::prcs_out()
{
return (m_prcs && m_pmemen)? ASSERT_LINE : CLEAR_LINE;
}
-READ_LINE_MEMBER( mofetta_device::cmas_out )
+int mofetta_device::cmas_out()
{
return (m_cmas && m_pmemen)? ASSERT_LINE : CLEAR_LINE;
}
@@ -1713,7 +1708,7 @@ READ_LINE_MEMBER( mofetta_device::cmas_out )
/*
Asserted when a PEB access occurs
*/
-READ_LINE_MEMBER( mofetta_device::dbc_out )
+int mofetta_device::dbc_out()
{
return (m_lasreq || m_cmas || m_rom1cs || m_skdrcs || !m_pmemen)? CLEAR_LINE : ASSERT_LINE;
}
@@ -1762,7 +1757,7 @@ void mofetta_device::cruwrite(offs_t offset, uint8_t data)
/*
Setting or clearing the MSAST line.
*/
-WRITE_LINE_MEMBER( mofetta_device::msast_in )
+void mofetta_device::msast_in(int state)
{
if (state == ASSERT_LINE)
{
@@ -1777,17 +1772,17 @@ WRITE_LINE_MEMBER( mofetta_device::msast_in )
m_msast = (line_state)state;
}
-WRITE_LINE_MEMBER( mofetta_device::pmemen_in )
+void mofetta_device::pmemen_in(int state)
{
m_pmemen = (state==ASSERT_LINE);
}
-WRITE_LINE_MEMBER( mofetta_device::lascs_in )
+void mofetta_device::lascs_in(int state)
{
m_lasreq = (state==ASSERT_LINE);
}
-WRITE_LINE_MEMBER( mofetta_device::skdrcs_in )
+void mofetta_device::skdrcs_in(int state)
{
m_skdrcs = (state==ASSERT_LINE);
}
@@ -1924,7 +1919,7 @@ int amigo_device::get_physical_address_debug(offs_t offset)
/*
Incoming READY line (SRDY)
*/
-WRITE_LINE_MEMBER( amigo_device::srdy_in )
+void amigo_device::srdy_in(int state)
{
LOGMASKED(LOG_READY, "Incoming SRDY = %d\n", state);
m_srdy = (line_state)state;
@@ -1937,7 +1932,7 @@ WRITE_LINE_MEMBER( amigo_device::srdy_in )
}
}
-WRITE_LINE_MEMBER( amigo_device::memen_in )
+void amigo_device::memen_in(int state)
{
m_memen = (state==ASSERT_LINE);
}
@@ -1945,7 +1940,7 @@ WRITE_LINE_MEMBER( amigo_device::memen_in )
/*
Polled from the mainboard
*/
-READ_LINE_MEMBER( amigo_device::cpury_out )
+int amigo_device::cpury_out()
{
return m_ready_out;
}
@@ -1953,7 +1948,7 @@ READ_LINE_MEMBER( amigo_device::cpury_out )
/*
Polled from the mainboard
*/
-READ_LINE_MEMBER( amigo_device::sramcs_out )
+int amigo_device::sramcs_out()
{
return m_sram_accessed && m_memen? ASSERT_LINE : CLEAR_LINE;
}
@@ -1964,7 +1959,7 @@ READ_LINE_MEMBER( amigo_device::sramcs_out )
This is actually more than needed because we only have 64K DRAM (which
would only need a 16 bit address), and Amigo itself selects it.
*/
-READ_LINE_MEMBER( amigo_device::skdrcs_out )
+int amigo_device::skdrcs_out()
{
return m_dram_accessed && (m_amstate == IDLE) && m_memen? ASSERT_LINE : CLEAR_LINE;
}
@@ -1972,7 +1967,7 @@ READ_LINE_MEMBER( amigo_device::skdrcs_out )
/*
Incoming CRUS line. Needed to set the mapper config addresses.
*/
-WRITE_LINE_MEMBER( amigo_device::crus_in )
+void amigo_device::crus_in(int state)
{
m_crus = (line_state)state;
}
@@ -1980,7 +1975,7 @@ WRITE_LINE_MEMBER( amigo_device::crus_in )
/*
Incoming LASCS line.
*/
-WRITE_LINE_MEMBER( amigo_device::lascs_in )
+void amigo_device::lascs_in(int state)
{
m_logical_space = (state==ASSERT_LINE);
}
@@ -2076,7 +2071,7 @@ void amigo_device::write(uint8_t data)
else LOGMASKED(LOG_WARN, "Invalid value written to Amigo: %02x\n", data);
}
-WRITE_LINE_MEMBER( amigo_device::clock_in )
+void amigo_device::clock_in(int state)
{
if (state==CLEAR_LINE)
{
@@ -2184,7 +2179,7 @@ void amigo_device::mapper_access_debug(int data)
}
}
-WRITE_LINE_MEMBER( amigo_device::holda_in )
+void amigo_device::holda_in(int state)
{
LOGMASKED(LOG_MAP, "HOLD acknowledged = %d\n", state);
m_hold_acknowledged = (state==ASSERT_LINE);
@@ -2383,7 +2378,7 @@ void oso_device::clear_int_status()
/*
Phi3 incoming clock pulse
*/
-WRITE_LINE_MEMBER( oso_device::clock_in )
+void oso_device::clock_in(int state)
{
m_phi3 = state;
if (state==ASSERT_LINE)
@@ -2739,7 +2734,6 @@ void oso_device::hexbus_value_changed(uint8_t data)
void oso_device::device_start()
{
m_status = m_xmit = m_control = m_data = 0;
- m_int.resolve_safe();
// Establish the downstream link in the parent class hexbus_chained_device
set_outbound_hexbus(m_hexbusout);
diff --git a/src/devices/bus/ti99/internal/998board.h b/src/devices/bus/ti99/internal/998board.h
index f699b8d02cf..fea5f18e412 100644
--- a/src/devices/bus/ti99/internal/998board.h
+++ b/src/devices/bus/ti99/internal/998board.h
@@ -107,29 +107,29 @@ public:
void set_address(offs_t offset, int state);
- DECLARE_READ_LINE_MEMBER( sprd_out );
- DECLARE_READ_LINE_MEMBER( spwt_out );
- DECLARE_READ_LINE_MEMBER( sccs_out );
- DECLARE_READ_LINE_MEMBER( sromcs_out );
+ int sprd_out();
+ int spwt_out();
+ int sccs_out();
+ int sromcs_out();
// Collective select line query
int gromcs_out();
- DECLARE_READ_LINE_MEMBER( vdprd_out );
- DECLARE_READ_LINE_MEMBER( vdpwt_out );
- DECLARE_READ_LINE_MEMBER( lascsq_out );
- DECLARE_READ_LINE_MEMBER( ggrdy_out );
- DECLARE_WRITE_LINE_MEMBER( hold_cpu );
+ int vdprd_out();
+ int vdpwt_out();
+ int lascsq_out();
+ int ggrdy_out();
+ void hold_cpu(int state);
- DECLARE_WRITE_LINE_MEMBER( crus_in );
- DECLARE_WRITE_LINE_MEMBER( crusgl_in );
- DECLARE_WRITE_LINE_MEMBER( clock_in );
- DECLARE_WRITE_LINE_MEMBER( memen_in );
+ void crus_in(int state);
+ void crusgl_in(int state);
+ void clock_in(int state);
+ void memen_in(int state);
- DECLARE_WRITE_LINE_MEMBER( sgmry );
- DECLARE_WRITE_LINE_MEMBER( tsgry );
- DECLARE_WRITE_LINE_MEMBER( p8gry );
- DECLARE_WRITE_LINE_MEMBER( p3gry );
+ void sgmry(int state);
+ void tsgry(int state);
+ void p8gry(int state);
+ void p3gry(int state);
private:
/*
@@ -258,22 +258,22 @@ public:
bool hexbus_access_debug();
bool intdsr_access_debug();
- DECLARE_WRITE_LINE_MEMBER( clock_in );
- DECLARE_WRITE_LINE_MEMBER( msast_in );
- DECLARE_WRITE_LINE_MEMBER( lascs_in );
- DECLARE_WRITE_LINE_MEMBER( pmemen_in );
- DECLARE_WRITE_LINE_MEMBER( skdrcs_in );
+ void clock_in(int state);
+ void msast_in(int state);
+ void lascs_in(int state);
+ void pmemen_in(int state);
+ void skdrcs_in(int state);
- DECLARE_READ_LINE_MEMBER( gromclk_out );
+ int gromclk_out();
- DECLARE_READ_LINE_MEMBER( alccs_out );
- DECLARE_READ_LINE_MEMBER( prcs_out );
- DECLARE_READ_LINE_MEMBER( cmas_out );
- DECLARE_READ_LINE_MEMBER( dbc_out );
+ int alccs_out();
+ int prcs_out();
+ int cmas_out();
+ int dbc_out();
- DECLARE_READ_LINE_MEMBER( rom1cs_out );
- DECLARE_READ_LINE_MEMBER( rom1am_out );
- DECLARE_READ_LINE_MEMBER( rom1al_out );
+ int rom1cs_out();
+ int rom1am_out();
+ int rom1al_out();
private:
// Memory cycle state
@@ -345,17 +345,17 @@ public:
int get_physical_address_debug(offs_t offset);
void mapper_access_debug(int data);
- DECLARE_WRITE_LINE_MEMBER( srdy_in );
- DECLARE_WRITE_LINE_MEMBER( clock_in );
- DECLARE_WRITE_LINE_MEMBER( crus_in );
- DECLARE_WRITE_LINE_MEMBER( lascs_in );
- DECLARE_WRITE_LINE_MEMBER( memen_in );
+ void srdy_in(int state);
+ void clock_in(int state);
+ void crus_in(int state);
+ void lascs_in(int state);
+ void memen_in(int state);
- DECLARE_WRITE_LINE_MEMBER( holda_in );
+ void holda_in(int state);
- DECLARE_READ_LINE_MEMBER( cpury_out );
- DECLARE_READ_LINE_MEMBER( sramcs_out );
- DECLARE_READ_LINE_MEMBER( skdrcs_out );
+ int cpury_out();
+ int sramcs_out();
+ int skdrcs_out();
void connect_sram(uint8_t* sram) { m_sram = sram; }
bool mapper_accessed() { return m_mapper_accessed; }
@@ -460,7 +460,7 @@ public:
void device_start() override;
void hexbus_value_changed(uint8_t data) override;
- WRITE_LINE_MEMBER( clock_in );
+ void clock_in(int state);
// INT line
devcb_write_line m_int;
@@ -556,16 +556,16 @@ public:
void cruwrite(offs_t offset, uint8_t data);
// Control lines
- DECLARE_WRITE_LINE_MEMBER( clock_in );
- DECLARE_WRITE_LINE_MEMBER( dbin_in );
- DECLARE_WRITE_LINE_MEMBER( msast_in );
- DECLARE_WRITE_LINE_MEMBER( crus_in );
- DECLARE_WRITE_LINE_MEMBER( ptgen_in );
- DECLARE_WRITE_LINE_MEMBER( reset_console );
- DECLARE_WRITE_LINE_MEMBER( hold_cpu );
- DECLARE_WRITE_LINE_MEMBER( ggrdy_in );
+ void clock_in(int state);
+ void dbin_in(int state);
+ void msast_in(int state);
+ void crus_in(int state);
+ void ptgen_in(int state);
+ void reset_console(int state);
+ void hold_cpu(int state);
+ void ggrdy_in(int state);
- DECLARE_WRITE_LINE_MEMBER( holda_line );
+ void holda_line(int state);
auto ready_cb() { return m_ready.bind(); }
auto reset_cb() { return m_console_reset.bind(); }
@@ -574,13 +574,13 @@ public:
void set_paddress(int address);
// Ready lines from GROMs
- DECLARE_WRITE_LINE_MEMBER( system_grom_ready );
- DECLARE_WRITE_LINE_MEMBER( ptts_grom_ready );
- DECLARE_WRITE_LINE_MEMBER( p8_grom_ready );
- DECLARE_WRITE_LINE_MEMBER( p3_grom_ready );
- DECLARE_WRITE_LINE_MEMBER( sound_ready );
- DECLARE_WRITE_LINE_MEMBER( speech_ready );
- DECLARE_WRITE_LINE_MEMBER( pbox_ready );
+ void system_grom_ready(int state);
+ void ptts_grom_ready(int state);
+ void p8_grom_ready(int state);
+ void p3_grom_ready(int state);
+ void sound_ready(int state);
+ void speech_ready(int state);
+ void pbox_ready(int state);
protected:
void device_start() override;
diff --git a/src/devices/bus/ti99/internal/buffram.cpp b/src/devices/bus/ti99/internal/buffram.cpp
index 2747db9dd92..00356eb7817 100644
--- a/src/devices/bus/ti99/internal/buffram.cpp
+++ b/src/devices/bus/ti99/internal/buffram.cpp
@@ -47,14 +47,14 @@ void buffered_ram_device::nvram_default()
bool buffered_ram_device::nvram_read(util::read_stream &file)
{
- size_t actual;
- return !file.read(m_mem.get(), m_size, actual) && actual == m_size;
+ auto const [err, actual] = util::read(file, m_mem.get(), m_size);
+ return !err && (actual == m_size);
}
bool buffered_ram_device::nvram_write(util::write_stream &file)
{
- size_t actual;
- return !file.write(m_mem.get(), m_size, actual) && actual == m_size;
+ auto const [err, actua] = util::write(file, m_mem.get(), m_size);
+ return !err;
}
} // end namespace bus::ti99::internal
diff --git a/src/devices/bus/ti99/internal/datamux.cpp b/src/devices/bus/ti99/internal/datamux.cpp
index 95412e296e9..d87b2df75e6 100644
--- a/src/devices/bus/ti99/internal/datamux.cpp
+++ b/src/devices/bus/ti99/internal/datamux.cpp
@@ -72,13 +72,13 @@
#include "datamux.h"
#include "cpu/tms9900/tms99com.h"
-#define LOG_WARN (1U<<1) // Warnings
-#define LOG_READY (1U<<2) // READY line
-#define LOG_ACCESS (1U<<3) // Access to this GROM
-#define LOG_ADDRESS (1U<<4) // Address register
-#define LOG_WAITCOUNT (1U<<5) // Wait state counter
+#define LOG_WARN (1U << 1) // Warnings
+#define LOG_READY (1U << 2) // READY line
+#define LOG_ACCESS (1U << 3) // Access to this GROM
+#define LOG_ADDRESS (1U << 4) // Address register
+#define LOG_WAITCOUNT (1U << 5) // Wait state counter
-#define VERBOSE ( LOG_GENERAL | LOG_WARN )
+#define VERBOSE (LOG_GENERAL | LOG_WARN)
#include "logmacro.h"
@@ -481,7 +481,7 @@ void datamux_device::setaddress(offs_t offset, uint16_t busctrl)
The datamux is connected to the clock line in order to operate
the wait state counter and to read/write the bytes.
*/
-WRITE_LINE_MEMBER( datamux_device::clock_in )
+void datamux_device::clock_in(int state)
{
// return immediately if the datamux is currently inactive
if (m_waitcount>0)
@@ -548,7 +548,7 @@ void datamux_device::ready_join()
m_ready((m_sysready==CLEAR_LINE || m_muxready==CLEAR_LINE)? CLEAR_LINE : ASSERT_LINE);
}
-WRITE_LINE_MEMBER( datamux_device::ready_line )
+void datamux_device::ready_line(int state)
{
if (state != m_sysready) LOGMASKED(LOG_READY, "READY line from PBox = %d\n", state);
m_sysready = (line_state)state;
@@ -557,7 +557,7 @@ WRITE_LINE_MEMBER( datamux_device::ready_line )
}
/* Called from VDP via console. */
-WRITE_LINE_MEMBER( datamux_device::gromclk_in )
+void datamux_device::gromclk_in(int state)
{
// Don't propagate the clock in idle phase
if (m_grom_idle) return;
@@ -581,10 +581,9 @@ WRITE_LINE_MEMBER( datamux_device::gromclk_in )
DEVICE LIFECYCLE FUNCTIONS
***************************************************************************/
-void datamux_device::device_start(void)
+void datamux_device::device_start()
{
m_muxready = ASSERT_LINE;
- m_ready.resolve();
// Register persistable state variables
save_item(NAME(m_addr_buf));
@@ -599,11 +598,11 @@ void datamux_device::device_start(void)
save_item(NAME(m_grom_idle));
}
-void datamux_device::device_stop(void)
+void datamux_device::device_stop()
{
}
-void datamux_device::device_reset(void)
+void datamux_device::device_reset()
{
m_consolerom = (uint16_t*)owner()->memregion(TI99_CONSOLEROM)->base();
m_use32k = (ioport("RAM")->read()==1);
diff --git a/src/devices/bus/ti99/internal/datamux.h b/src/devices/bus/ti99/internal/datamux.h
index 8fb9a7a8c08..f83b81dc807 100644
--- a/src/devices/bus/ti99/internal/datamux.h
+++ b/src/devices/bus/ti99/internal/datamux.h
@@ -48,11 +48,11 @@ public:
void write(offs_t offset, uint16_t data);
void setaddress(offs_t offset, uint16_t busctrl);
- DECLARE_WRITE_LINE_MEMBER( clock_in );
- DECLARE_WRITE_LINE_MEMBER( dbin_in );
- DECLARE_WRITE_LINE_MEMBER( ready_line );
+ void clock_in(int state);
+ void dbin_in(int state);
+ void ready_line(int state);
- DECLARE_WRITE_LINE_MEMBER( gromclk_in );
+ void gromclk_in(int state);
auto ready_cb() { return m_ready.bind(); }
diff --git a/src/devices/bus/ti99/internal/evpcconn.cpp b/src/devices/bus/ti99/internal/evpcconn.cpp
index 2b7647d52dd..5c9114e53c7 100644
--- a/src/devices/bus/ti99/internal/evpcconn.cpp
+++ b/src/devices/bus/ti99/internal/evpcconn.cpp
@@ -26,20 +26,19 @@ DEFINE_DEVICE_TYPE(TI99_EVPCCONN, bus::ti99::internal::evpc_clock_connector, "ti
namespace bus::ti99::internal {
-evpc_clock_connector::evpc_clock_connector(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, TI99_EVPCCONN, tag, owner, clock),
- m_vdpint(*this)
+evpc_clock_connector::evpc_clock_connector(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, TI99_EVPCCONN, tag, owner, clock),
+ m_vdpint(*this)
{
}
-WRITE_LINE_MEMBER( evpc_clock_connector::vclock_line )
+void evpc_clock_connector::vclock_line(int state)
{
m_vdpint(state);
}
void evpc_clock_connector::device_start()
{
- m_vdpint.resolve();
}
} // end namespace bus::ti99::internal
diff --git a/src/devices/bus/ti99/internal/evpcconn.h b/src/devices/bus/ti99/internal/evpcconn.h
index 4216b7e0028..09b1b576521 100644
--- a/src/devices/bus/ti99/internal/evpcconn.h
+++ b/src/devices/bus/ti99/internal/evpcconn.h
@@ -20,7 +20,7 @@ class evpc_clock_connector : public device_t
public:
evpc_clock_connector(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_WRITE_LINE_MEMBER( vclock_line );
+ void vclock_line(int state);
void device_start() override;
auto vdpint_cb() { return m_vdpint.bind(); }
diff --git a/src/devices/bus/ti99/internal/genboard.cpp b/src/devices/bus/ti99/internal/genboard.cpp
index e22bb72caa8..e9815a9a806 100644
--- a/src/devices/bus/ti99/internal/genboard.cpp
+++ b/src/devices/bus/ti99/internal/genboard.cpp
@@ -411,25 +411,25 @@
***************************************************************************/
#include "emu.h"
-#define LOG_WARN (1U<<1)
-#define LOG_DETAIL (1U<<2)
-#define LOG_READ (1U<<3)
-#define LOG_WRITE (1U<<4)
-#define LOG_KEYBOARD (1U<<5)
-#define LOG_CLOCK (1U<<6)
-#define LOG_READY (1U<<7)
-#define LOG_SETTING (1U<<8)
-#define LOG_CRU (1U<<9)
-#define LOG_CRUKEY (1U<<10)
-#define LOG_DECODE (1U<<11)
-#define LOG_ADDRESS (1U<<12)
-#define LOG_LINES (1U<<13)
-#define LOG_WAIT (1U<<14)
-#define LOG_GROM (1U<<15)
-#define LOG_MAPPER (1U<<16)
+#define LOG_WARN (1U << 1)
+#define LOG_DETAIL (1U << 2)
+#define LOG_READ (1U << 3)
+#define LOG_WRITE (1U << 4)
+#define LOG_KEYBOARD (1U << 5)
+#define LOG_CLOCK (1U << 6)
+#define LOG_READY (1U << 7)
+#define LOG_SETTING (1U << 8)
+#define LOG_CRU (1U << 9)
+#define LOG_CRUKEY (1U << 10)
+#define LOG_DECODE (1U << 11)
+#define LOG_ADDRESS (1U << 12)
+#define LOG_LINES (1U << 13)
+#define LOG_WAIT (1U << 14)
+#define LOG_GROM (1U << 15)
+#define LOG_MAPPER (1U << 16)
// Minimum log should be warnings
-#define VERBOSE ( LOG_GENERAL | LOG_WARN )
+#define VERBOSE (LOG_GENERAL | LOG_WARN)
#include "genboard.h"
#include "logmacro.h"
@@ -563,7 +563,7 @@ void geneve_gate_array_device::cru_ctrl_write(offs_t offset, uint8_t data)
Pull down or release the clock line.
Called by setting CRU bit 1EF0 to 0 or 1.
*/
-WRITE_LINE_MEMBER( geneve_gate_array_device::set_keyboard_clock)
+void geneve_gate_array_device::set_keyboard_clock(int state)
{
m_keyb_clk(state);
}
@@ -576,7 +576,7 @@ WRITE_LINE_MEMBER( geneve_gate_array_device::set_keyboard_clock)
Called by setting CRU bit 1EF2 to 0 or 1
*/
-WRITE_LINE_MEMBER( geneve_gate_array_device::enable_shift_register)
+void geneve_gate_array_device::enable_shift_register(int state)
{
m_shift_reg_enabled = (state==ASSERT_LINE);
@@ -607,7 +607,7 @@ void geneve_gate_array_device::shift_reg_changed()
Incoming keyboard strobe. When 0, push the current data line level into
the shift register at the leftmost position.
*/
-WRITE_LINE_MEMBER( geneve_gate_array_device::kbdclk )
+void geneve_gate_array_device::kbdclk(int state)
{
LOGMASKED(LOG_KEYBOARD, "Keyboard clock: %d\n", state);
bool clock_falling_edge = (m_keyboard_last_clock == ASSERT_LINE && state == CLEAR_LINE);
@@ -624,7 +624,7 @@ WRITE_LINE_MEMBER( geneve_gate_array_device::kbdclk )
/*
Latch the value of the incoming data line.
*/
-WRITE_LINE_MEMBER( geneve_gate_array_device::kbddata )
+void geneve_gate_array_device::kbddata(int state)
{
LOGMASKED(LOG_KEYBOARD, "Keyboard data: %d\n", state);
m_keyboard_data_in = (line_state)state;
@@ -890,7 +890,7 @@ void geneve_gate_array_device::setaddress(offs_t address, uint8_t busctrl)
The Gate Array uses the clock to operate the wait state flags. The actual
wait state generation is up to the PAL chip.
*/
-WRITE_LINE_MEMBER( geneve_gate_array_device::clock_in )
+void geneve_gate_array_device::clock_in(int state)
{
// Falling CLK
if (state == CLEAR_LINE)
@@ -906,64 +906,64 @@ WRITE_LINE_MEMBER( geneve_gate_array_device::clock_in )
READY line from the peribox. Together with the sndready and the READY output
of the Gate Array itself, this forms a wired AND.
*/
-WRITE_LINE_MEMBER( geneve_gate_array_device::extready_in )
+void geneve_gate_array_device::extready_in(int state)
{
LOGMASKED(LOG_READY, "External READY = %d\n", state);
m_extready = (state==ASSERT_LINE);
}
-WRITE_LINE_MEMBER( geneve_gate_array_device::sndready_in )
+void geneve_gate_array_device::sndready_in(int state)
{
LOGMASKED(LOG_READY, "Sound READY = %d\n", state);
m_sndready = (state==ASSERT_LINE);
}
-READ_LINE_MEMBER(geneve_gate_array_device::csw_out)
+int geneve_gate_array_device::csw_out()
{
// Do not access a port-based device in debugger mode
if (m_debug) return CLEAR_LINE;
return ((m_decoded.function == MLVIDEO) && !m_decoded.read)? ASSERT_LINE : CLEAR_LINE;
}
-READ_LINE_MEMBER(geneve_gate_array_device::csr_out)
+int geneve_gate_array_device::csr_out()
{
// Do not access a port-based device in debugger mode
if (m_debug) return CLEAR_LINE;
return ((m_decoded.function == MLVIDEO) && m_decoded.read)? ASSERT_LINE : CLEAR_LINE;
}
-READ_LINE_MEMBER(geneve_gate_array_device::romen_out)
+int geneve_gate_array_device::romen_out()
{
// Do not restrict to read-only, as we could have a PFM here
decdata* dec = (m_debug)? &m_decdebug : &m_decoded;
return (dec->function == MPEPROM)? ASSERT_LINE : CLEAR_LINE;
}
-READ_LINE_MEMBER(geneve_gate_array_device::ramen_out)
+int geneve_gate_array_device::ramen_out()
{
decdata* dec = (m_debug)? &m_decdebug : &m_decoded;
return (dec->function == MPSRAM)? ASSERT_LINE : CLEAR_LINE;
}
-READ_LINE_MEMBER(geneve_gate_array_device::ramenx_out)
+int geneve_gate_array_device::ramenx_out()
{
decdata* dec = (m_debug)? &m_decdebug : &m_decoded;
return (dec->function == MPSRAMX)? ASSERT_LINE : CLEAR_LINE;
}
-READ_LINE_MEMBER(geneve_gate_array_device::rtcen_out)
+int geneve_gate_array_device::rtcen_out()
{
decdata* dec = (m_debug)? &m_decdebug : &m_decoded;
return (dec->function == MLCLOCK)? ASSERT_LINE : CLEAR_LINE;
}
-READ_LINE_MEMBER(geneve_gate_array_device::snden_out)
+int geneve_gate_array_device::snden_out()
{
decdata* dec = (m_debug)? &m_decdebug : &m_decoded;
return ((dec->function == MLSOUND) && !dec->read)? ASSERT_LINE : CLEAR_LINE;
}
-READ_LINE_MEMBER(geneve_gate_array_device::dben_out)
+int geneve_gate_array_device::dben_out()
{
decdata* dec = (m_debug)? &m_decdebug : &m_decoded;
return accessing_box_s(dec->function, false)? ASSERT_LINE : CLEAR_LINE;
@@ -980,7 +980,7 @@ READ_LINE_MEMBER(geneve_gate_array_device::dben_out)
// - we access DRAM and have timode==1 OR
// - extready = 0
-READ_LINE_MEMBER(geneve_gate_array_device::gaready_out)
+int geneve_gate_array_device::gaready_out()
{
if (m_debug) return ASSERT_LINE; // Always READY when debugging
// Return true (READY=1) when we are accessing SRAM/SRAMX and when we do not have extra waitstates
@@ -1082,10 +1082,6 @@ int geneve_gate_array_device::get_prefix(int lines)
void geneve_gate_array_device::device_start()
{
- m_keyint.resolve_safe();
- m_keyb_clk.resolve_safe();
- m_keyb_data.resolve_safe();
-
m_geneve_mode = false;
m_direct_mode = true;
@@ -1193,7 +1189,7 @@ geneve_pal_device::geneve_pal_device(const machine_config &mconfig, const char *
/*
READY input from the Gate Array.
*/
-WRITE_LINE_MEMBER(geneve_pal_device::gaready_in)
+void geneve_pal_device::gaready_in(int state)
{
bool prev = m_pin3;
m_pin3 = (state==ASSERT_LINE);
@@ -1208,7 +1204,7 @@ WRITE_LINE_MEMBER(geneve_pal_device::gaready_in)
/*
Video read (ASSERT=low).
*/
-WRITE_LINE_MEMBER(geneve_pal_device::csr_in)
+void geneve_pal_device::csr_in(int state)
{
bool prev = m_pin4;
m_pin4 = (state==CLEAR_LINE);
@@ -1222,7 +1218,7 @@ WRITE_LINE_MEMBER(geneve_pal_device::csr_in)
/*
Video write (ASSERT=low).
*/
-WRITE_LINE_MEMBER(geneve_pal_device::csw_in)
+void geneve_pal_device::csw_in(int state)
{
bool prev = m_pin9;
m_pin9 = (state==CLEAR_LINE);
@@ -1236,7 +1232,7 @@ WRITE_LINE_MEMBER(geneve_pal_device::csw_in)
/*
Memory enable (ASSERT=low); pass through
*/
-WRITE_LINE_MEMBER(geneve_pal_device::memen)
+void geneve_pal_device::memen(int state)
{
LOGMASKED(LOG_LINES, "MEMEN -> %d\n", state);
m_peribox->memen_in(state);
@@ -1249,7 +1245,7 @@ WRITE_LINE_MEMBER(geneve_pal_device::memen)
This function seems to have no effect. So either the equations are
wrong, or something else is going on.
*/
-WRITE_LINE_MEMBER(geneve_pal_device::sysspeed)
+void geneve_pal_device::sysspeed(int state)
{
bool prev = m_pin5;
m_pin5 = (state == ASSERT_LINE);
@@ -1264,7 +1260,7 @@ WRITE_LINE_MEMBER(geneve_pal_device::sysspeed)
Write vdp wait cycles (1=add 14 cycles, 0=add none)
see above for waitstate handling
*/
-WRITE_LINE_MEMBER(geneve_pal_device::vwaiten)
+void geneve_pal_device::vwaiten(int state)
{
bool prev = m_pin19;
m_pin19 = (state==ASSERT_LINE);
@@ -1278,7 +1274,7 @@ WRITE_LINE_MEMBER(geneve_pal_device::vwaiten)
/*
Clock input. This controls the state of the waitstate counter.
*/
-WRITE_LINE_MEMBER(geneve_pal_device::clock_in)
+void geneve_pal_device::clock_in(int state)
{
LOGMASKED(LOG_CLOCK, "CLK%s\n", state? "?" : "?");
// Set the FF
@@ -1382,8 +1378,6 @@ void geneve_pal_device::set_ready()
void geneve_pal_device::device_start()
{
- m_ready.resolve_safe();
-
save_item(NAME(m_pin3));
save_item(NAME(m_pin4));
save_item(NAME(m_pin5));
@@ -1438,7 +1432,7 @@ void genmod_decoder_device::set_function(int func, int page)
}
}
-WRITE_LINE_MEMBER(genmod_decoder_device::gaready_in)
+void genmod_decoder_device::gaready_in(int state)
{
m_gaready = state;
}
@@ -1447,7 +1441,7 @@ WRITE_LINE_MEMBER(genmod_decoder_device::gaready_in)
READY line from the box. Do not ignore this line, as it is important
for device operation.
*/
-WRITE_LINE_MEMBER(genmod_decoder_device::extready_in)
+void genmod_decoder_device::extready_in(int state)
{
m_extready = state;
}
@@ -1455,7 +1449,7 @@ WRITE_LINE_MEMBER(genmod_decoder_device::extready_in)
/*
READY line from the sound chip.
*/
-WRITE_LINE_MEMBER(genmod_decoder_device::sndready_in)
+void genmod_decoder_device::sndready_in(int state)
{
m_sndready = state;
}
@@ -1465,7 +1459,7 @@ WRITE_LINE_MEMBER(genmod_decoder_device::sndready_in)
The Genmod board does not look inside the Gate Array. The call we are using
is just a shorthand for evaluating the states of the select lines.
*/
-READ_LINE_MEMBER(genmod_decoder_device::gaready_out)
+int genmod_decoder_device::gaready_out()
{
int func = m_debug? m_function_debug : m_function;
int page = m_debug? m_page_debug : m_page;
@@ -1496,7 +1490,7 @@ READ_LINE_MEMBER(genmod_decoder_device::gaready_out)
Note: It is not sufficient to check for the page area; we need to check
the select lines (via the static functions).
*/
-READ_LINE_MEMBER(genmod_decoder_device::dben_out)
+int genmod_decoder_device::dben_out()
{
int func = m_debug? m_function_debug : m_function;
diff --git a/src/devices/bus/ti99/internal/genboard.h b/src/devices/bus/ti99/internal/genboard.h
index 4b5dd21124e..3f1d6a3e749 100644
--- a/src/devices/bus/ti99/internal/genboard.h
+++ b/src/devices/bus/ti99/internal/genboard.h
@@ -70,23 +70,23 @@ public:
void write(uint8_t data);
// Inputs
- DECLARE_WRITE_LINE_MEMBER( clock_in );
- DECLARE_WRITE_LINE_MEMBER( dbin_in );
- DECLARE_WRITE_LINE_MEMBER( extready_in );
- DECLARE_WRITE_LINE_MEMBER( sndready_in );
+ void clock_in(int state);
+ void dbin_in(int state);
+ void extready_in(int state);
+ void sndready_in(int state);
void cru_sstep_write(offs_t offset, uint8_t data);
void cru_ctrl_write(offs_t offset, uint8_t data);
// Outputs
- DECLARE_READ_LINE_MEMBER( csr_out );
- DECLARE_READ_LINE_MEMBER( csw_out );
- DECLARE_READ_LINE_MEMBER( rtcen_out );
- DECLARE_READ_LINE_MEMBER( romen_out );
- DECLARE_READ_LINE_MEMBER( ramen_out );
- DECLARE_READ_LINE_MEMBER( ramenx_out );
- DECLARE_READ_LINE_MEMBER( snden_out );
- DECLARE_READ_LINE_MEMBER( dben_out );
- DECLARE_READ_LINE_MEMBER( gaready_out );
+ int csr_out();
+ int csw_out();
+ int rtcen_out();
+ int romen_out();
+ int ramen_out();
+ int ramenx_out();
+ int snden_out();
+ int dben_out();
+ int gaready_out();
int get_prefix(int lines);
bool accessing_dram();
@@ -99,10 +99,10 @@ public:
offs_t get_dram_address();
// Keyboard support
- DECLARE_WRITE_LINE_MEMBER( set_keyboard_clock );
- DECLARE_WRITE_LINE_MEMBER( enable_shift_register );
- DECLARE_WRITE_LINE_MEMBER( kbdclk );
- DECLARE_WRITE_LINE_MEMBER( kbddata );
+ void set_keyboard_clock(int state);
+ void enable_shift_register(int state);
+ void kbdclk(int state);
+ void kbddata(int state);
auto kbdint_cb() { return m_keyint.bind(); }
auto kbdclk_cb() { return m_keyb_clk.bind(); }
auto kbddata_cb() { return m_keyb_data.bind(); }
@@ -252,13 +252,13 @@ class geneve_pal_device : public device_t
public:
geneve_pal_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_WRITE_LINE_MEMBER( gaready_in );
- DECLARE_WRITE_LINE_MEMBER( csw_in );
- DECLARE_WRITE_LINE_MEMBER( csr_in );
- DECLARE_WRITE_LINE_MEMBER( memen );
- DECLARE_WRITE_LINE_MEMBER( vwaiten ); // pin 19
- DECLARE_WRITE_LINE_MEMBER( sysspeed ); // pin 5
- DECLARE_WRITE_LINE_MEMBER( clock_in );
+ void gaready_in(int state);
+ void csw_in(int state);
+ void csr_in(int state);
+ void memen(int state);
+ void vwaiten(int state); // pin 19
+ void sysspeed(int state); // pin 5
+ void clock_in(int state);
auto ready_cb() { return m_ready.bind(); }
@@ -297,11 +297,11 @@ public:
void set_turbo(bool turbo) { m_turbo = turbo; }
void set_timode(bool timode) { m_timode = timode; }
- DECLARE_READ_LINE_MEMBER( gaready_out );
- DECLARE_READ_LINE_MEMBER( dben_out );
- DECLARE_WRITE_LINE_MEMBER( gaready_in );
- DECLARE_WRITE_LINE_MEMBER( extready_in );
- DECLARE_WRITE_LINE_MEMBER( sndready_in );
+ int gaready_out();
+ int dben_out();
+ void gaready_in(int state);
+ void extready_in(int state);
+ void sndready_in(int state);
private:
void device_start() override;
diff --git a/src/devices/bus/ti99/internal/genkbd.cpp b/src/devices/bus/ti99/internal/genkbd.cpp
index 5e22f27ee33..14f444c620d 100644
--- a/src/devices/bus/ti99/internal/genkbd.cpp
+++ b/src/devices/bus/ti99/internal/genkbd.cpp
@@ -30,10 +30,10 @@
#include "emu.h"
#include "genkbd.h"
-#define LOG_WARN (1U<<1)
-#define LOG_QUEUE (1U<<2)
-#define LOG_TRANSFER (1U<<3)
-#define LOG_LINES (1U<<4)
+#define LOG_WARN (1U << 1)
+#define LOG_QUEUE (1U << 2)
+#define LOG_TRANSFER (1U << 3)
+#define LOG_LINES (1U << 4)
#define VERBOSE (LOG_GENERAL | LOG_WARN)
@@ -544,7 +544,7 @@ void geneve_xt_101_hle_keyboard_device::post_in_key_queue(int keycode)
// clock_write -
//-------------------------------------------------
-WRITE_LINE_MEMBER(geneve_xt_101_hle_keyboard_device::clock_write)
+void geneve_xt_101_hle_keyboard_device::clock_write(int state)
{
LOGMASKED(LOG_LINES, "Clock write: %d\n", state);
m_clock_line = (line_state)state;
@@ -562,7 +562,7 @@ WRITE_LINE_MEMBER(geneve_xt_101_hle_keyboard_device::clock_write)
// data_write -
//-------------------------------------------------
-WRITE_LINE_MEMBER(geneve_xt_101_hle_keyboard_device::data_write)
+void geneve_xt_101_hle_keyboard_device::data_write(int state)
{
LOGMASKED(LOG_LINES, "Data write: %d\n", state);
m_data_line = (line_state)state;
@@ -600,7 +600,7 @@ void geneve_xt_101_hle_keyboard_device::device_reset()
}
-WRITE_LINE_MEMBER(geneve_xt_101_hle_keyboard_device::reset_line)
+void geneve_xt_101_hle_keyboard_device::reset_line(int state)
{
m_resetting = !state;
diff --git a/src/devices/bus/ti99/internal/genkbd.h b/src/devices/bus/ti99/internal/genkbd.h
index cf67ea8ee6c..94786af46fd 100644
--- a/src/devices/bus/ti99/internal/genkbd.h
+++ b/src/devices/bus/ti99/internal/genkbd.h
@@ -26,7 +26,7 @@ class geneve_xt_101_hle_keyboard_device : public device_t, public device_pc_kbd_
public:
// construction/destruction
geneve_xt_101_hle_keyboard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_WRITE_LINE_MEMBER(reset_line);
+ void reset_line(int state);
protected:
// device-level overrides
@@ -35,8 +35,8 @@ protected:
virtual ioport_constructor device_input_ports() const override;
// device_pc_kbd_interface overrides
- virtual DECLARE_WRITE_LINE_MEMBER(clock_write) override;
- virtual DECLARE_WRITE_LINE_MEMBER(data_write) override;
+ virtual void clock_write(int state) override;
+ virtual void data_write(int state) override;
TIMER_CALLBACK_MEMBER(poll_tick);
TIMER_CALLBACK_MEMBER(send_tick);
diff --git a/src/devices/bus/ti99/internal/ioport.cpp b/src/devices/bus/ti99/internal/ioport.cpp
index 4ab42b201b4..25252569e6d 100644
--- a/src/devices/bus/ti99/internal/ioport.cpp
+++ b/src/devices/bus/ti99/internal/ioport.cpp
@@ -86,7 +86,7 @@ namespace bus::ti99::internal {
ioport_device::ioport_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, TI99_IOPORT, tag, owner, clock),
- device_slot_interface(mconfig, *this),
+ device_single_card_slot_interface<ioport_attached_device>(mconfig, *this),
m_console_extint(*this),
m_console_ready(*this),
m_connected(nullptr)
@@ -123,25 +123,25 @@ void ioport_device::cruwrite(offs_t offset, uint8_t data)
m_connected->cruwrite(offset, data);
}
-WRITE_LINE_MEMBER(ioport_device::memen_in)
+void ioport_device::memen_in(int state)
{
if (m_connected != nullptr)
m_connected->memen_in(state);
}
-WRITE_LINE_MEMBER(ioport_device::msast_in)
+void ioport_device::msast_in(int state)
{
if (m_connected != nullptr)
m_connected->msast_in(state);
}
-WRITE_LINE_MEMBER(ioport_device::clock_in)
+void ioport_device::clock_in(int state)
{
if (m_connected != nullptr)
m_connected->clock_in(state);
}
-WRITE_LINE_MEMBER(ioport_device::reset_in)
+void ioport_device::reset_in(int state)
{
if (m_connected != nullptr)
m_connected->reset_in(state);
@@ -149,24 +149,22 @@ WRITE_LINE_MEMBER(ioport_device::reset_in)
void ioport_device::device_start()
{
- m_console_extint.resolve();
- m_console_ready.resolve();
if (m_connected != nullptr)
m_connected->set_ioport(this);
}
void ioport_device::device_config_complete()
{
- m_connected = static_cast<ioport_attached_device*>(subdevices().first());
+ m_connected = get_card_device();
}
-WRITE_LINE_MEMBER(ioport_attached_device::set_extint)
+void ioport_attached_device::set_extint(int state)
{
m_ioport->m_console_extint(state);
}
-WRITE_LINE_MEMBER(ioport_attached_device::set_ready)
+void ioport_attached_device::set_ready(int state)
{
m_ioport->m_console_ready(state);
}
diff --git a/src/devices/bus/ti99/internal/ioport.h b/src/devices/bus/ti99/internal/ioport.h
index 5c08beec760..29ac6fb7fc4 100644
--- a/src/devices/bus/ti99/internal/ioport.h
+++ b/src/devices/bus/ti99/internal/ioport.h
@@ -34,17 +34,17 @@ public:
virtual void setaddress_dbin(offs_t offset, int state) { }
virtual void crureadz(offs_t offset, uint8_t *value) { }
virtual void cruwrite(offs_t offset, uint8_t data) { }
- virtual DECLARE_WRITE_LINE_MEMBER( memen_in ) { }
- virtual DECLARE_WRITE_LINE_MEMBER( msast_in ) { }
- virtual DECLARE_WRITE_LINE_MEMBER( clock_in ) { }
- virtual DECLARE_WRITE_LINE_MEMBER( reset_in ) { }
+ virtual void memen_in(int state) { }
+ virtual void msast_in(int state) { }
+ virtual void clock_in(int state) { }
+ virtual void reset_in(int state) { }
void set_ioport(ioport_device* ioport) { m_ioport = ioport; }
protected:
// Methods called from the external device
- DECLARE_WRITE_LINE_MEMBER( set_extint );
- DECLARE_WRITE_LINE_MEMBER( set_ready );
+ void set_extint(int state);
+ void set_ready(int state);
private:
ioport_device* m_ioport;
};
@@ -53,7 +53,7 @@ private:
I/O port
********************************************************************/
-class ioport_device : public device_t, public device_slot_interface
+class ioport_device : public device_t, public device_single_card_slot_interface<ioport_attached_device>
{
friend class ioport_attached_device;
@@ -76,18 +76,18 @@ public:
void setaddress_dbin(offs_t offset, int state);
void crureadz(offs_t offset, uint8_t *value);
void cruwrite(offs_t offset, uint8_t data);
- DECLARE_WRITE_LINE_MEMBER( memen_in );
- DECLARE_WRITE_LINE_MEMBER( msast_in );
- DECLARE_WRITE_LINE_MEMBER( clock_in );
- DECLARE_WRITE_LINE_MEMBER( reset_in );
+ void memen_in(int state);
+ void msast_in(int state);
+ void clock_in(int state);
+ void reset_in(int state);
// Callbacks
auto extint_cb() { return m_console_extint.bind(); }
auto ready_cb() { return m_console_ready.bind(); }
protected:
- void device_start() override;
- void device_config_complete() override;
+ virtual void device_start() override;
+ virtual void device_config_complete() override;
// Methods called back from the external device
devcb_write_line m_console_extint; // EXTINT line
diff --git a/src/devices/bus/ti99/joyport/handset.cpp b/src/devices/bus/ti99/joyport/handset.cpp
index 046873f5fe6..d03480378ab 100644
--- a/src/devices/bus/ti99/joyport/handset.cpp
+++ b/src/devices/bus/ti99/joyport/handset.cpp
@@ -39,11 +39,11 @@
#include "emu.h"
#include "handset.h"
-#define LOG_WARN (1U<<1) // Warnings
-#define LOG_CONFIG (1U<<2) // Configuration
-#define LOG_JOYSTICK (1U<<3)
-#define LOG_HANDSET (1U<<4)
-#define LOG_CLOCK (1U<<5)
+#define LOG_WARN (1U << 1) // Warnings
+#define LOG_CONFIG (1U << 2) // Configuration
+#define LOG_JOYSTICK (1U << 3)
+#define LOG_HANDSET (1U << 4)
+#define LOG_CLOCK (1U << 5)
#define VERBOSE (LOG_CONFIG | LOG_WARN)
diff --git a/src/devices/bus/ti99/joyport/joyport.cpp b/src/devices/bus/ti99/joyport/joyport.cpp
index 77825e85f96..b8ebafe6ba5 100644
--- a/src/devices/bus/ti99/joyport/joyport.cpp
+++ b/src/devices/bus/ti99/joyport/joyport.cpp
@@ -87,19 +87,18 @@ void joyport_device::pulse_clock()
Propagate the interrupt to the defined target. Only used for the handset
at the prototype 99/4.
*/
-WRITE_LINE_MEMBER( joyport_device::set_interrupt )
+void joyport_device::set_interrupt(int state)
{
m_interrupt(state);
}
void joyport_device::device_start()
{
- m_interrupt.resolve();
}
void joyport_device::device_config_complete()
{
- m_connected = dynamic_cast<device_ti99_joyport_interface*>(subdevices().first());
+ m_connected = get_card_device();
}
/*****************************************************************************/
diff --git a/src/devices/bus/ti99/joyport/joyport.h b/src/devices/bus/ti99/joyport/joyport.h
index 40f7b358ac6..b377e6ce7c1 100644
--- a/src/devices/bus/ti99/joyport/joyport.h
+++ b/src/devices/bus/ti99/joyport/joyport.h
@@ -76,8 +76,8 @@ public:
auto int_cb() { return m_interrupt.bind(); }
protected:
- void device_start() override;
- void device_config_complete() override;
+ virtual void device_start() override;
+ virtual void device_config_complete() override;
private:
devcb_write_line m_interrupt;
diff --git a/src/devices/bus/ti99/peb/bwg.cpp b/src/devices/bus/ti99/peb/bwg.cpp
index 4950943a8a8..25472b0ed12 100644
--- a/src/devices/bus/ti99/peb/bwg.cpp
+++ b/src/devices/bus/ti99/peb/bwg.cpp
@@ -50,17 +50,17 @@
// ----------------------------------
// Flags for debugging
-#define LOG_WARN (1U<<1) // Warnings
-#define LOG_RW (1U<<2) // Read and write accesses
-#define LOG_CRU (1U<<3) // Show CRU bit accesses
-#define LOG_CRUD (1U<<4) // Show CRU bit accesses (details)
-#define LOG_READY (1U<<5) // Show ready line activity
-#define LOG_SIGNALS (1U<<6) // Show detailed signal activity
-#define LOG_ADDRESS (1U<<7) // Show address bus operations
-#define LOG_MOTOR (1U<<8) // Show motor operations
-#define LOG_CONFIG (1U<<9) // Configuration
-
-#define VERBOSE ( LOG_CONFIG | LOG_WARN )
+#define LOG_WARN (1U << 1) // Warnings
+#define LOG_RW (1U << 2) // Read and write accesses
+#define LOG_CRU (1U << 3) // Show CRU bit accesses
+#define LOG_CRUD (1U << 4) // Show CRU bit accesses (details)
+#define LOG_READY (1U << 5) // Show ready line activity
+#define LOG_SIGNALS (1U << 6) // Show detailed signal activity
+#define LOG_ADDRESS (1U << 7) // Show address bus operations
+#define LOG_MOTOR (1U << 8) // Show motor operations
+#define LOG_CONFIG (1U << 9) // Configuration
+
+#define VERBOSE (LOG_GENERAL | LOG_CONFIG | LOG_WARN)
#include "logmacro.h"
DEFINE_DEVICE_TYPE(TI99_BWG, bus::ti99::peb::snug_bwg_device, "ti99_bwg", "SNUG BwG Floppy Controller")
@@ -94,6 +94,7 @@ snug_bwg_device::snug_bwg_device(const machine_config &mconfig, const char *tag,
m_address(0),
m_dsrrom(nullptr),
m_buffer_ram(*this, BUFFER),
+ m_floppy(*this, "%u", 0),
m_sel_floppy(0),
m_wd1773(*this, FDC_TAG),
m_clock(*this, CLOCK_TAG),
@@ -123,7 +124,7 @@ void snug_bwg_device::operate_ready_line()
/*
Callbacks from the WD1773 chip
*/
-WRITE_LINE_MEMBER( snug_bwg_device::fdc_irq_w )
+void snug_bwg_device::fdc_irq_w(int state)
{
LOGMASKED(LOG_SIGNALS, "set intrq = %d\n", state);
m_IRQ = (line_state)state;
@@ -132,7 +133,7 @@ WRITE_LINE_MEMBER( snug_bwg_device::fdc_irq_w )
operate_ready_line();
}
-WRITE_LINE_MEMBER( snug_bwg_device::fdc_drq_w )
+void snug_bwg_device::fdc_drq_w(int state)
{
LOGMASKED(LOG_SIGNALS, "set drq = %d\n", state);
m_DRQ = (line_state)state;
@@ -355,10 +356,10 @@ void snug_bwg_device::crureadz(offs_t offset, uint8_t *value)
if ((offset & 0x00f0)==0)
{
// Check what drives are not connected
- reply = ((m_floppy[0] != nullptr)? 0 : 0x02) // DSK1
- | ((m_floppy[1] != nullptr)? 0 : 0x04) // DSK2
- | ((m_floppy[2] != nullptr)? 0 : 0x08) // DSK3
- | ((m_floppy[3] != nullptr)? 0 : 0x01); // DSK4
+ reply = ((m_floppy[0]->get_device() != nullptr)? 0 : 0x02) // DSK1
+ | ((m_floppy[1]->get_device() != nullptr)? 0 : 0x04) // DSK2
+ | ((m_floppy[2]->get_device() != nullptr)? 0 : 0x08) // DSK3
+ | ((m_floppy[3]->get_device() != nullptr)? 0 : 0x01); // DSK4
// DIP switches for step and date/time display
if (m_dip1 != 0) reply |= 0x10;
@@ -390,19 +391,19 @@ void snug_bwg_device::cruwrite(offs_t offset, uint8_t data)
}
}
-WRITE_LINE_MEMBER(snug_bwg_device::den_w)
+void snug_bwg_device::den_w(int state)
{
// (De)select the card. Indicated by a LED on the board.
m_selected = state;
LOGMASKED(LOG_CRU, "Map DSR (bit 0) = %d\n", m_selected);
}
-WRITE_LINE_MEMBER(snug_bwg_device::mop_w)
+void snug_bwg_device::mop_w(int state)
{
m_motormf->b_w(state);
}
-WRITE_LINE_MEMBER(snug_bwg_device::waiten_w)
+void snug_bwg_device::waiten_w(int state)
{
/* Set disk ready/hold (bit 2) */
// 0: ignore IRQ and DRQ
@@ -412,29 +413,29 @@ WRITE_LINE_MEMBER(snug_bwg_device::waiten_w)
LOGMASKED(LOG_CRU, "Arm wait state logic (bit 2) = %d\n", state);
}
-WRITE_LINE_MEMBER(snug_bwg_device::hlt_w)
+void snug_bwg_device::hlt_w(int state)
{
// Load disk heads (HLT pin) (bit 3). Not implemented.
LOGMASKED(LOG_CRU, "Set head load (bit 3) = %d\n", state);
}
/* Drive selects */
-WRITE_LINE_MEMBER(snug_bwg_device::dsel1_w)
+void snug_bwg_device::dsel1_w(int state)
{
select_drive(1, state);
}
-WRITE_LINE_MEMBER(snug_bwg_device::dsel2_w)
+void snug_bwg_device::dsel2_w(int state)
{
select_drive(2, state);
}
-WRITE_LINE_MEMBER(snug_bwg_device::dsel3_w)
+void snug_bwg_device::dsel3_w(int state)
{
select_drive(3, state);
}
-WRITE_LINE_MEMBER(snug_bwg_device::dsel4_w)
+void snug_bwg_device::dsel4_w(int state)
{
select_drive(4, state);
}
@@ -463,26 +464,26 @@ void snug_bwg_device::select_drive(int n, int state)
LOGMASKED(LOG_WARN, "Warning: DSK%d selected while DSK%d not yet unselected\n", n, m_sel_floppy);
}
- if (m_floppy[n-1] != nullptr)
+ if (m_floppy[n-1]->get_device() != nullptr)
{
m_sel_floppy = n;
- m_wd1773->set_floppy(m_floppy[n-1]);
- m_floppy[n-1]->ss_w(m_crulatch0_7->q7_r());
+ m_wd1773->set_floppy(m_floppy[n-1]->get_device());
+ m_floppy[n-1]->get_device()->ss_w(m_crulatch0_7->q7_r());
}
}
}
-WRITE_LINE_MEMBER(snug_bwg_device::sidsel_w)
+void snug_bwg_device::sidsel_w(int state)
{
// Select side of disk (bit 7)
if (m_sel_floppy != 0)
{
LOGMASKED(LOG_CRU, "Set side (bit 7) = %d on DSK%d\n", state, m_sel_floppy);
- m_floppy[m_sel_floppy-1]->ss_w(m_crulatch0_7->q7_r());
+ m_floppy[m_sel_floppy-1]->get_device()->ss_w(m_crulatch0_7->q7_r());
}
}
-WRITE_LINE_MEMBER(snug_bwg_device::dden_w)
+void snug_bwg_device::dden_w(int state)
{
/* double density enable (active low) */
LOGMASKED(LOG_CRU, "Set density (bit 10) = %d (%s)\n", state, (state!=0)? "single" : "double");
@@ -492,7 +493,7 @@ WRITE_LINE_MEMBER(snug_bwg_device::dden_w)
/*
All floppy motors are operated by the same line.
*/
-WRITE_LINE_MEMBER(snug_bwg_device::motorona_w)
+void snug_bwg_device::motorona_w(int state)
{
m_MOTOR_ON = state;
LOGMASKED(LOG_MOTOR, "Motor %s\n", state? "on" : "off");
@@ -502,7 +503,8 @@ WRITE_LINE_MEMBER(snug_bwg_device::motorona_w)
// Set all motors
for (auto & elem : m_floppy)
- if (elem != nullptr) elem->mon_w((state==ASSERT_LINE)? 0 : 1);
+ if (elem->get_device() != nullptr)
+ elem->get_device()->mon_w((state==ASSERT_LINE)? 0 : 1);
// The motor-on line also connects to the wait state logic
operate_ready_line();
@@ -542,12 +544,12 @@ void snug_bwg_device::device_reset()
m_WDsel = false;
m_WDsel0 = false;
- for (int i=0; i < 4; i++)
+ for (auto &flop : m_floppy)
{
- if (m_floppy[i] != nullptr)
- LOGMASKED(LOG_CONFIG, "Connector %d with %s\n", i, m_floppy[i]->name());
+ if (flop->get_device() != nullptr)
+ LOGMASKED(LOG_CONFIG, "Connector %d with %s\n", flop->basetag(), flop->get_device()->name());
else
- LOGMASKED(LOG_CONFIG, "Connector %d has no floppy attached\n", i);
+ LOGMASKED(LOG_CONFIG, "Connector %d has no floppy attached\n", flop->basetag());
}
m_wd1773->set_floppy(nullptr);
@@ -557,18 +559,6 @@ void snug_bwg_device::device_reset()
m_dip34 = ioport("BWGDIP34")->read();
}
-void snug_bwg_device::device_config_complete()
-{
- for (auto & elem : m_floppy)
- elem = nullptr;
-
- // Seems to be null when doing a "-listslots"
- if (subdevice("0")!=nullptr) m_floppy[0] = static_cast<floppy_image_device*>(subdevice("0")->subdevices().first());
- if (subdevice("1")!=nullptr) m_floppy[1] = static_cast<floppy_image_device*>(subdevice("1")->subdevices().first());
- if (subdevice("2")!=nullptr) m_floppy[2] = static_cast<floppy_image_device*>(subdevice("2")->subdevices().first());
- if (subdevice("3")!=nullptr) m_floppy[3] = static_cast<floppy_image_device*>(subdevice("3")->subdevices().first());
-}
-
INPUT_PORTS_START( bwg_fdc )
PORT_START( "BWGDIP1" )
PORT_DIPNAME( 0x01, 0x00, "BwG step rate" )
@@ -615,10 +605,10 @@ void snug_bwg_device::device_add_mconfig(machine_config& config)
MM58274C(config, CLOCK_TAG, 32.768_kHz_XTAL).set_mode_and_day(1, 0); // 24h, sunday
- FLOPPY_CONNECTOR(config, "0", bwg_floppies, "525dd", snug_bwg_device::floppy_formats).enable_sound(true);
- FLOPPY_CONNECTOR(config, "1", bwg_floppies, "525dd", snug_bwg_device::floppy_formats).enable_sound(true);
- FLOPPY_CONNECTOR(config, "2", bwg_floppies, nullptr, snug_bwg_device::floppy_formats).enable_sound(true);
- FLOPPY_CONNECTOR(config, "3", bwg_floppies, nullptr, snug_bwg_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[0], bwg_floppies, "525dd", snug_bwg_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[1], bwg_floppies, "525dd", snug_bwg_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[2], bwg_floppies, nullptr, snug_bwg_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[3], bwg_floppies, nullptr, snug_bwg_device::floppy_formats).enable_sound(true);
RAM(config, BUFFER).set_default_size("2K").set_default_value(0);
diff --git a/src/devices/bus/ti99/peb/bwg.h b/src/devices/bus/ti99/peb/bwg.h
index 671f584dc9a..4739c09c175 100644
--- a/src/devices/bus/ti99/peb/bwg.h
+++ b/src/devices/bus/ti99/peb/bwg.h
@@ -39,33 +39,32 @@ public:
void cruwrite(offs_t offset, uint8_t data) override;
protected:
- void device_start() override;
- void device_reset() override;
- void device_config_complete() override;
+ virtual void device_start() override;
+ virtual void device_reset() override;
- const tiny_rom_entry *device_rom_region() const override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
virtual void device_add_mconfig(machine_config &config) override;
- ioport_constructor device_input_ports() const override;
+ virtual ioport_constructor device_input_ports() const override;
private:
static void floppy_formats(format_registration &fr);
- DECLARE_WRITE_LINE_MEMBER( fdc_irq_w );
- DECLARE_WRITE_LINE_MEMBER( fdc_drq_w );
+ void fdc_irq_w(int state);
+ void fdc_drq_w(int state);
// Latch callbacks
- DECLARE_WRITE_LINE_MEMBER( den_w );
- DECLARE_WRITE_LINE_MEMBER( mop_w );
- DECLARE_WRITE_LINE_MEMBER( waiten_w );
- DECLARE_WRITE_LINE_MEMBER( hlt_w );
- DECLARE_WRITE_LINE_MEMBER( dsel1_w );
- DECLARE_WRITE_LINE_MEMBER( dsel2_w );
- DECLARE_WRITE_LINE_MEMBER( dsel3_w );
- DECLARE_WRITE_LINE_MEMBER( dsel4_w );
- DECLARE_WRITE_LINE_MEMBER( sidsel_w );
- DECLARE_WRITE_LINE_MEMBER( dden_w );
-
- DECLARE_WRITE_LINE_MEMBER( motorona_w );
+ void den_w(int state);
+ void mop_w(int state);
+ void waiten_w(int state);
+ void hlt_w(int state);
+ void dsel1_w(int state);
+ void dsel2_w(int state);
+ void dsel3_w(int state);
+ void dsel4_w(int state);
+ void sidsel_w(int state);
+ void dden_w(int state);
+
+ void motorona_w(int state);
void select_drive(int n, int state);
@@ -113,7 +112,7 @@ private:
required_device<ram_device> m_buffer_ram;
// Link to the attached floppy drives
- floppy_image_device* m_floppy[4];
+ required_device_array<floppy_connector, 4> m_floppy;
// Currently selected floppy drive (1-4, 0=none)
int m_sel_floppy;
diff --git a/src/devices/bus/ti99/peb/cc_fdc.cpp b/src/devices/bus/ti99/peb/cc_fdc.cpp
index 6762dea8a05..88fa46d2aa3 100644
--- a/src/devices/bus/ti99/peb/cc_fdc.cpp
+++ b/src/devices/bus/ti99/peb/cc_fdc.cpp
@@ -32,18 +32,18 @@
// ----------------------------------
// Flags for debugging
-#define LOG_WARN (1U<<1) // Warnings
-#define LOG_CONFIG (1U<<2) // Configuration
-#define LOG_EPROM (1U<<3) // Access to EPROM
-#define LOG_CONTR (1U<<4) // Access to controller
-#define LOG_RAM (1U<<5) // Access to SRAM
-#define LOG_READY (1U<<6) // READY line
-#define LOG_SIGNALS (1U<<7) // IRQ and HLD lines
-#define LOG_DRQ (1U<<8) // DRQ line (too noisy in SIGNALS)
-#define LOG_DRIVE (1U<<9) // Drive operations
-#define LOG_CRU (1U<<10) // CRU operations
-
-#define VERBOSE ( LOG_GENERAL | LOG_WARN | LOG_CONFIG )
+#define LOG_WARN (1U << 1) // Warnings
+#define LOG_CONFIG (1U << 2) // Configuration
+#define LOG_EPROM (1U << 3) // Access to EPROM
+#define LOG_CONTR (1U << 4) // Access to controller
+#define LOG_RAM (1U << 5) // Access to SRAM
+#define LOG_READY (1U << 6) // READY line
+#define LOG_SIGNALS (1U << 7) // IRQ and HLD lines
+#define LOG_DRQ (1U << 8) // DRQ line (too noisy in SIGNALS)
+#define LOG_DRIVE (1U << 9) // Drive operations
+#define LOG_CRU (1U << 10) // CRU operations
+
+#define VERBOSE (LOG_GENERAL | LOG_WARN | LOG_CONFIG)
#include "logmacro.h"
#define CCDCC_TAG "ti99_ccdcc"
@@ -72,12 +72,13 @@ namespace bus::ti99::peb {
// ----------------------------------
-corcomp_fdc_device::corcomp_fdc_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock):
+corcomp_fdc_device::corcomp_fdc_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, const char *dpname, const char *cpname):
device_t(mconfig, type, tag, owner, clock),
device_ti99_peribox_card_interface(mconfig, *this),
m_wdc(*this, WDC_TAG),
- m_decpal(nullptr),
- m_ctrlpal(nullptr),
+ m_decpal(*this, dpname),
+ m_ctrlpal(*this, cpname),
+ m_floppy(*this, "%u", 0),
m_motormf(*this, MOTORMF_TAG),
m_tms9901(*this, TMS9901_TAG),
m_buffer_ram(*this, BUFFER),
@@ -177,19 +178,19 @@ void corcomp_fdc_device::operate_ready_line()
/*
Callbacks from the WDC chip
*/
-WRITE_LINE_MEMBER( corcomp_fdc_device::fdc_irq_w )
+void corcomp_fdc_device::fdc_irq_w(int state)
{
LOGMASKED(LOG_SIGNALS, "INTRQ callback = %d\n", state);
operate_ready_line();
}
-WRITE_LINE_MEMBER( corcomp_fdc_device::fdc_drq_w )
+void corcomp_fdc_device::fdc_drq_w(int state)
{
LOGMASKED(LOG_DRQ, "DRQ callback = %d\n", state);
operate_ready_line();
}
-WRITE_LINE_MEMBER( corcomp_fdc_device::fdc_hld_w )
+void corcomp_fdc_device::fdc_hld_w(int state)
{
LOGMASKED(LOG_SIGNALS, "HLD callback = %d\n", state);
}
@@ -281,7 +282,7 @@ void corcomp_fdc_device::cruwrite(offs_t offset, uint8_t data)
}
}
-WRITE_LINE_MEMBER( corcomp_fdc_device::clock_in )
+void corcomp_fdc_device::clock_in(int state)
{
m_tms9901->phi_line(state);
}
@@ -329,7 +330,7 @@ uint8_t corcomp_fdc_device::tms9901_input(offs_t offset)
}
}
-WRITE_LINE_MEMBER( corcomp_fdc_device::select_dsk )
+void corcomp_fdc_device::select_dsk(int state)
{
if (state == CLEAR_LINE)
{
@@ -363,49 +364,51 @@ WRITE_LINE_MEMBER( corcomp_fdc_device::select_dsk )
}
LOGMASKED(LOG_DRIVE, "Select drive DSK%d\n", m_selected_drive);
- if (m_floppy[m_selected_drive-1] != nullptr)
+ if (m_floppy[m_selected_drive-1]->get_device() != nullptr)
{
- m_wdc->set_floppy(m_floppy[m_selected_drive-1]);
- m_floppy[m_selected_drive-1]->ss_w(m_tms9901->read_bit(tms9901_device::INT15_P7));
+ m_wdc->set_floppy(m_floppy[m_selected_drive-1]->get_device());
+ m_floppy[m_selected_drive-1]->get_device()->ss_w(m_tms9901->read_bit(tms9901_device::INT15_P7));
}
}
}
-WRITE_LINE_MEMBER( corcomp_fdc_device::side_select )
+void corcomp_fdc_device::side_select(int state)
{
// Select side of disk (bit 7)
if (m_selected_drive != 0)
{
LOGMASKED(LOG_DRIVE, "Set side (bit 7) = %d on DSK%d\n", state, m_selected_drive);
- m_floppy[m_selected_drive-1]->ss_w(state);
+ m_floppy[m_selected_drive-1]->get_device()->ss_w(state);
}
}
/*
All floppy motors are operated by the same line.
*/
-WRITE_LINE_MEMBER( corcomp_fdc_device::motor_w )
+void corcomp_fdc_device::motor_w(int state)
{
LOGMASKED(LOG_DRIVE, "Motor %s\n", state? "on" : "off");
m_wdc->set_force_ready(state==ASSERT_LINE);
// Set all motors
- for (auto & elem : m_floppy)
- if (elem != nullptr) elem->mon_w((state==ASSERT_LINE)? 0 : 1);
+ for (auto &elem : m_floppy)
+ if (elem->get_device() != nullptr)
+ elem->get_device()->mon_w((state==ASSERT_LINE)? 0 : 1);
+
operate_ready_line();
}
/*
Push the P11 state to the variable.
*/
-WRITE_LINE_MEMBER( corcomp_fdc_device::select_bank )
+void corcomp_fdc_device::select_bank(int state)
{
LOGMASKED(LOG_CRU, "Set bank %d\n", state);
m_banksel = (state==ASSERT_LINE);
operate_ready_line();
}
-WRITE_LINE_MEMBER( corcomp_fdc_device::select_card )
+void corcomp_fdc_device::select_card(int state)
{
LOGMASKED(LOG_CRU, "Select card = %d\n", state);
m_cardsel = (state==ASSERT_LINE);
@@ -426,24 +429,17 @@ void corcomp_fdc_device::device_start()
void corcomp_fdc_device::device_reset()
{
- for (int i=0; i < 4; i++)
+ for (auto &flop : m_floppy)
{
- if (m_floppy[i] != nullptr)
- LOGMASKED(LOG_CONFIG, "Connector %d with %s\n", i, m_floppy[i]->name());
+ if (flop->get_device() != nullptr)
+ LOGMASKED(LOG_CONFIG, "Connector %d with %s\n", flop->basetag(), flop->get_device()->name());
else
- LOGMASKED(LOG_CONFIG, "Connector %d has no floppy attached\n", i);
+ LOGMASKED(LOG_CONFIG, "Connector %d has no floppy attached\n", flop->basetag());
}
-}
-
-void corcomp_fdc_device::connect_drives()
-{
- for (auto & elem : m_floppy)
- elem = nullptr;
- if (subdevice("0")!=nullptr) m_floppy[0] = static_cast<floppy_image_device*>(subdevice("0")->subdevices().first());
- if (subdevice("1")!=nullptr) m_floppy[1] = static_cast<floppy_image_device*>(subdevice("1")->subdevices().first());
- if (subdevice("2")!=nullptr) m_floppy[2] = static_cast<floppy_image_device*>(subdevice("2")->subdevices().first());
- if (subdevice("3")!=nullptr) m_floppy[3] = static_cast<floppy_image_device*>(subdevice("3")->subdevices().first());
+ m_decpal->set_board(this);
+ m_ctrlpal->set_board(this);
+ m_ctrlpal->set_decoder(m_decpal);
}
INPUT_PORTS_START( cc_fdc )
@@ -528,10 +524,10 @@ void corcomp_fdc_device::common_config(machine_config& config)
m_motormf->set_clear_pin_value(1);
m_motormf->out_cb().set(FUNC(corcomp_fdc_device::motor_w));
- FLOPPY_CONNECTOR(config, "0", ccfdc_floppies, "525dd", corcomp_fdc_device::floppy_formats).enable_sound(true);
- FLOPPY_CONNECTOR(config, "1", ccfdc_floppies, "525dd", corcomp_fdc_device::floppy_formats).enable_sound(true);
- FLOPPY_CONNECTOR(config, "2", ccfdc_floppies, nullptr, corcomp_fdc_device::floppy_formats).enable_sound(true);
- FLOPPY_CONNECTOR(config, "3", ccfdc_floppies, nullptr, corcomp_fdc_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[0], ccfdc_floppies, "525dd", corcomp_fdc_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[1], ccfdc_floppies, "525dd", corcomp_fdc_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[2], ccfdc_floppies, nullptr, corcomp_fdc_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[3], ccfdc_floppies, nullptr, corcomp_fdc_device::floppy_formats).enable_sound(true);
// SRAM 2114 1Kx4
RAM(config, BUFFER).set_default_size("1k").set_default_value(0);
@@ -542,7 +538,7 @@ void corcomp_fdc_device::common_config(machine_config& config)
// ============================================================================
corcomp_dcc_device::corcomp_dcc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock):
- corcomp_fdc_device(mconfig, TI99_CCDCC, tag, owner, clock)
+ corcomp_fdc_device(mconfig, TI99_CCDCC, tag, owner, clock, CCDCC_PALU2_TAG, CCDCC_PALU1_TAG)
{
}
@@ -565,13 +561,6 @@ ROM_START( cc_dcc )
ROM_LOAD("ccdcc_v89.u4", 0x2000, 0x2000, CRC(9c4e5c08) SHA1(26f8096ae60f3839902b4e8764c5fde283ad4ba2)) /* 8K single ROM bank 2*/
ROM_END
-void corcomp_dcc_device::device_config_complete()
-{
- m_decpal = static_cast<ccfdc_dec_pal_device*>(subdevice(CCDCC_PALU2_TAG));
- m_ctrlpal = static_cast<ccfdc_sel_pal_device*>(subdevice(CCDCC_PALU1_TAG));
- connect_drives();
-}
-
ioport_constructor corcomp_fdc_device::device_input_ports() const
{
return INPUT_PORTS_NAME( cc_fdc );
@@ -603,15 +592,10 @@ ccfdc_sel_pal_device::ccfdc_sel_pal_device(const machine_config &mconfig, device
{
}
-void ccfdc_dec_pal_device::device_config_complete()
-{
- m_board = static_cast<corcomp_fdc_device*>(owner());
-}
-
/*
Indicates 9901 addressing.
*/
-READ_LINE_MEMBER( ccfdc_dec_pal_device::address9901 )
+int ccfdc_dec_pal_device::address9901()
{
return ((m_board->get_address() & 0xff80)==0x1100)? ASSERT_LINE : CLEAR_LINE;
}
@@ -619,7 +603,7 @@ READ_LINE_MEMBER( ccfdc_dec_pal_device::address9901 )
/*
Indicates SRAM addressing.
*/
-READ_LINE_MEMBER( ccfdc_dec_pal_device::addressram )
+int ccfdc_dec_pal_device::addressram()
{
return ((m_board->card_selected()) &&
(m_board->get_address() & 0xff80)==0x4000)? ASSERT_LINE : CLEAR_LINE;
@@ -628,7 +612,7 @@ READ_LINE_MEMBER( ccfdc_dec_pal_device::addressram )
/*
Indicates WDC addressing.
*/
-READ_LINE_MEMBER( ccfdc_dec_pal_device::addresswdc )
+int ccfdc_dec_pal_device::addresswdc()
{
return ((m_board->card_selected()) &&
(m_board->get_address() & 0xff80)==0x5f80)? ASSERT_LINE : CLEAR_LINE;
@@ -637,7 +621,7 @@ READ_LINE_MEMBER( ccfdc_dec_pal_device::addresswdc )
/*
Indicates DSR addressing.
*/
-READ_LINE_MEMBER( ccfdc_dec_pal_device::address4 )
+int ccfdc_dec_pal_device::address4()
{
return ((m_board->card_selected()) &&
(m_board->get_address() & 0xe000)==0x4000)? ASSERT_LINE : CLEAR_LINE;
@@ -646,7 +630,7 @@ READ_LINE_MEMBER( ccfdc_dec_pal_device::address4 )
/*
Indicates SRAM selection.
*/
-READ_LINE_MEMBER( ccfdc_sel_pal_device::selectram )
+int ccfdc_sel_pal_device::selectram()
{
return (m_decpal->addressram() && (m_board->upper_bank()))
? ASSERT_LINE : CLEAR_LINE;
@@ -655,7 +639,7 @@ READ_LINE_MEMBER( ccfdc_sel_pal_device::selectram )
/*
Indicates WDC selection.
*/
-READ_LINE_MEMBER( ccfdc_sel_pal_device::selectwdc )
+int ccfdc_sel_pal_device::selectwdc()
{
return (m_decpal->addresswdc() && ((m_board->get_address()&1)==0))? ASSERT_LINE : CLEAR_LINE;
}
@@ -663,7 +647,7 @@ READ_LINE_MEMBER( ccfdc_sel_pal_device::selectwdc )
/*
Indicates EPROM selection.
*/
-READ_LINE_MEMBER( ccfdc_sel_pal_device::selectdsr )
+int ccfdc_sel_pal_device::selectdsr()
{
return (m_decpal->address4()
&& !m_decpal->addresswdc()
@@ -690,7 +674,7 @@ ccdcc_palu1_device::ccdcc_palu1_device(const machine_config &mconfig, const char
/*
Wait state logic
*/
-READ_LINE_MEMBER( ccdcc_palu1_device::ready_out )
+int ccdcc_palu1_device::ready_out()
{
bool wdc = m_decpal->addresswdc(); // Addressing the WDC
bool lastdig = (m_board->get_address()&7)==6; // Address ends with 6 or e (5ff6, 5ffe)
@@ -705,18 +689,12 @@ READ_LINE_MEMBER( ccdcc_palu1_device::ready_out )
return ready;
}
-void ccdcc_palu1_device::device_config_complete()
-{
- m_board = static_cast<corcomp_fdc_device*>(owner());
- m_decpal = static_cast<ccfdc_dec_pal_device*>(owner()->subdevice(CCDCC_PALU2_TAG));
-}
-
// ============================================================================
// Revised CorComp floppy disk controller card REV A
// ============================================================================
corcomp_fdca_device::corcomp_fdca_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock):
- corcomp_fdc_device(mconfig, TI99_CCFDC, tag, owner, clock)
+ corcomp_fdc_device(mconfig, TI99_CCFDC, tag, owner, clock, CCFDC_PALU12_TAG, CCFDC_PALU6_TAG)
{
}
@@ -746,13 +724,6 @@ ROM_START( cc_fdcmg )
ROM_LOAD("ccfdc_v89mg.u2", 0x2000, 0x2000, CRC(0cad8f5b) SHA1(7744f777b51eedf614f766576bbc3f8c2c2e0042)) /* 16K single ROM */
ROM_END
-void corcomp_fdca_device::device_config_complete()
-{
- m_decpal = static_cast<ccfdc_dec_pal_device*>(subdevice(CCFDC_PALU12_TAG));
- m_ctrlpal = static_cast<ccfdc_sel_pal_device*>(subdevice(CCFDC_PALU6_TAG));
- connect_drives();
-}
-
const tiny_rom_entry *corcomp_fdca_device::device_rom_region() const
{
return ROM_NAME( cc_fdcmg );
@@ -773,7 +744,7 @@ ccfdc_palu12_device::ccfdc_palu12_device(const machine_config &mconfig, const ch
Indicates 9901 addressing. In this PAL version, the A9 address line is
also used.
*/
-READ_LINE_MEMBER( ccfdc_palu12_device::address9901 )
+int ccfdc_palu12_device::address9901()
{
return ((m_board->get_address() & 0xffc0)==0x1100)? ASSERT_LINE : CLEAR_LINE;
}
@@ -788,7 +759,7 @@ ccfdc_palu6_device::ccfdc_palu6_device(const machine_config &mconfig, const char
That is, when writing (/WE=0), A12 must be 1 (addresses 5ff8..e),
otherwise (/WE=1), A12 must be 0 (addresses 5ff0..6)
*/
-READ_LINE_MEMBER( ccfdc_palu6_device::selectwdc )
+int ccfdc_palu6_device::selectwdc()
{
return (m_decpal->addresswdc()
&& ((m_board->get_address()&1)==0)
@@ -799,7 +770,7 @@ READ_LINE_MEMBER( ccfdc_palu6_device::selectwdc )
Indicates EPROM selection. The Rev A selector PAL leads back some of
its outputs for this calculation.
*/
-READ_LINE_MEMBER( ccfdc_palu6_device::selectdsr )
+int ccfdc_palu6_device::selectdsr()
{
return (m_decpal->address4() && !selectwdc() && !selectram())? ASSERT_LINE : CLEAR_LINE;
}
@@ -809,11 +780,16 @@ READ_LINE_MEMBER( ccfdc_palu6_device::selectdsr )
board which evaluates whether the trap is active.
*/
-READ_LINE_MEMBER( ccfdc_palu6_device::ready_out )
+int ccfdc_palu6_device::ready_out()
{
bool wdc = m_decpal->addresswdc(); // Addressing the WDC
bool even = (m_board->get_address()&1)==0; // A15 = 0
- bool trap = static_cast<corcomp_fdca_device*>(m_board)->ready_trap_active(); // READY trap active
+ bool trap = false;
+
+ // The PAL u6 is only used on the Rev A board
+ corcomp_fdca_device* boarda = static_cast<corcomp_fdca_device*>(m_board);
+ trap = boarda->ready_trap_active(); // READY trap active
+
bool waitbyte = m_wdc->drq_r()==CLEAR_LINE; // We are waiting for a byte
bool noterm = m_wdc->intrq_r()==CLEAR_LINE; // There is no interrupt yet
@@ -823,10 +799,4 @@ READ_LINE_MEMBER( ccfdc_palu6_device::ready_out )
return ready;
}
-void ccfdc_palu6_device::device_config_complete()
-{
- m_board = static_cast<corcomp_fdca_device*>(owner());
- m_decpal = static_cast<ccfdc_dec_pal_device*>(owner()->subdevice(CCFDC_PALU12_TAG));
-}
-
} // end namespace bus::ti99::peb
diff --git a/src/devices/bus/ti99/peb/cc_fdc.h b/src/devices/bus/ti99/peb/cc_fdc.h
index e72bfa3ea57..736b8c0ae14 100644
--- a/src/devices/bus/ti99/peb/cc_fdc.h
+++ b/src/devices/bus/ti99/peb/cc_fdc.h
@@ -44,27 +44,26 @@ public:
void crureadz(offs_t offset, uint8_t *value) override;
void cruwrite(offs_t offset, uint8_t data) override;
- DECLARE_WRITE_LINE_MEMBER(clock_in) override;
+ void clock_in(int state) override;
- DECLARE_WRITE_LINE_MEMBER( fdc_irq_w );
- DECLARE_WRITE_LINE_MEMBER( fdc_drq_w );
- DECLARE_WRITE_LINE_MEMBER( fdc_hld_w );
+ void fdc_irq_w(int state);
+ void fdc_drq_w(int state);
+ void fdc_hld_w(int state);
uint8_t tms9901_input(offs_t offset);
- DECLARE_WRITE_LINE_MEMBER( select_dsk );
- DECLARE_WRITE_LINE_MEMBER( side_select );
- DECLARE_WRITE_LINE_MEMBER( motor_w );
- DECLARE_WRITE_LINE_MEMBER( select_card );
- DECLARE_WRITE_LINE_MEMBER( select_bank );
+ void select_dsk(int state);
+ void side_select(int state);
+ void motor_w(int state);
+ void select_card(int state);
+ void select_bank(int state);
protected:
- corcomp_fdc_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+ corcomp_fdc_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, const char *dpname, const char *cpname);
- void device_start() override;
- void device_reset() override;
- void connect_drives();
+ virtual void device_start() override;
+ virtual void device_reset() override;
virtual void device_add_mconfig(machine_config &config) override =0;
- ioport_constructor device_input_ports() const override;
+ virtual ioport_constructor device_input_ports() const override;
void common_config(machine_config& config);
@@ -74,8 +73,8 @@ protected:
required_device<wd_fdc_device_base> m_wdc;
// PALs
- ccfdc_dec_pal_device* m_decpal;
- ccfdc_sel_pal_device* m_ctrlpal;
+ required_device<ccfdc_dec_pal_device> m_decpal;
+ required_device<ccfdc_sel_pal_device> m_ctrlpal;
// Lines that are polled by the PAL chips
bool card_selected();
@@ -90,7 +89,7 @@ protected:
void operate_ready_line();
// Link to the attached floppy drives
- floppy_image_device* m_floppy[4];
+ required_device_array<floppy_connector, 4> m_floppy;
// Motor monoflop
required_device<ttl74123_device> m_motormf;
@@ -131,52 +130,56 @@ class corcomp_dcc_device : public corcomp_fdc_device
{
public:
corcomp_dcc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-private:
- void device_add_mconfig(machine_config &config) override;
- void device_config_complete() override;
- const tiny_rom_entry *device_rom_region() const override;
+protected:
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
};
// =========== Decoder PAL circuit ================
class ccfdc_dec_pal_device : public device_t
{
+ friend class corcomp_fdc_device;
public:
- DECLARE_READ_LINE_MEMBER(addresswdc);
- DECLARE_READ_LINE_MEMBER(address4);
- DECLARE_READ_LINE_MEMBER(addressram);
- virtual DECLARE_READ_LINE_MEMBER(address9901);
+ int addresswdc();
+ int address4();
+ int addressram();
+ virtual int address9901();
protected:
ccfdc_dec_pal_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
void device_start() override { }
- void device_config_complete() override;
corcomp_fdc_device* m_board;
required_device<tms9901_device> m_tms9901;
+
+ void set_board(corcomp_fdc_device* board) { m_board = board; }
};
// =========== Selector PAL circuit ================
class ccfdc_sel_pal_device : public device_t
{
+ friend class corcomp_fdc_device;
public:
- DECLARE_READ_LINE_MEMBER(selectram);
- virtual DECLARE_READ_LINE_MEMBER(selectwdc);
- virtual DECLARE_READ_LINE_MEMBER(selectdsr);
- virtual DECLARE_READ_LINE_MEMBER(ready_out) =0;
+ int selectram();
+ virtual int selectwdc();
+ virtual int selectdsr();
+ virtual int ready_out() =0;
protected:
ccfdc_sel_pal_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
- void device_start() override { }
- virtual void device_config_complete() override =0;
+ virtual void device_start() override { }
corcomp_fdc_device* m_board;
ccfdc_dec_pal_device* m_decpal;
required_device<ttl74123_device> m_motormf;
required_device<tms9901_device> m_tms9901;
required_device<wd_fdc_device_base> m_wdc;
+
+ void set_board(corcomp_fdc_device* board) { m_board = board; }
+ void set_decoder(ccfdc_dec_pal_device* decpal) { m_decpal = decpal; }
};
// =========== Specific decoder PAL circuit of the CCDCC ================
@@ -193,10 +196,7 @@ class ccdcc_palu1_device : public ccfdc_sel_pal_device
{
public:
ccdcc_palu1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ_LINE_MEMBER(ready_out) override;
-
-private:
- void device_config_complete() override;
+ int ready_out() override;
};
// ============================================================================
@@ -209,10 +209,10 @@ class corcomp_fdca_device : public corcomp_fdc_device
public:
corcomp_fdca_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+protected:
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
private:
- void device_add_mconfig(machine_config &config) override;
- void device_config_complete() override;
- const tiny_rom_entry *device_rom_region() const override;
bool ready_trap_active();
};
@@ -222,7 +222,7 @@ class ccfdc_palu12_device : public ccfdc_dec_pal_device
{
public:
ccfdc_palu12_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ_LINE_MEMBER(address9901) override;
+ int address9901() override;
};
// =========== Specific selector PAL circuit of the CCFDC ================
@@ -231,13 +231,10 @@ class ccfdc_palu6_device : public ccfdc_sel_pal_device
{
public:
ccfdc_palu6_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- DECLARE_READ_LINE_MEMBER(selectwdc) override;
- DECLARE_READ_LINE_MEMBER(selectdsr) override;
+ int selectwdc() override;
+ int selectdsr() override;
- DECLARE_READ_LINE_MEMBER(ready_out) override;
-
-private:
- void device_config_complete() override;
+ int ready_out() override;
};
} // end namespace bus::ti99::peb
diff --git a/src/devices/bus/ti99/peb/evpc.cpp b/src/devices/bus/ti99/peb/evpc.cpp
index 974d786d8ee..31fff7e1182 100644
--- a/src/devices/bus/ti99/peb/evpc.cpp
+++ b/src/devices/bus/ti99/peb/evpc.cpp
@@ -43,12 +43,12 @@
#include "speaker.h"
-#define LOG_WARN (1U<<1) // Warnings
-#define LOG_CRU (1U<<2) // CRU access
-#define LOG_MEM (1U<<3) // Memory access
-#define LOG_ADDRESS (1U<<4) // Addresses
+#define LOG_WARN (1U << 1) // Warnings
+#define LOG_CRU (1U << 2) // CRU access
+#define LOG_MEM (1U << 3) // Memory access
+#define LOG_ADDRESS (1U << 4) // Addresses
-#define VERBOSE ( LOG_GENERAL | LOG_WARN )
+#define VERBOSE (LOG_GENERAL | LOG_WARN)
#include "logmacro.h"
#define EVPC_SCREEN_TAG "screen"
@@ -133,8 +133,8 @@ void snug_enhanced_video_device::nvram_default()
bool snug_enhanced_video_device::nvram_read(util::read_stream &file)
{
- size_t actual;
- return !file.read(m_novram.get(), NOVRAM_SIZE, actual) && actual == NOVRAM_SIZE;
+ auto const [err, actual] = util::read(file, m_novram.get(), NOVRAM_SIZE);
+ return !err && (actual == NOVRAM_SIZE);
}
//-------------------------------------------------
@@ -144,8 +144,8 @@ bool snug_enhanced_video_device::nvram_read(util::read_stream &file)
bool snug_enhanced_video_device::nvram_write(util::write_stream &file)
{
- size_t actual;
- return !file.write(m_novram.get(), NOVRAM_SIZE, actual) && actual == NOVRAM_SIZE;
+ auto const [err, actual] = util::write(file, m_novram.get(), NOVRAM_SIZE);
+ return !err;
}
/*
@@ -399,7 +399,7 @@ void snug_enhanced_video_device::cruwrite(offs_t offset, uint8_t data)
/*
READY line for the sound chip
*/
-WRITE_LINE_MEMBER( snug_enhanced_video_device::ready_line )
+void snug_enhanced_video_device::ready_line(int state)
{
m_slot->set_ready(state);
}
@@ -438,7 +438,7 @@ void snug_enhanced_video_device::device_stop()
For the SGCPU, the signal is delivered by the LCP line.
*/
-WRITE_LINE_MEMBER( snug_enhanced_video_device::video_interrupt_in )
+void snug_enhanced_video_device::video_interrupt_in(int state)
{
// This method is frequently called without level change, so we only
// react on changes
diff --git a/src/devices/bus/ti99/peb/evpc.h b/src/devices/bus/ti99/peb/evpc.h
index 683933a5780..f2f14675cf1 100644
--- a/src/devices/bus/ti99/peb/evpc.h
+++ b/src/devices/bus/ti99/peb/evpc.h
@@ -62,9 +62,9 @@ protected:
virtual bool nvram_write(util::write_stream &file) override;
private:
- DECLARE_WRITE_LINE_MEMBER( ready_line );
+ void ready_line(int state);
- DECLARE_WRITE_LINE_MEMBER( video_interrupt_in );
+ void video_interrupt_in(int state);
int m_address;
int m_dsr_page;
diff --git a/src/devices/bus/ti99/peb/forti.cpp b/src/devices/bus/ti99/peb/forti.cpp
index 0ee053a740c..25c00556534 100644
--- a/src/devices/bus/ti99/peb/forti.cpp
+++ b/src/devices/bus/ti99/peb/forti.cpp
@@ -30,9 +30,9 @@
#include "emu.h"
#include "forti.h"
-#define LOG_READY (1U<<1)
+#define LOG_READY (1U << 1)
-#define VERBOSE ( LOG_GENERAL )
+#define VERBOSE (LOG_GENERAL)
#include "logmacro.h"
@@ -66,7 +66,7 @@ void forti_device::readz(offs_t offset, uint8_t *value)
/*
READY callbacks from the sound chips.
*/
-WRITE_LINE_MEMBER( forti_device::ready_sound )
+void forti_device::ready_sound(int state)
{
LOGMASKED(LOG_READY, "READY (%d, %d, %d, %d)\n", m_generator1->ready_r(),
m_generator2->ready_r(), m_generator3->ready_r(), m_generator4->ready_r());
diff --git a/src/devices/bus/ti99/peb/forti.h b/src/devices/bus/ti99/peb/forti.h
index 69ad6ddfcab..6deb68f05ed 100644
--- a/src/devices/bus/ti99/peb/forti.h
+++ b/src/devices/bus/ti99/peb/forti.h
@@ -31,7 +31,7 @@ public:
void crureadz(offs_t offset, uint8_t *value) override { }
void cruwrite(offs_t offset, uint8_t data) override { }
- DECLARE_WRITE_LINE_MEMBER( ready_sound );
+ void ready_sound(int state);
private:
void device_start() override;
diff --git a/src/devices/bus/ti99/peb/hfdc.cpp b/src/devices/bus/ti99/peb/hfdc.cpp
index d760f09da20..ad116788507 100644
--- a/src/devices/bus/ti99/peb/hfdc.cpp
+++ b/src/devices/bus/ti99/peb/hfdc.cpp
@@ -59,19 +59,20 @@
#include "formats/mfm_hd.h"
#include "formats/ti99_dsk.h" // Format
-#define LOG_WARN (1U<<1) // Warnings
-#define LOG_EMU (1U<<2)
-#define LOG_COMP (1U<<3)
-#define LOG_RAM (1U<<4)
-#define LOG_ROM (1U<<5)
-#define LOG_LINES (1U<<6)
-#define LOG_DMA (1U<<7)
-#define LOG_MOTOR (1U<<8)
-#define LOG_INT (1U<<9)
-#define LOG_CRU (1U<<10)
-#define LOG_CONFIG (1U<<15) // Configuration
-
-#define VERBOSE ( LOG_GENERAL | LOG_CONFIG | LOG_WARN )
+#define LOG_WARN (1U << 1) // Warnings
+#define LOG_EMU (1U << 2)
+#define LOG_COMP (1U << 3)
+#define LOG_RAM (1U << 4)
+#define LOG_ROM (1U << 5)
+#define LOG_LINES (1U << 6)
+#define LOG_DMA (1U << 7)
+#define LOG_MOTOR (1U << 8)
+#define LOG_INT (1U << 9)
+#define LOG_CRU (1U << 10)
+#define LOG_SKCOM (1U << 11)
+#define LOG_CONFIG (1U << 15) // Configuration
+
+#define VERBOSE (LOG_GENERAL | LOG_CONFIG | LOG_WARN)
#include "logmacro.h"
DEFINE_DEVICE_TYPE(TI99_HFDC, bus::ti99::peb::myarc_hfdc_device, "ti99_hfdc", "Myarc Hard and Floppy Disk Controller")
@@ -101,6 +102,8 @@ myarc_hfdc_device::myarc_hfdc_device(const machine_config &mconfig, const char *
m_motor_on_timer(nullptr),
m_hdc9234(*this, FDC_TAG),
m_clock(*this, CLOCK_TAG),
+ m_floppy(*this, "f%u", 1),
+ m_harddisk(*this, "h%u", 1),
m_current_floppy(nullptr),
m_current_harddisk(nullptr),
m_current_floppy_index(NONE),
@@ -546,7 +549,7 @@ void myarc_hfdc_device::harddisk_ready_callback(mfm_harddisk_device *harddisk, i
*/
void myarc_hfdc_device::harddisk_skcom_callback(mfm_harddisk_device *harddisk, int state)
{
- LOGMASKED(LOG_LINES, "HD seek complete = %d\n", state);
+ LOGMASKED(LOG_SKCOM, "HD seek complete = %d\n", state);
set_bits(m_status_latch, hdc92x4_device::DS_SKCOM, (state==ASSERT_LINE));
signal_drive_status();
}
@@ -726,7 +729,7 @@ void myarc_hfdc_device::connect_floppy_unit(int index)
LOGMASKED(LOG_LINES, "Select floppy drive DSK%d\n", index+1);
// Connect new drive
- m_current_floppy = m_floppy_unit[index];
+ m_current_floppy = m_floppy[index]->get_device();
m_current_floppy_index = index;
// We don't use the READY line of floppy drives.
@@ -756,7 +759,7 @@ void myarc_hfdc_device::connect_harddisk_unit(int index)
LOGMASKED(LOG_LINES, "Select hard disk WDS%d\n", index+1);
// Connect new drive
- m_current_harddisk = m_harddisk_unit[index];
+ m_current_harddisk = m_harddisk[index]->get_device();
m_current_hd_index = index;
LOGMASKED(LOG_LINES, "Connect index callback WDS%d\n", index+1);
@@ -818,14 +821,14 @@ void myarc_hfdc_device::set_floppy_motors_running(bool run)
}
// Set all motors
- for (auto & elem : m_floppy_unit)
- if (elem != nullptr) elem->mon_w((run)? 0 : 1);
+ for (auto & elem : m_floppy)
+ if (elem->get_device() != nullptr) elem->get_device()->mon_w((run)? 0 : 1);
}
/*
Called whenever the state of the HDC9234 interrupt pin changes.
*/
-WRITE_LINE_MEMBER( myarc_hfdc_device::intrq_w )
+void myarc_hfdc_device::intrq_w(int state)
{
m_irq = (line_state)state;
LOGMASKED(LOG_INT, "INT pin from controller = %d, propagating to INTA*\n", state);
@@ -840,7 +843,7 @@ WRITE_LINE_MEMBER( myarc_hfdc_device::intrq_w )
Called whenever the HDC9234 desires bus access to the buffer RAM. The
controller expects a call to dmarq in 1 byte time.
*/
-WRITE_LINE_MEMBER( myarc_hfdc_device::dmarq_w )
+void myarc_hfdc_device::dmarq_w(int state)
{
LOGMASKED(LOG_DMA, "DMARQ pin from controller = %d\n", state);
if (state == ASSERT_LINE)
@@ -852,7 +855,7 @@ WRITE_LINE_MEMBER( myarc_hfdc_device::dmarq_w )
/*
Called whenever the state of the HDC9234 DMA in progress changes.
*/
-WRITE_LINE_MEMBER( myarc_hfdc_device::dip_w )
+void myarc_hfdc_device::dip_w(int state)
{
m_dip = (line_state)state;
}
@@ -942,20 +945,20 @@ void myarc_hfdc_device::device_reset()
m_lastval = 0;
m_readyflags = 0;
- for (int i=0; i < 4; i++)
+ for (auto &flop : m_floppy)
{
- if (m_floppy_unit[i] != nullptr)
- LOGMASKED(LOG_CONFIG, "FD connector %d with %s\n", i+1, m_floppy_unit[i]->name());
+ if (flop->get_device() != nullptr)
+ LOGMASKED(LOG_CONFIG, "FD connector %d with %s\n", flop->basetag(), flop->get_device()->name());
else
- LOGMASKED(LOG_CONFIG, "FD connector %d has no floppy attached\n", i+1);
+ LOGMASKED(LOG_CONFIG, "FD connector %d has no floppy attached\n", flop->basetag());
}
- for (int i=0; i < 3; i++)
+ for (auto &hard : m_harddisk)
{
- if (m_harddisk_unit[i] != nullptr)
- LOGMASKED(LOG_CONFIG, "HD connector %d with %s\n", i+1, m_harddisk_unit[i]->name());
+ if (hard->get_device() != nullptr)
+ LOGMASKED(LOG_CONFIG, "HD connector %d with %s\n", hard->basetag(), hard->get_device()->name());
else
- LOGMASKED(LOG_CONFIG, "HD connector %d has no drive attached\n", i+1);
+ LOGMASKED(LOG_CONFIG, "HD connector %d has no floppy attached\n", hard->basetag());
}
// Disconnect all units
@@ -963,29 +966,6 @@ void myarc_hfdc_device::device_reset()
disconnect_hard_drives();
}
-void myarc_hfdc_device::device_config_complete()
-{
- for (int i=0; i < 3; i++)
- {
- m_floppy_unit[i] = nullptr;
- m_harddisk_unit[i] = nullptr;
- }
- m_floppy_unit[3] = nullptr;
-
- // Seems to be null when doing a "-listslots"
- if (subdevice("f1")!=nullptr)
- {
- m_floppy_unit[0] = static_cast<floppy_connector*>(subdevice("f1"))->get_device();
- m_floppy_unit[1] = static_cast<floppy_connector*>(subdevice("f2"))->get_device();
- m_floppy_unit[2] = static_cast<floppy_connector*>(subdevice("f3"))->get_device();
- m_floppy_unit[3] = static_cast<floppy_connector*>(subdevice("f4"))->get_device();
-
- m_harddisk_unit[0] = static_cast<mfm_harddisk_connector*>(subdevice("h1"))->get_device();
- m_harddisk_unit[1] = static_cast<mfm_harddisk_connector*>(subdevice("h2"))->get_device();
- m_harddisk_unit[2] = static_cast<mfm_harddisk_connector*>(subdevice("h3"))->get_device();
- }
-}
-
/*
The HFDC controller can be configured for different CRU base addresses,
but DSK1-DSK4 are only available for CRU 1100. For all other addresses,
@@ -1079,15 +1059,15 @@ void myarc_hfdc_device::device_add_mconfig(machine_config& config)
m_hdc9234->dmaout_cb().set(FUNC(myarc_hfdc_device::write_buffer));
// First two floppy drives shall be connected by default
- FLOPPY_CONNECTOR(config, "f1", hfdc_floppies, "525dd", myarc_hfdc_device::floppy_formats).enable_sound(true);
- FLOPPY_CONNECTOR(config, "f2", hfdc_floppies, "525dd", myarc_hfdc_device::floppy_formats).enable_sound(true);
- FLOPPY_CONNECTOR(config, "f3", hfdc_floppies, nullptr, myarc_hfdc_device::floppy_formats).enable_sound(true);
- FLOPPY_CONNECTOR(config, "f4", hfdc_floppies, nullptr, myarc_hfdc_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[0], hfdc_floppies, "525dd", myarc_hfdc_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[1], hfdc_floppies, "525dd", myarc_hfdc_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[2], hfdc_floppies, nullptr, myarc_hfdc_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[3], hfdc_floppies, nullptr, myarc_hfdc_device::floppy_formats).enable_sound(true);
// Hard disks don't go without image (other than floppy drives)
- MFM_HD_CONNECTOR(config, "h1", hfdc_harddisks, nullptr, MFM_BYTE, 3000, 20, MFMHD_GEN_FORMAT);
- MFM_HD_CONNECTOR(config, "h2", hfdc_harddisks, nullptr, MFM_BYTE, 3000, 20, MFMHD_GEN_FORMAT);
- MFM_HD_CONNECTOR(config, "h3", hfdc_harddisks, nullptr, MFM_BYTE, 3000, 20, MFMHD_GEN_FORMAT);
+ MFM_HD_CONNECTOR(config, m_harddisk[0], hfdc_harddisks, nullptr, MFM_BYTE, 3000, 20, MFMHD_GEN_FORMAT);
+ MFM_HD_CONNECTOR(config, m_harddisk[1], hfdc_harddisks, nullptr, MFM_BYTE, 3000, 20, MFMHD_GEN_FORMAT);
+ MFM_HD_CONNECTOR(config, m_harddisk[2], hfdc_harddisks, nullptr, MFM_BYTE, 3000, 20, MFMHD_GEN_FORMAT);
MM58274C(config, CLOCK_TAG, 0).set_mode_and_day(1, 0); // 24h, sunday
diff --git a/src/devices/bus/ti99/peb/hfdc.h b/src/devices/bus/ti99/peb/hfdc.h
index ee167421e48..a600412849a 100644
--- a/src/devices/bus/ti99/peb/hfdc.h
+++ b/src/devices/bus/ti99/peb/hfdc.h
@@ -44,8 +44,6 @@ public:
virtual void cruwrite(offs_t offset, uint8_t data) override;
protected:
- virtual void device_config_complete() override;
-
virtual void device_start() override;
virtual void device_reset() override;
@@ -56,9 +54,9 @@ protected:
TIMER_CALLBACK_MEMBER(motor_off);
private:
- DECLARE_WRITE_LINE_MEMBER( dmarq_w );
- DECLARE_WRITE_LINE_MEMBER( intrq_w );
- DECLARE_WRITE_LINE_MEMBER( dip_w );
+ void dmarq_w(int state);
+ void intrq_w(int state);
+ void dip_w(int state);
void auxbus_out(offs_t offset, uint8_t data);
uint8_t read_buffer();
void write_buffer(uint8_t data);
@@ -101,10 +99,10 @@ private:
required_device<mm58274c_device> m_clock;
// Link to the attached floppy drives
- floppy_image_device* m_floppy_unit[4];
+ required_device_array<floppy_connector, 4> m_floppy;
// Link to the attached hard disks
- mfm_harddisk_device* m_harddisk_unit[3];
+ required_device_array<mfm_harddisk_connector, 3> m_harddisk;
// Currently selected floppy drive
floppy_image_device* m_current_floppy;
diff --git a/src/devices/bus/ti99/peb/horizon.cpp b/src/devices/bus/ti99/peb/horizon.cpp
index 4f45d0021e9..20c2cda8835 100644
--- a/src/devices/bus/ti99/peb/horizon.cpp
+++ b/src/devices/bus/ti99/peb/horizon.cpp
@@ -126,16 +126,17 @@
#include "emu.h"
#include "horizon.h"
-#define LOG_WARN (1U<<1) // Warnings
-#define LOG_CONFIG (1U<<2) // Configuration
-#define LOG_32K (1U<<3) // 32K optional RAM r/w
-#define LOG_DSR (1U<<4) // DSR
-#define LOG_RAM (1U<<5) // RAM chips
-#define LOG_ORAM (1U<<6) // outside of RAM chips
-#define LOG_CRU (1U<<7) // CRU
-#define LOG_PAGE (1U<<8) // Page access
-
-#define VERBOSE ( LOG_GENERAL | LOG_CONFIG | LOG_WARN )
+#define LOG_WARN (1U << 1) // Warnings
+#define LOG_CONFIG (1U << 2) // Configuration
+#define LOG_32K (1U << 3) // 32K optional RAM r/w
+#define LOG_DSR (1U << 4) // DSR
+#define LOG_RAM (1U << 5) // RAM chips
+#define LOG_ORAM (1U << 6) // outside of RAM chips
+#define LOG_CRU (1U << 7) // CRU
+#define LOG_PAGE (1U << 8) // Page access
+#define LOG_LINE (1U << 9) // Control lines (like RESET)
+
+#define VERBOSE (LOG_GENERAL | LOG_CONFIG | LOG_WARN)
#include "logmacro.h"
@@ -167,6 +168,7 @@ horizon_ramdisk_device::horizon_ramdisk_device(const machine_config &mconfig, co
m_phoenix_split(false),
m_hideswitch(false),
m_rambo_supported(false),
+ m_reset_in(false),
m_modified(false),
m_page(0),
m_bank(0),
@@ -324,7 +326,6 @@ void horizon_ramdisk_device::read_write(offs_t offset, uint8_t *value, bool writ
*/
void horizon_ramdisk_device::crureadz(offs_t offset, uint8_t *value)
{
- return;
}
/*
@@ -393,6 +394,20 @@ void horizon_ramdisk_device::get_address_prefix()
}
}
+void horizon_ramdisk_device::reset_in(int state)
+{
+ m_reset_in = (state==ASSERT_LINE);
+
+ // While the hideswitch is on, the /RESET line is pulled down
+ if (!m_hideswitch)
+ {
+ LOGMASKED(LOG_LINE, "RESET line=%d\n", m_reset_in);
+ // Reset the 259 latches
+ m_crulatch_u3->clear(m_reset_in);
+ m_crulatch_u4->clear(m_reset_in);
+ }
+}
+
void horizon_ramdisk_device::device_start(void)
{
machine().save().register_postload(save_prepost_delegate(FUNC(horizon_ramdisk_device::get_address_prefix),this));
@@ -421,6 +436,11 @@ INPUT_CHANGED_MEMBER( horizon_ramdisk_device::hs_changed )
{
LOGMASKED(LOG_CONFIG, "Hideswitch changed to %d\n", newval);
m_hideswitch = (newval!=0);
+ if (!m_reset_in)
+ {
+ m_crulatch_u3->clear(m_hideswitch);
+ m_crulatch_u4->clear(m_hideswitch);
+ }
}
else
{
@@ -463,8 +483,8 @@ bool horizon_ramdisk_device::nvram_read(util::read_stream &file)
// Read complete file, at most ramsize+dsrsize
// Mind that the configuration may have changed
- size_t filesize;
- if (file.read(&buffer[0], ramsize + dsrsize, filesize))
+ auto const [err, filesize] = util::read(file, &buffer[0], ramsize + dsrsize);
+ if (err)
return false;
int nvramsize = int(filesize) - dsrsize;
@@ -493,8 +513,8 @@ bool horizon_ramdisk_device::nvram_write(util::write_stream &file)
memcpy(&buffer[ramsize], m_dsrram->pointer(), dsrsize);
// Store both parts in one file
- size_t filesize;
- return !file.write(buffer.get(), ramsize + dsrsize, filesize) && filesize == ramsize + dsrsize;
+ auto const [err, filesize] = util::write(file, buffer.get(), ramsize + dsrsize);
+ return !err;
}
bool horizon_ramdisk_device::nvram_can_write() const
diff --git a/src/devices/bus/ti99/peb/horizon.h b/src/devices/bus/ti99/peb/horizon.h
index 77643cd9ba3..dc15c8586bc 100644
--- a/src/devices/bus/ti99/peb/horizon.h
+++ b/src/devices/bus/ti99/peb/horizon.h
@@ -46,6 +46,8 @@ protected:
virtual bool nvram_write(util::write_stream &file) override;
virtual bool nvram_can_write() const override;
+ void reset_in(int state) override;
+
private:
required_device<ram_device> m_ram;
required_device<ram_device> m_dsrram;
@@ -66,6 +68,8 @@ private:
bool m_hideswitch;
bool m_rambo_supported;
+ bool m_reset_in;
+
// Do not save if nothing was modified.
bool m_modified;
diff --git a/src/devices/bus/ti99/peb/hsgpl.cpp b/src/devices/bus/ti99/peb/hsgpl.cpp
index fc687b25785..11c593cd656 100644
--- a/src/devices/bus/ti99/peb/hsgpl.cpp
+++ b/src/devices/bus/ti99/peb/hsgpl.cpp
@@ -121,18 +121,18 @@
#include "emu.h"
#include "hsgpl.h"
-#define LOG_WARN (1U<<1) // Warnings
-#define LOG_CONFIG (1U<<2) // Configuration
-#define LOG_PORT (1U<<3)
-#define LOG_DSR (1U<<4)
-#define LOG_BANKING (1U<<5)
-#define LOG_CRU (1U<<6)
-#define LOG_ADDRESS (1U<<7)
-#define LOG_READ (1U<<8)
-#define LOG_WRITE (1U<<9)
-#define LOG_IGNORE (1U<<10)
-
-#define VERBOSE ( LOG_CONFIG | LOG_WARN )
+#define LOG_WARN (1U << 1) // Warnings
+#define LOG_CONFIG (1U << 2) // Configuration
+#define LOG_PORT (1U << 3)
+#define LOG_DSR (1U << 4)
+#define LOG_BANKING (1U << 5)
+#define LOG_CRU (1U << 6)
+#define LOG_ADDRESS (1U << 7)
+#define LOG_READ (1U << 8)
+#define LOG_WRITE (1U << 9)
+#define LOG_IGNORE (1U << 10)
+
+#define VERBOSE (LOG_CONFIG | LOG_WARN)
#include "logmacro.h"
diff --git a/src/devices/bus/ti99/peb/memex.cpp b/src/devices/bus/ti99/peb/memex.cpp
index 1ee9bf423e1..67011503bf6 100644
--- a/src/devices/bus/ti99/peb/memex.cpp
+++ b/src/devices/bus/ti99/peb/memex.cpp
@@ -15,13 +15,13 @@
#include "emu.h"
#include "memex.h"
-#define LOG_WARN (1U<<1)
-#define LOG_CONFIG (1U<<2)
-#define LOG_READ (1U<<3)
-#define LOG_WRITE (1U<<4)
-#define LOG_BLOCK (1U<<5)
+#define LOG_WARN (1U << 1)
+#define LOG_CONFIG (1U << 2)
+#define LOG_READ (1U << 3)
+#define LOG_WRITE (1U << 4)
+#define LOG_BLOCK (1U << 5)
-#define VERBOSE ( LOG_CONFIG | LOG_WARN )
+#define VERBOSE (LOG_CONFIG | LOG_WARN)
#include "logmacro.h"
diff --git a/src/devices/bus/ti99/peb/myarcfdc.cpp b/src/devices/bus/ti99/peb/myarcfdc.cpp
index 7df7cf0d261..de8d98962db 100644
--- a/src/devices/bus/ti99/peb/myarcfdc.cpp
+++ b/src/devices/bus/ti99/peb/myarcfdc.cpp
@@ -28,17 +28,17 @@
// ----------------------------------
// Flags for debugging
-#define LOG_WARN (1U<<1) // Warnings
-#define LOG_CONFIG (1U<<2) // Configuration
-#define LOG_EPROM (1U<<3) // Access to EPROM
-#define LOG_CONTR (1U<<4) // Access to controller
-#define LOG_RAM (1U<<5) // Access to SRAM
-#define LOG_IRQ (1U<<7) // IRQ line
-#define LOG_DRQ (1U<<8) // DRQ line
-#define LOG_DRIVE (1U<<9) // Drive operations
-#define LOG_CRU (1U<<10) // CRU operations
-
-#define VERBOSE ( LOG_GENERAL | LOG_WARN | LOG_CONFIG )
+#define LOG_WARN (1U << 1) // Warnings
+#define LOG_CONFIG (1U << 2) // Configuration
+#define LOG_EPROM (1U << 3) // Access to EPROM
+#define LOG_CONTR (1U << 4) // Access to controller
+#define LOG_RAM (1U << 5) // Access to SRAM
+#define LOG_IRQ (1U << 6) // IRQ line
+#define LOG_DRQ (1U << 7) // DRQ line
+#define LOG_DRIVE (1U << 8) // Drive operations
+#define LOG_CRU (1U << 9) // CRU operations
+
+#define VERBOSE (LOG_GENERAL | LOG_WARN | LOG_CONFIG)
#include "logmacro.h"
#define BUFFER_TAG "ram"
@@ -64,6 +64,7 @@ myarc_fdc_device::myarc_fdc_device(const machine_config &mconfig, const char *ta
m_buffer_ram(*this, BUFFER_TAG),
m_pal(*this, PAL_TAG),
m_dsrrom(nullptr),
+ m_floppy(*this, "%u", 0),
m_banksel(false),
m_cardsel(false),
m_selected_drive(0),
@@ -257,61 +258,61 @@ void myarc_fdc_device::cruwrite(offs_t offset, uint8_t data)
/*
Callbacks from the WDC chip
*/
-WRITE_LINE_MEMBER( myarc_fdc_device::fdc_irq_w )
+void myarc_fdc_device::fdc_irq_w(int state)
{
LOGMASKED(LOG_IRQ, "INTRQ callback = %d\n", state);
}
-WRITE_LINE_MEMBER( myarc_fdc_device::fdc_drq_w )
+void myarc_fdc_device::fdc_drq_w(int state)
{
LOGMASKED(LOG_DRQ, "DRQ callback = %d\n", state);
}
-WRITE_LINE_MEMBER( myarc_fdc_device::fdc_mon_w )
+void myarc_fdc_device::fdc_mon_w(int state)
{
LOGMASKED(LOG_DRIVE, "MON callback = %d\n", state);
// All MON lines are connected
// Do not start the motors when no drive is selected. However, motors
// can always be stopped.
if (m_selected_drive != 0 || state==1)
- for (int i = 0; i < 4; i++)
- if (m_floppy[i] != nullptr) m_floppy[i]->mon_w(state);
+ for (auto &flop : m_floppy)
+ if (flop->get_device() != nullptr) flop->get_device()->mon_w(state);
}
/*
Callbacks from the 74LS259 latch
*/
-WRITE_LINE_MEMBER( myarc_fdc_device::den_w )
+void myarc_fdc_device::den_w(int state)
{
LOGMASKED(LOG_CRU, "Card enable = %d\n", state);
m_cardsel = (state==1);
}
-WRITE_LINE_MEMBER( myarc_fdc_device::wdreset_w )
+void myarc_fdc_device::wdreset_w(int state)
{
LOGMASKED(LOG_CRU, "Controller reset = %d\n", state);
m_wdc->mr_w(state);
}
-WRITE_LINE_MEMBER( myarc_fdc_device::sidsel_w )
+void myarc_fdc_device::sidsel_w(int state)
{
LOGMASKED(LOG_CRU, "Side select = %d\n", state);
if (m_selected_drive != 0)
{
LOGMASKED(LOG_DRIVE, "Set side = %d on DSK%d\n", state, m_selected_drive);
- m_floppy[m_selected_drive-1]->ss_w(state);
+ m_floppy[m_selected_drive-1]->get_device()->ss_w(state);
}
}
// Selects the EPROM bank, and also controls the DDEN line
-WRITE_LINE_MEMBER( myarc_fdc_device::bankdden_w )
+void myarc_fdc_device::bankdden_w(int state)
{
LOGMASKED(LOG_CRU, "EPROM bank select = %d\n", state);
m_banksel = (state==ASSERT_LINE);
m_wdc->dden_w(state==1);
}
-WRITE_LINE_MEMBER( myarc_fdc_device::drivesel_w )
+void myarc_fdc_device::drivesel_w(int state)
{
int driveno = 0;
@@ -335,12 +336,12 @@ WRITE_LINE_MEMBER( myarc_fdc_device::drivesel_w )
}
else
{
- if (m_floppy[driveno-1] != nullptr)
+ if (m_floppy[driveno-1]->get_device() != nullptr)
{
m_selected_drive = driveno;
LOGMASKED(LOG_DRIVE, "Select drive DSK%d\n", driveno);
- m_wdc->set_floppy(m_floppy[driveno-1]);
- m_floppy[driveno-1]->ss_w(m_drivelatch->q2_r());
+ m_wdc->set_floppy(m_floppy[driveno-1]->get_device());
+ m_floppy[driveno-1]->get_device()->ss_w(m_drivelatch->q2_r());
}
}
}
@@ -356,23 +357,22 @@ void myarc_fdc_device::device_start()
void myarc_fdc_device::device_reset()
{
+ for (auto &flop : m_floppy)
+ {
+ if (flop->get_device() != nullptr)
+ LOGMASKED(LOG_CONFIG, "Connector %d with %s\n", flop->basetag(), flop->get_device()->name());
+ else
+ LOGMASKED(LOG_CONFIG, "Connector %d has no floppy attached\n", flop->basetag());
+ }
+
if (ioport("CONTROLLER")->read()==0)
m_wdc = m_wd1770;
else
m_wdc = m_wd1772;
m_dec_high = (ioport("AMADECODE")->read()!=0);
-}
-void myarc_fdc_device::device_config_complete()
-{
- for (auto & elem : m_floppy)
- elem = nullptr;
-
- if (subdevice("0")!=nullptr) m_floppy[0] = static_cast<floppy_image_device*>(subdevice("0")->subdevices().first());
- if (subdevice("1")!=nullptr) m_floppy[1] = static_cast<floppy_image_device*>(subdevice("1")->subdevices().first());
- if (subdevice("2")!=nullptr) m_floppy[2] = static_cast<floppy_image_device*>(subdevice("2")->subdevices().first());
- if (subdevice("3")!=nullptr) m_floppy[3] = static_cast<floppy_image_device*>(subdevice("3")->subdevices().first());
+ m_pal->set_board(this);
}
void myarc_fdc_device::floppy_formats(format_registration &fr)
@@ -459,10 +459,10 @@ void myarc_fdc_device::device_add_mconfig(machine_config& config)
DDCC1_PAL(config, PAL_TAG, 0);
// Floppy drives
- FLOPPY_CONNECTOR(config, "0", myarc_ddcc_floppies, "525dd", myarc_fdc_device::floppy_formats).enable_sound(true);
- FLOPPY_CONNECTOR(config, "1", myarc_ddcc_floppies, "525dd", myarc_fdc_device::floppy_formats).enable_sound(true);
- FLOPPY_CONNECTOR(config, "2", myarc_ddcc_floppies, nullptr, myarc_fdc_device::floppy_formats).enable_sound(true);
- FLOPPY_CONNECTOR(config, "3", myarc_ddcc_floppies, nullptr, myarc_fdc_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[0], myarc_ddcc_floppies, "525dd", myarc_fdc_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[1], myarc_ddcc_floppies, "525dd", myarc_fdc_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[2], myarc_ddcc_floppies, nullptr, myarc_fdc_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[3], myarc_ddcc_floppies, nullptr, myarc_fdc_device::floppy_formats).enable_sound(true);
}
ioport_constructor myarc_fdc_device::device_input_ports() const
@@ -512,9 +512,4 @@ bool ddcc1_pal_device::cs259()
return ((m_board->get_address() & 0xff00)==0x1100);
}
-void ddcc1_pal_device::device_config_complete()
-{
- m_board = static_cast<myarc_fdc_device*>(owner());
-}
-
} // end namespace bus::ti99::peb
diff --git a/src/devices/bus/ti99/peb/myarcfdc.h b/src/devices/bus/ti99/peb/myarcfdc.h
index 89106b73e5a..2e3bd355576 100644
--- a/src/devices/bus/ti99/peb/myarcfdc.h
+++ b/src/devices/bus/ti99/peb/myarcfdc.h
@@ -38,27 +38,27 @@ public:
void crureadz(offs_t offset, uint8_t *value) override;
void cruwrite(offs_t offset, uint8_t data) override;
-private:
- void device_start() override;
- void device_reset() override;
- void device_config_complete() override;
+protected:
+ virtual void device_start() override;
+ virtual void device_reset() override;
- const tiny_rom_entry *device_rom_region() const override;
- void device_add_mconfig(machine_config &config) override;
- ioport_constructor device_input_ports() const override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual ioport_constructor device_input_ports() const override;
+private:
static void floppy_formats(format_registration &fr);
// Callback methods
- DECLARE_WRITE_LINE_MEMBER( fdc_irq_w );
- DECLARE_WRITE_LINE_MEMBER( fdc_drq_w );
- DECLARE_WRITE_LINE_MEMBER( fdc_mon_w );
+ void fdc_irq_w(int state);
+ void fdc_drq_w(int state);
+ void fdc_mon_w(int state);
- DECLARE_WRITE_LINE_MEMBER( den_w );
- DECLARE_WRITE_LINE_MEMBER( wdreset_w );
- DECLARE_WRITE_LINE_MEMBER( sidsel_w );
- DECLARE_WRITE_LINE_MEMBER( bankdden_w );
- DECLARE_WRITE_LINE_MEMBER( drivesel_w );
+ void den_w(int state);
+ void wdreset_w(int state);
+ void sidsel_w(int state);
+ void bankdden_w(int state);
+ void drivesel_w(int state);
// Deliver the current state of the address bus
offs_t get_address();
@@ -86,7 +86,7 @@ private:
uint8_t* m_dsrrom;
// Link to the attached floppy drives
- floppy_image_device* m_floppy[4];
+ required_device_array<floppy_connector, 4> m_floppy;
// Debugger accessors
void debug_read(offs_t offset, uint8_t* value);
@@ -111,6 +111,8 @@ private:
// =========== Decoder PAL circuit ================
class ddcc1_pal_device : public device_t
{
+ friend class myarc_fdc_device;
+
public:
ddcc1_pal_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
@@ -123,9 +125,8 @@ public:
private:
void device_start() override { }
- void device_config_complete() override;
-
myarc_fdc_device* m_board;
+ void set_board(myarc_fdc_device* board) { m_board = board; }
};
} // end namespace bus::ti99::peb
diff --git a/src/devices/bus/ti99/peb/pcode.cpp b/src/devices/bus/ti99/peb/pcode.cpp
index 0c5e4e4fb57..270e18d169c 100644
--- a/src/devices/bus/ti99/peb/pcode.cpp
+++ b/src/devices/bus/ti99/peb/pcode.cpp
@@ -75,14 +75,14 @@
#include "emu.h"
#include "pcode.h"
-#define LOG_WARN (1U<<1) // Warnings
-#define LOG_CONFIG (1U<<2) // Configuration
-#define LOG_ROM (1U<<3)
-#define LOG_GROM (1U<<4)
-#define LOG_SWITCH (1U<<5)
-#define LOG_CRU (1U<<6)
+#define LOG_WARN (1U << 1) // Warnings
+#define LOG_CONFIG (1U << 2) // Configuration
+#define LOG_ROM (1U << 3)
+#define LOG_GROM (1U << 4)
+#define LOG_SWITCH (1U << 5)
+#define LOG_CRU (1U << 6)
-#define VERBOSE ( LOG_CONFIG | LOG_WARN )
+#define VERBOSE (LOG_CONFIG | LOG_WARN)
#include "logmacro.h"
@@ -214,7 +214,7 @@ void ti_pcode_card_device::write(offs_t offset, uint8_t data)
/*
Common READY* line from the GROMs.
*/
-WRITE_LINE_MEMBER( ti_pcode_card_device::ready_line )
+void ti_pcode_card_device::ready_line(int state)
{
m_slot->set_ready(state);
}
@@ -224,7 +224,7 @@ WRITE_LINE_MEMBER( ti_pcode_card_device::ready_line )
clock input for the GROMs, which are thus running at a lower rate than
those in the console driven by the VDP (477 kHz).
*/
-WRITE_LINE_MEMBER( ti_pcode_card_device::clock_in)
+void ti_pcode_card_device::clock_in(int state)
{
m_clock_count = (m_clock_count+1) & 0x03; // four pulses high, four pulses low
if (m_clock_count==0)
@@ -260,12 +260,12 @@ void ti_pcode_card_device::cruwrite(offs_t offset, uint8_t data)
m_crulatch->write_bit((offset & 0x80) >> 5 | (offset & 0x06) >> 1, data);
}
-WRITE_LINE_MEMBER(ti_pcode_card_device::pcpage_w)
+void ti_pcode_card_device::pcpage_w(int state)
{
m_selected = state;
}
-WRITE_LINE_MEMBER(ti_pcode_card_device::ekrpg_w)
+void ti_pcode_card_device::ekrpg_w(int state)
{
m_bank_select = state ? 2 : 1; // we're calling this bank 1 and bank 2
LOGMASKED(LOG_CRU, "Select rom bank %d\n", m_bank_select);
diff --git a/src/devices/bus/ti99/peb/pcode.h b/src/devices/bus/ti99/peb/pcode.h
index dd1ce542d1a..2092046b071 100644
--- a/src/devices/bus/ti99/peb/pcode.h
+++ b/src/devices/bus/ti99/peb/pcode.h
@@ -33,7 +33,7 @@ public:
void cruwrite(offs_t offset, uint8_t data) override;
void setaddress_dbin(offs_t offset, int state) override;
- DECLARE_WRITE_LINE_MEMBER(clock_in) override;
+ void clock_in(int state) override;
DECLARE_INPUT_CHANGED_MEMBER( switch_changed );
@@ -46,10 +46,10 @@ protected:
virtual ioport_constructor device_input_ports() const override;
private:
- DECLARE_WRITE_LINE_MEMBER(ready_line);
+ void ready_line(int state);
- DECLARE_WRITE_LINE_MEMBER(pcpage_w);
- DECLARE_WRITE_LINE_MEMBER(ekrpg_w);
+ void pcpage_w(int state);
+ void ekrpg_w(int state);
void debugger_read(offs_t addr, uint8_t& value);
diff --git a/src/devices/bus/ti99/peb/peribox.cpp b/src/devices/bus/ti99/peb/peribox.cpp
index cc8b07500f0..4df80e153d5 100644
--- a/src/devices/bus/ti99/peb/peribox.cpp
+++ b/src/devices/bus/ti99/peb/peribox.cpp
@@ -201,12 +201,12 @@ CRUCLK* 51||52 DBIN
#include "scsicard.h"
#include "tipi.h"
-#define LOG_WARN (1U<<1) // Warnings
-#define LOG_CONFIG (1U<<2) // Configuration
-#define LOG_INT (1U<<3)
-#define LOG_READY (1U<<4)
+#define LOG_WARN (1U << 1) // Warnings
+#define LOG_CONFIG (1U << 2) // Configuration
+#define LOG_INT (1U << 3)
+#define LOG_READY (1U << 4)
-#define VERBOSE ( LOG_CONFIG | LOG_WARN )
+#define VERBOSE (LOG_CONFIG | LOG_WARN)
#include "logmacro.h"
@@ -323,7 +323,7 @@ void peribox_device::cruwrite(offs_t offset, uint8_t data)
/*
RESET line from the console.
*/
-WRITE_LINE_MEMBER(peribox_device::reset_in)
+void peribox_device::reset_in(int state)
{
for (int i=2; i <= 8; i++)
{
@@ -335,7 +335,7 @@ WRITE_LINE_MEMBER(peribox_device::reset_in)
And here are finally the two mythical lines SENILA* and SENILB*; mythical
since there is no report of any software that ever used them.
*/
-WRITE_LINE_MEMBER(peribox_device::senila)
+void peribox_device::senila(int state)
{
for (int i=2; i <= 8; i++)
{
@@ -343,7 +343,7 @@ WRITE_LINE_MEMBER(peribox_device::senila)
}
}
-WRITE_LINE_MEMBER(peribox_device::senilb)
+void peribox_device::senilb(int state)
{
for (int i=2; i <= 8; i++)
{
@@ -354,7 +354,7 @@ WRITE_LINE_MEMBER(peribox_device::senilb)
/*
MEMEN input. Used to start the external memory access cycle.
*/
-WRITE_LINE_MEMBER(peribox_device::memen_in)
+void peribox_device::memen_in(int state)
{
m_memen = (state==ASSERT_LINE);
}
@@ -362,7 +362,7 @@ WRITE_LINE_MEMBER(peribox_device::memen_in)
/*
MSAST input. Defined by TI-99/8; we ignore this part in the PEB.
*/
-WRITE_LINE_MEMBER(peribox_device::msast_in)
+void peribox_device::msast_in(int state)
{
m_msast = (state==ASSERT_LINE);
}
@@ -371,7 +371,7 @@ WRITE_LINE_MEMBER(peribox_device::msast_in)
CLKOUT line
*/
-WRITE_LINE_MEMBER(peribox_device::clock_in)
+void peribox_device::clock_in(int state)
{
for (int i=2; i <= 8; i++)
{
@@ -452,13 +452,7 @@ void peribox_device::set_slot_loaded(int slot, peribox_slot_device* slotdev)
void peribox_device::device_start()
{
- // Resolve the callback lines to the console
- m_slot1_inta.resolve();
- m_slot1_intb.resolve();
- m_slot1_lcp.resolve();
- m_slot1_ready.resolve();
-
- m_ioport_connected = (m_slot1_inta.isnull()); // TODO: init
+ m_ioport_connected = (m_slot1_inta.isunset()); // TODO: init
LOGMASKED(LOG_CONFIG, "AMA/B/C address prefix set to %05x\n", m_address_prefix);
for (int i=2; i < 9; i++)
@@ -689,6 +683,7 @@ peribox_slot_device::peribox_slot_device(const machine_config &mconfig, const ch
device_t(mconfig, TI99_PERIBOX_SLOT, tag, owner, clock),
device_single_card_slot_interface<device_ti99_peribox_card_interface>(mconfig, *this),
m_card(nullptr),
+ m_peb(nullptr),
m_slotnumber(0)
{
}
@@ -718,22 +713,22 @@ void peribox_slot_device::cruwrite(offs_t offset, uint8_t data)
m_card->cruwrite(offset, data);
}
-WRITE_LINE_MEMBER( peribox_slot_device::senila )
+void peribox_slot_device::senila(int state)
{
m_card->set_senila(state);
}
-WRITE_LINE_MEMBER( peribox_slot_device::senilb )
+void peribox_slot_device::senilb(int state)
{
m_card->set_senilb(state);
}
-WRITE_LINE_MEMBER( peribox_slot_device::clock_in )
+void peribox_slot_device::clock_in(int state)
{
m_card->clock_in(state);
}
-WRITE_LINE_MEMBER( peribox_slot_device::reset_in )
+void peribox_slot_device::reset_in(int state)
{
m_card->reset_in(state);
}
@@ -745,37 +740,37 @@ void peribox_slot_device::device_start()
void peribox_slot_device::device_config_complete()
{
m_card = get_card_device();
- peribox_device *peb = dynamic_cast<peribox_device*>(owner());
- if (peb)
- peb->set_slot_loaded(m_slotnumber, m_card ? this : nullptr);
+ m_peb = dynamic_cast<peribox_device*>(owner());
+ if (m_peb)
+ m_peb->set_slot_loaded(m_slotnumber, m_card ? this : nullptr);
}
/*
These methods are called from the expansion cards. They add the
slot number to identify the slot to the box.
*/
-WRITE_LINE_MEMBER( peribox_slot_device::set_inta )
+void peribox_slot_device::set_inta(int state)
{
- peribox_device *peb = static_cast<peribox_device*>(owner());
- peb->inta_join(m_slotnumber, state);
+ if (m_peb)
+ m_peb->inta_join(m_slotnumber, state);
}
-WRITE_LINE_MEMBER( peribox_slot_device::set_intb )
+void peribox_slot_device::set_intb(int state)
{
- peribox_device *peb = static_cast<peribox_device*>(owner());
- peb->intb_join(m_slotnumber, state);
+ if (m_peb)
+ m_peb->intb_join(m_slotnumber, state);
}
-WRITE_LINE_MEMBER( peribox_slot_device::lcp_line )
+void peribox_slot_device::lcp_line(int state)
{
- peribox_device *peb = static_cast<peribox_device*>(owner());
- peb->lcp_join(m_slotnumber, state);
+ if (m_peb)
+ m_peb->lcp_join(m_slotnumber, state);
}
-WRITE_LINE_MEMBER( peribox_slot_device::set_ready )
+void peribox_slot_device::set_ready(int state)
{
- peribox_device *peb = static_cast<peribox_device*>(owner());
- peb->ready_join(m_slotnumber, state);
+ if (m_peb)
+ m_peb->ready_join(m_slotnumber, state);
}
/***************************************************************************/
diff --git a/src/devices/bus/ti99/peb/peribox.h b/src/devices/bus/ti99/peb/peribox.h
index b54467f1055..d8e19ff0e66 100644
--- a/src/devices/bus/ti99/peb/peribox.h
+++ b/src/devices/bus/ti99/peb/peribox.h
@@ -44,14 +44,14 @@ public:
void crureadz(offs_t offset, uint8_t *value) override;
void cruwrite(offs_t offset, uint8_t data) override;
- DECLARE_WRITE_LINE_MEMBER(senila);
- DECLARE_WRITE_LINE_MEMBER(senilb);
+ void senila(int state);
+ void senilb(int state);
- DECLARE_WRITE_LINE_MEMBER( memen_in ) override;
- DECLARE_WRITE_LINE_MEMBER( msast_in ) override;
+ void memen_in(int state) override;
+ void msast_in(int state) override;
- DECLARE_WRITE_LINE_MEMBER( clock_in ) override;
- DECLARE_WRITE_LINE_MEMBER( reset_in ) override;
+ void clock_in(int state) override;
+ void reset_in(int state) override;
// Part of configuration
void set_prefix(int prefix) { m_address_prefix = prefix; }
@@ -125,7 +125,7 @@ public:
peribox_sg_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
- void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override;
};
/*
@@ -137,7 +137,7 @@ public:
peribox_ev_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
- void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override;
};
@@ -163,7 +163,7 @@ public:
peribox_genmod_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
- void device_add_mconfig(machine_config &config) override;
+ virtual void device_add_mconfig(machine_config &config) override;
};
/*****************************************************************************
@@ -181,8 +181,8 @@ public:
virtual void cruwrite(offs_t offset, uint8_t data) = 0;
virtual void setaddress_dbin(offs_t offset, int state) { }
- virtual DECLARE_WRITE_LINE_MEMBER(clock_in) { }
- virtual DECLARE_WRITE_LINE_MEMBER(reset_in) { }
+ virtual void clock_in(int state) { }
+ virtual void reset_in(int state) { }
void set_senila(int state) { m_senila = state; }
void set_senilb(int state) { m_senilb = state; }
@@ -233,16 +233,16 @@ public:
void write(offs_t offset, uint8_t data);
void setaddress_dbin(offs_t offset, int state);
- DECLARE_WRITE_LINE_MEMBER(senila);
- DECLARE_WRITE_LINE_MEMBER(senilb);
- DECLARE_WRITE_LINE_MEMBER(clock_in);
- DECLARE_WRITE_LINE_MEMBER(reset_in);
+ void senila(int state);
+ void senilb(int state);
+ void clock_in(int state);
+ void reset_in(int state);
// Called from the card (direction to box)
- DECLARE_WRITE_LINE_MEMBER( set_inta );
- DECLARE_WRITE_LINE_MEMBER( set_intb );
- DECLARE_WRITE_LINE_MEMBER( lcp_line );
- DECLARE_WRITE_LINE_MEMBER( set_ready );
+ void set_inta(int state);
+ void set_intb(int state);
+ void lcp_line(int state);
+ void set_ready(int state);
void crureadz(offs_t offset, uint8_t *value);
void cruwrite(offs_t offset, uint8_t data);
@@ -251,12 +251,13 @@ public:
void set_number(int number) { m_slotnumber = number; }
protected:
- void device_start() override;
- void device_config_complete() override;
+ virtual void device_start() override;
+ virtual void device_config_complete() override;
private:
int get_index_from_tagname();
device_ti99_peribox_card_interface *m_card;
+ peribox_device *m_peb;
int m_slotnumber;
const char* card_name() { return m_card->device().tag(); }
};
diff --git a/src/devices/bus/ti99/peb/pgram.cpp b/src/devices/bus/ti99/peb/pgram.cpp
index c6ece9407a0..007f168ab63 100644
--- a/src/devices/bus/ti99/peb/pgram.cpp
+++ b/src/devices/bus/ti99/peb/pgram.cpp
@@ -116,16 +116,16 @@
#include "emu.h"
#include "pgram.h"
-#define LOG_WARN (1U<<1)
-#define LOG_WP (1U<<2)
-#define LOG_DSR (1U<<3)
-#define LOG_RAM (1U<<4)
-#define LOG_GRAM (1U<<5)
-#define LOG_GRAMADDR (1U<<6)
-#define LOG_CRU (1U<<7)
-#define LOG_BANK (1U<<8)
-
-#define VERBOSE ( LOG_GENERAL | LOG_WARN )
+#define LOG_WARN (1U << 1)
+#define LOG_WP (1U << 2)
+#define LOG_DSR (1U << 3)
+#define LOG_RAM (1U << 4)
+#define LOG_GRAM (1U << 5)
+#define LOG_GRAMADDR (1U << 6)
+#define LOG_CRU (1U << 7)
+#define LOG_BANK (1U << 8)
+
+#define VERBOSE (LOG_GENERAL | LOG_WARN)
#include "logmacro.h"
diff --git a/src/devices/bus/ti99/peb/samsmem.cpp b/src/devices/bus/ti99/peb/samsmem.cpp
index d38f877fc9f..dd509e8e3d2 100644
--- a/src/devices/bus/ti99/peb/samsmem.cpp
+++ b/src/devices/bus/ti99/peb/samsmem.cpp
@@ -112,12 +112,12 @@ void sams_memory_expansion_device::cruwrite(offs_t offset, uint8_t data)
m_crulatch->write_bit((offset & 0x000e) >> 1, data);
}
-WRITE_LINE_MEMBER(sams_memory_expansion_device::access_mapper_w)
+void sams_memory_expansion_device::access_mapper_w(int state)
{
m_access_mapper = state;
}
-WRITE_LINE_MEMBER(sams_memory_expansion_device::map_mode_w)
+void sams_memory_expansion_device::map_mode_w(int state)
{
m_map_mode = state;
}
diff --git a/src/devices/bus/ti99/peb/samsmem.h b/src/devices/bus/ti99/peb/samsmem.h
index 8cf3105cc85..6cd900e7361 100644
--- a/src/devices/bus/ti99/peb/samsmem.h
+++ b/src/devices/bus/ti99/peb/samsmem.h
@@ -40,8 +40,8 @@ protected:
virtual void device_add_mconfig(machine_config &config) override;
private:
- DECLARE_WRITE_LINE_MEMBER(access_mapper_w);
- DECLARE_WRITE_LINE_MEMBER(map_mode_w);
+ void access_mapper_w(int state);
+ void map_mode_w(int state);
// Console RAM
required_device<ram_device> m_ram;
diff --git a/src/devices/bus/ti99/peb/scsicard.cpp b/src/devices/bus/ti99/peb/scsicard.cpp
index 5f9dfbf19e6..4ffe141aeb7 100644
--- a/src/devices/bus/ti99/peb/scsicard.cpp
+++ b/src/devices/bus/ti99/peb/scsicard.cpp
@@ -112,22 +112,24 @@
Thanks to Don O'Neil of WHT for providing the required schematics, ROM dumps,
and documentation
+ TODO: Enable block DMA. The only other driver using eop is lbpc.
+
*****************************************************************************/
#include "emu.h"
#include "scsicard.h"
#include "bus/nscsi/devices.h"
-#define LOG_WARN (1U<<1)
-#define LOG_CRU (1U<<2)
-#define LOG_EPROM (1U<<3)
-#define LOG_RAM (1U<<4)
-#define LOG_CONTR (1U<<5)
-#define LOG_CB (1U<<6)
-#define LOG_READY (1U<<7)
-#define LOG_DMA (1U<<8)
+#define LOG_WARN (1U << 1)
+#define LOG_CRU (1U << 2)
+#define LOG_EPROM (1U << 3)
+#define LOG_RAM (1U << 4)
+#define LOG_CONTR (1U << 5)
+#define LOG_CB (1U << 6)
+#define LOG_READY (1U << 7)
+#define LOG_DMA (1U << 8)
-#define VERBOSE ( LOG_GENERAL | LOG_WARN )
+#define VERBOSE (LOG_GENERAL | LOG_WARN)
#include "logmacro.h"
@@ -260,12 +262,12 @@ void whtech_scsi_card_device::readz(offs_t offset, uint8_t *value)
if ((m_address & 0x0010)==0x0000)
{
int reg = (m_address >> 1)&0x07;
+
// If we are in DMA mode, reading from register 6 means DMA read
- if ((m_controller->read(2) & 0x02) && (reg == 6))
+ if (m_drq && (reg == 6))
{
- LOGMASKED(LOG_DMA, "CTR: DMA in (%s)\n", machine().describe_context());
*value = m_controller->dma_r();
- LOGMASKED(LOG_DMA, "CTR: DMA -> %02x\n", *value);
+ LOGMASKED(LOG_DMA, "CTR: DMA in [%d] -> %02x (%s)\n", m_dmacount++, *value, machine().describe_context());
}
else
{
@@ -304,9 +306,9 @@ void whtech_scsi_card_device::write(offs_t offset, uint8_t data)
int reg = (m_address >> 1)&0x07;
// If we are in DMA mode, writing to register 0 means DMA write
- if ((m_controller->read(2) & 0x02) && (reg == 0))
+ if (m_drq && (reg == 0))
{
- LOGMASKED(LOG_DMA, "CTR: DMA out <- %02x (%s)\n", data, machine().describe_context());
+ LOGMASKED(LOG_DMA, "CTR: DMA out <- %02x [%d] (%s)\n", data, m_dmacount++, machine().describe_context());
m_controller->dma_w(data);
}
else
@@ -338,7 +340,7 @@ void whtech_scsi_card_device::cruwrite(offs_t offset, uint8_t data)
/*
Callbacks for the controller chip.
*/
-WRITE_LINE_MEMBER( whtech_scsi_card_device::drq_w )
+void whtech_scsi_card_device::drq_w(int state)
{
LOGMASKED(LOG_CB, "DRQ pin from controller = %d\n", state);
bool drq = (state==ASSERT_LINE);
@@ -350,7 +352,7 @@ WRITE_LINE_MEMBER( whtech_scsi_card_device::drq_w )
operate_ready_line();
}
-WRITE_LINE_MEMBER( whtech_scsi_card_device::irq_w )
+void whtech_scsi_card_device::irq_w(int state)
{
LOGMASKED(LOG_CB, "IRQ pin from controller = %d\n", state);
bool irq = (state==ASSERT_LINE);
@@ -373,7 +375,8 @@ void whtech_scsi_card_device::device_add_mconfig(machine_config &config)
RAM(config, BUFFER).set_default_size("32K").set_default_value(0);
// PLD circuit
- WHTSCSI_PLD(config, PLD_TAG, 0);
+ WHTSCSI_PLD(config, m_pld, 0);
+ m_pld->set_board(this);
// SCSI bus
NSCSI_BUS(config, m_scsibus);
@@ -613,36 +616,37 @@ void whtscsi_pld_device::cruwrite(offs_t offset, uint8_t data)
int crubase = m_board->get_sw1();
if ((offset & 0xff00)==crubase)
{
- LOGMASKED(LOG_CRU, "CRU %04x <- %d (%s)\n", offset & 0xffff, data, machine().describe_context());
+ // LOGMASKED(LOG_CRU, "CRU %04x <- %d (%s)\n", offset & 0xffff, data, machine().describe_context());
int bit = (offset >> 1) & 0x1f;
switch (bit)
{
case 0: // card activation
- LOGMASKED(LOG_CRU, "DSR %s\n", (data!=0)? "on" : "off");
+ LOGMASKED(LOG_CRU, "DSR %s (%s)\n", (data!=0)? "on" : "off", machine().describe_context());
m_selected = (data != 0);
break;
case 1: // SRAM shadow
- LOGMASKED(LOG_CRU, "SRAM shadow %s\n", (data!=0)? "on" : "off");
+ LOGMASKED(LOG_CRU, "SRAM shadow %s (%s)\n", (data!=0)? "on" : "off", machine().describe_context());
m_sram_shadow = (data != 0);
break;
case 2: // DMA lock enable
- LOGMASKED(LOG_CRU, "DMA lock %s\n", (data!=0)? "on" : "off");
+ LOGMASKED(LOG_CRU, "DMA lock %s (%s)\n", (data!=0)? "on" : "off", machine().describe_context());
m_dma_lock = (data != 0);
+ m_board->m_dmacount = 0;
break;
case 3: // SCSI EOP
- LOGMASKED(LOG_CRU, "SCSI EOP %s\n", (data!=0)? "on" : "off");
+ LOGMASKED(LOG_CRU, "SCSI EOP %s (%s)\n", (data!=0)? "on" : "off", machine().describe_context());
m_board->signal_scsi_eop((data != 0)? ASSERT_LINE : CLEAR_LINE);
break;
case 4:
- LOGMASKED(LOG_CRU, "Word transfer %s\n", (data!=0)? "on" : "off");
+ LOGMASKED(LOG_CRU, "Word transfer %s (%s)\n", (data!=0)? "on" : "off", machine().describe_context());
m_word_transfer = (data != 0);
break;
case 5:
- LOGMASKED(LOG_CRU, "Bank swap %s\n", (data!=0)? "on" : "off");
+ LOGMASKED(LOG_CRU, "Bank swap %s (%s)\n", (data!=0)? "on" : "off", machine().describe_context());
m_bank_swapped = (data != 0);
break;
case 6:
- LOGMASKED(LOG_CRU, "Block mode %s (not implemented)\n", (data!=0)? "on" : "off");
+ LOGMASKED(LOG_CRU, "Block mode %s (not implemented) (%s)\n", (data!=0)? "on" : "off", machine().describe_context());
break;
case 8:
case 9:
@@ -651,6 +655,7 @@ void whtscsi_pld_device::cruwrite(offs_t offset, uint8_t data)
m_eprom_bank = m_eprom_bank | (1<<(bit-8));
else
m_eprom_bank = m_eprom_bank & ~(1<<(bit-8));
+ LOGMASKED(LOG_CRU, "Set EPROM bank %d (%s)\n", m_eprom_bank, machine().describe_context());
break;
case 12:
case 13:
@@ -659,6 +664,7 @@ void whtscsi_pld_device::cruwrite(offs_t offset, uint8_t data)
m_sram_bank = m_sram_bank | (1<<(bit-12));
else
m_sram_bank = m_sram_bank & ~(1<<(bit-12));
+ LOGMASKED(LOG_CRU, "Set SRAM bank %d (%s)\n", m_sram_bank, machine().describe_context());
break;
default:
break;
@@ -690,9 +696,4 @@ void whtscsi_pld_device::update_line_states(int address, bool drq, bool irq)
m_readyout = (irq || !m_dma_lock)? true : drq;
}
-void whtscsi_pld_device::device_config_complete()
-{
- m_board = static_cast<whtech_scsi_card_device*>(owner());
-}
-
} // end namespace bus::ti99::peb
diff --git a/src/devices/bus/ti99/peb/scsicard.h b/src/devices/bus/ti99/peb/scsicard.h
index a55ad228886..e41bdcc3948 100644
--- a/src/devices/bus/ti99/peb/scsicard.h
+++ b/src/devices/bus/ti99/peb/scsicard.h
@@ -35,19 +35,20 @@ public:
void crureadz(offs_t offset, uint8_t *value) override;
void cruwrite(offs_t offset, uint8_t data) override;
- DECLARE_WRITE_LINE_MEMBER( drq_w );
- DECLARE_WRITE_LINE_MEMBER( irq_w );
+ void drq_w(int state);
+ void irq_w(int state);
void debug_read(offs_t offset, uint8_t* value);
void debug_write(offs_t offset, uint8_t data);
-private:
- void device_start() override;
- void device_reset() override;
- void device_add_mconfig(machine_config &config) override;
- ioport_constructor device_input_ports() const override;
- const tiny_rom_entry *device_rom_region() const override;
+protected:
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual ioport_constructor device_input_ports() const override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+private:
// SCSI card on-board SRAM (32K)
required_device<ram_device> m_buffer_ram;
@@ -69,6 +70,9 @@ private:
// Settings
int m_sw2;
+ // Debugging
+ int m_dmacount;
+
// Latches for the lines
// Should be removed and accessor functions be added to ncr5380
bool m_irq;
@@ -90,6 +94,8 @@ private:
class whtscsi_pld_device : public device_t
{
+ friend class whtech_scsi_card_device;
+
public:
whtscsi_pld_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
@@ -110,13 +116,14 @@ public:
void update_line_states(int address, bool drq, bool irq);
-private:
- void device_start() override;
- void device_reset() override;
- void device_config_complete() override;
+protected:
+ virtual void device_start() override;
+ virtual void device_reset() override;
+private:
whtech_scsi_card_device* m_board;
+ void set_board(whtech_scsi_card_device* board) { m_board = board; }
bool busen();
// Flags
diff --git a/src/devices/bus/ti99/peb/sidmaster.cpp b/src/devices/bus/ti99/peb/sidmaster.cpp
index 9b6eb0af129..2fac13f654b 100644
--- a/src/devices/bus/ti99/peb/sidmaster.cpp
+++ b/src/devices/bus/ti99/peb/sidmaster.cpp
@@ -24,10 +24,10 @@
#include "emu.h"
#include "sidmaster.h"
-#define LOG_WARN (1U<<1)
-#define LOG_WRITE (1U<<2)
+#define LOG_WARN (1U << 1)
+#define LOG_WRITE (1U << 2)
-#define VERBOSE ( LOG_GENERAL | LOG_WARN )
+#define VERBOSE (LOG_GENERAL | LOG_WARN)
#include "logmacro.h"
diff --git a/src/devices/bus/ti99/peb/spchsyn.cpp b/src/devices/bus/ti99/peb/spchsyn.cpp
index 302758f3f4e..8639f4ffa43 100644
--- a/src/devices/bus/ti99/peb/spchsyn.cpp
+++ b/src/devices/bus/ti99/peb/spchsyn.cpp
@@ -27,13 +27,13 @@
#include "machine/spchrom.h"
#include "speaker.h"
-#define LOG_WARN (1U<<1) // Warnings
-#define LOG_CONFIG (1U<<2)
-#define LOG_MEM (1U<<3)
-#define LOG_ADDR (1U<<4)
-#define LOG_READY (1U<<5)
+#define LOG_WARN (1U << 1) // Warnings
+#define LOG_CONFIG (1U << 2)
+#define LOG_MEM (1U << 3)
+#define LOG_ADDR (1U << 4)
+#define LOG_READY (1U << 5)
-#define VERBOSE ( LOG_CONFIG | LOG_WARN )
+#define VERBOSE (LOG_CONFIG | LOG_WARN)
#include "logmacro.h"
DEFINE_DEVICE_TYPE(TI99_SPEECH, bus::ti99::peb::ti_speech_synthesizer_device, "ti99_speech", "TI-99 Speech synthesizer (on adapter card)")
@@ -120,7 +120,7 @@ void ti_speech_synthesizer_device::setaddress_dbin(offs_t offset, int state)
/****************************************************************************/
-WRITE_LINE_MEMBER( ti_speech_synthesizer_device::speech_ready )
+void ti_speech_synthesizer_device::speech_ready(int state)
{
// The TMS5200 implementation uses true/false, not ASSERT/CLEAR semantics
// and we have to adapt a /READY to a READY line.
diff --git a/src/devices/bus/ti99/peb/spchsyn.h b/src/devices/bus/ti99/peb/spchsyn.h
index 5bf71658e4b..7322714883e 100644
--- a/src/devices/bus/ti99/peb/spchsyn.h
+++ b/src/devices/bus/ti99/peb/spchsyn.h
@@ -40,7 +40,7 @@ protected:
virtual ioport_constructor device_input_ports() const override;
private:
- DECLARE_WRITE_LINE_MEMBER( speech_ready );
+ void speech_ready(int state);
required_device<cd2501e_device> m_vsp;
bool m_reading;
diff --git a/src/devices/bus/ti99/peb/ti_fdc.cpp b/src/devices/bus/ti99/peb/ti_fdc.cpp
index b68147a8193..3daeb24d41f 100644
--- a/src/devices/bus/ti99/peb/ti_fdc.cpp
+++ b/src/devices/bus/ti99/peb/ti_fdc.cpp
@@ -17,19 +17,19 @@
#include "formats/ti99_dsk.h"
#include "machine/rescap.h"
-#define LOG_WARN (1U<<1) // Warnings
-#define LOG_CONFIG (1U<<2)
-#define LOG_RW (1U<<3)
-#define LOG_PORTS (1U<<4) // too noisy in RW
-#define LOG_CRU (1U<<5)
-#define LOG_READY (1U<<6)
-#define LOG_SIGNALS (1U<<7)
-#define LOG_DRQ (1U<<8) // too noisy in SIGNALS
-#define LOG_DATA (1U<<9)
-#define LOG_MOTOR (1U<<10)
-#define LOG_ADDRESS (1U<<11)
-
-#define VERBOSE ( LOG_CONFIG | LOG_WARN )
+#define LOG_WARN (1U << 1) // Warnings
+#define LOG_CONFIG (1U << 2)
+#define LOG_RW (1U << 3)
+#define LOG_PORTS (1U << 4) // too noisy in RW
+#define LOG_CRU (1U << 5)
+#define LOG_READY (1U << 6)
+#define LOG_SIGNALS (1U << 7)
+#define LOG_DRQ (1U << 8) // too noisy in SIGNALS
+#define LOG_DATA (1U << 9)
+#define LOG_MOTOR (1U << 10)
+#define LOG_ADDRESS (1U << 11)
+
+#define VERBOSE (LOG_GENERAL | LOG_CONFIG | LOG_WARN)
#include "logmacro.h"
DEFINE_DEVICE_TYPE(TI99_FDC, bus::ti99::peb::ti_fdc_device, "ti99_fdc", "TI-99 Standard DSSD Floppy Controller")
@@ -56,6 +56,7 @@ ti_fdc_device::ti_fdc_device(const machine_config &mconfig, const char *tag, dev
m_crulatch(*this, "crulatch"),
m_motormf(*this, "motormf"),
m_dsrrom(nullptr),
+ m_floppy(*this, "%u", 0),
m_sel_floppy(0)
{
}
@@ -79,21 +80,21 @@ void ti_fdc_device::operate_ready_line()
/*
* Callbacks from the FD1771 chip
*/
-WRITE_LINE_MEMBER( ti_fdc_device::fdc_irq_w )
+void ti_fdc_device::fdc_irq_w(int state)
{
m_IRQ = state? ASSERT_LINE : CLEAR_LINE;
LOGMASKED(LOG_SIGNALS, "INTRQ callback = %d\n", m_IRQ);
operate_ready_line();
}
-WRITE_LINE_MEMBER( ti_fdc_device::fdc_drq_w )
+void ti_fdc_device::fdc_drq_w(int state)
{
m_DRQ = state? ASSERT_LINE : CLEAR_LINE;
LOGMASKED(LOG_DRQ, "DRQ callback = %d\n", m_DRQ);
operate_ready_line();
}
-WRITE_LINE_MEMBER( ti_fdc_device::fdc_hld_w )
+void ti_fdc_device::fdc_hld_w(int state)
{
m_HLD = state? ASSERT_LINE : CLEAR_LINE;
LOGMASKED(LOG_SIGNALS, "HLD callback = %d\n", m_HLD);
@@ -230,7 +231,7 @@ void ti_fdc_device::cruwrite(offs_t offset, uint8_t data)
m_crulatch->write_bit((offset >> 1) & 0x07, BIT(data, 0));
}
-WRITE_LINE_MEMBER(ti_fdc_device::dskpgena_w)
+void ti_fdc_device::dskpgena_w(int state)
{
// (De)select the card. Indicated by a LED on the board.
m_selected = state;
@@ -240,12 +241,12 @@ WRITE_LINE_MEMBER(ti_fdc_device::dskpgena_w)
/*
Trigger the motor monoflop.
*/
-WRITE_LINE_MEMBER(ti_fdc_device::kaclk_w)
+void ti_fdc_device::kaclk_w(int state)
{
m_motormf->b_w(state);
}
-WRITE_LINE_MEMBER(ti_fdc_device::dvena_w)
+void ti_fdc_device::dvena_w(int state)
{
m_DVENA = state;
LOGMASKED(LOG_MOTOR, "Motor %s\n", state? "on" : "off");
@@ -255,13 +256,14 @@ WRITE_LINE_MEMBER(ti_fdc_device::dvena_w)
// Set all motors
for (auto & elem : m_floppy)
- if (elem != nullptr) elem->mon_w((state==ASSERT_LINE)? 0 : 1);
+ if (elem->get_device() != nullptr)
+ elem->get_device()->mon_w((state==ASSERT_LINE)? 0 : 1);
// The motor-on line also connects to the wait state logic
operate_ready_line();
}
-WRITE_LINE_MEMBER(ti_fdc_device::waiten_w)
+void ti_fdc_device::waiten_w(int state)
{
// Set disk ready/hold (bit 2)
// 0: ignore IRQ and DRQ
@@ -271,33 +273,34 @@ WRITE_LINE_MEMBER(ti_fdc_device::waiten_w)
LOGMASKED(LOG_CRU, "Arm wait state logic (bit 2) = %d\n", state);
}
-WRITE_LINE_MEMBER(ti_fdc_device::hlt_w)
+void ti_fdc_device::hlt_w(int state)
{
// Load disk heads (HLT pin) (bit 3). Not implemented.
LOGMASKED(LOG_CRU, "Set head load (bit 3) = %d\n", state);
}
-WRITE_LINE_MEMBER(ti_fdc_device::sidsel_w)
+void ti_fdc_device::sidsel_w(int state)
{
// Select side of disk (bit 7)
LOGMASKED(LOG_CRU, "Set side (bit 7) = %d\n", state);
- if (m_sel_floppy != 0) m_floppy[m_sel_floppy-1]->ss_w(state);
+ if (m_sel_floppy > 0)
+ m_floppy[m_sel_floppy-1]->get_device()->ss_w(state);
}
/*
Drive selects
*/
-WRITE_LINE_MEMBER(ti_fdc_device::dsel1_w)
+void ti_fdc_device::dsel1_w(int state)
{
select_drive(1, state);
}
-WRITE_LINE_MEMBER(ti_fdc_device::dsel2_w)
+void ti_fdc_device::dsel2_w(int state)
{
select_drive(2, state);
}
-WRITE_LINE_MEMBER(ti_fdc_device::dsel3_w)
+void ti_fdc_device::dsel3_w(int state)
{
select_drive(3, state);
}
@@ -324,11 +327,11 @@ void ti_fdc_device::select_drive(int n, int state)
LOGMASKED(LOG_WARN, "Warning: DSK%d selected while DSK%d not yet unselected\n", n, m_sel_floppy);
}
- if (m_floppy[n-1] != nullptr)
+ if (m_floppy[n-1]->get_device() != nullptr)
{
m_sel_floppy = n;
- m_fd1771->set_floppy(m_floppy[n-1]);
- m_floppy[n-1]->ss_w(m_crulatch->q7_r());
+ m_fd1771->set_floppy(m_floppy[n-1]->get_device());
+ m_floppy[n-1]->get_device()->ss_w(m_crulatch->q7_r());
}
}
}
@@ -358,27 +361,17 @@ void ti_fdc_device::device_reset()
m_inDsrArea = false;
m_WDsel = false;
- for (int i=0; i < 3; i++)
+ for (auto &flop : m_floppy)
{
- if (m_floppy[i] != nullptr)
- LOGMASKED(LOG_CONFIG, "Connector %d with %s\n", i, m_floppy[i]->name());
+ if (flop->get_device() != nullptr)
+ LOGMASKED(LOG_CONFIG, "Connector %d with %s\n", flop->basetag(), flop->get_device()->name());
else
- LOGMASKED(LOG_CONFIG, "No floppy attached to connector %d\n", i);
+ LOGMASKED(LOG_CONFIG, "Connector %d has no floppy attached\n", flop->basetag());
}
m_sel_floppy = 0;
}
-void ti_fdc_device::device_config_complete()
-{
- // Seems to be null when doing a "-listslots"
- for (auto &elem : m_floppy)
- elem = nullptr;
- if (subdevice("0")!=nullptr) m_floppy[0] = static_cast<floppy_image_device*>(subdevice("0")->subdevices().first());
- if (subdevice("1")!=nullptr) m_floppy[1] = static_cast<floppy_image_device*>(subdevice("1")->subdevices().first());
- if (subdevice("2")!=nullptr) m_floppy[2] = static_cast<floppy_image_device*>(subdevice("2")->subdevices().first());
-}
-
void ti_fdc_device::floppy_formats(format_registration &fr)
{
fr.add_mfm_containers();
@@ -404,9 +397,9 @@ void ti_fdc_device::device_add_mconfig(machine_config& config)
m_fd1771->drq_wr_callback().set(FUNC(ti_fdc_device::fdc_drq_w));
m_fd1771->hld_wr_callback().set(FUNC(ti_fdc_device::fdc_hld_w));
- FLOPPY_CONNECTOR(config, "0", tifdc_floppies, "525dd", ti_fdc_device::floppy_formats).enable_sound(true);
- FLOPPY_CONNECTOR(config, "1", tifdc_floppies, "525dd", ti_fdc_device::floppy_formats).enable_sound(true);
- FLOPPY_CONNECTOR(config, "2", tifdc_floppies, nullptr, ti_fdc_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[0], tifdc_floppies, "525dd", ti_fdc_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[1], tifdc_floppies, "525dd", ti_fdc_device::floppy_formats).enable_sound(true);
+ FLOPPY_CONNECTOR(config, m_floppy[2], tifdc_floppies, nullptr, ti_fdc_device::floppy_formats).enable_sound(true);
LS259(config, m_crulatch); // U23
m_crulatch->q_out_cb<0>().set(FUNC(ti_fdc_device::dskpgena_w));
diff --git a/src/devices/bus/ti99/peb/ti_fdc.h b/src/devices/bus/ti99/peb/ti_fdc.h
index 81c2324dbc9..3b67295d367 100644
--- a/src/devices/bus/ti99/peb/ti_fdc.h
+++ b/src/devices/bus/ti99/peb/ti_fdc.h
@@ -38,30 +38,29 @@ public:
// bool dvena_r();
protected:
- void device_start() override;
- void device_reset() override;
- void device_config_complete() override;
+ virtual void device_start() override;
+ virtual void device_reset() override;
- const tiny_rom_entry *device_rom_region() const override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
virtual void device_add_mconfig(machine_config &config) override;
private:
static void floppy_formats(format_registration &fr);
- DECLARE_WRITE_LINE_MEMBER(fdc_irq_w);
- DECLARE_WRITE_LINE_MEMBER(fdc_drq_w);
- DECLARE_WRITE_LINE_MEMBER(fdc_hld_w);
+ void fdc_irq_w(int state);
+ void fdc_drq_w(int state);
+ void fdc_hld_w(int state);
- DECLARE_WRITE_LINE_MEMBER(dskpgena_w);
- DECLARE_WRITE_LINE_MEMBER(kaclk_w);
- DECLARE_WRITE_LINE_MEMBER(waiten_w);
- DECLARE_WRITE_LINE_MEMBER(hlt_w);
- DECLARE_WRITE_LINE_MEMBER(sidsel_w);
+ void dskpgena_w(int state);
+ void kaclk_w(int state);
+ void waiten_w(int state);
+ void hlt_w(int state);
+ void sidsel_w(int state);
- DECLARE_WRITE_LINE_MEMBER(dvena_w);
- DECLARE_WRITE_LINE_MEMBER(dsel1_w);
- DECLARE_WRITE_LINE_MEMBER(dsel2_w);
- DECLARE_WRITE_LINE_MEMBER(dsel3_w);
+ void dvena_w(int state);
+ void dsel1_w(int state);
+ void dsel2_w(int state);
+ void dsel3_w(int state);
void select_drive(int n, int state);
@@ -105,7 +104,7 @@ private:
uint8_t* m_dsrrom;
// Link to the attached floppy drives
- floppy_image_device* m_floppy[3];
+ required_device_array<floppy_connector, 3> m_floppy;
// Currently selected floppy drive
int m_sel_floppy;
diff --git a/src/devices/bus/ti99/peb/ti_rs232.cpp b/src/devices/bus/ti99/peb/ti_rs232.cpp
index 841acf44ac7..1005029b23c 100644
--- a/src/devices/bus/ti99/peb/ti_rs232.cpp
+++ b/src/devices/bus/ti99/peb/ti_rs232.cpp
@@ -105,17 +105,17 @@
#include "emu.h"
#include "ti_rs232.h"
-#define LOG_WARN (1U<<1) // Warnings
-#define LOG_CONFIG (1U<<2)
-#define LOG_LINES (1U<<3)
-#define LOG_SETTING (1U<<4)
-#define LOG_STATE (1U<<5)
-#define LOG_MAP (1U<<6)
-#define LOG_IN (1U<<7)
-#define LOG_OUT (1U<<8)
-#define LOG_ILA (1U<<9)
-
-#define VERBOSE ( LOG_CONFIG | LOG_WARN )
+#define LOG_WARN (1U << 1) // Warnings
+#define LOG_CONFIG (1U << 2)
+#define LOG_LINES (1U << 3)
+#define LOG_SETTING (1U << 4)
+#define LOG_STATE (1U << 5)
+#define LOG_MAP (1U << 6)
+#define LOG_IN (1U << 7)
+#define LOG_OUT (1U << 8)
+#define LOG_ILA (1U << 9)
+
+#define VERBOSE (LOG_CONFIG | LOG_WARN)
#include "logmacro.h"
DEFINE_DEVICE_TYPE(TI99_RS232, bus::ti99::peb::ti_rs232_pio_device, "ti99_rs232", "TI-99 RS232/PIO interface")
@@ -186,14 +186,14 @@ ti_pio_attached_device::ti_pio_attached_device(const machine_config &mconfig, co
/*
Initialize rs232 unit and open image
*/
-image_init_result ti_rs232_attached_device::call_load()
+std::pair<std::error_condition, std::string> ti_rs232_attached_device::call_load()
{
m_uart->set_clock(true);
// The following line may cause trouble in the init phase
// card->incoming_dtr(devnumber, (m_file!=nullptr)? ASSERT_LINE : CLEAR_LINE);
- return image_init_result::PASS; // OK
+ return std::make_pair(std::error_condition(), std::string()); // OK
}
void ti_rs232_attached_device::call_unload()
@@ -204,21 +204,19 @@ void ti_rs232_attached_device::call_unload()
/*
Initialize pio unit and open image
*/
-image_init_result ti_pio_attached_device::call_load()
+std::pair<std::error_condition, std::string> ti_pio_attached_device::call_load()
{
- ti_rs232_pio_device* card = static_cast<ti_rs232_pio_device*>(owner());
-
// tell whether the image is readable
- card->m_pio_readable = true;
+ m_card->m_pio_readable = true;
// tell whether the image is writable
- card->m_pio_writable = !is_readonly();
+ m_card->m_pio_writable = !is_readonly();
- if (card->m_pio_write && card->m_pio_writable)
- card->m_pio_handshakein = false; // receiver ready
+ if (m_card->m_pio_write && m_card->m_pio_writable)
+ m_card->m_pio_handshakein = false; // receiver ready
else
- card->m_pio_handshakein = true;
+ m_card->m_pio_handshakein = true;
- return image_init_result::PASS; // OK
+ return std::make_pair(std::error_condition(), std::string()); // OK
}
/*
@@ -226,11 +224,9 @@ image_init_result ti_pio_attached_device::call_load()
*/
void ti_pio_attached_device::call_unload()
{
- ti_rs232_pio_device* card = static_cast<ti_rs232_pio_device*>(owner());
-
- card->m_pio_writable = false;
- card->m_pio_handshakein = true; /* receiver not ready */
- card->m_pio_sparein = false;
+ m_card->m_pio_writable = false;
+ m_card->m_pio_handshakein = true; /* receiver not ready */
+ m_card->m_pio_sparein = false;
}
/****************************************************************************/
@@ -293,17 +289,17 @@ void ti_rs232_pio_device::cruwrite(offs_t offset, uint8_t data)
}
}
-WRITE_LINE_MEMBER(ti_rs232_pio_device::selected_w)
+void ti_rs232_pio_device::selected_w(int state)
{
m_selected = state;
}
-WRITE_LINE_MEMBER(ti_rs232_pio_device::pio_direction_in_w)
+void ti_rs232_pio_device::pio_direction_in_w(int state)
{
m_pio_direction_in = state;
}
-WRITE_LINE_MEMBER(ti_rs232_pio_device::pio_handshake_out_w)
+void ti_rs232_pio_device::pio_handshake_out_w(int state)
{
m_pio_handshakeout = state;
if (m_pio_write && m_pio_writable && (!m_pio_direction_in))
@@ -342,31 +338,31 @@ WRITE_LINE_MEMBER(ti_rs232_pio_device::pio_handshake_out_w)
}
}
-WRITE_LINE_MEMBER(ti_rs232_pio_device::pio_spareout_w)
+void ti_rs232_pio_device::pio_spareout_w(int state)
{
m_pio_spareout = state;
}
-WRITE_LINE_MEMBER(ti_rs232_pio_device::flag0_w)
+void ti_rs232_pio_device::flag0_w(int state)
{
m_flag0 = state;
}
-WRITE_LINE_MEMBER(ti_rs232_pio_device::cts0_w)
+void ti_rs232_pio_device::cts0_w(int state)
{
// Set the CTS line for RS232/1
LOGMASKED(LOG_LINES, "(1/3) Setting CTS* via CRU to %d\n", state);
output_line_state(0, tms9902_device::CTS, state ? 0 : tms9902_device::CTS);
}
-WRITE_LINE_MEMBER(ti_rs232_pio_device::cts1_w)
+void ti_rs232_pio_device::cts1_w(int state)
{
// Set the CTS line for RS232/2
LOGMASKED(LOG_LINES, "(2/4) Setting CTS* via CRU to %d\n", state);
output_line_state(1, tms9902_device::CTS, state ? 0 : tms9902_device::CTS);
}
-WRITE_LINE_MEMBER(ti_rs232_pio_device::led_w)
+void ti_rs232_pio_device::led_w(int state)
{
m_led = state;
}
@@ -931,7 +927,7 @@ void ti_rs232_pio_device::output_line_state(int uartind, int mask, uint8_t value
/*
Propagates the /INT signal of the UARTs to the /INT line of the pbox.
*/
-WRITE_LINE_MEMBER( ti_rs232_pio_device::int0_callback )
+void ti_rs232_pio_device::int0_callback(int state)
{
int senila_bit = SENILA_0_BIT;
@@ -941,7 +937,7 @@ WRITE_LINE_MEMBER( ti_rs232_pio_device::int0_callback )
m_slot->set_inta(state);
}
-WRITE_LINE_MEMBER( ti_rs232_pio_device::int1_callback )
+void ti_rs232_pio_device::int1_callback(int state)
{
int senila_bit = SENILA_1_BIT;
@@ -957,12 +953,12 @@ WRITE_LINE_MEMBER( ti_rs232_pio_device::int1_callback )
Instead, we check for signal line change or data transmission
and call the respective function
*/
-WRITE_LINE_MEMBER( ti_rs232_pio_device::rcv0_callback )
+void ti_rs232_pio_device::rcv0_callback(int state)
{
receive_data_or_line_state(0);
}
-WRITE_LINE_MEMBER( ti_rs232_pio_device::rcv1_callback )
+void ti_rs232_pio_device::rcv1_callback(int state)
{
receive_data_or_line_state(1);
}
@@ -1108,6 +1104,7 @@ void ti_rs232_pio_device::device_add_mconfig(machine_config &config)
m_serdev1->connect(m_uart1);
TI99_PIO_DEV(config, m_piodev, 0);
+ m_piodev->set_card(this);
LS259(config, m_crulatch); // U12
m_crulatch->q_out_cb<0>().set(FUNC(ti_rs232_pio_device::selected_w));
diff --git a/src/devices/bus/ti99/peb/ti_rs232.h b/src/devices/bus/ti99/peb/ti_rs232.h
index e7970538504..edd20827765 100644
--- a/src/devices/bus/ti99/peb/ti_rs232.h
+++ b/src/devices/bus/ti99/peb/ti_rs232.h
@@ -38,31 +38,31 @@ public:
void cruwrite(offs_t offset, uint8_t data) override;
protected:
- void device_start() override;
- void device_reset() override;
- void device_stop() override;
- const tiny_rom_entry *device_rom_region() const override;
- void device_add_mconfig(machine_config &config) override;
- ioport_constructor device_input_ports() const override;
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void device_stop() override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual ioport_constructor device_input_ports() const override;
private:
- DECLARE_WRITE_LINE_MEMBER(int0_callback);
- DECLARE_WRITE_LINE_MEMBER(int1_callback);
- DECLARE_WRITE_LINE_MEMBER(rcv0_callback);
- DECLARE_WRITE_LINE_MEMBER(rcv1_callback);
+ void int0_callback(int state);
+ void int1_callback(int state);
+ void rcv0_callback(int state);
+ void rcv1_callback(int state);
void xmit0_callback(uint8_t data);
void xmit1_callback(uint8_t data);
void ctrl0_callback(offs_t offset, uint8_t data);
void ctrl1_callback(offs_t offset, uint8_t data);
- DECLARE_WRITE_LINE_MEMBER(selected_w);
- DECLARE_WRITE_LINE_MEMBER(pio_direction_in_w);
- DECLARE_WRITE_LINE_MEMBER(pio_handshake_out_w);
- DECLARE_WRITE_LINE_MEMBER(pio_spareout_w);
- DECLARE_WRITE_LINE_MEMBER(flag0_w);
- DECLARE_WRITE_LINE_MEMBER(cts0_w);
- DECLARE_WRITE_LINE_MEMBER(cts1_w);
- DECLARE_WRITE_LINE_MEMBER(led_w);
+ void selected_w(int state);
+ void pio_direction_in_w(int state);
+ void pio_handshake_out_w(int state);
+ void pio_spareout_w(int state);
+ void flag0_w(int state);
+ void cts0_w(int state);
+ void cts1_w(int state);
+ void led_w(int state);
void incoming_dtr(int uartind, line_state value);
void transmit_data(int uartind, uint8_t value);
@@ -146,7 +146,7 @@ public:
protected:
void device_start() override { }
- image_init_result call_load() override;
+ std::pair<std::error_condition, std::string> call_load() override;
void call_unload() override;
private:
@@ -159,6 +159,7 @@ private:
*/
class ti_pio_attached_device : public device_t, public device_image_interface
{
+ friend class ti_rs232_pio_device;
public:
ti_pio_attached_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
@@ -174,8 +175,12 @@ public:
protected:
void device_start() override { }
- image_init_result call_load() override;
+ std::pair<std::error_condition, std::string> call_load() override;
void call_unload() override;
+
+private:
+ ti_rs232_pio_device* m_card;
+ void set_card(ti_rs232_pio_device* card) { m_card = card; }
};
} // end namespace bus::ti99::peb
diff --git a/src/devices/bus/ti99/peb/tipi.cpp b/src/devices/bus/ti99/peb/tipi.cpp
index 92f45710d33..558705af4eb 100644
--- a/src/devices/bus/ti99/peb/tipi.cpp
+++ b/src/devices/bus/ti99/peb/tipi.cpp
@@ -76,16 +76,16 @@
#include "emu.h"
#include "tipi.h"
-#define LOG_WARN (1U<<1)
-#define LOG_EPROM (1U<<2)
-#define LOG_CRU (1U<<3)
-#define LOG_PORTS (1U<<4)
-#define LOG_RPI (1U<<5)
-#define LOG_QUEUE (1U<<6)
-#define LOG_PROT (1U<<7)
-#define LOG_DETAIL (1U<<8)
-
-#define VERBOSE ( LOG_GENERAL | LOG_WARN )
+#define LOG_WARN (1U << 1)
+#define LOG_EPROM (1U << 2)
+#define LOG_CRU (1U << 3)
+#define LOG_PORTS (1U << 4)
+#define LOG_RPI (1U << 5)
+#define LOG_QUEUE (1U << 6)
+#define LOG_PROT (1U << 7)
+#define LOG_DETAIL (1U << 8)
+
+#define VERBOSE (LOG_GENERAL | LOG_WARN)
#define RASPI "rpi"
#include "logmacro.h"
@@ -648,7 +648,11 @@ void tipi_card_device::device_add_mconfig(machine_config &config)
ROM_START( tipi )
ROM_REGION(0x8000, TI99_DSRROM, 0)
- ROM_LOAD("tipidsr.u2", 0x0000, 0x8000, CRC(a54e65af) SHA1(f930e4b079a5b6b24dc20f262e9c599d2051b6be))
+ ROM_DEFAULT_BIOS("2023")
+ ROM_SYSTEM_BIOS(0, "2021", "TIPI DSR (2021)" )
+ ROMX_LOAD("tipidsr.u2", 0x0000, 0x8000, CRC(a54e65af) SHA1(f930e4b079a5b6b24dc20f262e9c599d2051b6be), ROM_BIOS(0))
+ ROM_SYSTEM_BIOS(1, "2023", "TIPI DSR (2023)" )
+ ROMX_LOAD("tipidsr_2023.u2", 0x0000, 0x8000, CRC(666f0b63) SHA1(70950e647d5a5102695580064b0bf8d2703586d3), ROM_BIOS(1))
ROM_END
@@ -675,9 +679,9 @@ tipi_attached_device::tipi_attached_device(const machine_config &mconfig, const
/*
Initialize connection
*/
-image_init_result tipi_attached_device::call_load()
+std::pair<std::error_condition, std::string> tipi_attached_device::call_load()
{
- return image_init_result::PASS; // OK
+ return std::make_pair(std::error_condition(), std::string()); // OK
}
void tipi_attached_device::call_unload()
diff --git a/src/devices/bus/ti99/peb/tipi.h b/src/devices/bus/ti99/peb/tipi.h
index 3703e246599..20c978638f4 100644
--- a/src/devices/bus/ti99/peb/tipi.h
+++ b/src/devices/bus/ti99/peb/tipi.h
@@ -116,7 +116,7 @@ public:
protected:
void device_start() override { }
void call_unload() override;
- image_init_result call_load() override;
+ std::pair<std::error_condition, std::string> call_load() override;
};
diff --git a/src/devices/bus/ti99/peb/tn_ide.cpp b/src/devices/bus/ti99/peb/tn_ide.cpp
index f4ae600ce67..52c30daa262 100644
--- a/src/devices/bus/ti99/peb/tn_ide.cpp
+++ b/src/devices/bus/ti99/peb/tn_ide.cpp
@@ -122,15 +122,15 @@
#include "emu.h"
#include "tn_ide.h"
-#define LOG_WARN (1U<<1)
-#define LOG_CRU (1U<<2)
-#define LOG_RTC (1U<<3)
-#define LOG_XRAM (1U<<4)
-#define LOG_SRAM (1U<<5)
-#define LOG_ATA (1U<<6)
-#define LOG_SRAMH (1U<<7)
+#define LOG_WARN (1U << 1)
+#define LOG_CRU (1U << 2)
+#define LOG_RTC (1U << 3)
+#define LOG_XRAM (1U << 4)
+#define LOG_SRAM (1U << 5)
+#define LOG_ATA (1U << 6)
+#define LOG_SRAMH (1U << 7)
-#define VERBOSE ( LOG_GENERAL | LOG_WARN )
+#define VERBOSE (LOG_GENERAL | LOG_WARN)
#include "logmacro.h"
@@ -594,7 +594,7 @@ void nouspikel_ide_card_device::cruwrite(offs_t offset, uint8_t data)
}
template<int rtctype>
-WRITE_LINE_MEMBER(nouspikel_ide_card_device::rtc_int_callback)
+void nouspikel_ide_card_device::rtc_int_callback(int state)
{
if (state)
m_rtc_int |= 1 << rtctype;
@@ -605,13 +605,13 @@ WRITE_LINE_MEMBER(nouspikel_ide_card_device::rtc_int_callback)
m_slot->set_inta(state ? CLEAR_LINE : ASSERT_LINE);
}
-WRITE_LINE_MEMBER(nouspikel_ide_card_device::ide_interrupt_callback)
+void nouspikel_ide_card_device::ide_interrupt_callback(int state)
{
m_ideint = (state==ASSERT_LINE);
if (m_crulatch->q6_r()==1) m_slot->set_inta(state);
}
-WRITE_LINE_MEMBER(nouspikel_ide_card_device::resetdr_callback)
+void nouspikel_ide_card_device::resetdr_callback(int state)
{
if (m_crulatch->q6_r()==1 && (state==0))
// not implemented
diff --git a/src/devices/bus/ti99/peb/tn_ide.h b/src/devices/bus/ti99/peb/tn_ide.h
index f3174e2c0ee..fba16021778 100644
--- a/src/devices/bus/ti99/peb/tn_ide.h
+++ b/src/devices/bus/ti99/peb/tn_ide.h
@@ -71,9 +71,9 @@ private:
// Genmod decoding. If not used, the AME line is pulled up, and the AMD line is pulled down
bool m_genmod;
- template<int rtctype> DECLARE_WRITE_LINE_MEMBER(rtc_int_callback);
- DECLARE_WRITE_LINE_MEMBER(ide_interrupt_callback);
- DECLARE_WRITE_LINE_MEMBER(resetdr_callback);
+ template<int rtctype> void rtc_int_callback(int state);
+ void ide_interrupt_callback(int state);
+ void resetdr_callback(int state);
void decode(offs_t offset, bool& mmap, bool& sramsel, bool& xramsel, bool& rtcsel, bool& cs1fx, bool& cs3fx);
diff --git a/src/devices/bus/ti99/peb/tn_usbsm.cpp b/src/devices/bus/ti99/peb/tn_usbsm.cpp
index 5a2a266661b..a031613ca5a 100644
--- a/src/devices/bus/ti99/peb/tn_usbsm.cpp
+++ b/src/devices/bus/ti99/peb/tn_usbsm.cpp
@@ -42,9 +42,9 @@
#include "emu.h"
#include "tn_usbsm.h"
-#define LOG_WARN (1U<<1) // Warnings
+#define LOG_WARN (1U << 1) // Warnings
-#define VERBOSE ( LOG_WARN )
+#define VERBOSE (LOG_WARN)
#include "logmacro.h"
diff --git a/src/devices/bus/ti99x/990_dk.cpp b/src/devices/bus/ti99x/990_dk.cpp
index f9815b2302a..bc08be51f59 100644
--- a/src/devices/bus/ti99x/990_dk.cpp
+++ b/src/devices/bus/ti99x/990_dk.cpp
@@ -870,7 +870,6 @@ LEGACY_FLOPPY_OPTIONS_END
void fd800_legacy_device::device_start()
{
logerror("fd800: start\n");
- m_int_line.resolve();
for (auto & elem : m_drv)
{
diff --git a/src/devices/bus/ti99x/990_hd.cpp b/src/devices/bus/ti99x/990_hd.cpp
index d9a35d67b30..33f8a1424ab 100644
--- a/src/devices/bus/ti99x/990_hd.cpp
+++ b/src/devices/bus/ti99x/990_hd.cpp
@@ -46,16 +46,6 @@ static inline uint32_t get_UINT32BE(UINT32BE word)
return (word.bytes[0] << 24) | (word.bytes[1] << 16) | (word.bytes[2] << 8) | word.bytes[3];
}
-#ifdef UNUSED_FUNCTION
-static inline void set_UINT32BE(UINT32BE *word, uint32_t data)
-{
- word->bytes[0] = (data >> 24) & 0xff;
- word->bytes[1] = (data >> 16) & 0xff;
- word->bytes[2] = (data >> 8) & 0xff;
- word->bytes[3] = data & 0xff;
-}
-#endif
-
/* disk image header */
struct disk_image_header
{
@@ -162,24 +152,20 @@ int ti990_hdc_device::get_id_from_device( device_t *device )
/*
Initialize hard disk unit and open a hard disk image
*/
-DEVICE_IMAGE_LOAD_MEMBER( ti990_hdc_device::load_hd )
+std::error_condition ti990_hdc_device::load_hd(device_image_interface &image)
{
int id = get_id_from_device( &image.device() );
hd_unit_t *d;
- hard_disk_file *hd_file;
d = &m_d[id];
- d->img = &image;
+ d->img = downcast<harddisk_image_device *>(&image);
- hd_file = dynamic_cast<harddisk_image_device *>(&image)->get_hard_disk_file();
-
- if ( hd_file )
+ if ( d->img->exists() )
{
d->format = format_mame;
- d->hd_handle = hd_file;
/* use standard hard disk image header. */
- const auto &standard_header = d->hd_handle->get_info();
+ const auto &standard_header = d->img->get_info();
d->cylinders = standard_header.cylinders;
d->heads = standard_header.heads;
@@ -194,7 +180,6 @@ DEVICE_IMAGE_LOAD_MEMBER( ti990_hdc_device::load_hd )
/* set file descriptor */
d->format = format_old;
- d->hd_handle = nullptr;
/* use custom image header. */
/* to convert old header-less images to this format, insert a 16-byte
@@ -206,7 +191,7 @@ DEVICE_IMAGE_LOAD_MEMBER( ti990_hdc_device::load_hd )
d->format = format_mame; /* don't care */
d->wp = 1;
d->unsafe = 1;
- return image_init_result::FAIL;
+ return image_error::UNSPECIFIED;
}
d->cylinders = get_UINT32BE(custom_header.cylinders);
@@ -218,10 +203,9 @@ DEVICE_IMAGE_LOAD_MEMBER( ti990_hdc_device::load_hd )
if (d->bytes_per_sector > MAX_SECTOR_SIZE)
{
d->format = format_mame;
- d->hd_handle = nullptr;
d->wp = 1;
d->unsafe = 1;
- return image_init_result::FAIL;
+ return image_error::INVALIDIMAGE;
}
/* tell whether the image is writable */
@@ -231,13 +215,13 @@ DEVICE_IMAGE_LOAD_MEMBER( ti990_hdc_device::load_hd )
/* set attention line */
m_w[0] |= (0x80 >> id);
- return image_init_result::PASS;
+ return std::error_condition();
}
/*
close a hard disk image
*/
-DEVICE_IMAGE_UNLOAD_MEMBER( ti990_hdc_device::unload_hd )
+void ti990_hdc_device::unload_hd(device_image_interface &image)
{
int id = get_id_from_device(&image.device());
hd_unit_t *d;
@@ -245,7 +229,6 @@ DEVICE_IMAGE_UNLOAD_MEMBER( ti990_hdc_device::unload_hd )
d = &m_d[id];
d->format = format_mame; /* don't care */
- d->hd_handle = nullptr;
d->wp = 1;
d->unsafe = 1;
@@ -258,20 +241,7 @@ DEVICE_IMAGE_UNLOAD_MEMBER( ti990_hdc_device::unload_hd )
*/
int ti990_hdc_device::is_unit_loaded(int unit)
{
- int reply = 0;
-
- switch (m_d[unit].format)
- {
- case format_mame:
- reply = (m_d[unit].hd_handle != nullptr);
- break;
-
- case format_old:
- reply = (m_d[unit].img->exists() ? 1 : 0);
- break;
- }
-
- return reply;
+ return m_d[unit].img->exists();
}
/*
@@ -305,10 +275,9 @@ int ti990_hdc_device::cur_disk_unit()
*/
void ti990_hdc_device::update_interrupt()
{
- if (!m_interrupt_callback.isnull())
- m_interrupt_callback((m_w[7] & w7_idle)
- && (((m_w[7] & w7_int_enable) && (m_w[7] & (w7_complete | w7_error)))
- || ((m_w[0] & (m_w[0] >> 4)) & w0_attn_mask)));
+ m_interrupt_callback((m_w[7] & w7_idle)
+ && (((m_w[7] & w7_int_enable) && (m_w[7] & (w7_complete | w7_error)))
+ || ((m_w[0] & (m_w[0] >> 4)) & w0_attn_mask)));
}
/*
@@ -363,7 +332,7 @@ int ti990_hdc_device::read_sector(int unit, unsigned int lba, void *buffer, unsi
switch (m_d[unit].format)
{
case format_mame:
- bytes_read = m_d[unit].bytes_per_sector * m_d[unit].hd_handle->read(lba, buffer);
+ bytes_read = m_d[unit].bytes_per_sector * m_d[unit].img->read(lba, buffer);
if (bytes_read > bytes_to_read)
bytes_read = bytes_to_read;
break;
@@ -393,7 +362,7 @@ int ti990_hdc_device::write_sector(int unit, unsigned int lba, const void *buffe
switch (m_d[unit].format)
{
case format_mame:
- bytes_written = m_d[unit].bytes_per_sector * m_d[unit].hd_handle->write(lba, buffer);
+ bytes_written = m_d[unit].bytes_per_sector * m_d[unit].img->write(lba, buffer);
if (bytes_written > bytes_to_write)
bytes_written = bytes_to_write;
break;
@@ -972,14 +941,11 @@ ti990_hdc_device::ti990_hdc_device(const machine_config &mconfig, const char *ta
void ti990_hdc_device::device_start()
{
- int i;
-
/* initialize harddisk information */
/* attention lines will be set by DEVICE_IMAGE_LOAD */
- for (i=0; i<MAX_DISK_UNIT; i++)
+ for (int i=0; i<MAX_DISK_UNIT; i++)
{
m_d[i].format = format_mame;
- m_d[i].hd_handle = nullptr;
m_d[i].wp = 1;
m_d[i].unsafe = 1;
}
@@ -987,12 +953,10 @@ void ti990_hdc_device::device_start()
m_w[7] = w7_idle;
/* get references to harddisk devices */
- m_d[0].img = dynamic_cast<device_image_interface *>(subdevice("harddisk1"));
- m_d[1].img = dynamic_cast<device_image_interface *>(subdevice("harddisk2"));
- m_d[2].img = dynamic_cast<device_image_interface *>(subdevice("harddisk3"));
- m_d[3].img = dynamic_cast<device_image_interface *>(subdevice("harddisk4"));
-
- m_interrupt_callback.resolve_safe();
+ m_d[0].img = dynamic_cast<harddisk_image_device *>(subdevice("harddisk1"));
+ m_d[1].img = dynamic_cast<harddisk_image_device *>(subdevice("harddisk2"));
+ m_d[2].img = dynamic_cast<harddisk_image_device *>(subdevice("harddisk3"));
+ m_d[3].img = dynamic_cast<harddisk_image_device *>(subdevice("harddisk4"));
update_interrupt();
}
diff --git a/src/devices/bus/ti99x/990_hd.h b/src/devices/bus/ti99x/990_hd.h
index f934775654e..d5b9f60b477 100644
--- a/src/devices/bus/ti99x/990_hd.h
+++ b/src/devices/bus/ti99x/990_hd.h
@@ -18,8 +18,8 @@ public:
uint16_t read(offs_t offset);
void write(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
- DECLARE_DEVICE_IMAGE_LOAD_MEMBER( load_hd );
- DECLARE_DEVICE_IMAGE_UNLOAD_MEMBER( unload_hd );
+ std::error_condition load_hd(device_image_interface &image);
+ void unload_hd(device_image_interface &image);
template <typename T> void set_memory_space(T &&tag, int spacenum) { m_memory_space.set_tag(std::forward<T>(tag), spacenum); }
auto int_cb() { return m_interrupt_callback.bind(); }
@@ -59,9 +59,8 @@ private:
/* disk drive unit descriptor */
struct hd_unit_t
{
- device_image_interface *img; /* image descriptor */
+ harddisk_image_device *img; /* image descriptor */
format_t format;
- hard_disk_file *hd_handle; /* mame hard disk descriptor - only if format == format_mame */
unsigned int wp : 1; /* true if disk is write-protected */
unsigned int unsafe : 1; /* true when a disk has just been connected */
diff --git a/src/devices/bus/ti99x/990_tap.cpp b/src/devices/bus/ti99x/990_tap.cpp
index dff4f68a7a0..58f3619c101 100644
--- a/src/devices/bus/ti99x/990_tap.cpp
+++ b/src/devices/bus/ti99x/990_tap.cpp
@@ -35,6 +35,9 @@
#include "imagedev/magtape.h"
+#include <algorithm>
+#include <iterator>
+
enum
{
w0_offline = 0x8000,
@@ -895,14 +898,14 @@ public:
// construction/destruction
ti990_tape_image_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- // image-level overrides
+ // device_image_interface implementation
virtual const char *file_extensions() const noexcept override { return "tap"; }
- virtual image_init_result call_load() override;
+ virtual std::pair<std::error_condition, std::string> call_load() override;
virtual void call_unload() override;
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
private:
@@ -935,12 +938,12 @@ int ti990_tape_image_device::tape_get_id()
/*
Open a tape image
*/
-image_init_result ti990_tape_image_device::call_load()
+std::pair<std::error_condition, std::string> ti990_tape_image_device::call_load()
{
tap_990_device* tpc = downcast<tap_990_device*>(owner());
tpc->set_tape(tape_get_id(), this, true, false, is_readonly());
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
/*
@@ -968,8 +971,7 @@ tap_990_device::tap_990_device(const machine_config &mconfig, const char *tag, d
void tap_990_device::device_start()
{
- m_int_line.resolve();
- memset(m_w, 0, sizeof(m_w));
+ std::fill(std::begin(m_w), std::end(m_w), 0);
// The PE bit is always set for the MT3200 (but not MT1600)
// According to MT3200 manual, w7 bit #4 (reserved) is always set
diff --git a/src/devices/bus/ti99x/990_tap.h b/src/devices/bus/ti99x/990_tap.h
index 00168cd896b..26ee8edbef6 100644
--- a/src/devices/bus/ti99x/990_tap.h
+++ b/src/devices/bus/ti99x/990_tap.h
@@ -30,7 +30,7 @@ public:
auto int_cb() { return m_int_line.bind(); }
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
virtual void device_add_mconfig(machine_config &config) override;
diff --git a/src/devices/bus/tiki100/8088.cpp b/src/devices/bus/tiki100/8088.cpp
index bd2ad5e4354..28fd3e16c0d 100644
--- a/src/devices/bus/tiki100/8088.cpp
+++ b/src/devices/bus/tiki100/8088.cpp
@@ -36,6 +36,10 @@ ROM_START( tiki100_8088 )
ROM_REGION( 0x100, "u26", 0 )
ROM_LOAD( "53ls140.u26", 0x000, 0x100, CRC(fc5902e1) SHA1(afb9cb54ab6fc449e7544ddb3cbebc3770c4f937) )
+
+ ROM_REGION( 0x2000, "pals", 0 )
+ ROM_LOAD( "8088_pal16l2.u38.jed", 0x0000, 0x031f, CRC(d7f6abfe) SHA1(df58cecf1f99182820bcbf24c58b44d205668963) )
+ ROM_LOAD( "8088_pal16r6a-2.u47.jed", 0x1000, 0x0b06, CRC(ecd32454) SHA1(b6d4a7a3eb29d97971443b8a31ec5a4ce5ced0d8) )
ROM_END
diff --git a/src/devices/bus/tiki100/exp.cpp b/src/devices/bus/tiki100/exp.cpp
index fee968f40d7..a78b143146d 100644
--- a/src/devices/bus/tiki100/exp.cpp
+++ b/src/devices/bus/tiki100/exp.cpp
@@ -58,11 +58,15 @@ tiki100_bus_device::tiki100_bus_device(const machine_config &mconfig, const char
m_irq_cb(*this),
m_nmi_cb(*this),
m_busrq_cb(*this),
- m_in_mrq_cb(*this),
+ m_in_mrq_cb(*this, 0),
m_out_mrq_cb(*this)
{
}
+tiki100_bus_device::~tiki100_bus_device()
+{
+}
+
//-------------------------------------------------
// device_start - device-specific startup
@@ -70,12 +74,6 @@ tiki100_bus_device::tiki100_bus_device(const machine_config &mconfig, const char
void tiki100_bus_device::device_start()
{
- // resolve callbacks
- m_irq_cb.resolve_safe();
- m_nmi_cb.resolve_safe();
- m_busrq_cb.resolve_safe();
- m_in_mrq_cb.resolve();
- m_out_mrq_cb.resolve();
}
@@ -85,7 +83,7 @@ void tiki100_bus_device::device_start()
void tiki100_bus_device::add_card(device_tiki100bus_card_interface &card)
{
- m_device_list.append(card);
+ m_device_list.emplace_back(card);
card.m_bus = this;
}
@@ -97,13 +95,8 @@ void tiki100_bus_device::add_card(device_tiki100bus_card_interface &card)
uint8_t tiki100_bus_device::mrq_r(offs_t offset, uint8_t data, bool &mdis)
{
- device_tiki100bus_card_interface *entry = m_device_list.first();
-
- while (entry)
- {
- data &= entry->mrq_r(offset, data, mdis);
- entry = entry->next();
- }
+ for (device_tiki100bus_card_interface &entry : m_device_list)
+ data &= entry.mrq_r(offset, data, mdis);
return data;
}
@@ -115,13 +108,8 @@ uint8_t tiki100_bus_device::mrq_r(offs_t offset, uint8_t data, bool &mdis)
void tiki100_bus_device::mrq_w(offs_t offset, uint8_t data)
{
- device_tiki100bus_card_interface *entry = m_device_list.first();
-
- while (entry)
- {
- entry->mrq_w(offset, data);
- entry = entry->next();
- }
+ for (device_tiki100bus_card_interface &entry : m_device_list)
+ entry.mrq_w(offset, data);
}
@@ -131,13 +119,8 @@ void tiki100_bus_device::mrq_w(offs_t offset, uint8_t data)
uint8_t tiki100_bus_device::iorq_r(offs_t offset, uint8_t data)
{
- device_tiki100bus_card_interface *entry = m_device_list.first();
-
- while (entry)
- {
- data &= entry->iorq_r(offset, data);
- entry = entry->next();
- }
+ for (device_tiki100bus_card_interface &entry : m_device_list)
+ data &= entry.iorq_r(offset, data);
return data;
}
@@ -149,13 +132,8 @@ uint8_t tiki100_bus_device::iorq_r(offs_t offset, uint8_t data)
void tiki100_bus_device::iorq_w(offs_t offset, uint8_t data)
{
- device_tiki100bus_card_interface *entry = m_device_list.first();
-
- while (entry)
- {
- entry->iorq_w(offset, data);
- entry = entry->next();
- }
+ for (device_tiki100bus_card_interface &entry : m_device_list)
+ entry.iorq_w(offset, data);
}
@@ -163,15 +141,10 @@ void tiki100_bus_device::iorq_w(offs_t offset, uint8_t data)
// busak_w - bus acknowledge write
//-------------------------------------------------
-WRITE_LINE_MEMBER( tiki100_bus_device::busak_w )
+void tiki100_bus_device::busak_w(int state)
{
- device_tiki100bus_card_interface *entry = m_device_list.first();
-
- while (entry)
- {
- entry->busak_w(state);
- entry = entry->next();
- }
+ for (device_tiki100bus_card_interface &entry : m_device_list)
+ entry.busak_w(state);
}
@@ -187,8 +160,7 @@ WRITE_LINE_MEMBER( tiki100_bus_device::busak_w )
device_tiki100bus_card_interface::device_tiki100bus_card_interface(const machine_config &mconfig, device_t &device) :
device_interface(device, "tiki100bus"),
m_bus(nullptr),
- m_busak(CLEAR_LINE),
- m_next(nullptr)
+ m_busak(CLEAR_LINE)
{
m_slot = dynamic_cast<tiki100_bus_slot_device *>(device.owner());
}
diff --git a/src/devices/bus/tiki100/exp.h b/src/devices/bus/tiki100/exp.h
index 7625971a47d..4f49a8cd546 100644
--- a/src/devices/bus/tiki100/exp.h
+++ b/src/devices/bus/tiki100/exp.h
@@ -16,6 +16,9 @@
#include "machine/z80daisy.h"
+#include <functional>
+#include <vector>
+
//**************************************************************************
@@ -33,11 +36,8 @@ class tiki100_bus_slot_device;
class device_tiki100bus_card_interface : public device_interface
{
friend class tiki100_bus_device;
- template <class ElementType> friend class simple_list;
public:
- device_tiki100bus_card_interface *next() const { return m_next; }
-
// memory access
virtual uint8_t mrq_r(offs_t offset, uint8_t data, bool &mdis) { mdis = 1; return data; }
virtual void mrq_w(offs_t offset, uint8_t data) { }
@@ -62,9 +62,6 @@ protected:
tiki100_bus_device *m_bus;
tiki100_bus_slot_device *m_slot;
int m_busak;
-
-private:
- device_tiki100bus_card_interface *m_next;
};
@@ -92,10 +89,10 @@ public:
template <typename T> void set_bus(T &&tag) { m_bus.set_tag(std::forward<T>(tag)); }
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
- // device_z80daisy_interface overrides
+ // device_z80daisy_interface implementation
virtual int z80daisy_irq_state() override { return get_card_device() ? m_card->z80daisy_irq_state() : 0; }
virtual int z80daisy_irq_ack() override { return get_card_device() ? m_card->z80daisy_irq_ack() : 0; }
virtual void z80daisy_irq_reti() override { if (get_card_device()) m_card->z80daisy_irq_reti(); }
@@ -118,7 +115,7 @@ class tiki100_bus_device : public device_t
public:
// construction/destruction
tiki100_bus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- ~tiki100_bus_device() { m_device_list.detach_all(); }
+ ~tiki100_bus_device();
auto irq_wr_callback() { return m_irq_cb.bind(); }
auto nmi_wr_callback() { return m_nmi_cb.bind(); }
@@ -135,27 +132,29 @@ public:
uint8_t iorq_r(offs_t offset, uint8_t data);
void iorq_w(offs_t offset, uint8_t data);
- DECLARE_WRITE_LINE_MEMBER( busak_w );
+ void busak_w(int state);
// peripheral interface
- DECLARE_WRITE_LINE_MEMBER( irq_w ) { m_irq_cb(state); }
- DECLARE_WRITE_LINE_MEMBER( nmi_w ) { m_nmi_cb(state); }
- DECLARE_WRITE_LINE_MEMBER( busrq_w ) { m_busrq_cb(state); }
+ void irq_w(int state) { m_irq_cb(state); }
+ void nmi_w(int state) { m_nmi_cb(state); }
+ void busrq_w(int state) { m_busrq_cb(state); }
uint8_t exin_mrq_r(offs_t offset) { return m_in_mrq_cb(offset); }
void exin_mrq_w(offs_t offset, uint8_t data) { m_out_mrq_cb(offset, data); }
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
private:
+ using card_vector = std::vector<std::reference_wrapper<device_tiki100bus_card_interface> >;
+
devcb_write_line m_irq_cb;
devcb_write_line m_nmi_cb;
devcb_write_line m_busrq_cb;
devcb_read8 m_in_mrq_cb;
devcb_write8 m_out_mrq_cb;
- simple_list<device_tiki100bus_card_interface> m_device_list;
+ card_vector m_device_list;
};
diff --git a/src/devices/bus/tim011/aycard.cpp b/src/devices/bus/tim011/aycard.cpp
new file mode 100644
index 00000000000..9969716fb44
--- /dev/null
+++ b/src/devices/bus/tim011/aycard.cpp
@@ -0,0 +1,84 @@
+// license:BSD-3-Clause
+// copyright-holders:Marko Solajic, Miodrag Milanovic
+/**********************************************************************
+
+ TIM-011 AY Card
+
+ Card created by Zoran Urosevic.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "aycard.h"
+#include "speaker.h"
+#include "sound/ay8910.h"
+
+namespace {
+
+static INPUT_PORTS_START(joystick)
+ PORT_START("JOY")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT) PORT_8WAY
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT) PORT_8WAY
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN) PORT_8WAY
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_UP) PORT_8WAY
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_BUTTON1)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_BUTTON3)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_BUTTON2)
+INPUT_PORTS_END
+
+class tim011_aycard_device :
+ public device_t,
+ public bus::tim011::device_exp_interface
+{
+public:
+ // construction/destruction
+ tim011_aycard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device_t implementation
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ // device-level overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(joystick); }
+
+private:
+ required_device<ay8910_device> m_psg;
+};
+
+
+tim011_aycard_device::tim011_aycard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, TIM011_AYCARD, tag, owner, clock)
+ , bus::tim011::device_exp_interface(mconfig, *this)
+ , m_psg(*this, "ay8912")
+{
+}
+
+/*----------------------------------
+ device_t implementation
+----------------------------------*/
+
+void tim011_aycard_device::device_start()
+{
+}
+
+void tim011_aycard_device::device_reset()
+{
+ m_slot->m_io->install_write_handler(0x00f4, 0x00f4, emu::rw_delegate(m_psg, FUNC(ay8910_device::data_w)));
+ m_slot->m_io->install_read_handler (0x00fc, 0x00fc, emu::rw_delegate(m_psg, FUNC(ay8910_device::data_r)));
+ m_slot->m_io->install_write_handler(0x00fc, 0x00fc, emu::rw_delegate(m_psg, FUNC(ay8910_device::address_w)));
+}
+
+void tim011_aycard_device::device_add_mconfig(machine_config &config)
+{
+ /* sound hardware */
+ SPEAKER(config, "mono").front_center();
+ AY8912(config, m_psg, 1.8432_MHz_XTAL);
+ m_psg->add_route(ALL_OUTPUTS, "mono", 0.25);
+}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(TIM011_AYCARD, bus::tim011::device_exp_interface, tim011_aycard_device, "ay", "AY card")
diff --git a/src/devices/bus/tim011/aycard.h b/src/devices/bus/tim011/aycard.h
new file mode 100644
index 00000000000..89b35dd2e49
--- /dev/null
+++ b/src/devices/bus/tim011/aycard.h
@@ -0,0 +1,12 @@
+// license:BSD-3-Clause
+// copyright-holders:Marko Solajic, Miodrag Milanovic
+#ifndef MAME_BUS_TIM011_AYCARD_H
+#define MAME_BUS_TIM011_AYCARD_H
+
+#pragma once
+
+#include "exp.h"
+
+DECLARE_DEVICE_TYPE_NS(TIM011_AYCARD, bus::tim011, device_exp_interface)
+
+#endif // MAME_BUS_TIM011_AYCARD_H
diff --git a/src/devices/bus/tim011/exp.cpp b/src/devices/bus/tim011/exp.cpp
new file mode 100644
index 00000000000..a67b1199908
--- /dev/null
+++ b/src/devices/bus/tim011/exp.cpp
@@ -0,0 +1,54 @@
+// license:BSD-3-Clause
+// copyright-holders:Marko Solajic, Miodrag Milanovic
+/**********************************************************************
+
+ TIM-011 Expansion Port emulation
+
+**********************************************************************/
+
+#include "emu.h"
+#include "exp.h"
+
+DEFINE_DEVICE_TYPE(TIM011_EXPANSION_SLOT, bus::tim011::exp_slot_device, "tim011_exp_slot", "TIM-011 Expansion port")
+
+namespace bus::tim011 {
+
+/***********************************************************************
+ CARD INTERFACE
+***********************************************************************/
+
+device_exp_interface::device_exp_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "tim011exp")
+{
+ m_slot = dynamic_cast<exp_slot_device *>(device.owner());
+}
+
+/***********************************************************************
+ SLOT DEVICE
+***********************************************************************/
+
+exp_slot_device::exp_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, TIM011_EXPANSION_SLOT, tag, owner, clock),
+ device_single_card_slot_interface<device_exp_interface>(mconfig, *this),
+ m_io(*this, finder_base::DUMMY_TAG, -1),
+ m_int_handler(*this),
+ m_nmi_handler(*this)
+{
+}
+
+/*----------------------------------
+ device_t implementation
+----------------------------------*/
+
+void exp_slot_device::device_start()
+{
+}
+
+} // namespace bus::tim011
+
+#include "aycard.h"
+
+void tim011_exp_devices(device_slot_interface &device)
+{
+ device.option_add("ay", TIM011_AYCARD);
+}
diff --git a/src/devices/bus/tim011/exp.h b/src/devices/bus/tim011/exp.h
new file mode 100644
index 00000000000..06dcf0f3e1a
--- /dev/null
+++ b/src/devices/bus/tim011/exp.h
@@ -0,0 +1,102 @@
+// license:BSD-3-Clause
+// copyright-holders:Marko Solajic, Miodrag Milanovic
+/*********************************************************************
+
+ TIM-011 Expansion Port emulation
+
+**********************************************************************
+
+ Pinout:
+
+ TIM011 Expansion Connector
+ 40 pin male, on main board
+
+ *******
+ VCC 1 * . . * 2 VCC
+ GND 3 * . . * 4 GND
+ /RD 5 * . . * 6 PHI
+ /WR 7 * . . * 8 /RESET
+ E 9 * . . * 10 /LIR
+ /NMI 11 * . . * 12 /EXPSEL (E0-FF)
+ /WAIT 13 * . . * 14 NC
+ /INT0 15 * . . * 16 /HALT
+ ST 17 . . * 18 NC
+ A0 19 . . * 20 A1
+ /TEND0 21 . . * 22 A2
+ A3 23 * . . * 24 A4
+ /DREQ0 25 * . . * 26 /IOE
+ 8MHZ 27 * . . * 28 RESET
+ D7 29 * . . * 30 D6
+ D5 31 * . . * 32 D3
+ D4 33 * . . * 34 D2
+ D1 35 * . . * 36 D0
+ GND 37 * . . * 38 GND
+ NC 39 * . . * 40 NC
+ *******
+
+**********************************************************************/
+
+#ifndef MAME_BUS_TIM011_EXP_H
+#define MAME_BUS_TIM011_EXP_H
+
+#pragma once
+
+namespace bus::tim011 {
+
+class device_exp_interface;
+
+class exp_slot_device : public device_t, public device_single_card_slot_interface<device_exp_interface>
+{
+public:
+ // construction/destruction
+ template <typename T>
+ exp_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&slot_options, const char *default_option)
+ : exp_slot_device(mconfig, tag, owner)
+ {
+ option_reset();
+ slot_options(*this);
+ set_default_option(default_option);
+ set_fixed(false);
+ }
+
+ exp_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock = 0);
+
+ template <typename T> void set_io_space(T &&tag, int spacenum) { m_io.set_tag(std::forward<T>(tag), spacenum); }
+
+ // callbacks
+ auto int_handler() { return m_int_handler.bind(); }
+ auto nmi_handler() { return m_nmi_handler.bind(); }
+
+ // called from expansion device
+ void int_w(int state) { m_int_handler(state); }
+ void nmi_w(int state) { m_nmi_handler(state); }
+
+ required_address_space m_io;
+
+protected:
+ // device_t implementation
+ virtual void device_start() override;
+
+private:
+ devcb_write_line m_int_handler;
+ devcb_write_line m_nmi_handler;
+};
+
+// ======================> device_exp_interface
+
+class device_exp_interface : public device_interface
+{
+protected:
+ // construction/destruction
+ device_exp_interface(const machine_config &mconfig, device_t &device);
+
+ exp_slot_device *m_slot;
+};
+
+} // namespace bus::tim011
+
+DECLARE_DEVICE_TYPE_NS(TIM011_EXPANSION_SLOT, bus::tim011, exp_slot_device)
+
+void tim011_exp_devices(device_slot_interface &device);
+
+#endif // MAME_BUS_TIM011_EXP_H
diff --git a/src/devices/bus/tvc/hbf.cpp b/src/devices/bus/tvc/hbf.cpp
index c12b4ab90cc..43d95a753a3 100644
--- a/src/devices/bus/tvc/hbf.cpp
+++ b/src/devices/bus/tvc/hbf.cpp
@@ -9,6 +9,8 @@
#include "emu.h"
#include "hbf.h"
+#include "formats/tvc_dsk.h"
+
/***************************************************************************
IMPLEMENTATION
diff --git a/src/devices/bus/tvc/hbf.h b/src/devices/bus/tvc/hbf.h
index b53a3b7520d..463a5209309 100644
--- a/src/devices/bus/tvc/hbf.h
+++ b/src/devices/bus/tvc/hbf.h
@@ -8,7 +8,6 @@
#include "tvc.h"
#include "imagedev/floppy.h"
#include "machine/wd_fdc.h"
-#include "formats/tvc_dsk.h"
//**************************************************************************
diff --git a/src/devices/bus/tvc/tvc.cpp b/src/devices/bus/tvc/tvc.cpp
index d3b4cee5652..c1c8dc902e6 100644
--- a/src/devices/bus/tvc/tvc.cpp
+++ b/src/devices/bus/tvc/tvc.cpp
@@ -75,10 +75,6 @@ tvcexp_slot_device::~tvcexp_slot_device()
void tvcexp_slot_device::device_start()
{
m_cart = get_card_device();
-
- // resolve callbacks
- m_out_irq_cb.resolve_safe();
- m_out_nmi_cb.resolve_safe();
}
/*-------------------------------------------------
diff --git a/src/devices/bus/uts_kbd/400kbd.cpp b/src/devices/bus/uts_kbd/400kbd.cpp
index 50e05d4eddf..f6b8ca736ac 100644
--- a/src/devices/bus/uts_kbd/400kbd.cpp
+++ b/src/devices/bus/uts_kbd/400kbd.cpp
@@ -52,7 +52,7 @@ void uts_400_keyboard_device::device_start()
save_item(NAME(m_prog_line));
}
-WRITE_LINE_MEMBER(uts_400_keyboard_device::ready_w)
+void uts_400_keyboard_device::ready_w(int state)
{
m_ready_line = bool(state);
}
@@ -77,12 +77,12 @@ void uts_400_keyboard_device::p2_w(u8 data)
m_p2_output = data;
}
-READ_LINE_MEMBER(uts_400_keyboard_device::t1_r)
+int uts_400_keyboard_device::t1_r()
{
return m_ready_line;
}
-WRITE_LINE_MEMBER(uts_400_keyboard_device::prog_w)
+void uts_400_keyboard_device::prog_w(int state)
{
if (!m_prog_line && state)
m_input_select = m_p2_output & 0x0f;
@@ -167,7 +167,7 @@ static INPUT_PORTS_START(uts_400kbd)
PORT_START("KEY8")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F6 F15")
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F5 F14")
- PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("(Xchg " UTF8_DOWN " Xchg " UTF8_UP ")")
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(u8"(Xchg \u2193 Xchg \u2191)") // U+2193 = ↓, U+2191 = ↑
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Disp 1-2")
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Hang Up")
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Ws Mode Sys Mode")
@@ -189,9 +189,9 @@ static INPUT_PORTS_START(uts_400kbd)
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('x') PORT_CHAR('X') PORT_CODE(KEYCODE_X)
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Cursor to Home") PORT_CHAR(UCHAR_MAMEKEY(HOME)) PORT_CODE(KEYCODE_HOME)
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('a') PORT_CHAR('A') PORT_CODE(KEYCODE_A)
- PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("(Cursor \xe2\x86\x99)") // ↙
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(u8"(Cursor \u2199)") // U+2199 = ↙
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Left Back Space") PORT_CODE(KEYCODE_TAB)
- PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("SOE \xe2\x96\xb6") // ▶
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(u8"SOE \u25b6") // U+25B6 = ▶
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Erase Char") PORT_CODE(KEYCODE_ESC)
PORT_START("KEYB")
diff --git a/src/devices/bus/uts_kbd/400kbd.h b/src/devices/bus/uts_kbd/400kbd.h
index 8e73bc10dbd..808c52fec5a 100644
--- a/src/devices/bus/uts_kbd/400kbd.h
+++ b/src/devices/bus/uts_kbd/400kbd.h
@@ -14,7 +14,7 @@ public:
uts_400_keyboard_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
protected:
- virtual DECLARE_WRITE_LINE_MEMBER(ready_w) override;
+ virtual void ready_w(int state) override;
virtual ioport_constructor device_input_ports() const override;
virtual void device_start() override;
@@ -25,8 +25,8 @@ private:
u8 bus_r();
void p1_w(u8 data);
void p2_w(u8 data);
- DECLARE_READ_LINE_MEMBER(t1_r);
- DECLARE_WRITE_LINE_MEMBER(prog_w);
+ int t1_r();
+ void prog_w(int state);
void ext_map(address_map &map);
diff --git a/src/devices/bus/uts_kbd/extw.cpp b/src/devices/bus/uts_kbd/extw.cpp
index 950d8b244f2..344159485a5 100644
--- a/src/devices/bus/uts_kbd/extw.cpp
+++ b/src/devices/bus/uts_kbd/extw.cpp
@@ -61,7 +61,7 @@ void uts_extw_keyboard_device::device_start()
save_item(NAME(m_prog_line));
}
-WRITE_LINE_MEMBER(uts_extw_keyboard_device::ready_w)
+void uts_extw_keyboard_device::ready_w(int state)
{
m_ready_line = bool(state);
}
@@ -93,12 +93,12 @@ void uts_extw_keyboard_device::t0_clock(u32 clk)
{
}
-READ_LINE_MEMBER(uts_extw_keyboard_device::t1_r)
+int uts_extw_keyboard_device::t1_r()
{
return BIT(m_shift_register, 7);
}
-WRITE_LINE_MEMBER(uts_extw_keyboard_device::prog_w)
+void uts_extw_keyboard_device::prog_w(int state)
{
if (!m_prog_line && state)
{
diff --git a/src/devices/bus/uts_kbd/extw.h b/src/devices/bus/uts_kbd/extw.h
index 21599139ec1..1bde8144781 100644
--- a/src/devices/bus/uts_kbd/extw.h
+++ b/src/devices/bus/uts_kbd/extw.h
@@ -14,7 +14,7 @@ public:
uts_extw_keyboard_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
protected:
- virtual DECLARE_WRITE_LINE_MEMBER(ready_w) override;
+ virtual void ready_w(int state) override;
virtual ioport_constructor device_input_ports() const override;
virtual void device_start() override;
@@ -26,8 +26,8 @@ private:
void p1_w(u8 data);
void p2_w(u8 data);
void t0_clock(u32 clk);
- DECLARE_READ_LINE_MEMBER(t1_r);
- DECLARE_WRITE_LINE_MEMBER(prog_w);
+ int t1_r();
+ void prog_w(int state);
void prog_map(address_map &map);
void ext_map(address_map &map);
diff --git a/src/devices/bus/uts_kbd/uts_kbd.cpp b/src/devices/bus/uts_kbd/uts_kbd.cpp
index 8a379b69f0c..5f1cc77eab5 100644
--- a/src/devices/bus/uts_kbd/uts_kbd.cpp
+++ b/src/devices/bus/uts_kbd/uts_kbd.cpp
@@ -50,11 +50,6 @@ void uts_keyboard_port_device::device_config_complete()
m_kbd = get_card_device();
}
-void uts_keyboard_port_device::device_resolve_objects()
-{
- m_rxd_callback.resolve_safe();
-}
-
void uts_keyboard_port_device::device_start()
{
}
diff --git a/src/devices/bus/uts_kbd/uts_kbd.h b/src/devices/bus/uts_kbd/uts_kbd.h
index c0d6d9b0824..5d34f7f98cb 100644
--- a/src/devices/bus/uts_kbd/uts_kbd.h
+++ b/src/devices/bus/uts_kbd/uts_kbd.h
@@ -42,16 +42,15 @@ public:
auto rxd_callback() { return m_rxd_callback.bind(); }
// line handler
- inline DECLARE_WRITE_LINE_MEMBER(ready_w);
+ inline void ready_w(int state);
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_config_complete() override;
- virtual void device_resolve_objects() override;
virtual void device_start() override;
// called from keyboard
- DECLARE_WRITE_LINE_MEMBER(write_rxd) { m_rxd_callback(state); }
+ void write_rxd(int state) { m_rxd_callback(state); }
private:
// user callback
@@ -72,9 +71,9 @@ protected:
device_uts_keyboard_interface(const machine_config &mconfig, device_t &device);
virtual ~device_uts_keyboard_interface();
- DECLARE_WRITE_LINE_MEMBER(write_rxd) { m_port->write_rxd(state); }
+ void write_rxd(int state) { m_port->write_rxd(state); }
- virtual DECLARE_WRITE_LINE_MEMBER(ready_w) = 0;
+ virtual void ready_w(int state) = 0;
private:
// parent port
@@ -92,7 +91,7 @@ extern void uts10_keyboards(device_slot_interface &slot);
// INLINE FUNCTIONS
//**************************************************************************
-WRITE_LINE_MEMBER(uts_keyboard_port_device::ready_w)
+void uts_keyboard_port_device::ready_w(int state)
{
if (m_kbd != nullptr)
m_kbd->ready_w(state);
diff --git a/src/devices/bus/vboy/rom.cpp b/src/devices/bus/vboy/rom.cpp
index 14fac38ca1f..20ba18ff62a 100644
--- a/src/devices/bus/vboy/rom.cpp
+++ b/src/devices/bus/vboy/rom.cpp
@@ -9,6 +9,7 @@
#include "bus/generic/slot.h"
//#define VERBOSE 1
+//#define LOG_OUTPUT_FUNC osd_printf_info
#include "logmacro.h"
@@ -38,7 +39,7 @@ vboy_flat_rom_device::vboy_flat_rom_device(machine_config const &mconfig, device
}
-image_init_result vboy_flat_rom_device::load()
+std::error_condition vboy_flat_rom_device::load()
{
// if the host has supplied a ROM space, install with appropriate mirroring
memory_region *const romregion(memregion("^rom"));
@@ -61,9 +62,8 @@ image_init_result vboy_flat_rom_device::load()
romregion->bytes() >> 2,
0x00ff'ffff >> 2,
0,
- 0,
rom_base(),
- [this, rom = reinterpret_cast<u32 *>(romregion->base())] (offs_t begin, offs_t end, offs_t mirror, offs_t src)
+ [this, rom = &romregion->as_u32()] (offs_t begin, offs_t end, offs_t mirror, offs_t src)
{
LOG(
"Install ROM 0x%08X-0x%08X at 0x%08X-0x%08X mirror %08X\n",
@@ -76,7 +76,7 @@ image_init_result vboy_flat_rom_device::load()
});
}
- return image_init_result::PASS;
+ return std::error_condition();
}
@@ -96,10 +96,10 @@ vboy_flat_rom_sram_device::vboy_flat_rom_sram_device(machine_config const &mconf
}
-image_init_result vboy_flat_rom_sram_device::load()
+std::error_condition vboy_flat_rom_sram_device::load()
{
- image_init_result const result(vboy_flat_rom_device::load());
- if (image_init_result::PASS != result)
+ std::error_condition const result(vboy_flat_rom_device::load());
+ if (result)
return result;
memory_region *const sramregion(memregion("^sram"));
@@ -117,7 +117,6 @@ image_init_result vboy_flat_rom_sram_device::load()
sramregion->bytes() >> 1,
0x00ff'ffff >> 2,
0,
- 0,
chip_base(),
[this, sramregion] (offs_t begin, offs_t end, offs_t mirror, offs_t src)
{
@@ -150,7 +149,6 @@ image_init_result vboy_flat_rom_sram_device::load()
sramregion->bytes() >> 2,
0x00ff'ffff >> 2,
0,
- 0,
chip_base(),
[this, sramregion] (offs_t begin, offs_t end, offs_t mirror, offs_t src)
{
@@ -183,7 +181,7 @@ image_init_result vboy_flat_rom_sram_device::load()
battery_load(sramregion->base(), sramregion->bytes(), nullptr);
}
- return image_init_result::PASS;
+ return std::error_condition();
}
diff --git a/src/devices/bus/vboy/rom.h b/src/devices/bus/vboy/rom.h
index 79ad95f2e9a..5e369783a10 100644
--- a/src/devices/bus/vboy/rom.h
+++ b/src/devices/bus/vboy/rom.h
@@ -18,7 +18,7 @@ public:
vboy_flat_rom_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
// device_vboy_cart_interface implementation
- virtual image_init_result load() override ATTR_COLD;
+ virtual std::error_condition load() override ATTR_COLD;
protected:
vboy_flat_rom_device(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock);
@@ -34,7 +34,7 @@ public:
vboy_flat_rom_sram_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
// device_vboy_cart_interface implementation
- virtual image_init_result load() override ATTR_COLD;
+ virtual std::error_condition load() override ATTR_COLD;
virtual void unload() override ATTR_COLD;
};
diff --git a/src/devices/bus/vboy/slot.cpp b/src/devices/bus/vboy/slot.cpp
index abbbd527941..9b9cf4e88ea 100644
--- a/src/devices/bus/vboy/slot.cpp
+++ b/src/devices/bus/vboy/slot.cpp
@@ -17,6 +17,7 @@
#include <cstring>
//#define VERBOSE 1
+//#define LOG_OUTPUT_FUNC osd_printf_info
#include "logmacro.h"
@@ -27,6 +28,7 @@
DEFINE_DEVICE_TYPE(VBOY_CART_SLOT, vboy_cart_slot_device, "vboy_cart_slot", "Nintendo Virtual Boy Cartridge Slot")
+
//**************************************************************************
// vboy_cart_slot_device
//**************************************************************************
@@ -47,38 +49,36 @@ vboy_cart_slot_device::vboy_cart_slot_device(machine_config const &mconfig, char
}
-image_init_result vboy_cart_slot_device::call_load()
+std::pair<std::error_condition, std::string> vboy_cart_slot_device::call_load()
{
if (!m_cart)
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
memory_region *romregion(loaded_through_softlist() ? memregion("rom") : nullptr);
if (loaded_through_softlist() && !romregion)
- {
- seterror(image_error::INVALIDIMAGE, "Software list item has no 'rom' data area");
- return image_init_result::FAIL;
- }
+ return std::make_pair(image_error::BADSOFTWARE, "Software list item has no 'rom' data area");
u32 const len(loaded_through_softlist() ? romregion->bytes() : length());
if ((0x0000'0003 & len) || (0x0100'0000 < len))
- {
- seterror(image_error::INVALIDIMAGE, "Unsupported cartridge size (must be a multiple of 4 bytes no larger than 16 MiB)");
- return image_init_result::FAIL;
- }
+ return std::make_pair(image_error::INVALIDLENGTH, "Unsupported cartridge size (must be a multiple of 4 bytes no larger than 16 MiB)");
if (!loaded_through_softlist())
{
LOG("Allocating %u byte cartridge ROM region\n", len);
- romregion = machine().memory().region_alloc(subtag("rom").c_str(), len, 4, ENDIANNESS_LITTLE);
- u32 const cnt(fread(romregion->base(), len));
+ romregion = machine().memory().region_alloc(subtag("rom"), len, 4, ENDIANNESS_LITTLE);
+ u32 *const rombase(reinterpret_cast<u32 *>(romregion->base()));
+ u32 const cnt(fread(rombase, len));
if (cnt != len)
+ return std::make_pair(std::errc::io_error, "Error reading cartridge file");
+
+ if (ENDIANNESS_NATIVE != ENDIANNESS_LITTLE)
{
- seterror(image_error::UNSPECIFIED, "Error reading cartridge file");
- return image_init_result::FAIL;
+ for (u32 i = 0; (len / 4) > i; ++i)
+ rombase[i] = swapendian_int32(rombase[i]);
}
}
- return m_cart->load();
+ return std::make_pair(m_cart->load(), std::string());
}
@@ -102,12 +102,6 @@ void vboy_cart_slot_device::device_validity_check(validity_checker &valid) const
}
-void vboy_cart_slot_device::device_resolve_objects()
-{
- m_intcro.resolve_safe();
-}
-
-
void vboy_cart_slot_device::device_start()
{
if (!m_exp_space && ((m_exp_space.finder_tag() != finder_base::DUMMY_TAG) || (m_exp_space.spacenum() >= 0)))
@@ -125,27 +119,38 @@ void vboy_cart_slot_device::device_start()
std::string vboy_cart_slot_device::get_default_card_software(get_default_card_software_hook &hook) const
{
- std::string const image_name(mconfig().options().image_option(instance_name()).value());
- software_part const *const part(!image_name.empty() ? find_software_item(image_name, true) : nullptr);
- if (part)
+ if (hook.image_file())
{
- //printf("[%s] Found software part for image name '%s'\n", tag(), image_name.c_str());
- for (rom_entry const &entry : part->romdata())
+ // TODO: is there a header field or something indicating presence of save RAM?
+ osd_printf_verbose("[%s] Assuming plain ROM cartridge\n", tag());
+ return "flatrom";
+ }
+ else
+ {
+ std::string const image_name(mconfig().options().image_option(instance_name()).value());
+ software_part const *const part(!image_name.empty() ? find_software_item(image_name, true) : nullptr);
+ if (part)
{
- if (ROMENTRY_ISREGION(entry) && (entry.name() == "sram"))
+ osd_printf_verbose("[%s] Found software part for image name '%s'\n", tag(), image_name);
+ for (rom_entry const &entry : part->romdata())
{
- //printf("[%s] Found 'sram' data area, enabling cartridge backup RAM\n", tag());
- return "flatrom_sram";
+ if (ROMENTRY_ISREGION(entry) && (entry.name() == "sram"))
+ {
+ osd_printf_verbose("[%s] Found 'sram' data area, enabling cartridge backup RAM\n", tag());
+ return "flatrom_sram";
+ }
}
+ osd_printf_verbose("[%s] No 'sram' data area found, assuming plain ROM cartridge\n", tag());
+ return "flatrom";
+ }
+ else
+ {
+ osd_printf_verbose("[%s] No software part found for image name '%s'\n", tag(), image_name);
}
- }
- else
- {
- //printf("[%s] No software part found for image name '%s'\n", tag(), image_name.c_str());
}
- //printf("[%s] Assuming plain ROM cartridge\n", tag());
- return "flatrom";
+ // leave the slot empty
+ return std::string();
}
diff --git a/src/devices/bus/vboy/slot.h b/src/devices/bus/vboy/slot.h
index 650c3380636..850841de194 100644
--- a/src/devices/bus/vboy/slot.h
+++ b/src/devices/bus/vboy/slot.h
@@ -64,6 +64,10 @@
#include "imagedev/cartrom.h"
+#include <cassert>
+#include <string>
+#include <utility>
+
//**************************************************************************
// FORWARD DECLARATIONS
@@ -101,7 +105,7 @@ public:
template <typename T> void set_rom(T &&tag, int no, offs_t base) { m_rom_space.set_tag(std::forward<T>(tag), no); m_rom_base = base; }
// device_image_interface implementation
- virtual image_init_result call_load() override;
+ virtual std::pair<std::error_condition, std::string> call_load() override;
virtual void call_unload() override;
virtual bool is_reset_on_load() const noexcept override { return true; }
virtual char const *image_interface() const noexcept override { return "vboy_cart"; }
@@ -113,7 +117,6 @@ public:
protected:
// device_t implementation
virtual void device_validity_check(validity_checker &valid) const override ATTR_COLD;
- virtual void device_resolve_objects() override ATTR_COLD;
virtual void device_start() override ATTR_COLD;
private:
@@ -134,19 +137,19 @@ private:
class device_vboy_cart_interface : public device_interface
{
public:
- virtual image_init_result load() ATTR_COLD = 0;
+ virtual std::error_condition load() ATTR_COLD = 0;
virtual void unload() ATTR_COLD;
protected:
device_vboy_cart_interface(machine_config const &mconfig, device_t &device);
- bool has_slot() const { return nullptr != m_slot; }
- address_space *exp_space() { return m_slot ? m_slot->m_exp_space.target() : nullptr; }
- address_space *chip_space() { return m_slot ? m_slot->m_chip_space.target() : nullptr; }
- address_space *rom_space() { return m_slot ? m_slot->m_rom_space.target() : nullptr; }
- offs_t exp_base() { return m_slot ? m_slot->m_exp_base : 0U; }
- offs_t chip_base() { return m_slot ? m_slot->m_chip_base : 0U; }
- offs_t rom_base() { return m_slot ? m_slot->m_rom_base : 0U; }
+ bool has_slot() const noexcept { return nullptr != m_slot; }
+ address_space *exp_space() noexcept { return m_slot ? m_slot->m_exp_space.target() : nullptr; }
+ address_space *chip_space() noexcept { return m_slot ? m_slot->m_chip_space.target() : nullptr; }
+ address_space *rom_space() noexcept { return m_slot ? m_slot->m_rom_space.target() : nullptr; }
+ offs_t exp_base() noexcept { return m_slot ? m_slot->m_exp_base : 0U; }
+ offs_t chip_base() noexcept { return m_slot ? m_slot->m_chip_base : 0U; }
+ offs_t rom_base() noexcept { return m_slot ? m_slot->m_rom_base : 0U; }
void battery_load(void *buffer, int length, int fill) { assert(m_slot); m_slot->battery_load(buffer, length, fill); }
void battery_load(void *buffer, int length, void *def_buffer) { assert(m_slot); m_slot->battery_load(buffer, length, def_buffer); }
diff --git a/src/devices/bus/vc4000/slot.cpp b/src/devices/bus/vc4000/slot.cpp
index ce8acfcbf43..ac0d7ce2de7 100644
--- a/src/devices/bus/vc4000/slot.cpp
+++ b/src/devices/bus/vc4000/slot.cpp
@@ -45,11 +45,11 @@ device_vc4000_cart_interface::~device_vc4000_cart_interface()
// rom_alloc - alloc the space for the cart
//-------------------------------------------------
-void device_vc4000_cart_interface::rom_alloc(uint32_t size, const char *tag)
+void device_vc4000_cart_interface::rom_alloc(uint32_t size)
{
if (m_rom == nullptr)
{
- m_rom = device().machine().memory().region_alloc(std::string(tag).append(VC4000SLOT_ROM_REGION_TAG).c_str(), size, 1, ENDIANNESS_LITTLE)->base();
+ m_rom = device().machine().memory().region_alloc(device().subtag("^cart:rom"), size, 1, ENDIANNESS_LITTLE)->base();
m_rom_size = size;
}
}
@@ -168,19 +168,16 @@ static const char *vc4000_get_slot(int type)
call load
-------------------------------------------------*/
-image_init_result vc4000_cart_slot_device::call_load()
+std::pair<std::error_condition, std::string> vc4000_cart_slot_device::call_load()
{
if (m_cart)
{
- uint32_t size = !loaded_through_softlist() ? length() : get_software_region_length("rom");
+ uint32_t const size = !loaded_through_softlist() ? length() : get_software_region_length("rom");
if (size > 0x1800)
- {
- seterror(image_error::INVALIDIMAGE, "Image extends beyond the expected size for a VC4000 cart");
- return image_init_result::FAIL;
- }
+ return std::make_pair(image_error::INVALIDLENGTH, "Image exceeds the expected size for a VC4000 cartridge (6K)");
- m_cart->rom_alloc(size, tag());
+ m_cart->rom_alloc(size);
if (!loaded_through_softlist())
fread(m_cart->get_rom_base(), size);
@@ -210,11 +207,9 @@ image_init_result vc4000_cart_slot_device::call_load()
}
//printf("Type: %s\n", vc4000_get_slot(m_type));
-
- return image_init_result::PASS;
}
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
diff --git a/src/devices/bus/vc4000/slot.h b/src/devices/bus/vc4000/slot.h
index 39de8414d0b..457f266dade 100644
--- a/src/devices/bus/vc4000/slot.h
+++ b/src/devices/bus/vc4000/slot.h
@@ -6,8 +6,6 @@
#include "imagedev/cartrom.h"
-#define VC4000SLOT_ROM_REGION_TAG ":cart:rom"
-
/* PCB */
enum
{
@@ -32,7 +30,7 @@ public:
virtual uint8_t read_ram(offs_t offset) { return 0xff; }
virtual void write_ram(offs_t offset, uint8_t data) { }
- void rom_alloc(uint32_t size, const char *tag);
+ void rom_alloc(uint32_t size);
void ram_alloc(uint32_t size);
uint8_t* get_rom_base() { return m_rom; }
uint8_t* get_ram_base() { return &m_ram[0]; }
@@ -71,15 +69,15 @@ public:
vc4000_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual ~vc4000_cart_slot_device();
- // image-level overrides
- virtual image_init_result call_load() override;
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
virtual void call_unload() override { }
virtual bool is_reset_on_load() const noexcept override { return true; }
virtual const char *image_interface() const noexcept override { return "vc4000_cart"; }
virtual const char *file_extensions() const noexcept override { return "bin,rom"; }
- // slot interface overrides
+ // device_slot_interface implementation
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
int get_type() { return m_type; }
@@ -100,7 +98,7 @@ protected:
device_t *owner,
uint32_t clock);
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
int m_type;
diff --git a/src/devices/bus/vcs/rom.cpp b/src/devices/bus/vcs/rom.cpp
index aca703e58ac..f40591e1173 100644
--- a/src/devices/bus/vcs/rom.cpp
+++ b/src/devices/bus/vcs/rom.cpp
@@ -451,7 +451,7 @@ void a26_rom_e0_device::install_memory_handlers(address_space *space)
template <uint8_t Bank>
void a26_rom_e0_device::switch_bank(offs_t offset, uint8_t data)
-{
+{
m_bank[Bank]->set_entry(offset & 7);
}
@@ -677,7 +677,7 @@ void a26_rom_fv_device::switch_bank(offs_t offset, uint8_t data)
"JVP Bankswitch" Carts:
read/write access to 0x0fa0-0x0fc0 determines the
4K ROM bank to be read.
-
+
GAMES: No test case!?!
-------------------------------------------------*/
diff --git a/src/devices/bus/vcs/vcs_slot.cpp b/src/devices/bus/vcs/vcs_slot.cpp
index cc6fd49d7b4..344071724e9 100644
--- a/src/devices/bus/vcs/vcs_slot.cpp
+++ b/src/devices/bus/vcs/vcs_slot.cpp
@@ -80,7 +80,7 @@ void device_vcs_cart_interface::rom_alloc(uint32_t size, const char *tag)
{
if (m_rom == nullptr)
{
- m_rom = device().machine().memory().region_alloc(std::string(tag).append(":cart:rom").c_str(), size, 1, ENDIANNESS_LITTLE)->base();
+ m_rom = device().machine().memory().region_alloc(std::string(tag).append(":cart:rom"), size, 1, ENDIANNESS_LITTLE)->base();
m_rom_size = size;
}
}
@@ -199,7 +199,7 @@ static const char *vcs_get_slot(int type)
return "a26_2k_4k";
}
-image_init_result vcs_cart_slot_device::call_load()
+std::pair<std::error_condition, std::string> vcs_cart_slot_device::call_load()
{
if (m_cart)
{
@@ -221,12 +221,11 @@ image_init_result vcs_cart_slot_device::call_load()
break;
default:
- seterror(image_error::INVALIDIMAGE, "Invalid ROM file size" );
- return image_init_result::FAIL;
+ return std::make_pair(image_error::INVALIDLENGTH, "Unsupported cartridge ROM file size");
}
m_cart->rom_alloc(len, tag());
- uint8_t *ROM = m_cart->get_rom_base();
+ uint8_t *const ROM = m_cart->get_rom_base();
if (loaded_through_softlist())
{
@@ -310,11 +309,9 @@ image_init_result vcs_cart_slot_device::call_load()
m_cart->setup_addon_ptr((uint8_t *)m_cart->get_rom_base() + 0x2000);
m_cart->install_memory_handlers(m_address_space.target());
-
- return image_init_result::PASS;
}
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
@@ -777,8 +774,7 @@ std::string vcs_cart_slot_device::get_default_card_software(get_default_card_sof
hook.image_file()->length(len); // FIXME: check error return, guard against excessively large files
std::vector<uint8_t> rom(len);
- size_t actual;
- hook.image_file()->read(&rom[0], len, actual); // FIXME: check error return or read returning short
+ read(*hook.image_file(), &rom[0], len); // FIXME: check error return or read returning short
int const type = identify_cart_type(&rom[0], len);
char const *const slot_string = vcs_get_slot(type);
diff --git a/src/devices/bus/vcs/vcs_slot.h b/src/devices/bus/vcs/vcs_slot.h
index 4595602961a..3b014f5c352 100644
--- a/src/devices/bus/vcs/vcs_slot.h
+++ b/src/devices/bus/vcs/vcs_slot.h
@@ -31,26 +31,26 @@ public:
template <typename T> void set_address_space(T &&tag, int no) { m_address_space.set_tag(std::forward<T>(tag), no); }
- // image-level overrides
- virtual image_init_result call_load() override;
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
virtual void call_unload() override;
virtual bool is_reset_on_load() const noexcept override { return true; }
virtual const char *image_interface() const noexcept override { return "a2600_cart"; }
virtual const char *file_extensions() const noexcept override { return "bin,a26"; }
- // slot interface overrides
+ // device_slot_interface implementation
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
int get_cart_type() { return m_type; }
static int identify_cart_type(const uint8_t *ROM, uint32_t len);
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
private:
- device_vcs_cart_interface* m_cart;
+ device_vcs_cart_interface *m_cart;
int m_type;
optional_address_space m_address_space;
diff --git a/src/devices/bus/vcs_ctrl/ctrl.cpp b/src/devices/bus/vcs_ctrl/ctrl.cpp
index c1d462b8e84..afef3a923bf 100644
--- a/src/devices/bus/vcs_ctrl/ctrl.cpp
+++ b/src/devices/bus/vcs_ctrl/ctrl.cpp
@@ -58,8 +58,6 @@ vcs_control_port_device::vcs_control_port_device(const machine_config &mconfig,
void vcs_control_port_device::device_start()
{
m_device = dynamic_cast<device_vcs_control_port_interface *>(get_card_device());
-
- m_write_trigger.resolve_safe();
}
@@ -67,6 +65,7 @@ void vcs_control_port_device::device_start()
// SLOT_INTERFACE( vcs_control_port_devices )
//-------------------------------------------------
+#include "cx85.h"
#include "joybooster.h"
#include "joystick.h"
#include "keypad.h"
@@ -84,4 +83,11 @@ void vcs_control_port_devices(device_slot_interface &device)
device.option_add("joybstr", VCS_JOYSTICK_BOOSTER);
device.option_add("wheel", VCS_WHEEL);
device.option_add("keypad", VCS_KEYPAD);
+ device.option_add("cx85", ATARI_CX85);
+}
+
+void a800_control_port_devices(device_slot_interface &device)
+{
+ vcs_control_port_devices(device);
+ device.set_option_machine_config("pad", &vcs_paddles_device::reverse_players);
}
diff --git a/src/devices/bus/vcs_ctrl/ctrl.h b/src/devices/bus/vcs_ctrl/ctrl.h
index 25ac788e389..6e129ba62c9 100644
--- a/src/devices/bus/vcs_ctrl/ctrl.h
+++ b/src/devices/bus/vcs_ctrl/ctrl.h
@@ -37,6 +37,9 @@ public:
virtual bool has_pot_x() { return false; }
virtual bool has_pot_y() { return false; }
+ // FIXME: should be made protected when port definitions become member functions
+ inline void trigger_w(int state);
+
protected:
device_vcs_control_port_interface(const machine_config &mconfig, device_t &device);
@@ -72,11 +75,11 @@ public:
// bit 1 - pin 2 - Down
// bit 2 - pin 3 - Left
// bit 3 - pin 4 - Right
- // bit 4 - pin 5 -
+ // pin 5 - Pot X
// bit 5 - pin 6 - Button
// pin 7 - +5V
// pin 8 - GND
- // bit 6 - pin 9 -
+ // pin 9 - Pot Y
//
uint8_t read_joy() { return exists() ? m_device->vcs_joy_r() : 0xff; }
uint8_t read_pot_x() { return exists() ? m_device->vcs_pot_x_r() : 0xff; }
@@ -100,10 +103,16 @@ private:
devcb_write_line m_write_trigger;
};
+inline void device_vcs_control_port_interface::trigger_w(int state)
+{
+ m_port->trigger_w(state);
+}
+
// device type definition
DECLARE_DEVICE_TYPE(VCS_CONTROL_PORT, vcs_control_port_device)
void vcs_control_port_devices(device_slot_interface &device);
+void a800_control_port_devices(device_slot_interface &device);
#endif // MAME_BUS_CVS_CTRL_CTRL_H
diff --git a/src/devices/bus/vcs_ctrl/cx85.cpp b/src/devices/bus/vcs_ctrl/cx85.cpp
new file mode 100644
index 00000000000..f4543e6cd34
--- /dev/null
+++ b/src/devices/bus/vcs_ctrl/cx85.cpp
@@ -0,0 +1,126 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/**********************************************************************
+
+ Atari CX85 Numeric Keypad
+
+ Normal Atari 400/800 usage has this connect to controller port 2.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "cx85.h"
+
+#include "machine/rescap.h"
+
+
+//**************************************************************************
+// DEVICE TYPE DEFINITION
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(ATARI_CX85, atari_cx85_device, "atari_cx85", "Atari CX85 Numeric Keypad")
+
+
+//**************************************************************************
+// INPUT PORTS
+//**************************************************************************
+
+static INPUT_PORTS_START(atari_cx85)
+ PORT_START("X1")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Keypad -") PORT_CODE(KEYCODE_PLUS_PAD)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Keypad 3") PORT_CODE(KEYCODE_3_PAD)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Keypad 9") PORT_CODE(KEYCODE_9_PAD)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Keypad 6") PORT_CODE(KEYCODE_6_PAD)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("X2")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Keypad + Enter") PORT_CODE(KEYCODE_ENTER_PAD)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Keypad 2") PORT_CODE(KEYCODE_2_PAD)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Keypad 8") PORT_CODE(KEYCODE_8_PAD)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Keypad 5") PORT_CODE(KEYCODE_5_PAD)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("X3")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Keypad .") PORT_CODE(KEYCODE_DEL_PAD)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Keypad 1") PORT_CODE(KEYCODE_1_PAD)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Keypad 7") PORT_CODE(KEYCODE_7_PAD)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Keypad 4") PORT_CODE(KEYCODE_4_PAD)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_UNUSED)
+
+ PORT_START("X4")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Keypad 0") PORT_CODE(KEYCODE_0_PAD)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Keypad F4 (Yes)") PORT_CODE(KEYCODE_MINUS_PAD)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Keypad F2 (No)") PORT_CODE(KEYCODE_SLASH_PAD)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Keypad F3 (Delete)") PORT_CODE(KEYCODE_ASTERISK)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("Keypad F1 (Escape)") PORT_CODE(KEYCODE_NUMLOCK)
+INPUT_PORTS_END
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// atari_cx85_device - constructor
+//-------------------------------------------------
+
+atari_cx85_device::atari_cx85_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, ATARI_CX85, tag, owner, clock)
+ , device_vcs_control_port_interface(mconfig, *this)
+ , m_encoder(*this, "encoder")
+{
+}
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void atari_cx85_device::device_add_mconfig(machine_config &config)
+{
+ MM74C923(config, m_encoder, 0); // MCM74C923N
+ m_encoder->set_cap_osc(CAP_U(.1));
+ m_encoder->set_cap_debounce(CAP_U(.47));
+ m_encoder->data_tri_callback().set_constant(0);
+ m_encoder->x1_rd_callback().set_ioport("X1");
+ m_encoder->x2_rd_callback().set_ioport("X2");
+ m_encoder->x3_rd_callback().set_ioport("X3");
+ m_encoder->x4_rd_callback().set_ioport("X4");
+ m_encoder->da_wr_callback().set(FUNC(atari_cx85_device::trigger_w)).invert();
+}
+
+//-------------------------------------------------
+// device_input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor atari_cx85_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(atari_cx85);
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void atari_cx85_device::device_start()
+{
+}
+
+//-------------------------------------------------
+// vcs_joy_r - read digital inputs
+//-------------------------------------------------
+
+u8 atari_cx85_device::vcs_joy_r()
+{
+ // 74C923 outputs are buffered through 4049B
+ return (~m_encoder->read() & 0x0f) | (m_encoder->da_r() ? 0 : 0x20);
+}
+
+//-------------------------------------------------
+// vcs_pot_x_r - sample B pot
+//-------------------------------------------------
+
+u8 atari_cx85_device::vcs_pot_x_r()
+{
+ // Schematics suggests this should also be inverted through 4049B, but drivers seem to work the opposite way
+ return BIT(m_encoder->read(), 4) ? 0xff : 0;
+}
diff --git a/src/devices/bus/vcs_ctrl/cx85.h b/src/devices/bus/vcs_ctrl/cx85.h
new file mode 100644
index 00000000000..32fca503a9f
--- /dev/null
+++ b/src/devices/bus/vcs_ctrl/cx85.h
@@ -0,0 +1,54 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/**********************************************************************
+
+ Atari CX85 Numeric Keypad
+
+**********************************************************************/
+
+#ifndef MAME_BUS_VCS_CTRL_CX85_H
+#define MAME_BUS_VCS_CTRL_CX85_H
+
+#pragma once
+
+#include "ctrl.h"
+#include "machine/mm74c922.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> atari_cx85_device
+
+class atari_cx85_device : public device_t,
+ public device_vcs_control_port_interface
+{
+public:
+ // construction/destruction
+ atari_cx85_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+
+ // optional information overrides
+ virtual ioport_constructor device_input_ports() const override;
+
+ // device_vcs_control_port_interface overrides
+ virtual u8 vcs_joy_r() override;
+ virtual u8 vcs_pot_x_r() override;
+
+ virtual bool has_pot_x() override { return true; }
+ virtual bool has_pot_y() override { return false; } // pin 9 not used
+
+private:
+ required_device<mm74c923_device> m_encoder;
+};
+
+
+// device type declaration
+DECLARE_DEVICE_TYPE(ATARI_CX85, atari_cx85_device)
+
+#endif // MAME_BUS_VCS_CTRL_CX85_H
diff --git a/src/devices/bus/vcs_ctrl/joybooster.cpp b/src/devices/bus/vcs_ctrl/joybooster.cpp
index 9ea3b813ac1..630f1e07def 100644
--- a/src/devices/bus/vcs_ctrl/joybooster.cpp
+++ b/src/devices/bus/vcs_ctrl/joybooster.cpp
@@ -2,8 +2,14 @@
// copyright-holders:Curt Coder
/**********************************************************************
- Atari Video Computer System digital joystick emulation with
- boostergrip adapter
+ CBS Electronics Booster-Grip Joystick Adaptor
+
+ This peripheral device, which adds two extra buttons to an
+ ordinary single-button joystick, was packaged with the Atari 2600
+ version of Omega Race. CBS Electronics also advertised it as a
+ pack-in for their unreleased 2600 title Wings (it does not work
+ with the known prototype). The homebrew Thrust games optionally
+ support the Booster-Grip as well.
**********************************************************************/
@@ -16,7 +22,7 @@
// DEVICE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(VCS_JOYSTICK_BOOSTER, vcs_joystick_booster_device, "vcs_joystick_booster", "Atari / CBM Digital joystick with Boostergrip")
+DEFINE_DEVICE_TYPE(VCS_JOYSTICK_BOOSTER, vcs_joystick_booster_device, "vcs_joystick_booster", "CBS Electronics Booster-Grip Joystick Adaptor")
static INPUT_PORTS_START( vcs_joystick_booster )
@@ -25,7 +31,7 @@ static INPUT_PORTS_START( vcs_joystick_booster )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY // Pin 2
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY // Pin 3
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY // Pin 4
- PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 ) // Pin 6
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_WRITE_LINE_MEMBER(vcs_joystick_booster_device, trigger_w) // Pin 6
PORT_BIT( 0xd0, IP_ACTIVE_LOW, IPT_UNUSED )
// Pin 5
diff --git a/src/devices/bus/vcs_ctrl/joybooster.h b/src/devices/bus/vcs_ctrl/joybooster.h
index 8b3cf922a1b..23f97fdb7a7 100644
--- a/src/devices/bus/vcs_ctrl/joybooster.h
+++ b/src/devices/bus/vcs_ctrl/joybooster.h
@@ -29,13 +29,6 @@ public:
// construction/destruction
vcs_joystick_booster_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- // optional information overrides
- virtual ioport_constructor device_input_ports() const override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
-
// device_vcs_control_port_interface overrides
virtual uint8_t vcs_joy_r() override;
virtual uint8_t vcs_pot_x_r() override;
@@ -44,6 +37,13 @@ protected:
virtual bool has_pot_x() override { return true; }
virtual bool has_pot_y() override { return true; }
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+
+ // optional information overrides
+ virtual ioport_constructor device_input_ports() const override;
+
private:
required_ioport m_joy;
required_ioport m_potx;
diff --git a/src/devices/bus/vcs_ctrl/joystick.cpp b/src/devices/bus/vcs_ctrl/joystick.cpp
index c911f435a0c..e68ec423d67 100644
--- a/src/devices/bus/vcs_ctrl/joystick.cpp
+++ b/src/devices/bus/vcs_ctrl/joystick.cpp
@@ -24,7 +24,7 @@ static INPUT_PORTS_START( vcs_joystick )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY
- PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 )
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_WRITE_LINE_MEMBER(vcs_joystick_device, trigger_w)
PORT_BIT( 0xd0, IP_ACTIVE_LOW, IPT_UNUSED )
INPUT_PORTS_END
diff --git a/src/devices/bus/vcs_ctrl/joystick.h b/src/devices/bus/vcs_ctrl/joystick.h
index dcae27d2965..1c8f941a633 100644
--- a/src/devices/bus/vcs_ctrl/joystick.h
+++ b/src/devices/bus/vcs_ctrl/joystick.h
@@ -28,15 +28,15 @@ public:
// construction/destruction
vcs_joystick_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- // optional information overrides
- virtual ioport_constructor device_input_ports() const override;
+ // device_vcs_control_port_interface overrides
+ virtual uint8_t vcs_joy_r() override;
protected:
// device-level overrides
virtual void device_start() override;
- // device_vcs_control_port_interface overrides
- virtual uint8_t vcs_joy_r() override;
+ // optional information overrides
+ virtual ioport_constructor device_input_ports() const override;
private:
required_ioport m_joy;
diff --git a/src/devices/bus/vcs_ctrl/keypad.cpp b/src/devices/bus/vcs_ctrl/keypad.cpp
index 97a43253c08..888cae738f5 100644
--- a/src/devices/bus/vcs_ctrl/keypad.cpp
+++ b/src/devices/bus/vcs_ctrl/keypad.cpp
@@ -58,7 +58,7 @@ vcs_keypad_device::vcs_keypad_device(const machine_config &mconfig, const char *
device_t(mconfig, VCS_KEYPAD, tag, owner, clock),
device_vcs_control_port_interface(mconfig, *this),
m_keypad(*this, "KEYPAD"),
- m_column(0)
+ m_row(0)
{
}
@@ -69,8 +69,7 @@ vcs_keypad_device::vcs_keypad_device(const machine_config &mconfig, const char *
void vcs_keypad_device::device_start()
{
- m_column = 0;
- save_item(NAME(m_column));
+ save_item(NAME(m_row));
}
@@ -78,64 +77,26 @@ void vcs_keypad_device::device_start()
// vcs_joy_w - joystick write
//-------------------------------------------------
-uint8_t vcs_keypad_device::vcs_joy_r()
+void vcs_keypad_device::vcs_joy_w(uint8_t data)
{
- for ( int i = 0; i < 4; i++ )
- {
- if ( ! ( ( m_column >> i ) & 0x01 ) )
- {
- if ( ( m_keypad->read() >> 3*i ) & 0x04 )
- {
- return 0xff;
- }
- else
- {
- return 0;
- }
- }
- }
- return 0xff;
+ m_row = data & 0x0f;
}
-void vcs_keypad_device::vcs_joy_w( uint8_t data )
+uint8_t vcs_keypad_device::read_keys(uint8_t col)
{
- m_column = data & 0x0F;
-}
+ uint8_t val = 0;
-uint8_t vcs_keypad_device::vcs_pot_x_r()
-{
- for ( int i = 0; i < 4; i++ )
+ for (int row = 0; row < 4; row++)
{
- if ( ! ( ( m_column >> i ) & 0x01 ) )
+ if (!BIT(m_row, row))
{
- if ( ( m_keypad->read() >> 3*i ) & 0x01 )
- {
- return 0;
- }
- else
+ if (!BIT(m_keypad->read(), 3*row + col))
{
- return 0xff;
+ val = 0xff;
}
+ break;
}
}
- return 0;
-}
-uint8_t vcs_keypad_device::vcs_pot_y_r()
-{
- for ( int i = 0; i < 4; i++ )
- {
- if ( ! ( ( m_column >> i ) & 0x01 ) )
- {
- if ( ( m_keypad->read() >> 3*i ) & 0x02 )
- {
- return 0;
- }
- else
- {
- return 0xff;
- }
- }
- }
- return 0;
+ return val;
}
diff --git a/src/devices/bus/vcs_ctrl/keypad.h b/src/devices/bus/vcs_ctrl/keypad.h
index 37733cc135c..13218b0bf0c 100644
--- a/src/devices/bus/vcs_ctrl/keypad.h
+++ b/src/devices/bus/vcs_ctrl/keypad.h
@@ -28,26 +28,28 @@ public:
// construction/destruction
vcs_keypad_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- // optional information overrides
- virtual ioport_constructor device_input_ports() const override;
+ // device_vcs_control_port_interface overrides
+ virtual uint8_t vcs_joy_r() override { return ~read_keys(2); }
+ virtual uint8_t vcs_pot_x_r() override { return read_keys(0); }
+ virtual uint8_t vcs_pot_y_r() override { return read_keys(1); }
+ virtual void vcs_joy_w(uint8_t data) override;
+
+ virtual bool has_pot_x() override { return true; }
+ virtual bool has_pot_y() override { return true; }
protected:
// device-level overrides
virtual void device_start() override;
- // device_vcs_control_port_interface overrides
- virtual uint8_t vcs_joy_r() override;
- virtual void vcs_joy_w( uint8_t data ) override;
- virtual uint8_t vcs_pot_x_r() override;
- virtual uint8_t vcs_pot_y_r() override;
-
- virtual bool has_pot_x() override { return true; }
- virtual bool has_pot_y() override { return true; }
+ // optional information overrides
+ virtual ioport_constructor device_input_ports() const override;
private:
+ uint8_t read_keys(uint8_t column);
+
required_ioport m_keypad;
- uint8_t m_column;
+ uint8_t m_row;
};
diff --git a/src/devices/bus/vcs_ctrl/lightpen.h b/src/devices/bus/vcs_ctrl/lightpen.h
index f0b2805bdd6..82c4f06c5aa 100644
--- a/src/devices/bus/vcs_ctrl/lightpen.h
+++ b/src/devices/bus/vcs_ctrl/lightpen.h
@@ -28,8 +28,8 @@ public:
// construction/destruction
vcs_lightpen_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- // optional information overrides
- virtual ioport_constructor device_input_ports() const override;
+ // device_vcs_control_port_interface overrides
+ virtual uint8_t vcs_joy_r() override;
DECLARE_INPUT_CHANGED_MEMBER( trigger );
@@ -37,8 +37,8 @@ protected:
// device-level overrides
virtual void device_start() override;
- // device_vcs_control_port_interface overrides
- virtual uint8_t vcs_joy_r() override;
+ // optional information overrides
+ virtual ioport_constructor device_input_ports() const override;
private:
required_ioport m_joy;
diff --git a/src/devices/bus/vcs_ctrl/mouse.cpp b/src/devices/bus/vcs_ctrl/mouse.cpp
index 611ae081da4..c1087bb32c1 100644
--- a/src/devices/bus/vcs_ctrl/mouse.cpp
+++ b/src/devices/bus/vcs_ctrl/mouse.cpp
@@ -28,7 +28,7 @@ DEFINE_DEVICE_TYPE(VCS_MOUSE, vcs_mouse_device, "vcs_mouse", "Atari / CBM Mouse"
static INPUT_PORTS_START( vcs_mouse )
PORT_START("JOY")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON2 )
- PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 )
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_WRITE_LINE_MEMBER(vcs_mouse_device, trigger_w)
PORT_BIT( 0xde, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_START("POTX")
diff --git a/src/devices/bus/vcs_ctrl/mouse.h b/src/devices/bus/vcs_ctrl/mouse.h
index eab33d64aab..e90f413f8b3 100644
--- a/src/devices/bus/vcs_ctrl/mouse.h
+++ b/src/devices/bus/vcs_ctrl/mouse.h
@@ -28,13 +28,6 @@ public:
// construction/destruction
vcs_mouse_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- // optional information overrides
- virtual ioport_constructor device_input_ports() const override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
-
// device_vcs_control_port_interface overrides
virtual uint8_t vcs_joy_r() override;
virtual uint8_t vcs_pot_x_r() override;
@@ -43,6 +36,13 @@ protected:
virtual bool has_pot_x() override { return true; }
virtual bool has_pot_y() override { return true; }
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+
+ // optional information overrides
+ virtual ioport_constructor device_input_ports() const override;
+
private:
required_ioport m_joy;
required_ioport m_potx;
diff --git a/src/devices/bus/vcs_ctrl/paddles.cpp b/src/devices/bus/vcs_ctrl/paddles.cpp
index 46084663356..f46478d8e41 100644
--- a/src/devices/bus/vcs_ctrl/paddles.cpp
+++ b/src/devices/bus/vcs_ctrl/paddles.cpp
@@ -20,18 +20,17 @@ DEFINE_DEVICE_TYPE(VCS_PADDLES, vcs_paddles_device, "vcs_paddles", "Atari / CBM
static INPUT_PORTS_START( vcs_paddles )
PORT_START("JOY")
- PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2)
- PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1)
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) // pin 3
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1) // pin 4
PORT_BIT( 0xf3, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_START("POTX")
- PORT_BIT( 0xff, 0x80, IPT_PADDLE) PORT_PLAYER(1) PORT_SENSITIVITY(30) PORT_KEYDELTA(20) PORT_MINMAX(0, 255)
+ PORT_BIT( 0xff, 0x80, IPT_PADDLE) PORT_PLAYER(1) PORT_SENSITIVITY(30) PORT_KEYDELTA(20) PORT_MINMAX(0, 255) PORT_REVERSE // pin 5
PORT_START("POTY")
- PORT_BIT( 0xff, 0x80, IPT_PADDLE) PORT_PLAYER(2) PORT_SENSITIVITY(30) PORT_KEYDELTA(20) PORT_MINMAX(0, 255)
+ PORT_BIT( 0xff, 0x80, IPT_PADDLE) PORT_PLAYER(2) PORT_SENSITIVITY(30) PORT_KEYDELTA(20) PORT_MINMAX(0, 255) PORT_REVERSE // pin 9
INPUT_PORTS_END
-
//-------------------------------------------------
// input_ports - device-specific input ports
//-------------------------------------------------
@@ -56,7 +55,8 @@ vcs_paddles_device::vcs_paddles_device(const machine_config &mconfig, const char
device_vcs_control_port_interface(mconfig, *this),
m_joy(*this, "JOY"),
m_potx(*this, "POTX"),
- m_poty(*this, "POTY")
+ m_poty(*this, "POTY"),
+ m_reverse_players(false)
{
}
@@ -76,7 +76,8 @@ void vcs_paddles_device::device_start()
uint8_t vcs_paddles_device::vcs_joy_r()
{
- return m_joy->read();
+ uint8_t const data = m_joy->read();
+ return m_reverse_players ? bitswap<8>(data, 7, 6, 5, 4, 2, 3, 1, 0) : data;
}
@@ -86,7 +87,7 @@ uint8_t vcs_paddles_device::vcs_joy_r()
uint8_t vcs_paddles_device::vcs_pot_x_r()
{
- return m_potx->read();
+ return m_reverse_players ? m_poty->read() : m_potx->read();
}
@@ -96,5 +97,5 @@ uint8_t vcs_paddles_device::vcs_pot_x_r()
uint8_t vcs_paddles_device::vcs_pot_y_r()
{
- return m_poty->read();
+ return m_reverse_players ? m_potx->read() : m_poty->read();
}
diff --git a/src/devices/bus/vcs_ctrl/paddles.h b/src/devices/bus/vcs_ctrl/paddles.h
index e88084066ee..941bea3fc5a 100644
--- a/src/devices/bus/vcs_ctrl/paddles.h
+++ b/src/devices/bus/vcs_ctrl/paddles.h
@@ -28,12 +28,7 @@ public:
// construction/destruction
vcs_paddles_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- // optional information overrides
- virtual ioport_constructor device_input_ports() const override;
-
-protected:
- // device-level overrides
- virtual void device_start() override;
+ static void reverse_players(device_t *device) { downcast<vcs_paddles_device &>(*device).m_reverse_players = true; }
// device_vcs_control_port_interface overrides
virtual uint8_t vcs_joy_r() override;
@@ -43,10 +38,19 @@ protected:
virtual bool has_pot_x() override { return true; }
virtual bool has_pot_y() override { return true; }
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+
+ // optional information overrides
+ virtual ioport_constructor device_input_ports() const override;
+
private:
required_ioport m_joy;
required_ioport m_potx;
required_ioport m_poty;
+
+ bool m_reverse_players;
};
diff --git a/src/devices/bus/vcs_ctrl/wheel.cpp b/src/devices/bus/vcs_ctrl/wheel.cpp
index 76e86530cf8..57c5c9863ed 100644
--- a/src/devices/bus/vcs_ctrl/wheel.cpp
+++ b/src/devices/bus/vcs_ctrl/wheel.cpp
@@ -20,7 +20,7 @@ DEFINE_DEVICE_TYPE(VCS_WHEEL, vcs_wheel_device, "vcs_wheel", "Atari / CBM Drivin
static INPUT_PORTS_START( vcs_wheel )
PORT_START("JOY")
- PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 ) // Pin 6
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_WRITE_LINE_MEMBER(vcs_wheel_device, trigger_w) // Pin 6
PORT_BIT( 0xdc, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_START("WHEEL")
@@ -73,5 +73,5 @@ uint8_t vcs_wheel_device::vcs_joy_r()
{
static const uint8_t driving_lookup[4] = { 0x00, 0x02, 0x03, 0x01 };
- return m_joy->read() | driving_lookup[ ( m_wheel->read() & 0x18 ) >> 3 ];
+ return m_joy->read() | driving_lookup[BIT(m_wheel->read(), 3, 2)];
}
diff --git a/src/devices/bus/vcs_ctrl/wheel.h b/src/devices/bus/vcs_ctrl/wheel.h
index 369afe7c614..8919e2d2888 100644
--- a/src/devices/bus/vcs_ctrl/wheel.h
+++ b/src/devices/bus/vcs_ctrl/wheel.h
@@ -28,15 +28,15 @@ public:
// construction/destruction
vcs_wheel_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- // optional information overrides
- virtual ioport_constructor device_input_ports() const override;
+ // device_vcs_control_port_interface overrides
+ virtual uint8_t vcs_joy_r() override;
protected:
// device-level overrides
virtual void device_start() override;
- // device_vcs_control_port_interface overrides
- virtual uint8_t vcs_joy_r() override;
+ // optional information overrides
+ virtual ioport_constructor device_input_ports() const override;
private:
required_ioport m_joy;
diff --git a/src/devices/bus/vectrex/slot.cpp b/src/devices/bus/vectrex/slot.cpp
index 71b9be61a83..2b5ebd481a1 100644
--- a/src/devices/bus/vectrex/slot.cpp
+++ b/src/devices/bus/vectrex/slot.cpp
@@ -44,11 +44,11 @@ device_vectrex_cart_interface::~device_vectrex_cart_interface()
// rom_alloc - alloc the space for the cart
//-------------------------------------------------
-void device_vectrex_cart_interface::rom_alloc(uint32_t size, const char *tag)
+void device_vectrex_cart_interface::rom_alloc(uint32_t size)
{
if (m_rom == nullptr)
{
- m_rom = device().machine().memory().region_alloc(std::string(tag).append(VECSLOT_ROM_REGION_TAG).c_str(), size, 1, ENDIANNESS_LITTLE)->base();
+ m_rom = device().machine().memory().region_alloc(device().subtag("^cart:rom"), size, 1, ENDIANNESS_LITTLE)->base();
m_rom_size = size;
}
}
@@ -136,21 +136,17 @@ static const char *vectrex_get_slot(int type)
call load
-------------------------------------------------*/
-image_init_result vectrex_cart_slot_device::call_load()
+std::pair<std::error_condition, std::string> vectrex_cart_slot_device::call_load()
{
if (m_cart)
{
- uint32_t size = !loaded_through_softlist() ? length() : get_software_region_length("rom");
- uint8_t *ROM;
+ uint32_t const size = !loaded_through_softlist() ? length() : get_software_region_length("rom");
if (size > 0x10000)
- {
- seterror(image_error::INVALIDIMAGE, "Unsupported cartridge size");
- return image_init_result::FAIL;
- }
+ return std::make_pair(image_error::INVALIDLENGTH, "Unsupported cartridge size (must be no larger than 64K)");
- m_cart->rom_alloc((size < 0x1000) ? 0x1000 : size, tag());
- ROM = m_cart->get_rom_base();
+ m_cart->rom_alloc((size < 0x1000) ? 0x1000 : size);
+ uint8_t *const ROM = m_cart->get_rom_base();
if (!loaded_through_softlist())
fread(ROM, size);
@@ -159,10 +155,7 @@ image_init_result vectrex_cart_slot_device::call_load()
// Verify the file is accepted by the Vectrex bios
if (memcmp(ROM, "g GCE", 5))
- {
- seterror(image_error::INVALIDIMAGE, "Invalid image");
- return image_init_result::FAIL;
- }
+ return std::make_pair(image_error::INVALIDIMAGE, "Invalid Vectrex ROM");
// determine type
m_type = VECTREX_STD;
@@ -182,11 +175,9 @@ image_init_result vectrex_cart_slot_device::call_load()
if (!memcmp(ROM + 0x11, "3D MINE STORM", 13))
m_vec3d = VEC3D_MINEST;
-
- return image_init_result::PASS;
}
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
@@ -203,8 +194,7 @@ std::string vectrex_cart_slot_device::get_default_card_software(get_default_card
std::uint64_t size;
hook.image_file()->length(size);
std::vector<uint8_t> rom(size);
- std::size_t actual;
- hook.image_file()->read(&rom[0], size, actual);
+ read(*hook.image_file(), &rom[0], size);
int type = VECTREX_STD;
if (!memcmp(&rom[0x06], "SRAM", 4)) // FIXME: bounds check!
diff --git a/src/devices/bus/vectrex/slot.h b/src/devices/bus/vectrex/slot.h
index d010bae8e62..3be89a8bbd1 100644
--- a/src/devices/bus/vectrex/slot.h
+++ b/src/devices/bus/vectrex/slot.h
@@ -43,7 +43,7 @@ public:
virtual void write_ram(offs_t offset, uint8_t data) { }
virtual void write_bank(uint8_t data) { }
- void rom_alloc(uint32_t size, const char *tag);
+ void rom_alloc(uint32_t size);
uint8_t* get_rom_base() { return m_rom; }
uint32_t get_rom_size() { return m_rom_size; }
@@ -67,15 +67,15 @@ public:
vectrex_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual ~vectrex_cart_slot_device();
- // image-level overrides
- virtual image_init_result call_load() override;
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
virtual void call_unload() override { }
virtual bool is_reset_on_load() const noexcept override { return true; }
virtual const char *image_interface() const noexcept override { return "vectrex_cart"; }
virtual const char *file_extensions() const noexcept override { return "bin,gam,vec"; }
- // slot interface overrides
+ // device_slot_interface implementation
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
int get_type() { return m_type; }
@@ -87,11 +87,11 @@ public:
void write_bank(uint8_t data);
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
int m_type, m_vec3d;
- device_vectrex_cart_interface* m_cart;
+ device_vectrex_cart_interface *m_cart;
};
@@ -99,11 +99,4 @@ protected:
// device type definition
DECLARE_DEVICE_TYPE(VECTREX_CART_SLOT, vectrex_cart_slot_device)
-
-/***************************************************************************
- DEVICE CONFIGURATION MACROS
- ***************************************************************************/
-
-#define VECSLOT_ROM_REGION_TAG ":cart:rom"
-
#endif // MAME_BUS_VECTREX_SLOT_H
diff --git a/src/devices/bus/vic10/exp.cpp b/src/devices/bus/vic10/exp.cpp
index c09651066ba..2e050b40cc3 100644
--- a/src/devices/bus/vic10/exp.cpp
+++ b/src/devices/bus/vic10/exp.cpp
@@ -7,9 +7,11 @@
**********************************************************************/
#include "emu.h"
-#include "emuopts.h"
#include "exp.h"
+#include "formats/cbm_crt.h"
+
+#include <tuple>
//**************************************************************************
@@ -73,12 +75,6 @@ vic10_expansion_slot_device::vic10_expansion_slot_device(const machine_config &m
void vic10_expansion_slot_device::device_start()
{
m_card = get_card_device();
-
- // resolve callbacks
- m_write_irq.resolve_safe();
- m_write_res.resolve_safe();
- m_write_cnt.resolve_safe();
- m_write_sp.resolve_safe();
}
@@ -86,28 +82,37 @@ void vic10_expansion_slot_device::device_start()
// call_load -
//-------------------------------------------------
-image_init_result vic10_expansion_slot_device::call_load()
+std::pair<std::error_condition, std::string> vic10_expansion_slot_device::call_load()
{
+ std::error_condition err;
+
if (m_card)
{
- size_t size;
-
if (!loaded_through_softlist())
{
- size = length();
+ util::core_file &file = image_core_file();
+ size_t const size = length();
if (is_filetype("80"))
{
- fread(m_card->m_lorom, 0x2000);
+ size_t actual;
+ std::tie(err, m_card->m_lorom, actual) = read(file, 0x2000);
+ if (!err && (actual != 0x2000))
+ err = std::errc::io_error;
- if (size == 0x4000)
+ if (!err && (size == 0x4000))
{
- fread(m_card->m_uprom, 0x2000);
+ std::tie(err, m_card->m_uprom, actual) = read(file, 0x2000);
+ if (!err && (actual != 0x2000))
+ err = std::errc::io_error;
}
}
else if (is_filetype("e0"))
{
- fread(m_card->m_uprom, size);
+ size_t actual;
+ std::tie(err, m_card->m_uprom, actual) = read(file, size);
+ if (!err && (actual != size))
+ err = std::errc::io_error;
}
else if (is_filetype("crt"))
{
@@ -116,7 +121,7 @@ image_init_result vic10_expansion_slot_device::call_load()
int exrom = 1;
int game = 1;
- if (cbm_crt_read_header(image_core_file(), &roml_size, &romh_size, &exrom, &game))
+ if (cbm_crt_read_header(file, &roml_size, &romh_size, &exrom, &game))
{
uint8_t *roml = nullptr;
uint8_t *romh = nullptr;
@@ -127,9 +132,13 @@ image_init_result vic10_expansion_slot_device::call_load()
if (roml_size) roml = m_card->m_lorom.get();
if (romh_size) romh = m_card->m_lorom.get();
- cbm_crt_read_data(image_core_file(), roml, romh);
+ cbm_crt_read_data(file, roml, romh);
}
}
+ else
+ {
+ err = image_error::INVALIDIMAGE;
+ }
}
else
{
@@ -139,7 +148,7 @@ image_init_result vic10_expansion_slot_device::call_load()
}
}
- return image_init_result::PASS;
+ return std::make_pair(err, std::string());
}
@@ -186,8 +195,8 @@ void vic10_expansion_slot_device::cd_w(offs_t offset, uint8_t data, int lorom, i
}
}
-READ_LINE_MEMBER( vic10_expansion_slot_device::p0_r ) { int state = 0; if (m_card != nullptr) state = m_card->vic10_p0_r(); return state; }
-WRITE_LINE_MEMBER( vic10_expansion_slot_device::p0_w ) { if (m_card != nullptr) m_card->vic10_p0_w(state); }
+int vic10_expansion_slot_device::p0_r() { int state = 0; if (m_card != nullptr) state = m_card->vic10_p0_r(); return state; }
+void vic10_expansion_slot_device::p0_w(int state) { if (m_card != nullptr) m_card->vic10_p0_w(state); }
//-------------------------------------------------
diff --git a/src/devices/bus/vic10/exp.h b/src/devices/bus/vic10/exp.h
index 36098dfc2cf..58b6d555718 100644
--- a/src/devices/bus/vic10/exp.h
+++ b/src/devices/bus/vic10/exp.h
@@ -37,7 +37,6 @@
#pragma once
#include "imagedev/cartrom.h"
-#include "formats/cbm_crt.h"
//**************************************************************************
@@ -73,27 +72,27 @@ public:
// computer interface
uint8_t cd_r(offs_t offset, uint8_t data, int lorom, int uprom, int exram);
void cd_w(offs_t offset, uint8_t data, int lorom, int uprom, int exram);
- DECLARE_READ_LINE_MEMBER( p0_r );
- DECLARE_WRITE_LINE_MEMBER( p0_w );
+ int p0_r();
+ void p0_w(int state);
// cartridge interface
- DECLARE_WRITE_LINE_MEMBER( irq_w ) { m_write_irq(state); }
- DECLARE_WRITE_LINE_MEMBER( res_w ) { m_write_res(state); }
- DECLARE_WRITE_LINE_MEMBER( cnt_w ) { m_write_cnt(state); }
- DECLARE_WRITE_LINE_MEMBER( sp_w ) { m_write_sp(state); }
+ void irq_w(int state) { m_write_irq(state); }
+ void res_w(int state) { m_write_res(state); }
+ void cnt_w(int state) { m_write_cnt(state); }
+ void sp_w(int state) { m_write_sp(state); }
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
- // image-level overrides
- virtual image_init_result call_load() override;
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
virtual bool is_reset_on_load() const noexcept override { return true; }
virtual const char *image_interface() const noexcept override { return "vic10_cart"; }
virtual const char *file_extensions() const noexcept override { return "80,e0"; }
- // slot interface overrides
+ // device_slot_interface implementation
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
devcb_write_line m_write_irq;
diff --git a/src/devices/bus/vic20/4cga.cpp b/src/devices/bus/vic20/4cga.cpp
index f806598433a..ea0b2ae5215 100644
--- a/src/devices/bus/vic20/4cga.cpp
+++ b/src/devices/bus/vic20/4cga.cpp
@@ -107,7 +107,7 @@ void c64_4cga_device::update_output()
// c64_pb_w - port B write
//-------------------------------------------------
-WRITE_LINE_MEMBER( c64_4cga_device::input_l )
+void c64_4cga_device::input_l(int state)
{
m_port = state;
update_output();
diff --git a/src/devices/bus/vic20/4cga.h b/src/devices/bus/vic20/4cga.h
index b4e1ada9a05..e6d101f94ca 100644
--- a/src/devices/bus/vic20/4cga.h
+++ b/src/devices/bus/vic20/4cga.h
@@ -32,22 +32,22 @@ public:
// optional information overrides
virtual ioport_constructor device_input_ports() const override;
- DECLARE_WRITE_LINE_MEMBER(write_joy3_0) { if (state) m_joy3 |= 1; else m_joy3 &= ~1; update_output(); }
- DECLARE_WRITE_LINE_MEMBER(write_joy3_1) { if (state) m_joy3 |= 2; else m_joy3 &= ~2; update_output(); }
- DECLARE_WRITE_LINE_MEMBER(write_joy3_2) { if (state) m_joy3 |= 4; else m_joy3 &= ~4; update_output(); }
- DECLARE_WRITE_LINE_MEMBER(write_joy3_3) { if (state) m_joy3 |= 8; else m_joy3 &= ~8; update_output(); }
+ void write_joy3_0(int state) { if (state) m_joy3 |= 1; else m_joy3 &= ~1; update_output(); }
+ void write_joy3_1(int state) { if (state) m_joy3 |= 2; else m_joy3 &= ~2; update_output(); }
+ void write_joy3_2(int state) { if (state) m_joy3 |= 4; else m_joy3 &= ~4; update_output(); }
+ void write_joy3_3(int state) { if (state) m_joy3 |= 8; else m_joy3 &= ~8; update_output(); }
- DECLARE_WRITE_LINE_MEMBER(write_joy4_0) { if (state) m_joy4 |= 1; else m_joy4 &= ~1; update_output(); }
- DECLARE_WRITE_LINE_MEMBER(write_joy4_1) { if (state) m_joy4 |= 2; else m_joy4 &= ~2; update_output(); }
- DECLARE_WRITE_LINE_MEMBER(write_joy4_2) { if (state) m_joy4 |= 4; else m_joy4 &= ~4; update_output(); }
- DECLARE_WRITE_LINE_MEMBER(write_joy4_3) { if (state) m_joy4 |= 8; else m_joy4 &= ~8; update_output(); }
+ void write_joy4_0(int state) { if (state) m_joy4 |= 1; else m_joy4 &= ~1; update_output(); }
+ void write_joy4_1(int state) { if (state) m_joy4 |= 2; else m_joy4 &= ~2; update_output(); }
+ void write_joy4_2(int state) { if (state) m_joy4 |= 4; else m_joy4 &= ~4; update_output(); }
+ void write_joy4_3(int state) { if (state) m_joy4 |= 8; else m_joy4 &= ~8; update_output(); }
protected:
// device-level overrides
virtual void device_start() override;
// device_pet_user_port_interface overrides
- virtual DECLARE_WRITE_LINE_MEMBER( input_l ) override;
+ virtual void input_l(int state) override;
private:
void update_output();
diff --git a/src/devices/bus/vic20/exp.cpp b/src/devices/bus/vic20/exp.cpp
index 0746b3092da..c635db5c35c 100644
--- a/src/devices/bus/vic20/exp.cpp
+++ b/src/devices/bus/vic20/exp.cpp
@@ -9,6 +9,10 @@
#include "emu.h"
#include "exp.h"
+#include "multibyte.h"
+
+#include <tuple>
+
//**************************************************************************
@@ -29,8 +33,8 @@ DEFINE_DEVICE_TYPE(VIC20_EXPANSION_SLOT, vic20_expansion_slot_device, "vic20_exp
device_vic20_expansion_card_interface::device_vic20_expansion_card_interface(const machine_config &mconfig, device_t &device)
: device_interface(device, "vic20exp")
+ , m_slot(dynamic_cast<vic20_expansion_slot_device *>(device.owner()))
{
- m_slot = dynamic_cast<vic20_expansion_slot_device *>(device.owner());
}
@@ -71,11 +75,6 @@ vic20_expansion_slot_device::vic20_expansion_slot_device(const machine_config &m
void vic20_expansion_slot_device::device_start()
{
m_card = get_card_device();
-
- // resolve callbacks
- m_write_irq.resolve_safe();
- m_write_nmi.resolve_safe();
- m_write_res.resolve_safe();
}
@@ -92,36 +91,146 @@ void vic20_expansion_slot_device::device_reset()
// call_load -
//-------------------------------------------------
-image_init_result vic20_expansion_slot_device::call_load()
+std::pair<std::error_condition, std::string> vic20_expansion_slot_device::call_load()
{
+ std::error_condition err;
+
if (m_card)
{
if (!loaded_through_softlist())
{
- if (is_filetype("20")) fread(m_card->m_blk1, 0x2000);
- else if (is_filetype("40")) fread(m_card->m_blk2, 0x2000);
- else if (is_filetype("60")) fread(m_card->m_blk3, 0x2000);
- else if (is_filetype("70")) fread(m_card->m_blk3, 0x2000, 0x1000);
- else if (is_filetype("a0")) fread(m_card->m_blk5, 0x2000);
- else if (is_filetype("b0")) fread(m_card->m_blk5, 0x2000, 0x1000);
+ util::core_file &file = image_core_file();
+
+ if (is_filetype("20"))
+ {
+ size_t actual;
+ std::tie(err, m_card->m_blk1, actual) = read(file, 0x2000);
+ if (!err && (actual != 0x2000))
+ err = std::errc::io_error;
+ }
+ else if (is_filetype("40"))
+ {
+ size_t actual;
+ std::tie(err, m_card->m_blk2, actual) = read(file, 0x2000);
+ if (!err && (actual != 0x2000))
+ err = std::errc::io_error;
+ }
+ else if (is_filetype("60"))
+ {
+ size_t actual;
+ std::tie(err, m_card->m_blk3, actual) = read(file, 0x2000);
+ if (!err && (actual != 0x2000))
+ err = std::errc::io_error;
+ }
+ else if (is_filetype("70"))
+ {
+ try
+ {
+ m_card->m_blk3 = make_unique_clear<uint8_t []>(0x2000);
+ size_t actual;
+ std::tie(err, actual) = read(file, &m_card->m_blk3[0x1000], 0x1000);
+ if (!err && (actual != 0x1000))
+ err = std::errc::io_error;
+ }
+ catch (std::bad_alloc const &)
+ {
+ err = std::errc::not_enough_memory;
+ }
+ }
+ else if (is_filetype("a0"))
+ {
+ size_t actual;
+ std::tie(err, m_card->m_blk5, actual) = read(file, 0x2000);
+ if (!err && (actual != 0x2000))
+ err = std::errc::io_error;
+ }
+ else if (is_filetype("b0"))
+ {
+ try
+ {
+ m_card->m_blk5 = make_unique_clear<uint8_t []>(0x2000);
+ size_t actual;
+ std::tie(err, actual) = read(file, &m_card->m_blk5[0x1000], 0x1000);
+ if (!err && (actual != 0x1000))
+ err = std::errc::io_error;
+ }
+ catch (std::bad_alloc const &)
+ {
+ err = std::errc::not_enough_memory;
+ }
+ }
else if (is_filetype("crt"))
{
+ size_t actual;
+
// read the header
uint8_t header[2];
- fread(&header, 2);
- uint16_t address = (header[1] << 8) | header[0];
+ std::tie(err, actual) = read(file, &header, 2);
+ if (!err && (actual != 2))
+ err = std::errc::io_error;
- switch (address)
+ if (!err)
{
- case 0x2000: fread(m_card->m_blk1, 0x2000); break;
- case 0x4000: fread(m_card->m_blk2, 0x2000); break;
- case 0x6000: fread(m_card->m_blk3, 0x2000); break;
- case 0x7000: fread(m_card->m_blk3, 0x2000, 0x1000); break;
- case 0xa000: fread(m_card->m_blk5, 0x2000); break;
- case 0xb000: fread(m_card->m_blk5, 0x2000, 0x1000); break;
- default: return image_init_result::FAIL;
+ uint16_t const address = get_u16le(&header[0]);
+ switch (address)
+ {
+ case 0x2000:
+ std::tie(err, m_card->m_blk1, actual) = read(file, 0x2000);
+ if (!err && (actual != 0x2000))
+ err = std::errc::io_error;
+ break;
+ case 0x4000:
+ std::tie(err, m_card->m_blk2, actual) = read(file, 0x2000);
+ if (!err && (actual != 0x2000))
+ err = std::errc::io_error;
+ break;
+ case 0x6000:
+ std::tie(err, m_card->m_blk3, actual) = read(file, 0x2000);
+ if (!err && (actual != 0x2000))
+ err = std::errc::io_error;
+ break;
+ case 0x7000:
+ try
+ {
+ m_card->m_blk3 = make_unique_clear<uint8_t []>(0x2000);
+ size_t actual;
+ std::tie(err, actual) = read(file, &m_card->m_blk3[0x1000], 0x1000);
+ if (!err && (actual != 0x1000))
+ err = std::errc::io_error;
+ }
+ catch (std::bad_alloc const &)
+ {
+ err = std::errc::not_enough_memory;
+ }
+ break;
+ case 0xa000:
+ std::tie(err, m_card->m_blk5, actual) = read(file, 0x2000);
+ if (!err && (actual != 0x2000))
+ err = std::errc::io_error;
+ break;
+ case 0xb000:
+ try
+ {
+ m_card->m_blk5 = make_unique_clear<uint8_t []>(0x2000);
+ size_t actual;
+ std::tie(err, actual) = read(file, &m_card->m_blk5[0x1000], 0x1000);
+ if (!err && (actual != 0x1000))
+ err = std::errc::io_error;
+ }
+ catch (std::bad_alloc const &)
+ {
+ err = std::errc::not_enough_memory;
+ }
+ break;
+ default:
+ return std::make_pair(image_error::INVALIDIMAGE, "Unsupported address in CRT file header");
+ }
}
}
+ else
+ {
+ err = image_error::INVALIDIMAGE;
+ }
}
else
{
@@ -132,7 +241,7 @@ image_init_result vic20_expansion_slot_device::call_load()
}
}
- return image_init_result::PASS;
+ return std::make_pair(err, std::string());
}
diff --git a/src/devices/bus/vic20/exp.h b/src/devices/bus/vic20/exp.h
index 124bc7bb9c1..6a0fb941737 100644
--- a/src/devices/bus/vic20/exp.h
+++ b/src/devices/bus/vic20/exp.h
@@ -75,23 +75,23 @@ public:
void cd_w(offs_t offset, uint8_t data, int ram1, int ram2, int ram3, int blk1, int blk2, int blk3, int blk5, int io2, int io3);
// cartridge interface
- DECLARE_WRITE_LINE_MEMBER( irq_w ) { m_write_irq(state); }
- DECLARE_WRITE_LINE_MEMBER( nmi_w ) { m_write_nmi(state); }
- DECLARE_WRITE_LINE_MEMBER( res_w ) { m_write_res(state); }
+ void irq_w(int state) { m_write_irq(state); }
+ void nmi_w(int state) { m_write_nmi(state); }
+ void res_w(int state) { m_write_res(state); }
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
virtual void device_reset() override;
- // image-level overrides
- virtual image_init_result call_load() override;
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
virtual bool is_reset_on_load() const noexcept override { return true; }
virtual const char *image_interface() const noexcept override { return "vic1001_cart"; }
virtual const char *file_extensions() const noexcept override { return "20,40,60,70,a0,b0,crt"; }
- // slot interface overrides
+ // device_slot_interface implementation
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
devcb_write_line m_write_irq;
@@ -124,7 +124,7 @@ protected:
std::unique_ptr<uint8_t[]> m_blk3;
std::unique_ptr<uint8_t[]> m_blk5;
- vic20_expansion_slot_device *m_slot;
+ vic20_expansion_slot_device *const m_slot;
};
diff --git a/src/devices/bus/vic20/megacart.cpp b/src/devices/bus/vic20/megacart.cpp
index 21171bf4343..74da56d5395 100644
--- a/src/devices/bus/vic20/megacart.cpp
+++ b/src/devices/bus/vic20/megacart.cpp
@@ -65,6 +65,25 @@ void vic20_megacart_device::device_reset()
}
+void vic20_megacart_device::nvram_default()
+{
+}
+
+
+bool vic20_megacart_device::nvram_read(util::read_stream &file)
+{
+ auto const [err, actual] = read(file, m_nvram, 0x2000);
+ return !err && (actual == 0x2000);
+}
+
+
+bool vic20_megacart_device::nvram_write(util::write_stream &file)
+{
+ auto const [err, actual] = write(file, m_nvram, 0x2000);
+ return !err;
+}
+
+
//-------------------------------------------------
// vic20_cd_r - cartridge data read
//-------------------------------------------------
diff --git a/src/devices/bus/vic20/megacart.h b/src/devices/bus/vic20/megacart.h
index e1c691a9a4b..f812e2b6f63 100644
--- a/src/devices/bus/vic20/megacart.h
+++ b/src/devices/bus/vic20/megacart.h
@@ -30,19 +30,17 @@ public:
vic20_megacart_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
- // device-level overrides
+ // device_t implementation
+ virtual void device_add_mconfig(machine_config &config) override;
virtual void device_start() override;
virtual void device_reset() override;
- // optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
-
- // device_nvram_interface overrides
- virtual void nvram_default() override { }
- virtual bool nvram_read(util::read_stream &file) override { size_t actual; return !file.read(m_nvram, 0x2000, actual) && actual == 0x2000; }
- virtual bool nvram_write(util::write_stream &file) override { size_t actual; return !file.write(m_nvram, 0x2000, actual) && actual == 0x2000; }
+ // device_nvram_interface implementation
+ virtual void nvram_default() override;
+ virtual bool nvram_read(util::read_stream &file) override;
+ virtual bool nvram_write(util::write_stream &file) override;
- // device_vic20_expansion_card_interface overrides
+ // device_vic20_expansion_card_interface implementation
virtual uint8_t vic20_cd_r(offs_t offset, uint8_t data, int ram1, int ram2, int ram3, int blk1, int blk2, int blk3, int blk5, int io2, int io3) override;
virtual void vic20_cd_w(offs_t offset, uint8_t data, int ram1, int ram2, int ram3, int blk1, int blk2, int blk3, int blk5, int io2, int io3) override;
diff --git a/src/devices/bus/vic20/speakeasy.cpp b/src/devices/bus/vic20/speakeasy.cpp
index 6128852d540..33f10916bbc 100644
--- a/src/devices/bus/vic20/speakeasy.cpp
+++ b/src/devices/bus/vic20/speakeasy.cpp
@@ -37,7 +37,7 @@ void vic20_speakeasy_device::device_add_mconfig(machine_config &config)
{
SPEAKER(config, "mono").front_center();
- VOTRAX_SC01(config, m_votrax, 720000).add_route(ALL_OUTPUTS, "mono", 0.85);
+ VOTRAX_SC01A(config, m_votrax, 720000).add_route(ALL_OUTPUTS, "mono", 0.85);
}
diff --git a/src/devices/bus/vic20/vic1011.cpp b/src/devices/bus/vic20/vic1011.cpp
index 893536a5b09..0554fb07036 100644
--- a/src/devices/bus/vic20/vic1011.cpp
+++ b/src/devices/bus/vic20/vic1011.cpp
@@ -56,7 +56,7 @@ void vic1011_device::device_start()
{
}
-WRITE_LINE_MEMBER( vic1011_device::output_rxd )
+void vic1011_device::output_rxd(int state)
{
output_b(state);
output_c(state);
diff --git a/src/devices/bus/vic20/vic1011.h b/src/devices/bus/vic20/vic1011.h
index e13bc6550ba..63490aaf087 100644
--- a/src/devices/bus/vic20/vic1011.h
+++ b/src/devices/bus/vic20/vic1011.h
@@ -29,10 +29,10 @@ public:
vic1011_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// device_pet_user_port_interface overrides
- virtual DECLARE_WRITE_LINE_MEMBER( input_d ) override;
- virtual DECLARE_WRITE_LINE_MEMBER( input_e ) override;
- virtual DECLARE_WRITE_LINE_MEMBER( input_j ) override;
- virtual DECLARE_WRITE_LINE_MEMBER( input_m ) override;
+ virtual void input_d(int state) override;
+ virtual void input_e(int state) override;
+ virtual void input_j(int state) override;
+ virtual void input_m(int state) override;
protected:
// device-level overrides
@@ -42,7 +42,7 @@ protected:
virtual void device_add_mconfig(machine_config &config) override;
private:
- DECLARE_WRITE_LINE_MEMBER( output_rxd );
+ void output_rxd(int state);
required_device<rs232_port_device> m_rs232;
};
diff --git a/src/devices/bus/vic20/vic1112.cpp b/src/devices/bus/vic20/vic1112.cpp
index ce878ee5f9f..c7043110992 100644
--- a/src/devices/bus/vic20/vic1112.cpp
+++ b/src/devices/bus/vic20/vic1112.cpp
@@ -27,7 +27,7 @@
DEFINE_DEVICE_TYPE(VIC1112, vic1112_device, "vic1112", "VIC-1112 IEEE-488 Interface")
-WRITE_LINE_MEMBER( vic1112_device::via0_irq_w )
+void vic1112_device::via0_irq_w(int state)
{
m_via0_irq = state;
@@ -85,7 +85,7 @@ void vic1112_device::via0_pb_w(uint8_t data)
}
-WRITE_LINE_MEMBER( vic1112_device::via1_irq_w )
+void vic1112_device::via1_irq_w(int state)
{
m_via1_irq = state;
diff --git a/src/devices/bus/vic20/vic1112.h b/src/devices/bus/vic20/vic1112.h
index 8353ad2390d..fc5c144a051 100644
--- a/src/devices/bus/vic20/vic1112.h
+++ b/src/devices/bus/vic20/vic1112.h
@@ -46,10 +46,10 @@ protected:
virtual void vic20_cd_w(offs_t offset, uint8_t data, int ram1, int ram2, int ram3, int blk1, int blk2, int blk3, int blk5, int io2, int io3) override;
private:
- DECLARE_WRITE_LINE_MEMBER( via0_irq_w );
+ void via0_irq_w(int state);
uint8_t via0_pb_r();
void via0_pb_w(uint8_t data);
- DECLARE_WRITE_LINE_MEMBER( via1_irq_w );
+ void via1_irq_w(int state);
required_device<via6522_device> m_via0;
required_device<via6522_device> m_via1;
diff --git a/src/devices/bus/vidbrain/comp_language.cpp b/src/devices/bus/vidbrain/comp_language.cpp
new file mode 100644
index 00000000000..10e7728c715
--- /dev/null
+++ b/src/devices/bus/vidbrain/comp_language.cpp
@@ -0,0 +1,101 @@
+// license:BSD-3-Clause
+// copyright-holders:hap
+// thanks-to:Sean Riddle
+/**********************************************************************
+
+ VideoBrain The Computational Language cartridge emulation
+ 14KB PROM (7*Intel B2616), 1KB RAM (2*Intel P2114L)
+
+**********************************************************************/
+
+#include "emu.h"
+#include "comp_language.h"
+
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(VB_COMP_LANGUAGE, videobrain_comp_language_cartridge_device, "vb_comp_language", "VideoBrain The Computational Language cartridge")
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// videobrain_comp_language_cartridge_device - constructor
+//-------------------------------------------------
+
+videobrain_comp_language_cartridge_device::videobrain_comp_language_cartridge_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, VB_COMP_LANGUAGE, tag, owner, clock),
+ device_videobrain_expansion_card_interface(mconfig, *this)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void videobrain_comp_language_cartridge_device::device_start()
+{
+ m_bank = 0;
+ save_item(NAME(m_bank));
+}
+
+
+//-------------------------------------------------
+// videobrain_bo_r - cartridge data read
+//-------------------------------------------------
+
+uint8_t videobrain_comp_language_cartridge_device::videobrain_bo_r(offs_t offset, int cs1, int cs2)
+{
+ uint8_t data = 0;
+
+ if (!cs1 || !cs2)
+ {
+ // fixed ROM A/B and RAM
+ if (offset >= 0x1c00)
+ data = m_ram[offset & m_ram_mask];
+ else
+ data = m_rom[offset & 0xfff & m_rom_mask];
+ }
+ else if (offset >= 0x3000)
+ {
+ // banked ROM
+ const int lut_roms[8] = { 2, 3, 4, 6, 4, 5 }; // C/D, E/G, E/F
+ const int bank = lut_roms[(m_bank << 1 | BIT(offset, 11)) % 6];
+ data = m_rom[((bank * 0x800) | (offset & 0x7ff)) & m_rom_mask];
+ }
+
+ return data;
+}
+
+
+//-------------------------------------------------
+// videobrain_bo_w - cartridge data write
+//-------------------------------------------------
+
+void videobrain_comp_language_cartridge_device::videobrain_bo_w(offs_t offset, uint8_t data, int cs1, int cs2)
+{
+ if (!cs1)
+ {
+ // bus conflict issue
+ const int lut_bank[4][4] =
+ {
+ // 1000 1001 100A 100F
+ { 0, 1, 2, 0 }, // 00
+ { 2, 1, 2, 1 }, // 55
+ { 0, 2, 2, 0 }, // AA
+ { 2, 2, 2, 2 } // FF
+ };
+ m_bank = lut_bank[data & 3][offset & 3];
+ }
+ else if (!cs2 && offset >= 0x1c00)
+ {
+ m_ram[offset & m_ram_mask] = data;
+ }
+}
diff --git a/src/devices/bus/vidbrain/comp_language.h b/src/devices/bus/vidbrain/comp_language.h
new file mode 100644
index 00000000000..146e2238efa
--- /dev/null
+++ b/src/devices/bus/vidbrain/comp_language.h
@@ -0,0 +1,46 @@
+// license:BSD-3-Clause
+// copyright-holders:hap
+/**********************************************************************
+
+ VideoBrain The Computational Language cartridge emulation
+
+**********************************************************************/
+
+#ifndef MAME_BUS_VIDBRAIN_COMP_LANGUAGE_H
+#define MAME_BUS_VIDBRAIN_COMP_LANGUAGE_H
+
+#pragma once
+
+#include "exp.h"
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> videobrain_comp_language_cartridge_device
+
+class videobrain_comp_language_cartridge_device : public device_t, public device_videobrain_expansion_card_interface
+{
+public:
+ // construction/destruction
+ videobrain_comp_language_cartridge_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+
+ // device_videobrain_expansion_card_interface overrides
+ virtual uint8_t videobrain_bo_r(offs_t offset, int cs1, int cs2) override;
+ virtual void videobrain_bo_w(offs_t offset, uint8_t data, int cs1, int cs2) override;
+
+private:
+ uint8_t m_bank;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(VB_COMP_LANGUAGE, videobrain_comp_language_cartridge_device)
+
+#endif // MAME_BUS_VIDBRAIN_COMP_LANGUAGE_H
diff --git a/src/devices/bus/vidbrain/exp.cpp b/src/devices/bus/vidbrain/exp.cpp
index 42cd7ebe9ba..4423ae3a385 100644
--- a/src/devices/bus/vidbrain/exp.cpp
+++ b/src/devices/bus/vidbrain/exp.cpp
@@ -37,7 +37,7 @@ device_videobrain_expansion_card_interface::device_videobrain_expansion_card_int
//-------------------------------------------------
-// videobrain_roml_pointer - get low ROM pointer
+// videobrain_rom_pointer - get ROM pointer
//-------------------------------------------------
uint8_t* device_videobrain_expansion_card_interface::videobrain_rom_pointer(running_machine &machine, size_t size)
@@ -45,7 +45,6 @@ uint8_t* device_videobrain_expansion_card_interface::videobrain_rom_pointer(runn
if (m_rom.empty())
{
m_rom.resize(size);
-
m_rom_mask = size - 1;
}
@@ -62,7 +61,6 @@ uint8_t* device_videobrain_expansion_card_interface::videobrain_ram_pointer(runn
if (m_ram.empty())
{
m_ram.resize(size);
-
m_ram_mask = size - 1;
}
@@ -95,9 +93,6 @@ videobrain_expansion_slot_device::videobrain_expansion_slot_device(const machine
void videobrain_expansion_slot_device::device_start()
{
m_cart = get_card_device();
-
- // resolve callbacks
- m_write_extres.resolve_safe();
}
@@ -105,29 +100,29 @@ void videobrain_expansion_slot_device::device_start()
// call_load -
//-------------------------------------------------
-image_init_result videobrain_expansion_slot_device::call_load()
+std::pair<std::error_condition, std::string> videobrain_expansion_slot_device::call_load()
{
if (m_cart)
{
- size_t size;
-
if (!loaded_through_softlist())
{
- size = length();
+ size_t const romsize = length();
- fread(m_cart->videobrain_rom_pointer(machine(), size), size);
+ fread(m_cart->videobrain_rom_pointer(machine(), romsize), romsize);
}
else
{
- size = get_software_region_length("rom");
- if (size) memcpy(m_cart->videobrain_rom_pointer(machine(), size), get_software_region("rom"), size);
+ size_t const romsize = get_software_region_length("rom");
+ if (romsize)
+ memcpy(m_cart->videobrain_rom_pointer(machine(), romsize), get_software_region("rom"), romsize);
- size = get_software_region_length("ram");
- if (size) memset(m_cart->videobrain_ram_pointer(machine(), size), 0, size);
+ size_t const ramsize = get_software_region_length("ram");
+ if (ramsize)
+ memset(m_cart->videobrain_ram_pointer(machine(), ramsize), 0, ramsize);
}
}
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
@@ -147,12 +142,16 @@ std::string videobrain_expansion_slot_device::get_default_card_software(get_defa
// slot devices
#include "std.h"
+#include "comp_language.h"
+#include "info_manager.h"
#include "money_minder.h"
#include "timeshare.h"
void vidbrain_expansion_cards(device_slot_interface &device)
{
device.option_add_internal("standard", VB_STD);
- device.option_add_internal("moneyminder", VB_MONEY_MINDER);
+ device.option_add_internal("comp_language", VB_COMP_LANGUAGE);
+ device.option_add_internal("info_manager", VB_INFO_MANAGER);
+ device.option_add_internal("money_minder", VB_MONEY_MINDER);
device.option_add_internal("timeshare", VB_TIMESHARE);
}
diff --git a/src/devices/bus/vidbrain/exp.h b/src/devices/bus/vidbrain/exp.h
index a72cc410adc..f4c75d1e169 100644
--- a/src/devices/bus/vidbrain/exp.h
+++ b/src/devices/bus/vidbrain/exp.h
@@ -89,8 +89,8 @@ class videobrain_expansion_slot_device : public device_t,
public:
// construction/destruction
template <typename T>
- videobrain_expansion_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, T &&opts, char const* dflt)
- : videobrain_expansion_slot_device(mconfig, tag, owner, 0)
+ videobrain_expansion_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, T &&opts, char const* dflt) :
+ videobrain_expansion_slot_device(mconfig, tag, owner, 0)
{
option_reset();
opts(*this);
@@ -109,27 +109,27 @@ public:
void cs1_w(offs_t offset, uint8_t data) { bo_w(offset + 0x1000, data, 0, 1); }
uint8_t cs2_r(offs_t offset) { return bo_r(offset + 0x1800, 1, 0); }
void cs2_w(offs_t offset, uint8_t data) { bo_w(offset + 0x1800, data, 1, 0); }
- uint8_t unmap_r(offs_t offset) { return bo_r(offset + 0x3000, 1, 0); }
- void unmap_w(offs_t offset, uint8_t data) { bo_w(offset + 0x3000, data, 1, 0); }
+ uint8_t unmap_r(offs_t offset) { return bo_r(offset + 0x3000, 1, 1); }
+ void unmap_w(offs_t offset, uint8_t data) { bo_w(offset + 0x3000, data, 1, 1); }
// cartridge interface
- DECLARE_WRITE_LINE_MEMBER( extres_w ) { m_write_extres(state); }
+ void extres_w(int state) { m_write_extres(state); }
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
- // image-level overrides
- virtual image_init_result call_load() override;
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
virtual bool is_reset_on_load() const noexcept override { return true; }
virtual const char *image_interface() const noexcept override { return "vidbrain_cart"; }
virtual const char *file_extensions() const noexcept override { return "bin"; }
- // slot interface overrides
+ // device_slot_interface implementation
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
- devcb_write_line m_write_extres;
+ devcb_write_line m_write_extres;
device_videobrain_expansion_card_interface *m_cart;
};
diff --git a/src/devices/bus/vidbrain/info_manager.cpp b/src/devices/bus/vidbrain/info_manager.cpp
new file mode 100644
index 00000000000..0220e2f5b9a
--- /dev/null
+++ b/src/devices/bus/vidbrain/info_manager.cpp
@@ -0,0 +1,77 @@
+// license:BSD-3-Clause
+// copyright-holders:hap
+/**********************************************************************
+
+ VideoBrain Info Manager cartridge emulation
+ 6KB EPROM (3*B2716), 1KB RAM (2*2114)
+
+ It has the same PCB layout as comp_language, with wire mods to put
+ the ROM/RAM at fixed addresses. There's a big orange label saying
+ "TEST UNIT NO. 14", and a handwritten one with "INFO. MGR SPECIAL".
+
+**********************************************************************/
+
+#include "emu.h"
+#include "info_manager.h"
+
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(VB_INFO_MANAGER, videobrain_info_manager_cartridge_device, "vb_info_manager", "VideoBrain Info Manager cartridge")
+
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// videobrain_info_manager_cartridge_device - constructor
+//-------------------------------------------------
+
+videobrain_info_manager_cartridge_device::videobrain_info_manager_cartridge_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, VB_INFO_MANAGER, tag, owner, clock),
+ device_videobrain_expansion_card_interface(mconfig, *this)
+{
+}
+
+
+//-------------------------------------------------
+// videobrain_bo_r - cartridge data read
+//-------------------------------------------------
+
+uint8_t videobrain_info_manager_cartridge_device::videobrain_bo_r(offs_t offset, int cs1, int cs2)
+{
+ uint8_t data = 0;
+
+ if (!cs1)
+ {
+ data = m_rom[offset & 0x7ff & m_rom_mask];
+ }
+ else if (!cs2)
+ {
+ data = m_ram[offset & m_ram_mask];
+ }
+ else if (offset >= 0x3000)
+ {
+ data = m_rom[offset & m_rom_mask];
+ }
+
+ return data;
+}
+
+
+//-------------------------------------------------
+// videobrain_bo_w - cartridge data write
+//-------------------------------------------------
+
+void videobrain_info_manager_cartridge_device::videobrain_bo_w(offs_t offset, uint8_t data, int cs1, int cs2)
+{
+ if (!cs2)
+ {
+ m_ram[offset & m_ram_mask] = data;
+ }
+}
diff --git a/src/devices/bus/vidbrain/info_manager.h b/src/devices/bus/vidbrain/info_manager.h
new file mode 100644
index 00000000000..b47103ce242
--- /dev/null
+++ b/src/devices/bus/vidbrain/info_manager.h
@@ -0,0 +1,43 @@
+// license:BSD-3-Clause
+// copyright-holders:hap
+/**********************************************************************
+
+ VideoBrain Info Manager cartridge emulation
+
+**********************************************************************/
+
+#ifndef MAME_BUS_VIDBRAIN_INFO_MANAGER_H
+#define MAME_BUS_VIDBRAIN_INFO_MANAGER_H
+
+#pragma once
+
+#include "exp.h"
+
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> videobrain_info_manager_cartridge_device
+
+class videobrain_info_manager_cartridge_device : public device_t, public device_videobrain_expansion_card_interface
+{
+public:
+ // construction/destruction
+ videobrain_info_manager_cartridge_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override { }
+
+ // device_videobrain_expansion_card_interface overrides
+ virtual uint8_t videobrain_bo_r(offs_t offset, int cs1, int cs2) override;
+ virtual void videobrain_bo_w(offs_t offset, uint8_t data, int cs1, int cs2) override;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(VB_INFO_MANAGER, videobrain_info_manager_cartridge_device)
+
+#endif // MAME_BUS_VIDBRAIN_INFO_MANAGER_H
diff --git a/src/devices/bus/vidbrain/money_minder.cpp b/src/devices/bus/vidbrain/money_minder.cpp
index b0f4826ca5d..305973a5d29 100644
--- a/src/devices/bus/vidbrain/money_minder.cpp
+++ b/src/devices/bus/vidbrain/money_minder.cpp
@@ -3,6 +3,7 @@
/**********************************************************************
VideoBrain Money Minder cartridge emulation
+ 4KB ROM (Rockwell R2332C), 1KB RAM (2*Synertek 2114)
**********************************************************************/
@@ -35,16 +36,7 @@ videobrain_money_minder_cartridge_device::videobrain_money_minder_cartridge_devi
//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-
-void videobrain_money_minder_cartridge_device::device_start()
-{
-}
-
-
-//-------------------------------------------------
-// videobrain_cd_r - cartridge data read
+// videobrain_bo_r - cartridge data read
//-------------------------------------------------
uint8_t videobrain_money_minder_cartridge_device::videobrain_bo_r(offs_t offset, int cs1, int cs2)
diff --git a/src/devices/bus/vidbrain/money_minder.h b/src/devices/bus/vidbrain/money_minder.h
index 23f219c4962..dcecdb83853 100644
--- a/src/devices/bus/vidbrain/money_minder.h
+++ b/src/devices/bus/vidbrain/money_minder.h
@@ -21,8 +21,7 @@
// ======================> videobrain_money_minder_cartridge_device
-class videobrain_money_minder_cartridge_device : public device_t,
- public device_videobrain_expansion_card_interface
+class videobrain_money_minder_cartridge_device : public device_t, public device_videobrain_expansion_card_interface
{
public:
// construction/destruction
@@ -30,7 +29,7 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override { }
// device_videobrain_expansion_card_interface overrides
virtual uint8_t videobrain_bo_r(offs_t offset, int cs1, int cs2) override;
diff --git a/src/devices/bus/vidbrain/std.cpp b/src/devices/bus/vidbrain/std.cpp
index 55b5c3ce22d..cb48b513e7d 100644
--- a/src/devices/bus/vidbrain/std.cpp
+++ b/src/devices/bus/vidbrain/std.cpp
@@ -35,15 +35,6 @@ videobrain_standard_cartridge_device::videobrain_standard_cartridge_device(const
//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-
-void videobrain_standard_cartridge_device::device_start()
-{
-}
-
-
-//-------------------------------------------------
// videobrain_bo_r - cartridge data read
//-------------------------------------------------
@@ -51,11 +42,7 @@ uint8_t videobrain_standard_cartridge_device::videobrain_bo_r(offs_t offset, int
{
uint8_t data = 0;
- if (!cs1)
- {
- data = m_rom[offset & m_rom_mask];
- }
- else if (!cs2)
+ if (!cs1 || !cs2)
{
data = m_rom[offset & m_rom_mask];
}
diff --git a/src/devices/bus/vidbrain/std.h b/src/devices/bus/vidbrain/std.h
index 7939501909f..d4a805fb591 100644
--- a/src/devices/bus/vidbrain/std.h
+++ b/src/devices/bus/vidbrain/std.h
@@ -21,8 +21,7 @@
// ======================> videobrain_standard_cartridge_device
-class videobrain_standard_cartridge_device : public device_t,
- public device_videobrain_expansion_card_interface
+class videobrain_standard_cartridge_device : public device_t, public device_videobrain_expansion_card_interface
{
public:
// construction/destruction
@@ -30,7 +29,7 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override { }
// device_videobrain_expansion_card_interface overrides
virtual uint8_t videobrain_bo_r(offs_t offset, int cs1, int cs2) override;
diff --git a/src/devices/bus/vidbrain/timeshare.cpp b/src/devices/bus/vidbrain/timeshare.cpp
index 709f16f5c74..614b66749a0 100644
--- a/src/devices/bus/vidbrain/timeshare.cpp
+++ b/src/devices/bus/vidbrain/timeshare.cpp
@@ -3,6 +3,7 @@
/**********************************************************************
VideoBrain Timeshare cartridge emulation
+ 2KB mask ROM (AMI), 1KB RAM (2*NatSemi MM2114N)
**********************************************************************/
@@ -35,15 +36,6 @@ videobrain_timeshare_cartridge_device::videobrain_timeshare_cartridge_device(con
//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-
-void videobrain_timeshare_cartridge_device::device_start()
-{
-}
-
-
-//-------------------------------------------------
// videobrain_bo_r - cartridge data read
//-------------------------------------------------
diff --git a/src/devices/bus/vidbrain/timeshare.h b/src/devices/bus/vidbrain/timeshare.h
index 7885772149d..3dccdf189e1 100644
--- a/src/devices/bus/vidbrain/timeshare.h
+++ b/src/devices/bus/vidbrain/timeshare.h
@@ -21,8 +21,7 @@
// ======================> videobrain_timeshare_cartridge_device
-class videobrain_timeshare_cartridge_device : public device_t,
- public device_videobrain_expansion_card_interface
+class videobrain_timeshare_cartridge_device : public device_t, public device_videobrain_expansion_card_interface
{
public:
// construction/destruction
@@ -30,7 +29,7 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override { }
// device_videobrain_expansion_card_interface overrides
virtual uint8_t videobrain_bo_r(offs_t offset, int cs1, int cs2) override;
diff --git a/src/devices/bus/vip/byteio.cpp b/src/devices/bus/vip/byteio.cpp
index 83236247ae7..0826cab70ac 100644
--- a/src/devices/bus/vip/byteio.cpp
+++ b/src/devices/bus/vip/byteio.cpp
@@ -58,9 +58,6 @@ vip_byteio_port_device::vip_byteio_port_device(const machine_config &mconfig, co
void vip_byteio_port_device::device_start()
{
m_cart = get_card_device();
-
- // resolve callbacks
- m_write_inst.resolve_safe();
}
@@ -75,9 +72,9 @@ void vip_byteio_port_device::device_reset()
uint8_t vip_byteio_port_device::in_r() { uint8_t data = 0xff; if (m_cart != nullptr) data = m_cart->vip_in_r(); return data; }
void vip_byteio_port_device::out_w(uint8_t data) { if (m_cart != nullptr) m_cart->vip_out_w(data); }
-READ_LINE_MEMBER( vip_byteio_port_device::ef3_r ) { int state = CLEAR_LINE; if (m_cart != nullptr) state = m_cart->vip_ef3_r(); return state; }
-READ_LINE_MEMBER( vip_byteio_port_device::ef4_r ) { int state = CLEAR_LINE; if (m_cart != nullptr) state = m_cart->vip_ef4_r(); return state; }
-WRITE_LINE_MEMBER( vip_byteio_port_device::q_w ) { if (m_cart != nullptr) m_cart->vip_q_w(state); }
+int vip_byteio_port_device::ef3_r() { int state = CLEAR_LINE; if (m_cart != nullptr) state = m_cart->vip_ef3_r(); return state; }
+int vip_byteio_port_device::ef4_r() { int state = CLEAR_LINE; if (m_cart != nullptr) state = m_cart->vip_ef4_r(); return state; }
+void vip_byteio_port_device::q_w(int state) { if (m_cart != nullptr) m_cart->vip_q_w(state); }
//-------------------------------------------------
diff --git a/src/devices/bus/vip/byteio.h b/src/devices/bus/vip/byteio.h
index 5cca82aea45..7d564f2bf03 100644
--- a/src/devices/bus/vip/byteio.h
+++ b/src/devices/bus/vip/byteio.h
@@ -74,12 +74,12 @@ public:
// computer interface
uint8_t in_r();
void out_w(uint8_t data);
- DECLARE_READ_LINE_MEMBER( ef3_r );
- DECLARE_READ_LINE_MEMBER( ef4_r );
- DECLARE_WRITE_LINE_MEMBER( q_w );
+ int ef3_r();
+ int ef4_r();
+ void q_w(int state);
// cartridge interface
- DECLARE_WRITE_LINE_MEMBER( inst_w ) { m_write_inst(state); }
+ void inst_w(int state) { m_write_inst(state); }
protected:
// device-level overrides
diff --git a/src/devices/bus/vip/exp.cpp b/src/devices/bus/vip/exp.cpp
index f6abf579f18..16374ed7941 100644
--- a/src/devices/bus/vip/exp.cpp
+++ b/src/devices/bus/vip/exp.cpp
@@ -68,11 +68,6 @@ vip_expansion_slot_device::vip_expansion_slot_device(const machine_config &mconf
void vip_expansion_slot_device::device_start()
{
m_card = get_card_device();
-
- // resolve callbacks
- m_write_int.resolve_safe();
- m_write_dma_out.resolve_safe();
- m_write_dma_in.resolve_safe();
}
@@ -182,7 +177,7 @@ uint32_t vip_expansion_slot_device::screen_update(screen_device &screen, bitmap_
return value;
}
-READ_LINE_MEMBER(vip_expansion_slot_device::ef1_r)
+int vip_expansion_slot_device::ef1_r()
{
int state = CLEAR_LINE;
if (m_card != nullptr)
@@ -190,7 +185,7 @@ READ_LINE_MEMBER(vip_expansion_slot_device::ef1_r)
return state;
}
-READ_LINE_MEMBER(vip_expansion_slot_device::ef3_r)
+int vip_expansion_slot_device::ef3_r()
{
int state = CLEAR_LINE;
if (m_card != nullptr)
@@ -198,7 +193,7 @@ READ_LINE_MEMBER(vip_expansion_slot_device::ef3_r)
return state;
}
-READ_LINE_MEMBER(vip_expansion_slot_device::ef4_r)
+int vip_expansion_slot_device::ef4_r()
{
int state = CLEAR_LINE;
if (m_card != nullptr)
@@ -212,19 +207,19 @@ void vip_expansion_slot_device::sc_w(offs_t offset, uint8_t data)
m_card->vip_sc_w(offset, data);
}
-WRITE_LINE_MEMBER(vip_expansion_slot_device::q_w)
+void vip_expansion_slot_device::q_w(int state)
{
if (m_card != nullptr)
m_card->vip_q_w(state);
}
-WRITE_LINE_MEMBER(vip_expansion_slot_device::tpb_w)
+void vip_expansion_slot_device::tpb_w(int state)
{
if (m_card != nullptr)
m_card->vip_tpb_w(state);
}
-WRITE_LINE_MEMBER(vip_expansion_slot_device::run_w)
+void vip_expansion_slot_device::run_w(int state)
{
if (m_card != nullptr)
m_card->vip_run_w(state);
diff --git a/src/devices/bus/vip/exp.h b/src/devices/bus/vip/exp.h
index aa50074e9ca..cdd03a768ea 100644
--- a/src/devices/bus/vip/exp.h
+++ b/src/devices/bus/vip/exp.h
@@ -74,18 +74,18 @@ public:
uint8_t dma_r(offs_t offset);
void dma_w(offs_t offset, uint8_t data);
uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
- DECLARE_READ_LINE_MEMBER(ef1_r);
- DECLARE_READ_LINE_MEMBER(ef3_r);
- DECLARE_READ_LINE_MEMBER(ef4_r);
+ int ef1_r();
+ int ef3_r();
+ int ef4_r();
void sc_w(offs_t offset, uint8_t data);
- DECLARE_WRITE_LINE_MEMBER(q_w);
- DECLARE_WRITE_LINE_MEMBER(tpb_w);
- DECLARE_WRITE_LINE_MEMBER(run_w);
+ void q_w(int state);
+ void tpb_w(int state);
+ void run_w(int state);
// cartridge interface
- DECLARE_WRITE_LINE_MEMBER(interrupt_w) { m_write_int(state); }
- DECLARE_WRITE_LINE_MEMBER(dma_out_w) { m_write_dma_out(state); }
- DECLARE_WRITE_LINE_MEMBER(dma_in_w) { m_write_dma_in(state); }
+ void interrupt_w(int state) { m_write_int(state); }
+ void dma_out_w(int state) { m_write_dma_out(state); }
+ void dma_in_w(int state) { m_write_dma_in(state); }
protected:
// device-level overrides
diff --git a/src/devices/bus/vip/vp575.h b/src/devices/bus/vip/vp575.h
index fb5c22f5628..19c1da4c50c 100644
--- a/src/devices/bus/vip/vp575.h
+++ b/src/devices/bus/vip/vp575.h
@@ -52,23 +52,23 @@ protected:
private:
static constexpr unsigned MAX_SLOTS = 5;
- DECLARE_WRITE_LINE_MEMBER( exp1_int_w ) { m_int[0] = state; update_interrupts(); }
- DECLARE_WRITE_LINE_MEMBER( exp2_int_w ) { m_int[1] = state; update_interrupts(); }
- DECLARE_WRITE_LINE_MEMBER( exp3_int_w ) { m_int[2] = state; update_interrupts(); }
- DECLARE_WRITE_LINE_MEMBER( exp4_int_w ) { m_int[3] = state; update_interrupts(); }
- DECLARE_WRITE_LINE_MEMBER( exp5_int_w ) { m_int[4] = state; update_interrupts(); }
-
- DECLARE_WRITE_LINE_MEMBER( exp1_dma_out_w ) { m_dma_out[0] = state; update_interrupts(); }
- DECLARE_WRITE_LINE_MEMBER( exp2_dma_out_w ) { m_dma_out[1] = state; update_interrupts(); }
- DECLARE_WRITE_LINE_MEMBER( exp3_dma_out_w ) { m_dma_out[2] = state; update_interrupts(); }
- DECLARE_WRITE_LINE_MEMBER( exp4_dma_out_w ) { m_dma_out[3] = state; update_interrupts(); }
- DECLARE_WRITE_LINE_MEMBER( exp5_dma_out_w ) { m_dma_out[4] = state; update_interrupts(); }
-
- DECLARE_WRITE_LINE_MEMBER( exp1_dma_in_w ) { m_dma_in[0] = state; update_interrupts(); }
- DECLARE_WRITE_LINE_MEMBER( exp2_dma_in_w ) { m_dma_in[1] = state; update_interrupts(); }
- DECLARE_WRITE_LINE_MEMBER( exp3_dma_in_w ) { m_dma_in[2] = state; update_interrupts(); }
- DECLARE_WRITE_LINE_MEMBER( exp4_dma_in_w ) { m_dma_in[3] = state; update_interrupts(); }
- DECLARE_WRITE_LINE_MEMBER( exp5_dma_in_w ) { m_dma_in[4] = state; update_interrupts(); }
+ void exp1_int_w(int state) { m_int[0] = state; update_interrupts(); }
+ void exp2_int_w(int state) { m_int[1] = state; update_interrupts(); }
+ void exp3_int_w(int state) { m_int[2] = state; update_interrupts(); }
+ void exp4_int_w(int state) { m_int[3] = state; update_interrupts(); }
+ void exp5_int_w(int state) { m_int[4] = state; update_interrupts(); }
+
+ void exp1_dma_out_w(int state) { m_dma_out[0] = state; update_interrupts(); }
+ void exp2_dma_out_w(int state) { m_dma_out[1] = state; update_interrupts(); }
+ void exp3_dma_out_w(int state) { m_dma_out[2] = state; update_interrupts(); }
+ void exp4_dma_out_w(int state) { m_dma_out[3] = state; update_interrupts(); }
+ void exp5_dma_out_w(int state) { m_dma_out[4] = state; update_interrupts(); }
+
+ void exp1_dma_in_w(int state) { m_dma_in[0] = state; update_interrupts(); }
+ void exp2_dma_in_w(int state) { m_dma_in[1] = state; update_interrupts(); }
+ void exp3_dma_in_w(int state) { m_dma_in[2] = state; update_interrupts(); }
+ void exp4_dma_in_w(int state) { m_dma_in[3] = state; update_interrupts(); }
+ void exp5_dma_in_w(int state) { m_dma_in[4] = state; update_interrupts(); }
void update_interrupts();
diff --git a/src/devices/bus/vip/vp590.cpp b/src/devices/bus/vip/vp590.cpp
index 296ce70fb8b..3988600f336 100644
--- a/src/devices/bus/vip/vp590.cpp
+++ b/src/devices/bus/vip/vp590.cpp
@@ -33,17 +33,17 @@ DEFINE_DEVICE_TYPE(VP590, vp590_device, "vp590", "VP-590 Color Board + VP-580 16
// CDP1862_INTERFACE( cgc_intf )
//-------------------------------------------------
-READ_LINE_MEMBER( vp590_device::rd_r )
+int vp590_device::rd_r()
{
return BIT(m_color, 1);
}
-READ_LINE_MEMBER( vp590_device::bd_r )
+int vp590_device::bd_r()
{
return BIT(m_color, 2);
}
-READ_LINE_MEMBER( vp590_device::gd_r )
+int vp590_device::gd_r()
{
return BIT(m_color, 3);
}
diff --git a/src/devices/bus/vip/vp590.h b/src/devices/bus/vip/vp590.h
index 9c69762f7be..54306da55a4 100644
--- a/src/devices/bus/vip/vp590.h
+++ b/src/devices/bus/vip/vp590.h
@@ -45,9 +45,9 @@ protected:
virtual int vip_ef4_r() override;
private:
- DECLARE_READ_LINE_MEMBER( rd_r );
- DECLARE_READ_LINE_MEMBER( bd_r );
- DECLARE_READ_LINE_MEMBER( gd_r );
+ int rd_r();
+ int bd_r();
+ int gd_r();
required_device<cdp1862_device> m_cgc;
memory_share_creator<uint8_t> m_color_ram;
diff --git a/src/devices/bus/vme/vme_cp31.cpp b/src/devices/bus/vme/cp31.cpp
index 2a59f92b7ed..14b739713fe 100644
--- a/src/devices/bus/vme/vme_cp31.cpp
+++ b/src/devices/bus/vme/cp31.cpp
@@ -25,19 +25,15 @@
#include "emu.h"
-#include "vme_cp31.h"
+#include "cp31.h"
-//#define LOG_GENERAL (1U << 0)
-#define LOG_SETUP (1U << 1)
-#define LOG_INT (1U << 2)
+#define LOG_INT (1U << 1)
-//#define VERBOSE (LOG_GENERAL | LOG_SETUP | LOG_INT)
+#define VERBOSE (0) // (LOG_GENERAL | LOG_INT)
//#define LOG_OUTPUT_FUNC printf
-
#include "logmacro.h"
-#define LOGSETUP(...) LOGMASKED(LOG_SETUP, __VA_ARGS__)
#define LOGINT(...) LOGMASKED(LOG_INT, __VA_ARGS__)
@@ -195,7 +191,7 @@ uint32_t vme_cp31_card_device::trap_r(offs_t offset, uint32_t mem_mask)
return 0xffffffff;
}
-WRITE_LINE_MEMBER(vme_cp31_card_device::bim_irq_callback)
+void vme_cp31_card_device::bim_irq_callback(int state)
{
LOGINT("%s(%02x)\n", FUNCNAME, state);
@@ -276,7 +272,6 @@ vme_cp31_card_device::vme_cp31_card_device(const machine_config &mconfig, device
, m_p_ram(*this, "dram")
, m_sysrom(*this, "user1")
{
- m_slot = 1;
}
//
diff --git a/src/devices/bus/vme/vme_cp31.h b/src/devices/bus/vme/cp31.h
index 38ff78d69b3..774de7c3152 100644
--- a/src/devices/bus/vme/vme_cp31.h
+++ b/src/devices/bus/vme/cp31.h
@@ -1,14 +1,14 @@
// license:BSD-3-Clause
// copyright-holders:Sergey Svishchev
-#ifndef MAME_BUS_VME_VME_CP31_H
-#define MAME_BUS_VME_VME_CP31_H
+#ifndef MAME_BUS_VME_CP31_H
+#define MAME_BUS_VME_CP31_H
#pragma once
#include "vme.h"
#include "bus/rs232/rs232.h"
-#include "cpu/m68000/m68000.h"
+#include "cpu/m68000/m68030.h"
#include "machine/68153bim.h"
#include "machine/68230pit.h"
#include "machine/68561mpcc.h"
@@ -36,7 +36,7 @@ protected:
TIMER_CALLBACK_MEMBER(bus_error_off);
private:
- required_device<m68000_base_device> m_maincpu;
+ required_device<m68000_musashi_device> m_maincpu;
required_device<bim68153_device> m_bim;
required_device<mpcc68561_device> m_mpcc;
required_device<rtc62421_device> m_rtc;
@@ -53,7 +53,7 @@ private:
uint8_t bim_irq_state;
int bim_irq_level;
- DECLARE_WRITE_LINE_MEMBER(bim_irq_callback);
+ void bim_irq_callback(int state);
void update_irq_to_maincpu();
void pit1_pb_w(uint8_t data);
@@ -69,4 +69,4 @@ private:
void cpu_space_map(address_map &map);
};
-#endif // MAME_BUS_VME_VME_CP31_H
+#endif // MAME_BUS_VME_CP31_H
diff --git a/src/devices/bus/vme/enp10.cpp b/src/devices/bus/vme/enp10.cpp
new file mode 100644
index 00000000000..e0406f1f91f
--- /dev/null
+++ b/src/devices/bus/vme/enp10.cpp
@@ -0,0 +1,221 @@
+// license:BSD-3-Clause
+// copyright-holders:Patrick Mackinlay
+
+/*
+ * Communication Machinery Corporation Ethernet Node Processor (ENP-10)
+ *
+ * Sources:
+ * - Ethernet Node Processor ENP-30 Reference Guide (6213000-05B), Communication Machinery Corporation, November 15, 1988
+ *
+ * TODO:
+ * - verify registers
+ * - uart?
+ */
+
+/*
+ * WIP
+ * ---
+ * - 0xef'8010-0xef'802f appears to be a uart, but doesn't match scn2681 per ENP-30 documentation?
+ * - following text is output to 0xef'8025 at startup:
+ * CMC ENP/10 CMOS - 112708 Bytes Free
+ * Ethernet Address: 02CF1F123456
+ * Allocating 30 receive buffers
+ * Allocating 30 transmit buffers
+ */
+
+#include "emu.h"
+#include "enp10.h"
+
+#define VERBOSE 0
+#include "logmacro.h"
+
+DEFINE_DEVICE_TYPE(VME_ENP10, vme_enp10_card_device, "enp10", "CMC ENP-10")
+
+vme_enp10_card_device::vme_enp10_card_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, VME_ENP10, tag, owner, clock)
+ , device_vme_card_interface(mconfig, *this)
+ , m_cpu(*this, "cpu")
+ , m_net(*this, "net")
+ , m_led(*this, "led%u", 0U)
+ , m_base(*this, "BASE")
+ , m_boot(*this, "boot")
+{
+}
+
+ROM_START(enp10)
+ ROM_REGION16_BE(0x4000, "eprom", 0)
+
+ ROM_SYSTEM_BIOS(0, "enp10_0", "CMC ENP/10 CMOS")
+ ROMX_LOAD("link_10_2.0_nh_rev.4.1h.u4", 0x0000, 0x2000, CRC(7532f2b1) SHA1(bdef6c525f451fbc67f3d4625c9db18975e7e1e4), ROM_SKIP(1) | ROM_BIOS(0))
+ ROMX_LOAD("link_10_2.0_nh_rev.k4.1l.u3", 0x0001, 0x2000, CRC(f2decb78) SHA1(795623274bfff6273790c30445e4dca4064859ed), ROM_SKIP(1) | ROM_BIOS(0))
+
+ ROM_SYSTEM_BIOS(1, "enp10_1", "CMC ENP/10 CMOS (SGI?)")
+ ROMX_LOAD("8845__070_0132_002s.u4", 0x0000, 0x2000, CRC(3ea05f63) SHA1(ee523928d27b854cd1be7e6aa2b8bb093d240022), ROM_SKIP(1) | ROM_BIOS(1))
+ ROMX_LOAD("8845__070_0131_002s.u3", 0x0001, 0x2000, CRC(d4439fb9) SHA1(51466000b613ab5c03b2bf933e1a485fe2e53d04), ROM_SKIP(1) | ROM_BIOS(1))
+
+ // hand-crafted prom containing address 02:cf:1f:12:34:56
+ ROM_REGION16_BE(0x20, "mac", 0)
+ ROM_LOAD("mac.bin", 0x00, 0x20, CRC(99ac9577) SHA1(b4d6bba88dd376cc492738d57742628f42e9265e))
+ROM_END
+
+static INPUT_PORTS_START(enp10)
+ PORT_START("BASE")
+ PORT_CONFNAME(0xff, 0xde, "Base Address")
+ PORT_CONFSETTING(0xd8, "0xd80000")
+ PORT_CONFSETTING(0xda, "0xda0000")
+ PORT_CONFSETTING(0xdc, "0xdc0000")
+ PORT_CONFSETTING(0xde, "0xde0000")
+INPUT_PORTS_END
+
+const tiny_rom_entry *vme_enp10_card_device::device_rom_region() const
+{
+ return ROM_NAME(enp10);
+}
+
+ioport_constructor vme_enp10_card_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(enp10);
+}
+
+void vme_enp10_card_device::device_start()
+{
+ m_led.resolve();
+
+ save_item(NAME(m_ivr));
+ save_item(NAME(m_csr));
+ save_item(NAME(m_ier));
+ save_item(NAME(m_tir));
+ save_item(NAME(m_rir));
+ save_item(NAME(m_uir));
+ save_item(NAME(m_rer));
+ save_item(NAME(m_exr));
+ save_item(NAME(m_hir));
+}
+
+void vme_enp10_card_device::device_reset()
+{
+ m_boot.select(0);
+
+ m_ivr = 0;
+ m_csr = 0;
+ m_ier = 0;
+ m_tir = 0;
+ m_rir = 0;
+ m_uir = 0;
+ m_rer = 0;
+ m_exr = 0;
+ m_hir = 0;
+
+ u32 const base = m_base->read() << 16;
+
+ vme_space(vme::AM_39).install_device(base, base | 0x1'ffff, *this, &vme_enp10_card_device::vme_map);
+ vme_space(vme::AM_3d).install_device(base, base | 0x1'ffff, *this, &vme_enp10_card_device::vme_map);
+
+ vme_irq_w<4>(1);
+}
+
+void vme_enp10_card_device::device_add_mconfig(machine_config &config)
+{
+ M68000(config, m_cpu, 20_MHz_XTAL / 2);
+ m_cpu->set_addrmap(AS_PROGRAM, &vme_enp10_card_device::cpu_map);
+
+ AM7990(config, m_net, 20_MHz_XTAL / 2);
+ m_net->intr_out().set_inputline(m_cpu, INPUT_LINE_IRQ6).invert();
+ m_net->dma_in().set([this](offs_t offset) { return m_cpu->space(0).read_word(offset); });
+ m_net->dma_out().set([this](offs_t offset, u16 data, u16 mem_mask) { m_cpu->space(0).write_word(offset, data, mem_mask); });
+
+ vme_iack().set(FUNC(vme_enp10_card_device::iack_r));
+}
+
+void vme_enp10_card_device::cpu_map(address_map &map)
+{
+ map(0xf0'0000, 0xf1'ffff).ram().share("ram");
+ map(0xf8'0000, 0xf8'3fff).rom().region("eprom", 0).mirror(0x02'0000);
+
+ map(0x00'0000, 0xf1'ffff).view(m_boot);
+ // map first 1k of eprom at 0x00'0000
+ m_boot[0](0x00'0000, 0x00'0fff).rom().region("eprom", 0);
+
+ // map first 1k of ram at 0x00'0000, unmap at 0xf0'0000
+ m_boot[1](0x00'0000, 0x01'ffff).ram().share("ram");
+ m_boot[1](0x00'1000, 0x01'ffff).unmaprw();
+ m_boot[1](0xf0'0000, 0xf0'0fff).unmaprw();
+
+ // uart: 16 byte registers 10-2f?
+ map(0xef'8010, 0xef'802f).noprw();
+
+ map(0xfe'0080, 0xfe'0081).umask16(0x00ff).rw(FUNC(vme_enp10_card_device::addr_r), FUNC(vme_enp10_card_device::irq_w));
+
+ map(0xfe'00a0, 0xfe'00a1).umask16(0x00ff).lrw8(
+ [this]() { return m_csr; }, "csr_r",
+ [this](u8 data)
+ {
+ LOG("csr_w 0x%02x\n", data);
+
+ m_led[0] = BIT(data, 6); // fail?
+ m_led[1] = BIT(data, 5); // run?
+
+ m_csr = data;
+ }, "csr_w");
+
+ map(0xfe'00c0, 0xfe'00c1).umask16(0x00ff).lrw8(NAME([this]() { return m_ier; }), NAME([this](u8 data) { m_ier = data; interrupt(); }));
+ map(0xfe'00c2, 0xfe'00c3).umask16(0x00ff).lrw8(NAME([this]() { return m_tir; }), NAME([this](u8 data) { m_tir = data; interrupt(); }));
+ map(0xfe'00c4, 0xfe'00c5).umask16(0x00ff).lrw8(NAME([this]() { return m_rir; }), NAME([this](u8 data) { m_rir = data; interrupt(); }));
+ map(0xfe'00c6, 0xfe'00c7).umask16(0x00ff).lrw8(NAME([this]() { return m_uir; }), NAME([this](u8 data) { m_uir = data; interrupt(); }));
+ map(0xfe'00ce, 0xfe'00cf).umask16(0x00ff).lrw8(NAME([this]() { return m_rer; }), NAME([this](u8 data) { m_rer = data; m_boot.select(BIT(data, 7)); }));
+
+ map(0xfe'00e0, 0xfe'00e1).umask16(0x00ff).lrw8(NAME([this]() { return m_exr; }), NAME([this](u8 data) { m_exr = data; })); // TODO: bit 1 parity error?
+ map(0xfe'00ee, 0xfe'00ef).umask16(0x00ff).lr8(NAME([]() { return 0; })); // TODO: bit 1 enables additional ram test?
+
+ map(0xfe'0200, 0xfe'0203).rw(m_net, FUNC(am7990_device::regs_r), FUNC(am7990_device::regs_w));
+ map(0xfe'0400, 0xfe'041f).rom().region("mac", 0);
+
+ // TODO: verify the next two registers
+ map(0xfe'0e00, 0xfe'0e01).umask16(0x00ff).lrw8(NAME([this]() { return m_hir; }), NAME([this](u8 data) { m_hir = data; interrupt(); }));
+ map(0xfe'0f00, 0xfe'0fff).umask16(0x00ff).lrw8(NAME([this]() { reset(); return 0; }), NAME([this](u8 data) { reset(); }));
+}
+
+void vme_enp10_card_device::vme_map(address_map &map)
+{
+ map(0x0'0000, 0x1'efff).lrw16(
+ [this](offs_t offset, u16 mem_mask) { return m_cpu->space(0).read_word(0xf0'0000 | (offset << 1), mem_mask); }, "mem_r",
+ [this](offs_t offset, u16 data, u16 mem_mask) { m_cpu->space(0).write_word(0xf0'0000 | (offset << 1), data, mem_mask); }, "mem_w");
+
+ map(0x1'f000, 0x1'ffff).lrw16(
+ [this](offs_t offset, u16 mem_mask) { return m_cpu->space(0).read_word(0xfe'0000 | (offset << 1), mem_mask); }, "reg_r",
+ [this](offs_t offset, u16 data, u16 mem_mask) { m_cpu->space(0).write_word(0xfe'0000 | (offset << 1), mem_mask); }, "reg_w");
+}
+
+u8 vme_enp10_card_device::addr_r()
+{
+ LOG("addr_r (%s)\n", machine().describe_context());
+
+ // TODO: what is returned here?
+ return m_base->read();
+}
+
+void vme_enp10_card_device::irq_w(u8 data)
+{
+ LOG("irq 0x%02x (%s)\n", data, machine().describe_context());
+
+ m_ivr = data;
+
+ vme_irq_w<4>(0);
+}
+
+u8 vme_enp10_card_device::iack_r()
+{
+ vme_irq_w<4>(1);
+
+ return m_ivr;
+}
+
+void vme_enp10_card_device::interrupt()
+{
+ bool const enable = BIT(m_ier, 7);
+
+ m_cpu->set_input_line(INPUT_LINE_IRQ2, enable && BIT(m_uir, 7));
+ m_cpu->set_input_line(INPUT_LINE_IRQ3, enable && BIT(m_hir, 7));
+ m_cpu->set_input_line(INPUT_LINE_IRQ4, enable && BIT(m_tir, 7));
+ m_cpu->set_input_line(INPUT_LINE_IRQ5, enable && BIT(m_rir, 7));
+}
diff --git a/src/devices/bus/vme/enp10.h b/src/devices/bus/vme/enp10.h
new file mode 100644
index 00000000000..c5997c945e4
--- /dev/null
+++ b/src/devices/bus/vme/enp10.h
@@ -0,0 +1,58 @@
+// license:BSD-3-Clause
+// copyright-holders:Patrick Mackinlay
+
+#ifndef MAME_BUS_VME_ENP10_H
+#define MAME_BUS_VME_ENP10_H
+
+#pragma once
+
+#include "cpu/m68000/m68000.h"
+#include "machine/am79c90.h"
+#include "bus/vme/vme.h"
+
+class vme_enp10_card_device
+ : public device_t
+ , public device_vme_card_interface
+{
+public:
+ vme_enp10_card_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual ioport_constructor device_input_ports() const override;
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+private:
+ void cpu_map(address_map &map);
+ void vme_map(address_map &map);
+
+ u8 addr_r();
+ void irq_w(u8 data);
+ u8 iack_r();
+
+ void interrupt();
+
+ required_device<m68000_device> m_cpu;
+ required_device<am7990_device> m_net;
+
+ output_finder<2> m_led;
+ required_ioport m_base;
+
+ u8 m_ivr; // interrupt vector register
+ u8 m_csr; // control/status register
+ u8 m_ier; // interrupt enable register
+ u8 m_tir; // transmit interrupt register
+ u8 m_rir; // receive interrupt register
+ u8 m_uir; // utility interrupt register
+ u8 m_rer; // ram/rom enable register
+ u8 m_exr; // exception register
+ u8 m_hir; // host interrupt register
+
+ memory_view m_boot;
+};
+
+DECLARE_DEVICE_TYPE(VME_ENP10, vme_enp10_card_device)
+
+#endif // MAME_BUS_VME_ENP10_H
diff --git a/src/devices/bus/vme/vme_hcpu30.cpp b/src/devices/bus/vme/hcpu30.cpp
index a68cdb319f2..2165a8c2c6d 100644
--- a/src/devices/bus/vme/vme_hcpu30.cpp
+++ b/src/devices/bus/vme/hcpu30.cpp
@@ -30,18 +30,14 @@
*/
#include "emu.h"
-#include "vme_hcpu30.h"
+#include "hcpu30.h"
-//#define LOG_GENERAL (1U << 0)
-#define LOG_SETUP (1U << 1)
-#define LOG_INT (1U << 2)
+#define LOG_INT (1U << 1)
-//#define VERBOSE (LOG_GENERAL | LOG_SETUP | LOG_INT)
+#define VERBOSE (0) // (LOG_GENERAL | LOG_INT)
//#define LOG_OUTPUT_FUNC printf
-
#include "logmacro.h"
-#define LOGSETUP(...) LOGMASKED(LOG_SETUP, __VA_ARGS__)
#define LOGINT(...) LOGMASKED(LOG_INT, __VA_ARGS__)
@@ -175,7 +171,7 @@ void vme_hcpu30_card_device::device_add_mconfig(machine_config &config)
M68020(config, m_maincpu, 16670000);
m_maincpu->set_addrmap(AS_PROGRAM, &vme_hcpu30_card_device::hcpu30_mem);
m_maincpu->set_addrmap(m68000_base_device::AS_CPU_SPACE, &vme_hcpu30_card_device::cpu_space_map);
- m_maincpu->disable_interrupt_mixer();
+ m_maincpu->set_interrupt_mixer(false);
// FIXME: functional test expects dtr->dcd, rts->cts connections on both ports and tx->rx connection on port B
DUSCC68562(config, m_dusccterm, DUSCC_CLOCK);
@@ -332,7 +328,7 @@ void vme_hcpu30_card_device::trap_w(offs_t offset, uint32_t data, uint32_t mem_m
}
// Active High?
-WRITE_LINE_MEMBER(vme_hcpu30_card_device::dusirq_callback)
+void vme_hcpu30_card_device::dusirq_callback(int state)
{
LOGINT("vme_hcpu30_card_device::dusirq_callback(%02x)\n", state);
m_irq_state &= ~(1 << 12);
@@ -340,7 +336,7 @@ WRITE_LINE_MEMBER(vme_hcpu30_card_device::dusirq_callback)
}
// Active Low?
-WRITE_LINE_MEMBER(vme_hcpu30_card_device::scsiirq_callback)
+void vme_hcpu30_card_device::scsiirq_callback(int state)
{
LOGINT("vme_hcpu30_card_device::scsiirq_callback(%02x)\n", state);
m_irq_state &= ~(1 << 8);
@@ -348,7 +344,7 @@ WRITE_LINE_MEMBER(vme_hcpu30_card_device::scsiirq_callback)
}
// Active Low?
-WRITE_LINE_MEMBER(vme_hcpu30_card_device::scsidrq_callback)
+void vme_hcpu30_card_device::scsidrq_callback(int state)
{
LOGINT("vme_hcpu30_card_device::scsidrq_callback(%02x)\n", state);
m_irq_state &= ~(1 << 7);
@@ -356,7 +352,7 @@ WRITE_LINE_MEMBER(vme_hcpu30_card_device::scsidrq_callback)
}
// Active Low?
-WRITE_LINE_MEMBER(vme_hcpu30_card_device::fdcirq_callback)
+void vme_hcpu30_card_device::fdcirq_callback(int state)
{
LOGINT("vme_hcpu30_card_device::fdcirq_callback(%02x)\n", state);
m_irq_state &= ~(1 << (8+2));
@@ -364,7 +360,7 @@ WRITE_LINE_MEMBER(vme_hcpu30_card_device::fdcirq_callback)
}
// Active Low?
-WRITE_LINE_MEMBER(vme_hcpu30_card_device::fdcdrq_callback)
+void vme_hcpu30_card_device::fdcdrq_callback(int state)
{
LOGINT("vme_hcpu30_card_device::fdcdrq_callback(%02x)\n", state);
#if 0
@@ -546,7 +542,6 @@ vme_hcpu30_card_device::vme_hcpu30_card_device(const machine_config &mconfig, de
, m_dips(*this, "SA1")
{
LOG("vme_hcpu30_card_device::vme_hcpu30_card_device ctor: %s\n", tag);
- m_slot = 1;
}
//
diff --git a/src/devices/bus/vme/vme_hcpu30.h b/src/devices/bus/vme/hcpu30.h
index 14c5e0059b0..b84cb120048 100644
--- a/src/devices/bus/vme/vme_hcpu30.h
+++ b/src/devices/bus/vme/hcpu30.h
@@ -1,7 +1,7 @@
// license:BSD-3-Clause
// copyright-holders:Sergey Svishchev
-#ifndef MAME_BUS_VME_VME_HCPU30_H
-#define MAME_BUS_VME_VME_HCPU30_H
+#ifndef MAME_BUS_VME_HCPU30_H
+#define MAME_BUS_VME_HCPU30_H
#pragma once
@@ -10,7 +10,8 @@
#include "bus/centronics/ctronics.h"
#include "bus/nscsi/hd.h"
#include "bus/rs232/rs232.h"
-#include "cpu/m68000/m68000.h"
+#include "cpu/m68000/m68020.h"
+#include "cpu/m68000/m68030.h"
#include "imagedev/floppy.h"
#include "machine/clock.h"
#include "machine/msm6242.h"
@@ -40,7 +41,7 @@ protected:
TIMER_CALLBACK_MEMBER(bus_error_off);
private:
- required_device<m68000_base_device> m_maincpu;
+ required_device<m68000_musashi_device> m_maincpu;
required_device<duscc68562_device> m_dusccterm;
required_device<wd33c93a_device> m_scsi;
required_device<upd765_family_device> m_fdc;
@@ -50,17 +51,17 @@ private:
required_device<centronics_device> m_centronics;
required_device<output_latch_device> m_cent_data_out;
required_device<input_buffer_device> m_cent_status_in;
- required_device<m68000_base_device> m_oscpu;
+ required_device<m68000_musashi_device> m_oscpu;
required_shared_ptr<uint32_t> m_mailbox;
required_shared_ptr<uint32_t> m_p_ram;
required_region_ptr<uint32_t> m_sysrom;
required_ioport m_dips;
- DECLARE_WRITE_LINE_MEMBER(dusirq_callback);
- DECLARE_WRITE_LINE_MEMBER(scsiirq_callback);
- DECLARE_WRITE_LINE_MEMBER(scsidrq_callback);
- DECLARE_WRITE_LINE_MEMBER(fdcirq_callback);
- DECLARE_WRITE_LINE_MEMBER(fdcdrq_callback);
+ void dusirq_callback(int state);
+ void scsiirq_callback(int state);
+ void scsidrq_callback(int state);
+ void fdcirq_callback(int state);
+ void fdcdrq_callback(int state);
// Pointer to System ROMs needed by bootvect_r and masking RAM buffer for post reset accesses
memory_passthrough_handler m_rom_shadow_tap;
@@ -90,4 +91,4 @@ private:
void oscpu_space_map(address_map &map);
};
-#endif // MAME_BUS_VME_VME_HCPU30_H
+#endif // MAME_BUS_VME_HCPU30_H
diff --git a/src/devices/bus/vme/hk68v10.cpp b/src/devices/bus/vme/hk68v10.cpp
new file mode 100644
index 00000000000..afee4bd1988
--- /dev/null
+++ b/src/devices/bus/vme/hk68v10.cpp
@@ -0,0 +1,364 @@
+// license:BSD-3-Clause
+// copyright-holders:Joakim Larsson Edstrom
+/***************************************************************************
+ *
+ * Heurikon HK68/V10 6U SBC driver, initially derived from hk68v10.c
+ *
+ * 21/08/2015
+ *
+ * I bought this board from http://www.retrotechnology.com without documentation.
+ * It has a Motorola 68010 CPU @ 10MHz and two 2764 EPROMS with HBUG firmware
+ * The board is very populated and suitable to run a real server OS supported by
+ * FPU,MMU and DMA controller chips. The firmware supports SCSI, Centronics/FPI
+ * and a serial port. I have not found so much on the FPI interface yet and it is
+ * possibly Heurikon specific. There is also a Heurikon Multibus board called
+ * HK68/M10 for which I might add support from specs, however would need a ROM
+ * to verify.
+ *
+ * ||
+ * || ||
+ * ||||--||
+ * ||||--||
+ * || ||____________________________________________________________ ___
+ * || | | | 12 PALs 68/V-... | | | | | |_| |
+ * || | | 2 x | |74 |74 |74 |74 | | | |
+ * || | | 74273 | VS4-01 VM4-00 | 244 573 645 645 | | |
+ * \==||| |SCSI | | VS3-00 VM3-03 | | | | | | | |
+ * ||| | | | VS2-01 VM2-02 |___|___|___|___| | | |
+ * || |NCR | | VS1-00 VM1-01 | | | | | | |
+ * || | 8530| 2 x | VBX-00 VDB-00 |74 |74 |74 | | |VME|
+ * || | | 74245 | VI1-00 VI2-00 | 244 641 245 | | |
+ * || | | | (90 deg ccw) | | | | | |P1 |
+ * SCSI || |_____| |_____________________|___|___|___| | | |
+ * port || | | _________ _________________________________ | | |
+ * || | | | || |74 |PAL | | | | |
+ * || | | | || 5 x | 244 MP2| 2 x | | | |
+ * || |CIO | | MC68881 || 74373 | | -00| 74646| | | |
+ * || |paral| | FPU || | | | | | | |
+ * || |Z8536| |_________||_________________|_ _| | | |_| |
+ * ||| | | | | | | ------------ |___|
+ * /==||| | | | | | | | 3 PALs | |
+ * FSM || | | | MC68010 | MC68451 | MC68450 | | MP1-00 | |
+ * 1234 || | | | CPU | MMU | DMA | | MX2-00 | |
+ * LEDs || |-----| |_________|__________|_________|__| MX1-01 |---|
+ * || | | ____ ____ ---| |__________|74 |
+ * \==||| | | | | | | |74| 4 x | 3 PALs |145|
+ * ||| |SCC | | | | | |804 74245 | CS3-00 |___|
+ * FPI || |seria| |U12 | |U23 | | | | CS2-00 | |
+ * paralell |Z8530A |HBUG| |HBUG| | | | CS1-00 | |___
+ * port || | | | | | | ---_---------------|__________| _| |
+ * || | | | | | | |MTTLDL|MDLDM| 2 x |___________ | | |
+ * ||| | | |____|_|____|_|____40|TTL75|74280| | | | |
+ * /==||| | || |19. | | | | | |_____| | | | |
+ * \==||| |_____||75 |6608|16 |20 |74|74| ______| 9 x 4 | | | |
+ * ||| +--------+|173| MHz| MHz | MHz| 74 08| | | RAM chips| | |VME|
+ * || | ||___|____|_____|____|__|__||74 74 | on SIL | | | |
+ * || | 2 x || | | |259|257 boards | | |P2 |
+ * || | SIL || 12 PALs 90 deg ccw|74| -______- | | | |
+ * || | boards || |240 | | | | | | |
+ * || | with 2 || BER-00 FPI-01 | | |74 74 | | | | |
+ * Serial|| | DIP16 || AC4-00 ARB-01 |__|___|138|257 | | | |
+ * port || | surf || AC3-00 INT-00 |______| | | | |
+ * || | mounted|| AC2-01 IAK-00 | | | | | | |
+ * || | chips || AC1-01 PAS-01 |74 |74| | | | |
+ * || | each || RFS-01 |590|257 | | | |
+ * ||| | || RCT-01 | | | | |_| |
+ * /==||| +--------+|__________________________|___|__|__________| |___|
+ * || ||------------------------------------------------------------+-+
+ * ||||--||
+ * ||||--||
+ * ||
+ *
+ * History of Heurikon
+ *---------------------
+ * The company was founded 1972 as cellar company. Heurikon was acquired
+ * 1989 by Computer Products, 1990 by Artesyn and finally in 2005 by Emerson
+ * Electric who consolidated it fully by 2009 and closed the office.
+ *
+ * Misc links about Heurikon and this board:
+ * http://www.heurikon.com/
+ * http://www.nytimes.com/1992/01/07/business/company-news-briefs.html
+ * http://bitsavers.informatik.uni-stuttgart.de/pdf/heurikon/brochures/HK68_V10_Brochure.pdf
+ * http://bitsavers.informatik.uni-stuttgart.de/pdf/heurikon/Heurikon_UNIX_System_V_and_V.2_Reference_Guide_Apr87.pdf
+ * From http://www.iri.tudelft.nl/~sfwww/manuals/OS9/PDF/9OM_30.pdf:
+ * "In most cases, you will only need to change the device base address. Some hardware implementations of the MC68451
+ * (specifically the Heurikon M10/V10 CPU's) use the DMA portion of the Address Space Table (AST) instead of the MPU
+ * section which is normally used. You should change the offsets for the AST registers to match your hardware. The
+ * ssmdefs.a file has conditional directives to accommodate either the standard or Heurikon style implementations."
+ *
+ * Address Map from the UNIX Ref Guide
+ * --------------------------------------------------------------------------
+ * Address Range Memory Space (physical) Notes
+ * --------------------------------------------------------------------------
+ * 0xffffff (top of memory)
+ * 0xffc200 0xffc220 Sky FFP 68881 FPU
+ * 0xff8000 ... MCT Reel-to-reel tape (V10) VME
+ * 0xff0000 0xff0100 Tapemaster(00B0,00B1) Reel-to-reel tape (M10) Multibus
+ * Ethernet(0010,0011)
+ * 0xff0000 (base of bus I/O)
+ *
+ * 0xfea000 SCC8530 device
+ * 0xfe9000 offset 6 seems also to be 2 access registers, ie register offset + data pairs
+ * 0xfe8000 offset E reading single byte
+ * 0xfe4000 front LED:s? or move ROM from 0x0 to 0xfc0000...
+ * 0xfe2000 cleared
+ * 0xfe0000 HK68 On-card I/O MMU, DMAC, SCC, SCSI
+ * 0xfc0000 HK68 ROM (128K) Hbug monitor
+ * 0xf00000 (reserved)
+ * (shared memory and logical area
+ * for shared text.)
+ * 0x800000 (Twilight Zone) (top of /dev/mem)
+ * 0x7c0000 (reserved)
+ * 0x780000 8 Chnl serial Expn(1-4) (CDC)
+ * HK68 (1-15) VRTX
+ * MLZ-93 (1-4) CP/M Shell
+ * 0x700000
+ * (open)
+ * 0x*00000 (maxmeml)
+ * RAM (bus) (optional)
+ * 0x200000 (top of 2 meg RAM)
+ * RAM (bus) (optional)
+ * 0x100000 (top of 1 meg RAM)
+ * User RAM
+ * 0x001000 UNIX Kernel
+ * Exception Vectors
+ * 0x000000 (bottom of memory)
+ * --------------------------------------------------------------------------
+ *
+ * Interrupt sources M10/V10
+ * ----------------------------------------------------------
+ * Description Device Lvl IRQ VME board
+ * /Board Vector Address
+ * ----------------------------------------------------------
+ * On board Sources M10/V10
+ *
+ * Off board Sources (other VME boards)
+ * EXOS Ethernet 5 4
+ * TapeMaster Reel-to-Reel Tape 3
+ * MCT Reel-to-Reel Tape 5
+ * CDC MB1031 Serial Expansion 2 2
+ * IT 2190 SMD Interface 1 3
+ * IT 3200 SMD Interface 3
+ * ----------------------------------------------------------
+ *
+ * DMAC Channel Assignments
+ * ----------------------------------------------------------
+ * Channel M10 V10
+ * ----------------------------------------------------------
+ * 0 SCSI SCSI
+ * 1 Streamer (P3) n/a
+ * 2 n/a n/a
+ * 3 SBX-FDIO n/a
+ * ----------------------------------------------------------
+ *
+ * TODO:
+ * - Add VME bus driver
+ * - Add DMA/MMU devices
+ * - Add CIO port
+ * - ADD SCSI controller device
+ * - dump PALs and describe descrete logic
+ * - Add LED:s
+ * - Add Jumpers and strap areas
+ * - Find and Boot Heurikon Unix from a SCSI device
+ * - Support that optional 68881 FPU
+ *
+ ****************************************************************************/
+
+#include "emu.h"
+#include "hk68v10.h"
+
+#include "cpu/m68000/m68010.h"
+#include "machine/z8536.h"
+#include "bus/rs232/rs232.h"
+#include "machine/clock.h"
+
+#define VERBOSE 0
+
+#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
+
+#if VERBOSE == 2
+#define logerror printf
+#endif
+
+#ifdef _MSC_VER
+#define FUNCNAME __func__
+#else
+#define FUNCNAME __PRETTY_FUNCTION__
+#endif
+
+#define BAUDGEN_CLOCK 19.6608_MHz_XTAL /* Raltron */
+#define SCC_CLOCK (BAUDGEN_CLOCK / 4) /* through a 74LS393 counter */
+
+DEFINE_DEVICE_TYPE(VME_HK68V10, vme_hk68v10_card_device, "hk68v10", "Heurikon HK68/V10")
+
+vme_hk68v10_card_device::vme_hk68v10_card_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, VME_HK68V10, tag, owner, clock)
+ , device_vme_card_interface(mconfig, *this)
+ , m_maincpu(*this, "maincpu")
+ , m_sccterm(*this, "scc")
+ , m_eprom(*this, "eprom")
+ , m_ram(*this, "ram")
+ //,m_cart(*this, "exp_rom1")
+{
+}
+
+void vme_hk68v10_card_device::hk68v10_mem(address_map &map)
+{
+ map.unmap_value_high();
+ map(0x000000, 0x1fffff).ram().share("ram"); /* 2 Mb RAM */
+ map(0xfc0000, 0xfdffff).rom().region("eprom", 0); /* System EPROM Area 128Kb HBUG */
+ map(0xFE9000, 0xFE9007).rw("cio", FUNC(z8536_device::read), FUNC(z8536_device::write)).umask16(0xff00);
+ map(0xfea000, 0xfea000).rw(m_sccterm, FUNC(scc8530_device::ca_r), FUNC(scc8530_device::ca_w)); /* Dual serial port Z80-SCC */
+ map(0xfea002, 0xfea002).rw(m_sccterm, FUNC(scc8530_device::cb_r), FUNC(scc8530_device::cb_w)); /* Dual serial port Z80-SCC */
+ map(0xfea004, 0xfea004).rw(m_sccterm, FUNC(scc8530_device::da_r), FUNC(scc8530_device::da_w)); /* Dual serial port Z80-SCC */
+ map(0xfea006, 0xfea006).rw(m_sccterm, FUNC(scc8530_device::db_r), FUNC(scc8530_device::db_w)); /* Dual serial port Z80-SCC */
+ //map(0x100000, 0xfeffff).rw(FUNC(vme_hk68v10_card_device::vme_a24_r), FUNC(vme_hk68v10_card_device::vme_a24_w)); /* VMEbus Rev B addresses (24 bits) - not verified */
+ //map(0xff0000, 0xffffff).rw(FUNC(vme_hk68v10_card_device::vme_a16_r), FUNC(vme_hk68v10_card_device::vme_a16_w)); /* VMEbus Rev B addresses (16 bits) - not verified */
+}
+
+/* Input ports */
+static INPUT_PORTS_START (hk68v10)
+INPUT_PORTS_END
+
+/* Start it up */
+void vme_hk68v10_card_device::device_start ()
+{
+ LOG(("%s\n", FUNCNAME));
+}
+
+void vme_hk68v10_card_device::device_reset ()
+{
+ LOG(("%s\n", FUNCNAME));
+
+ m_maincpu->space(AS_PROGRAM).install_rom(0, m_eprom->bytes() - 1, m_eprom->base());
+
+ m_boot_mph = m_maincpu->space(AS_PROGRAM).install_read_tap(0x000006, 0x000007, "boot",
+ [this](offs_t offset, uint16_t &data, uint16_t mem_mask)
+ {
+ if (!machine().side_effects_disabled() && ACCESSING_BITS_0_7)
+ {
+ m_maincpu->space(AS_PROGRAM).install_ram(0, m_ram.bytes() - 1, m_ram.target());
+ m_boot_mph.remove();
+ }
+ });
+}
+
+#if 0
+/* Dummy VME access methods until the VME bus device is ready for use */
+uint16_t vme_hk68v10_card_device::vme_a24_r(){
+ LOG(("%s\n", FUNCNAME));
+ return (uint16_t) 0;
+}
+
+void vme_hk68v10_card_device::vme_a24_w(uint16_t data){
+ LOG(("%s\n", FUNCNAME));
+}
+
+uint16_t vme_hk68v10_card_device::vme_a16_r(){
+ LOG(("%s\n", FUNCNAME));
+ return (uint16_t) 0;
+}
+
+void vme_hk68v10_card_device::vme_a16_w(uint16_t data){
+ LOG(("%s\n", FUNCNAME));
+}
+#endif
+
+/*
+ * Serial port clock source depends on the CPU clock and divider settings
+ * HBUG has a control byte that needs to be patched accordingly:
+ *
+ * CPU clock SCC clock Baud rate offset 0x0b value
+ * 10 Mhz 4.9152MHz 9600 15
+ * 10 Mhz 4.9152MHz 19200 55
+ * 12 Mhz 4.9152MHz 9600 16
+ * 12 Mhz 4.9152MHz 19200 56
+ *
+ * Configuration word detail:
+ * D15-D8 reserved ( = 0 )
+ * D7(MSB) = 0
+ * D6 = 0 for console default 9600 baud
+ * D6 = 1 for console default 19,200 baud
+ * D5,D4,D3,D2 = 0101 for 4.9152 Mhz SCC clock
+ * D1,DO
+ * 01 for 10 Mhz MPU clock
+ * D1,DO = 10 for 12 Mhz MPU clock
+ *
+ * Original HBUG configuration word: 0x003D = 0000 0000 0011 1101
+ */
+
+/*
+ * Machine configuration
+ */
+void vme_hk68v10_card_device::device_add_mconfig(machine_config &config)
+{
+ /* basic machine hardware */
+ M68010(config, m_maincpu, 10_MHz_XTAL);
+ m_maincpu->set_addrmap(AS_PROGRAM, &vme_hk68v10_card_device::hk68v10_mem);
+
+ Z8536(config, "cio", SCC_CLOCK);
+
+ /* Terminal Port config */
+ SCC8530N(config, m_sccterm, SCC_CLOCK);
+ m_sccterm->out_txda_callback().set("rs232trm", FUNC(rs232_port_device::write_txd));
+ m_sccterm->out_dtra_callback().set("rs232trm", FUNC(rs232_port_device::write_dtr));
+ m_sccterm->out_rtsa_callback().set("rs232trm", FUNC(rs232_port_device::write_rts));
+
+ rs232_port_device &rs232trm(RS232_PORT(config, "rs232trm", default_rs232_devices, "terminal"));
+ rs232trm.rxd_handler().set(m_sccterm, FUNC(scc8530_device::rxa_w));
+ rs232trm.cts_handler().set(m_sccterm, FUNC(scc8530_device::ctsa_w));
+}
+
+/* ROM definitions */
+ROM_START (hk68v10)
+ ROM_REGION16_BE (0x20000, "eprom", 0)
+
+ ROM_LOAD16_BYTE ("hk68kv10.u23.bin", 0x0001, 0x2000, CRC (632aa026) SHA1 (f2b1ed0cc38dfbeb1602c013e00757015400720d))
+ ROM_LOAD16_BYTE ("hk68kv10.u12.bin", 0x0000, 0x2000, CRC (f2d688e9) SHA1 (e68699965645f0ce53de47625163c3eb02c8b727))
+
+ /*
+ * System ROM information
+ *
+ * The ROMs contains HBUG v1.8, known commands from different sources:
+ *
+ * 'uc' Print HK68 Configuration
+ * 'um' Perform RAM test
+ * 'dm adrs' Display Memory
+ * 'sb adrs' Substitute Byte at adrs
+ * 'c adrs' Call Routine at adrs
+ * 'bw' Boot from Winchester
+ * 'bf' Boot from floppy (MIO, SBX-FDIO)
+ * 'bsf' Boot from floppy (SCSI)
+ * 'x' Display registers
+ *
+ * Setup sequence channel B
+ * :scc B Reg 04 <- 4c x16 clock, 2 stop bits, no parity
+ * :scc B Reg 05 <- ea Setting up the transmitter, Transmitter Enable 1, Transmitter Bits/Character 8, Send Break 0, RTS=1, DTR=1
+ * :scc B Reg 03 <- e1 Setting up the receiver, Receiver Enable 1, Auto Enables 1, Receiver Bits/Character 8
+ * :scc B Reg 09 <- 00 Master Interrupt Control - No reset 02 A&B: RTS=1 DTR=1 INT=0 Vector generated
+ * :scc B Reg 01 <- 00 Ext INT:0 Tx INT:0 Parity SC:0 Wait/Ready Enable:0 as Wait on Transmit, Rx INT:0
+ * :scc B Reg 0b <- 56 Clock Mode Control 55 Clock type TTL level on RTxC pin, RCV CLK=BRG, TRA CLK=BRG, TRxC pin is Output, TRxC CLK=BRG - not_implemented
+ * :scc B Reg 0c <- 0b Low byte of Time Constant for Baudrate generator -> 38400 baud
+ * :scc B Reg 0d <- 00 High byte of Time Constant for Baudrate generator
+ * :scc B Reg 0e <- 03 Misc Control Bits DPLL NULL Command, BRG enabled SRC=PCLK, BRG SRC bps=307200=PCLK 4915200/16, BRG OUT 9600=307200/16(32)
+ * Repeated for :scc A
+ * :scc B Reg 0c <- 0e Low byte of Time Constant for Baudrate generator -> 9600 baud
+ * :scc B Reg 0d <- 00 High byte of Time Constant for Baudrate generator
+ * Repeated for :scc A
+ */
+ROM_END
+
+
+const tiny_rom_entry *vme_hk68v10_card_device::device_rom_region() const
+{
+ return ROM_NAME(hk68v10);
+}
+
+ioport_constructor vme_hk68v10_card_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(hk68v10);
+}
+
+/* Driver */
+/* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS */
+//COMP( 1985, hk68v10, 0, 0, hk68v10, hk68v10, vme_hk68v10_card_device, empty_init, "Heurikon Corporation", "HK68/V10", MACHINE_NO_SOUND_HW )
diff --git a/src/devices/bus/vme/hk68v10.h b/src/devices/bus/vme/hk68v10.h
new file mode 100644
index 00000000000..4b7703ea880
--- /dev/null
+++ b/src/devices/bus/vme/hk68v10.h
@@ -0,0 +1,44 @@
+// license:BSD-3-Clause
+// copyright-holders:Joakim Larsson Edstrom
+
+#ifndef MAME_BUS_VME_HK68V10_H
+#define MAME_BUS_VME_HK68V10_H
+
+#pragma once
+
+#include "bus/vme/vme.h"
+#include "machine/z80scc.h"
+
+class vme_hk68v10_card_device
+ : public device_t
+ , public device_vme_card_interface
+{
+public:
+ vme_hk68v10_card_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual ioport_constructor device_input_ports() const override;
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+private:
+ //uint16_t vme_a24_r();
+ //void vme_a24_w(uint16_t data);
+ //uint16_t vme_a16_r();
+ //void vme_a16_w(uint16_t data);
+
+ void hk68v10_mem(address_map &map);
+
+ required_device<cpu_device> m_maincpu;
+ required_device<scc8530_device> m_sccterm;
+
+ required_memory_region m_eprom;
+ required_shared_ptr<uint16_t> m_ram;
+ memory_passthrough_handler m_boot_mph;
+};
+
+DECLARE_DEVICE_TYPE(VME_HK68V10, vme_hk68v10_card_device)
+
+#endif // MAME_BUS_VME_HK68V10_H
diff --git a/src/devices/bus/vme/vme_mvme120.cpp b/src/devices/bus/vme/mvme120.cpp
index 19ddaf9b391..f78076d44ad 100644
--- a/src/devices/bus/vme/vme_mvme120.cpp
+++ b/src/devices/bus/vme/mvme120.cpp
@@ -20,7 +20,7 @@
*/
#include "emu.h"
-#include "vme_mvme120.h"
+#include "mvme120.h"
#ifdef _MSC_VER
#define FUNCNAME __func__
@@ -28,18 +28,9 @@
#define FUNCNAME __PRETTY_FUNCTION__
#endif
-#define LOG_PRINTF (1U << 1)
-#define LOG_SETUP (1U << 2)
-#define LOG_GENERAL (1U << 3)
-
-#define VERBOSE (LOG_PRINTF | LOG_SETUP | LOG_GENERAL)
-
+#define VERBOSE (LOG_GENERAL)
#include "logmacro.h"
-#define LOGPRINTF(...) LOGMASKED(LOG_PRINTF, __VA_ARGS__)
-#define LOGSETUP(...) LOGMASKED(LOG_SETUP, __VA_ARGS__)
-#define LOGGENERAL(...) LOGMASKED(LOG_GENERAL, __VA_ARGS__)
-
// Clocks
#define MVME120_MASTER_CLOCK 20_MHz_XTAL
#define MVME120_CPU_CLOCK ( MVME120_MASTER_CLOCK / 2 )
@@ -50,10 +41,10 @@
#define MVME122_MFP_CLOCK ( MVME122_CPU_CLOCK / 4 )
// The four MVME12x card variants.
-DEFINE_DEVICE_TYPE(VME_MVME120, vme_mvme120_card_device, "mvme120", "Motorola MVME-120")
-DEFINE_DEVICE_TYPE(VME_MVME121, vme_mvme121_card_device, "mvme121", "Motorola MVME-121")
-DEFINE_DEVICE_TYPE(VME_MVME122, vme_mvme122_card_device, "mvme122", "Motorola MVME-122")
-DEFINE_DEVICE_TYPE(VME_MVME123, vme_mvme123_card_device, "mvme123", "Motorola MVME-123")
+DEFINE_DEVICE_TYPE(VME_MVME120, vme_mvme120_card_device, "mvme120", "Motorola MVME120")
+DEFINE_DEVICE_TYPE(VME_MVME121, vme_mvme121_card_device, "mvme121", "Motorola MVME121")
+DEFINE_DEVICE_TYPE(VME_MVME122, vme_mvme122_card_device, "mvme122", "Motorola MVME122")
+DEFINE_DEVICE_TYPE(VME_MVME123, vme_mvme123_card_device, "mvme123", "Motorola MVME123")
static INPUT_PORTS_START(mvme120)
PORT_START("S3")
@@ -264,7 +255,7 @@ void vme_mvme120_device::rom_shadow_tap(offs_t address, u16 data, u16 mem_mask)
}
}
-WRITE_LINE_MEMBER(vme_mvme120_device::watchdog_reset)
+void vme_mvme120_device::watchdog_reset(int state)
{
if(state)
{
@@ -273,7 +264,7 @@ WRITE_LINE_MEMBER(vme_mvme120_device::watchdog_reset)
}
}
-WRITE_LINE_MEMBER(vme_mvme120_device::mfp_interrupt)
+void vme_mvme120_device::mfp_interrupt(int state)
{
LOG("%s: MFP asserting interrupt\n", FUNCNAME);
diff --git a/src/devices/bus/vme/vme_mvme120.h b/src/devices/bus/vme/mvme120.h
index 0aeaa8d171d..5d221b0b3db 100644
--- a/src/devices/bus/vme/vme_mvme120.h
+++ b/src/devices/bus/vme/mvme120.h
@@ -1,11 +1,11 @@
// license:BSD-3-Clause
// copyright-holders:Katherine Rohl
-#ifndef MAME_BUS_VME_VME_MVME120_H
-#define MAME_BUS_VME_VME_MVME120_H
+#ifndef MAME_BUS_VME_MVME120_H
+#define MAME_BUS_VME_MVME120_H
#pragma once
-#include "cpu/m68000/m68000.h"
+#include "cpu/m68000/m68010.h"
#include "bus/vme/vme.h"
#include "bus/rs232/rs232.h"
#include "machine/clock.h"
@@ -81,8 +81,8 @@ protected:
void rom_shadow_tap(offs_t address, u16 data, u16 mem_mask);
- DECLARE_WRITE_LINE_MEMBER(watchdog_reset);
- DECLARE_WRITE_LINE_MEMBER(mfp_interrupt);
+ void watchdog_reset(int state);
+ void mfp_interrupt(int state);
const mvme12x_variant m_board_id;
};
@@ -150,4 +150,4 @@ protected:
virtual void device_add_mconfig(machine_config &config) override;
};
-#endif // MAME_BUS_VME_VME_MVME120_H
+#endif // MAME_BUS_VME_MVME120_H
diff --git a/src/devices/bus/vme/mvme147.cpp b/src/devices/bus/vme/mvme147.cpp
new file mode 100644
index 00000000000..64bb3ff3fdd
--- /dev/null
+++ b/src/devices/bus/vme/mvme147.cpp
@@ -0,0 +1,672 @@
+// license:BSD-3-Clause
+// copyright-holders:Joakim Larsson Edstrom
+/***************************************************************************
+ *
+ * Motorola MVME series of CPU boards: MVME-147
+ *
+ * 09/03/2016
+ *
+ * Thanks to Plamen Mihaylov and his site http://www.m88k.com/ I got the information
+ * required to start the work with this driver. The goal is to boot a tape through
+ * the MVME-350 device connected over a VME bus device.
+ *
+ *
+ * ||
+ * || || MVME-147
+ * ||||--||_____________________________________________________________
+ * ||||--|| +--------------+ +-------+ +--------------+ |
+ * || || | U22 147bug | | FPU | | VMEchip | _ |__
+ * Red C| DS1 | | | 68882 | | ASIC | | | |
+ * FAIL || +--------------+ | | | | | | |
+ * YellowC| DS2 | U30 147 bug | +-------+ | | | | |
+ * STAT || | | | | | | |
+ * Green C| DS3 +--------------+ | | | | |
+ * RUN || | | +--------------+ | | |
+ * Green C| DS4 | | +----------------+ | |VME|
+ * SCON || +--------------+ | FLEX 10K30AQ | | | |
+ * RMT RST= J4 | |+---------+| PLD | | |P1 |
+ * || | || || | | | |
+ * ABRT O== S1 +--------------+| || | | | |
+ * || | || | | | |
+ * RSET O== S2 | || | | | |
+ * || +---------+| | | | |
+ * || +----------------+ | | |
+ * || |_| |
+ * || +---------+ |___|
+ * || | | |
+ * || | | |
+ * || | | |
+ * || | | |
+ * || +---------+ |
+ * || |
+ * || |
+ * || |
+ * || |___
+ * || _| |
+ * || | | |
+ * || +------------+ | | |
+ * || | | | | |
+ * || | | | | |
+ * || | 7990 | | |VME|
+ * || | | | | |
+ * || | | | |P2 |
+ * || +------------+ | | |
+ * || | | |
+ * || +--------+ | | |
+ * || | | | | |
+ * || | 85C30 | | | |
+ * || | | | | |
+ * || +--------+ | | |
+ * || +--------+ | | |
+ * || | | |_| |
+ * || | 85C30 | |___|
+ * || || | | +
+ * ||||--|| +--------+ |
+ * ||||--||--------------------------------------------------------------+
+ * ||
+ *
+ * History of Motorola VME division (https://en.wikipedia.org/wiki/VMEbus)
+ *---------------------------------
+ * When Motorola released the 68000 processor 1979 the ambition of the deisgners
+ * was also to standardize a versatile CPU bus to be able to build computer
+ * systems without constructing PCB:s from scratch. This become VersaBus but the
+ * boards was really too big and the computer world already saw the systems shrink
+ * in size. Motorola's design center in Munich proposed to use the smaller and
+ * already used Euroboard form factor and call it Versabus-E. This later became
+ * VME which was standardized in the VITA organization 1981
+ *
+ * Misc links about Motorola VME division and this board:
+ * http://bitsavers.trailing-edge.com/pdf/motorola/_dataBooks/1987_Microcomputer_Systems_and_Components.pdf
+ * http://www.m88k.com/mvme147.html
+ *
+ * Description(s)
+ * -------------
+ * MVME-147 has the following feature set
+ * - 16, 25, or 33.33 MHz MC68030 enhanced 32-bit microprocessor
+ * - 16, 25, or 33.33 MHz MC68882 floating-point coprocessor
+ * - 4, 8, 16, or 32MB of shared DRAM, with programmable parity
+ * - 4K x 8 SRAM and time-of-day clock with battery backup (MK48T12)
+ * - Four 28/32-pin ROM/PROM/EPROM/EEPROM sockets, 16 bits wide
+ * - Double High (6U) VMEmodule
+ * - A32/D32 VMEbus master/slave interface with system controller function (VMEchip ASIC)
+ * - Four EIA-232-D serial communications ports (85C30 x 2)
+ * - Centronics compatible printer port ( PCC ASIC )
+ * - Two 16-bit timers and watchdog timer (PCC ASIC )
+ * - SCSI bus interface with DMA (WD33C93)
+ * - Ethernet transceiver interface (AM7990)
+ * - 4-level requester, 7-level interrupter, and 7-level interrupt handler for VMEbus (VMEchip ASIC)
+ *
+ * NOTE: This driver currently mimics the MVME147SRF configuration: 16MHz, 4Mb RAM, no parity, no ethernet (See TODO)
+ *
+ * Address Map
+ * --------------------------------------------------------------------------
+ * Decscription
+ * --------------------------------------------------------------------------
+ * 00000000 Boot ROM (4 cycles)/Onboard DRAM + VMEbus A32/A24 D32
+ * F0000000 VMEbus (A24 D16)
+ * F1000000 VMEbus (A32 D16)
+ * FF800000 ROM/EEPROM bank 1 D16
+ * FFA00000 ROM/EEPROM bank 2 D16
+ * FFC00000 reserved
+ * ------------------------ Local I/O devices D8/D16/D32
+ * FFFE0000-FFFE07F7 BB RAM D8 2040 bytes
+ * FFFE07F8-FFFE07FF BB TOD clock D8 8 bytes
+ * FFFE1000-FFFE100F PCC 32-bit registers D32 16 bytes
+ * FFFE1010-FFFE102F PCC 16-bit registers D16 32 bytes
+ * FFFE1800-FFFE1803 LANCE (AM7990) D16 4 bytes
+ * FFFE2000-FFFE201F VMEchip registers D16 32 bytes
+ * FFFE2800 Printer data (write only) D8
+ * FFFE2800 Printer status (read only) D8
+ * FFFE3000-FFFE3001 Serial 2 D8 2 bytes - 85C30
+ * FFFE3002-FFFE3003 Serial 1 D8 2 bytes
+ * FFFE3800-FFFE3801 Serial 4 D8 2 bytes - 85C30
+ * FFFE3802-FFFE3803 Serial 3 D8 2 bytes
+ * FFFE4000-FFFE401F SCSI registers (WD33C93) D8 32 bytes
+ * FFE50000 reserved
+ * FFFF0000 VMEbux short I/O D16
+ * --------------------------------------------------------------------------
+ *
+ * Interrupt sources MVME
+ * ----------------------------------------------------------
+ * Description Device Lvl IRQ VME board
+ * /Board Vector Address
+ * ----------------------------------------------------------
+ * On board Sources
+ *
+ * Off board Sources (other VME boards)
+ *
+ * ----------------------------------------------------------
+ *
+ * DMAC Channel Assignments
+ * ----------------------------------------------------------
+ * Channel MVME147
+ * ----------------------------------------------------------
+ *
+ *
+ * TODO:
+ * - Pass 147bug bootup tests
+ * - Add VME bus driver
+ * - Hook up MVME350
+ * - Get a tape file with a bootable data on it.
+ * - Add variants of boards, preferably as runtime configurations
+ *
+ ****************************************************************************/
+
+#include "emu.h"
+#include "mvme147.h"
+
+#include "cpu/m68000/m68030.h"
+#include "bus/rs232/rs232.h"
+#include "machine/clock.h"
+#include "machine/timekpr.h"
+
+#define VERBOSE (0) // (LOG_GENERAL)
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+
+#ifdef _MSC_VER
+#define FUNCNAME __func__
+#else
+#define FUNCNAME __PRETTY_FUNCTION__
+#endif
+
+
+/* from documentation: http://www.m88k.com/Docs/147/147aih.pdf but crystal and divider not known */
+#define BAUDGEN_CLOCK 5_MHz_XTAL
+#define SCC_CLOCK (BAUDGEN_CLOCK) /* This gives prompt at the RS232 terminal device (9600) */
+
+
+DEFINE_DEVICE_TYPE(VME_MVME147, vme_mvme147_card_device, "mvme147", "Motorola MVME147")
+
+vme_mvme147_card_device::vme_mvme147_card_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, VME_MVME147, tag, owner, clock)
+ , device_vme_card_interface(mconfig, *this)
+ , m_maincpu (*this, "maincpu")
+ , m_sccterm(*this, "scc")
+ , m_sccterm2(*this, "scc2")
+ , m_system(*this, "system")
+ , m_ram(*this, "ram")
+{
+}
+
+void vme_mvme147_card_device::mvme147_mem(address_map &map)
+{
+ map.unmap_value_high();
+ map(0x00000008, 0x003fffff).ram().share("ram"); /* 4 Mb RAM */
+ map(0xff800000, 0xff83ffff).rom().region("system", 0).mirror(0x1c0000); //mirror(0x00780000); /* ROM/EEPROM bank 1 - 147bug */
+ //map(0xffa00000, 0xffbfffff).rom().region("user", 0); //mirror(0x00780000); /* ROM/EEPROM bank 2 - unpopulated */
+
+ /* SGS-Thompson M48T18 RAM and clock chip, only 4088 bytes used, and 8 bytes for the RTC, out of 8Kb though */
+ map(0xfffe0000, 0xfffe0fff).rw("m48t18", FUNC(timekeeper_device::read), FUNC(timekeeper_device::write));
+
+ //map(0xfffe1000, 0xfffe100f).rw(FUNC(vme_mvme147_card_device::pcc32_r), FUNC(vme_mvme147_card_device::pcc32_w)); /* PCC 32 bits registers - needs U64 cast defined to work */
+ map(0xfffe1010, 0xfffe1017).rw(FUNC(vme_mvme147_card_device::pcc16_r), FUNC(vme_mvme147_card_device::pcc16_w)); /* PCC 16 bits registers */
+ map(0xfffe1018, 0xfffe102f).rw(FUNC(vme_mvme147_card_device::pcc8_r), FUNC(vme_mvme147_card_device::pcc8_w)); /* PCC 8 bits registers */
+ map(0xfffe2000, 0xfffe201b).rw(FUNC(vme_mvme147_card_device::vmechip_r), FUNC(vme_mvme147_card_device::vmechip_w)).umask32(0x00ff00ff); /* VMEchip 8 bits registers on odd adresses */
+
+ map(0xfffe3000, 0xfffe3003).rw(m_sccterm, FUNC(scc85c30_device::ab_dc_r), FUNC(scc85c30_device::ab_dc_w)); /* Port 1&2 - Dual serial port Z80-SCC */
+ map(0xfffe3800, 0xfffe3803).rw(m_sccterm2, FUNC(scc85c30_device::ab_dc_r), FUNC(scc85c30_device::ab_dc_w)); /* Port 3&4 - Dual serial port Z80-SCC */
+
+ //map(0x100000, 0xfeffff).rw(FUNC(vme_mvme147_card_device::vme_a24_r), FUNC(vme_mvme147_card_device::vme_a24_w)); /* VMEbus Rev B addresses (24 bits) - not verified */
+ //map(0xff0000, 0xffffff).rw(FUNC(vme_mvme147_card_device::vme_a16_r), FUNC(vme_mvme147_card_device::vme_a16_w)); /* VMEbus Rev B addresses (16 bits) - not verified */
+}
+
+/* Input ports */
+static INPUT_PORTS_START (mvme147)
+INPUT_PORTS_END
+
+/* Start it up */
+void vme_mvme147_card_device::device_start ()
+{
+ LOG("%s\n", FUNCNAME);
+
+ m_genpurp_stat = 0x02; /* Indicate power up reset */
+ m_vc_cntl_conf = 0x01; /* We are the system controller */
+}
+
+void vme_mvme147_card_device::device_reset ()
+{
+ LOG("%s\n", FUNCNAME);
+
+ m_maincpu->space(AS_PROGRAM).install_rom(0, m_system->bytes() - 1, m_system->base());
+
+ m_boot_mph = m_maincpu->space(AS_PROGRAM).install_read_tap(0x000004, 0x000007, "boot",
+ [this](offs_t offset, uint32_t &data, uint32_t mem_mask)
+ {
+ if (!machine().side_effects_disabled() && ACCESSING_BITS_0_15)
+ {
+ m_maincpu->space(AS_PROGRAM).install_ram(0, m_ram.bytes() - 1, m_ram.target());
+ m_boot_mph.remove();
+ }
+ });
+
+ m_genpurp_stat &= 0xfe; /* Clear parity error bit - not used by MAME at this point so just for the record */
+}
+
+/****
+ * PCC - Peripheral Channel Controller driver, might deserve its own driver but will rest here until another board wants it
+ */
+#if 0 /* Doesn't compile atm */
+uint32_t vme_mvme147_card_device::pcc32_r(offs_t offset){
+ LOG("%s[%04x]", FUNCNAME, offset);
+ switch(offset)
+ {
+ default:
+ LOG(" - unsupported register\n");
+ }
+ return 0x00;
+}
+
+void vme_mvme147_card_device::pcc32_w(offs_t offset, uint32_t data){
+ LOG("%s[%04x]= %08lx", FUNCNAME, offset, data);
+ switch(offset)
+ {
+ default:
+ LOG("- unsupported register\n");
+ }
+}
+#endif
+
+#define P16BASE 0xfffe1010
+#define P16_TIMER1_PRELOAD (P16BASE)
+#define P16_TIMER1_COUNT (P16BASE + 2)
+#define P16_TIMER2_PRELOAD (P16BASE + 4)
+#define P16_TIMER2_COUNT (P16BASE + 6)
+
+uint16_t vme_mvme147_card_device::pcc16_r(offs_t offset){
+ uint16_t ret = 0;
+
+ LOG("Call to %s[%04x]", FUNCNAME, offset);
+ switch(offset)
+ {
+ case P16_TIMER1_PRELOAD - P16BASE : LOG(" -> %02x Timer 1 preload - not implemented\n", ret); break;
+ case P16_TIMER1_COUNT - P16BASE : LOG(" -> %02x Timer 1 count - not implemented\n", ret); break;
+ case P16_TIMER2_PRELOAD - P16BASE : LOG(" -> %02x Timer 2 preload - not implemented\n", ret); break;
+ case P16_TIMER2_COUNT - P16BASE : LOG(" -> %02x Timer 2 count - not implemented\n", ret); break;
+ default:
+ LOG(" -> %02x unsupported register\n", ret);
+ }
+ return ret;
+}
+
+void vme_mvme147_card_device::pcc16_w(offs_t offset, uint16_t data){
+ LOG("Call to %s[%04x] <- %04x - ", FUNCNAME, offset, data);
+ switch(offset)
+ {
+ case P16_TIMER1_PRELOAD - P16BASE : LOG("Timer 1 preload - not implemented\n"); break;
+ case P16_TIMER1_COUNT - P16BASE : LOG("Timer 1 count - not implemented\n"); break;
+ case P16_TIMER2_PRELOAD - P16BASE : LOG("Timer 2 preload - not implemented\n"); break;
+ case P16_TIMER2_COUNT - P16BASE : LOG("Timer 2 count - not implemented\n"); break;
+ default:
+ LOG("unsupported register\n");
+ }
+}
+
+#define P8BASE 0xfffe1018
+#define P8_TIMER1_INT_CNTL 0xfffe1018
+#define P8_TIMER1_CNTL 0xfffe1019
+#define P8_TIMER2_INT_CNTL 0xfffe101A
+#define P8_TIMER2_CNTL 0xfffe101B
+#define P8_ACFAIL_INT_CNTL 0xfffe101C
+#define P8_WDOG_TIMER_CNTL 0xfffe101D
+#define P8_PRINTER_INT_CNTL 0xfffe101E
+#define P8_PRINTER_CNTL 0xfffe101F
+#define P8_DMA_INT_CNTL 0xfffe1020
+#define P8_DMA_CNTL_STAT 0xfffe1021
+#define P8_BUSERR_CNTL 0xfffe1022
+#define P8_DMA_STATUS 0xfffe1023
+#define P8_ABORT_INT_CNTL 0xfffe1024
+#define P8_TABADD_FC_CNTL 0xfffe1025
+#define P8_SERIAL_INT_CNTL 0xfffe1026
+#define P8_GEN_PURP_CNTL 0xfffe1027
+#define P8_LAN_INT_CNTL 0xfffe1028
+#define P8_GEN_PURP_STAT 0xfffe1029
+#define P8_SCSI_INT_CNTL 0xfffe102A
+#define P8_SLAVE_BASE_ADDR 0xfffe102B
+#define P8_SWI_1_CNTL 0xfffe102C
+#define P8_INT_VECT_BASE 0xfffe102D
+#define P8_SWI_2_CNTL 0xfffe102E
+#define P8_REVISION_LEVEL 0xfffe102F
+#define P8_PRINTER_DATA 0xfffe2800
+#define P8_PRINTER_STATUS 0xfffe2800
+
+uint8_t vme_mvme147_card_device::pcc8_r(offs_t offset){
+ uint8_t ret = 0;
+
+ LOG("Call to %s[%04x] ", FUNCNAME, offset);
+ switch(offset + P8BASE)
+ {
+ case P8_TIMER1_INT_CNTL : LOG(" -> %02x - Timer 1 Interrupt Control - not implemented\n", ret); break;
+ case P8_TIMER1_CNTL : LOG(" -> %02x - Timer 1 Control - not implemented\n", ret); break;
+ case P8_TIMER2_INT_CNTL : LOG(" -> %02x - Timer 2 Interrupt Control - not implemented\n", ret); break;
+ case P8_TIMER2_CNTL : LOG(" -> %02x - Timer 2 Control - not implemented\n", ret); break;
+ case P8_ACFAIL_INT_CNTL : LOG(" -> %02x - AC Fail Interrupt Control Register - not implemented\n", ret); break;
+ case P8_WDOG_TIMER_CNTL : LOG(" -> %02x - Watchdog Timer Control Register - not implemented\n", ret); break;
+ case P8_PRINTER_INT_CNTL : LOG(" -> %02x - Printer Interrupt Control Register - not implemented\n", ret); break;
+ case P8_PRINTER_CNTL : LOG(" -> %02x - Printer Control Register - not implemented\n", ret); break;
+ case P8_DMA_INT_CNTL : LOG(" -> %02x - DMA Interrupt Control Register - not implemented\n", ret); break;
+ case P8_DMA_CNTL_STAT : LOG(" -> %02x - DMA Control and Status Register - not implemented\n", ret); break;
+ case P8_BUSERR_CNTL : LOG(" -> %02x - Bus Error Interrupt Control Register - not implemented\n", ret); break;
+ case P8_DMA_STATUS : LOG(" -> %02x - DMA Status Register - not implemented\n", ret); break;
+ case P8_ABORT_INT_CNTL : LOG(" -> %02x - Abort Interrupt Control Register - not fully implemented\n", ret);
+ /* Bit 3 When this bit is high, the interrupt is enabled. The interrupt is disabled when this bit is low. This bit is cleared by reset.
+ Bit 6 This bit indicates the current state of the ABORT switch. When this bit is low, the ABORT switch is not pressed. When this bit is
+ high, the ABORT switch is pressed.
+ Bit 7 When this bit is high, an abort interrupt is being generated at Level 7. This bit is edge sensitive and it is set on the leading
+ edge of interrupt enable and abort. This bit is cleared when a 1 is written to it or when the interrupt is disabled. When cleared,
+ it remains cleared until the next leading edge of interrupt enable and abort. This bit is cleared by reset. */
+ ret = 0; /* Always return reset values for now */
+ break;
+ case P8_TABADD_FC_CNTL : LOG(" -> %02x - Table Address Function Code Register - not implemented\n", ret); break;
+ case P8_SERIAL_INT_CNTL : LOG(" -> %02x - Serial Port Interrupt Control Register - not implemented\n", ret); break;
+ case P8_GEN_PURP_CNTL : LOG(" -> %02x - General Purpose Control Register - not implemented\n", ret); break;
+ case P8_LAN_INT_CNTL : LOG(" -> %02x - LAN Interrupt Control Register - not implemented\n", ret); break;
+ case P8_GEN_PURP_STAT : LOG(" -> %02x - General Purpose Status Register\n", ret);
+ ret = m_genpurp_stat;
+ break;
+ case P8_SCSI_INT_CNTL : LOG(" -> %02x - SCSI Port Interrupt Control Register - not implemented\n", ret); break;
+ case P8_SLAVE_BASE_ADDR : LOG(" -> %02x - Slave Base Address Register - not implemented\n", ret); break;
+ case P8_SWI_1_CNTL : LOG(" -> %02x - Software Interrupt 1 Control Register - not implemented\n", ret); break;
+ case P8_INT_VECT_BASE : LOG(" -> %02x - Interrupt Vector Base - not implemented\n", ret); break;
+ case P8_SWI_2_CNTL : LOG(" -> %02x - Software Interrupt 2 Control Register - not implemented\n", ret); break;
+ case P8_REVISION_LEVEL : LOG(" -> %02x - PCC Revision Level Register - not implemented\n", ret); break;
+ case P8_PRINTER_STATUS : LOG(" -> %02x - Printer Status Register - not implemented\n", ret); break;
+ default:
+ LOG(" -> %02x - unsupported register\n", ret);
+ }
+ return ret;
+}
+
+void vme_mvme147_card_device::pcc8_w(offs_t offset, uint8_t data){
+ LOG("Call to %s[%04x] <- %02x - ", FUNCNAME, offset, data);
+ switch(offset + P8BASE)
+ {
+ case P8_TIMER1_INT_CNTL : LOG("Timer 1 Interrupt Control - not implemented\n"); break;
+ case P8_TIMER1_CNTL : LOG("Timer 1 Control - not implemented\n"); break;
+ case P8_TIMER2_INT_CNTL : LOG("Timer 2 Interrupt Control - not implemented\n"); break;
+ case P8_TIMER2_CNTL : LOG("Timer 2 Control - not implemented\n"); break;
+ case P8_ACFAIL_INT_CNTL : LOG("AC Fail Interrupt Control Register - not implemented\n"); break;
+ case P8_WDOG_TIMER_CNTL : LOG("Watchdog Timer Control Register - not implemented\n"); break;
+ case P8_PRINTER_INT_CNTL: LOG("Printer Interrupt Control Register - not implemented\n"); break;
+ case P8_PRINTER_CNTL : LOG("Printer Control Register - not implemented\n"); break;
+ case P8_DMA_INT_CNTL : LOG("DMA Interrupt Control Register - not implemented\n"); break;
+ case P8_DMA_CNTL_STAT : LOG("DMA Control and Status Register - not implemented\n"); break;
+ case P8_BUSERR_CNTL : LOG("Bus Error Interrupt Control Register - not implemented\n"); break;
+ case P8_DMA_STATUS : LOG("DMA Status Register - not implemented\n"); break;
+ case P8_ABORT_INT_CNTL : LOG("Abort Interrupt Control Register - not implemented\n"); break;
+ case P8_TABADD_FC_CNTL : LOG("Table Address Function Code Register - not implemented\n"); break;
+ case P8_SERIAL_INT_CNTL : LOG("Serial Port Interrupt Control Register - not implemented\n"); break;
+ case P8_GEN_PURP_CNTL : LOG("General Purpose Control Register - not implemented\n");
+ /*Bits 0-1 These bits control local RAM parity checking. These bits should not be enabled on the MVME147-010.
+ These bits are cleared by reset. x0 = parity disabled, x1 = parity enabled
+ Bit 2 This bit is used to test the parity generating and checking logic. When this bit is low, correct parity is written to the DRAM;
+ when high, incorrect parity is written to the DRAM. This bit is cleared by reset.
+ NOTE: We really don't care about DRAM parity!
+ Bit 3 When set, this bit is used to enable the local bus timer that is part of the PCC. Because the VMEchip also contains a local bus
+ timer, this bit should be cleared, turning off the PCC local bus timer. This bit is cleared by reset.
+ Bit 4 This bit is the master interrupt enable. When this bit is low, all interrupts on the MVME147 are disabled; when high, all
+ interrupts are enabled. This bit is cleared by reset
+ Bits 5-7 When the pattern %101 is written to these bits, the front panel RESET switch is disabled. The RESET switch is enabled for any
+ other pattern. These bits are cleared by reset.
+ TODO: Bit 4-7 needs to be implemented
+ */
+ break;
+ case P8_LAN_INT_CNTL : LOG("LAN Interrupt Control Register - not implemented\n"); break;
+ case P8_GEN_PURP_STAT : LOG("General Purpose Status Register\n");
+ /* Bit 0 This bit is set when a parity error occurs while the local processor is accessing RAM. This bit is cleared by writing a 1 to it.
+ This bit is cleared by reset.
+ Bit 1 This bit is set when a power-up reset occurs. It is cleared by writing a 1 to it.
+ When the MVME147BUG is installed, its initialization code clears this bit.
+ */
+ m_genpurp_stat &= ((data & 1) ? ~1 : 0xff); // Check if parity error bit needs to be cleared
+ m_genpurp_stat &= ((data & 2) ? ~2 : 0xff); // Check if power up reset bit needs to be cleared
+ break;
+ case P8_SCSI_INT_CNTL : LOG("SCSI Port Interrupt Control Register - not implemented\n"); break;
+ case P8_SLAVE_BASE_ADDR : LOG("Slave Base Address Register - not implemented\n"); break;
+ case P8_SWI_1_CNTL : LOG("Software Interrupt 1 Control Register - not implemented\n"); break;
+ case P8_INT_VECT_BASE : LOG("Interrupt Vector Base - not implemented\n"); break;
+ case P8_SWI_2_CNTL : LOG("Software Interrupt 2 Control Register - not implemented\n"); break;
+ case P8_REVISION_LEVEL : LOG("PCC Revision Level Register - not implemented\n"); break;
+ case P8_PRINTER_DATA : LOG("Printer Data Register - not implemented\n"); break;
+ default:
+ LOG("unsupported register\n");
+ }
+}
+
+/*
+ * VMEchip ASIC driver, might deserve its own driver but will rest here until another board wants it
+ */
+#define VCBASE 0xfffe2001
+#define VC_SYS_CNTL_CONF 0xfffe2001
+#define VC_VMEBUS_REQ_CONF 0xfffe2003
+#define VC_MASTER_CONF 0xfffe2005
+#define VC_SLAVE_CONF 0xfffe2007
+#define VC_TIMER_CONF 0xfffe2009
+#define VC_SLAVE_ADR_MOD 0xfffe200B
+#define VC_MASTER_ADR_MOD 0xfffe200D
+#define VC_INT_HNDL_MASK 0xfffe200F
+#define VC_UTIL_INT_MASK 0xfffe2011
+#define VC_UTIL_INT_VECT 0xfffe2013
+#define VC_INT_REQUEST 0xfffe2015
+#define VC_VMEBUS_STAT_ID 0xfffe2017
+#define VC_BUS_ERR_STATUS 0xfffe2019
+#define VC_GCSR_BASE_ADR 0xfffe201B
+
+
+uint8_t vme_mvme147_card_device::vmechip_r(offs_t offset){
+ uint8_t ret = 0;
+
+ LOG("Call to %s[%04x] ", FUNCNAME, offset);
+ switch(offset * 2 + VCBASE)
+ {
+ case VC_SYS_CNTL_CONF :
+ LOG(" -> %02x - System Controller Configuration Register - not implemented\n", ret);
+ ret = m_vc_cntl_conf;
+ break;
+ case VC_VMEBUS_REQ_CONF :
+ /*
+ Bits 0-1 These control bits configure the VMEbus requester level as shown in the table below:
+ RQLEV1 RQLEV0 Level
+ 0 0 0
+ 0 1 1
+ 1 0 2
+ 1 1 3
+ These bits are set to 1, 1 by any reset. Note that writes to REQLEV1,0 do not change the actual
+ requester level until the MVME147 goes through the action of having VMEbus mastership and releasing it. This means that
+ there are times when the value written into REQLEV1,0 do not match the current requester level (the request level is lagging).
+ During such times, reads to REQLEV1,0 reflect the actual requester level, not the value written into REQLEV1,0.
+ Bit 3 Setting this bit to 1 prevents the requester from releasing the VMEbus. However, unlike the DWB control bit, setting the
+ RNEVER bit does not cause the requester to request the VMEbus. Clearing the RNEVER bit allows the requester to
+ relinquish the VMEbus in accordance with the other control bits of the requester configuration register.
+ This bit is cleared by any reset.
+ Bit 4 The RWD bit allows software to configure the requester release mode. When the bit is set, if RNEVER and DWB are both
+ cleared to 0, the requester releases the VMEbus after the MC68030 completes a VMEbus cycle. When the bit is cleared, if
+ RNEVER and DWB are both cleared to 0, the requester operates in the Release-On-Request (ROR) mode. After acquiring control
+ of the VMEbus, it maintains control until it detects another request pending on the VMEbus. This bit is cleared by any reset.
+ Bit 5 The RONR bit controls the manner in which the VMEchip requests the VMEbus. When the bit is set; anytime the
+ MVME147 has bus mastership, then gives it up, the VMEchip does not request the VMEbus again until it detects the bus
+ request signal BR*, on its level, negated for at least 150 ns. When the VMEchip detects BR* negated, it refrains from
+ driving it again for at least 200 ns. This bit is cleared by any reset.
+ Bit 6 The DHB status bit is 1 when the MVME147 is VMEbus master and 0 when it is not.
+ Bit 7 Setting the DWB control bit to 1 causes the VMEchip to request the VMEbus (if not already bus master). When VMEbus
+ mastership has been obtained, it is not relinquished until after the DWB and RNEVER bits are both cleared.
+ This bit is cleared by any reset.
+ */
+ ret = 1 << 6; /* Let BUG147 think we are bus master. TODO: Implement proper VME bus signalling */
+ LOG(" -> %02x - VMEbus Requester Configuration Register - not implemented\n", ret);
+ break;
+ case VC_MASTER_CONF : LOG(" -> %02x - Master Configuration Register - not implemented\n", ret); break;
+ case VC_SLAVE_CONF : LOG(" -> %02x - Slave Configuration Register - not implemented\n", ret); break;
+ case VC_TIMER_CONF : LOG(" -> %02x - Timer Configuration Register - not implemented\n", ret);
+ /*Bits 0-1 These two bits configure the local time-out period. They are set to 1 by any reset.
+ LBTO1 LBTO0 Time-Out Period
+ 0 0 102 microseconds
+ 0 1 205 microseconds
+ 1 0 410 microseconds
+ 1 1 Timer disabled
+ The local bus timer activates bus error to the MC68030 when it tries to access nonexistent locations in the local memory map
+ Bits 2-3 These two bits configure the VMEbus access time-out period. They are set to 1 by any reset.
+ ACTO1 ACTO0 Time-Out Period
+ 0 0 102 microseconds
+ 0 1 1.6 millisecond
+ 1 0 51 milliseconds
+ 1 1 Timer disabled
+ The VMEbus access timer activates bus error to the MC68030 (except on write posted time-outs) when the VMEchip is
+ unsuccessful in obtaining the VMEbus within the time-out period
+ Bits 4-5 These two bits configure the VMEbus global time-out period. VBTO1 is set to 1 and VBTO0 is cleared to 0 by SYSRESET.
+ VBTO1 VBTO0 Time-Out Period
+ 0 0 102 microseconds
+ 0 1 205 microseconds
+ 1 0 410 microseconds
+ 1 1 Timer disabled
+ The VMEbus global timer activates BERR* on the VMEbus.
+ Bit 6 Setting ARBTO to 1 enables the VMEbus arbitration timer. The VMEbus arbitration timer activates BBSY* if it is not activated
+ within 410 us after the MVME147 arbiter issues a bus grant. The timer deactivates BBSY* as specified in the VMEbus specification.
+ This causes the arbiter to arbitrate any pending requests for the bus. This bit is set to 1 by SYSRESET.
+ */
+ break;
+ case VC_SLAVE_ADR_MOD : LOG(" -> %02x - Slave Address Modifier Register - not implemented\n", ret); break;
+ case VC_MASTER_ADR_MOD : LOG(" -> %02x - Master Address Modifier Register - not implemented\n", ret); break;
+ case VC_INT_HNDL_MASK : LOG(" -> %02x - Interrupt Handler Mask Register - not implemented\n", ret); break;
+ case VC_UTIL_INT_MASK : LOG(" -> %02x - Utility Interrupt Mask Register - not implemented\n", ret); break;
+ case VC_UTIL_INT_VECT : LOG(" -> %02x - Utility Interrupt Vector Register - not implemented\n", ret); break;
+ case VC_INT_REQUEST : LOG(" -> %02x - Interrupt Request Register - not implemented\n", ret); break;
+ case VC_VMEBUS_STAT_ID : LOG(" -> %02x - VMEbus Status/ID Register - not implemented\n", ret); break;
+ case VC_BUS_ERR_STATUS : LOG(" -> %02x - Bus Error Status Register - not implemented\n", ret); break;
+ case VC_GCSR_BASE_ADR : LOG(" -> %02x - GCSR Base Address Configuration Register - not implemented\n", ret); break;
+ default:
+ LOG("unsupported register");
+ }
+ return ret;
+}
+
+void vme_mvme147_card_device::vmechip_w(offs_t offset, uint8_t data){
+ LOG("Call to %s[%04x] <- %02x - ", FUNCNAME, offset, data);
+ switch(offset * 2 + VCBASE)
+ {
+ case VC_SYS_CNTL_CONF :
+ LOG("System Controller Configuration Register - not implemented\n");
+ m_vc_cntl_conf = data & 0xff;
+ break;
+ case VC_VMEBUS_REQ_CONF : LOG("VMEbus Requester Configuration Register - not implemented\n"); break;
+ case VC_MASTER_CONF : LOG("Master Configuration Register - not implemented\n"); break;
+ case VC_SLAVE_CONF : LOG("Slave Configuration Register - not implemented\n"); break;
+ case VC_TIMER_CONF : LOG("Timer Configuration Register - not implemented\n"); break;
+ case VC_SLAVE_ADR_MOD : LOG("Slave Address Modifier Register - not implemented\n"); break;
+ case VC_MASTER_ADR_MOD : LOG("Master Address Modifier Register - not implemented\n"); break;
+ case VC_INT_HNDL_MASK : LOG("Interrupt Handler Mask Register - not implemented\n"); break;
+ case VC_UTIL_INT_MASK : LOG("Utility Interrupt Mask Register - not implemented\n"); break;
+ case VC_UTIL_INT_VECT : LOG("Utility Interrupt Vector Register - not implemented\n"); break;
+ case VC_INT_REQUEST : LOG("Interrupt Request Register - not implemented\n"); break;
+ case VC_VMEBUS_STAT_ID : LOG("VMEbus Status/ID Register - not implemented\n"); break;
+ case VC_BUS_ERR_STATUS : LOG("Bus Error Status Register - not implemented\n"); break;
+ case VC_GCSR_BASE_ADR : LOG("GCSR Base Address Configuration Register - not implemented\n"); break;
+ default:
+ LOG("unsupported register\n");
+ }
+}
+
+
+#if 0
+/* Dummy VME access methods until the VME bus device is ready for use */
+uint16_t vme_mvme147_card_device::vme_a24_r(){
+ LOG("%s\n", FUNCNAME);
+ return (uint16_t) 0;
+}
+
+void vme_mvme147_card_device::vme_a24_w(uint16_t data){
+ LOG("%s\n", FUNCNAME);
+}
+
+uint16_t vme_mvme147_card_device::vme_a16_r(){
+ LOG("%s\n", FUNCNAME);
+ return (uint16_t) 0;
+}
+
+void vme_mvme147_card_device::vme_a16_w(uint16_t data){
+ LOG("%s\n", FUNCNAME);
+}
+#endif
+
+/*
+ * Machine configuration
+ */
+void vme_mvme147_card_device::device_add_mconfig(machine_config &config)
+{
+ /* basic machine hardware */
+ M68030(config, m_maincpu, 16_MHz_XTAL);
+ m_maincpu->set_addrmap(AS_PROGRAM, &vme_mvme147_card_device::mvme147_mem);
+
+ M48T02(config, "m48t18", 0); /* t08 differs only in accepted voltage levels compared to t18 */
+
+ /* Terminal Port config */
+ SCC85C30(config, m_sccterm, SCC_CLOCK);
+ m_sccterm->out_txda_callback().set("rs232trm", FUNC(rs232_port_device::write_txd));
+ m_sccterm->out_dtra_callback().set("rs232trm", FUNC(rs232_port_device::write_dtr));
+ m_sccterm->out_rtsa_callback().set("rs232trm", FUNC(rs232_port_device::write_rts));
+
+ rs232_port_device &rs232trm(RS232_PORT(config, "rs232trm", default_rs232_devices, "terminal"));
+ rs232trm.rxd_handler().set(m_sccterm, FUNC(scc85c30_device::rxa_w));
+ rs232trm.cts_handler().set(m_sccterm, FUNC(scc85c30_device::ctsa_w));
+
+ SCC85C30(config, m_sccterm2, SCC_CLOCK);
+}
+
+/* ROM definitions */
+ROM_START (mvme147)
+ ROM_REGION32_BE(0x40000, "system", 0)
+ ROM_DEFAULT_BIOS("147bug-v2.44")
+
+ ROM_SYSTEM_BIOS(0, "147bug-v2.44", "MVME147 147bug v2.44")
+ ROMX_LOAD("147bug-2.44-u22.bin", 0x00000, 0x20000, CRC (da09ce8a) SHA1 (3eaa8fa802187d9b08f453ff1ba64f5113a195a9), ROM_SKIP(1) | ROM_BIOS(0))
+ ROMX_LOAD("147bug-2.44-u30.bin", 0x00001, 0x20000, CRC (f883e17d) SHA1 (01fe43e5ddfd3cf8aabb5a5959c80a8b5ec5d895), ROM_SKIP(1) | ROM_BIOS(0))
+/*
+ * System ROM information
+ *
+ * 147bug version 2.44 is released 1999, coprighted by Motorola Inc from 1988
+ *
+ * 147bug SCC channel setup sequence
+ *----------------------------------
+ * 09 80 - Channel A reset
+ * 04 44 - x16 clock, 1 stop bits, no parity
+ * 03 C1 - 8 bit, receiver enable, auto enable off
+ * 01 00 -
+ * 02 70 - set interrupt vector 70
+ * 05 EA
+ * 0B 56
+ * 0C 0E - low baudrate divider
+ * 0D 00 - hi baudrate divider
+ * 0E 83 - Baud Rate Generator (BRG) enabled, PCLK is BRG source, BRG is DPLL source
+ * 06 00 - Tx sync character SDLC
+ * 07 00 - Rx sync character SDLC
+ * 0F 00 - disable all external interrupt and status
+ * 10
+ * channel B is identical but resets Channel B of course, SCC2 is also identical except using interrupt vector 71
+ */
+
+ ROM_SYSTEM_BIOS(1, "147bug-v2.43", "MVME147 147bug v2.43")
+ ROMX_LOAD("5741b42e.bin", 0x00000, 0x20000, CRC (2ba98f97) SHA1 (5f18c6dd6a7b03067890f0164ef3d37ced907d7f), ROM_SKIP(1) | ROM_BIOS(1))
+ ROMX_LOAD("5741b41e.bin", 0x00001, 0x20000, CRC (dfa014f2) SHA1 (ff9db90a05c295819ce7ca7c1a6ac67b04003728), ROM_SKIP(1) | ROM_BIOS(1))
+/*
+ * System ROM information
+ *
+ * 147bug version 2.43 is released 1992, coprighted by Motorola Inc from 1988
+ *
+ */
+
+ROM_END
+
+const tiny_rom_entry *vme_mvme147_card_device::device_rom_region() const
+{
+ return ROM_NAME(mvme147);
+}
+
+ioport_constructor vme_mvme147_card_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(mvme147);
+}
+
+/* Driver */
+// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS
+//COMP( 1989, mvme147, 0, 0, mvme147, mvme147, vme_mvme147_card_device, empty_init, "Motorola", "MVME-147", MACHINE_NO_SOUND_HW )
diff --git a/src/devices/bus/vme/mvme147.h b/src/devices/bus/vme/mvme147.h
new file mode 100644
index 00000000000..5ed9d879fef
--- /dev/null
+++ b/src/devices/bus/vme/mvme147.h
@@ -0,0 +1,59 @@
+// license:BSD-3-Clause
+// copyright-holders:Joakim Larsson Edstrom
+
+#ifndef MAME_BUS_VME_MVME147_H
+#define MAME_BUS_VME_MVME147_H
+
+#pragma once
+
+#include "bus/vme/vme.h"
+#include "machine/z80scc.h"
+
+class vme_mvme147_card_device
+ : public device_t
+ , public device_vme_card_interface
+{
+public:
+ vme_mvme147_card_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual ioport_constructor device_input_ports() const override;
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+private:
+ /* PCC - Peripheral Channel Controller */
+ //uint32_t pcc32_r(offs_t offset);
+ //void pcc32_w(offs_t offset, uint32_t data);
+ uint16_t pcc16_r(offs_t offset);
+ void pcc16_w(offs_t offset, uint16_t data);
+ uint8_t pcc8_r(offs_t offset);
+ void pcc8_w(offs_t offset, uint8_t data);
+ uint8_t vmechip_r(offs_t offset);
+ void vmechip_w(offs_t offset, uint8_t data);
+ //uint16_t vme_a24_r();
+ //void vme_a24_w(uint16_t data);
+ //uint16_t vme_a16_r();
+ //void vme_a16_w(uint16_t data);
+ void mvme147_mem(address_map &map);
+
+ required_device<cpu_device> m_maincpu;
+ required_device<scc85c30_device> m_sccterm;
+ required_device<scc85c30_device> m_sccterm2;
+
+ required_memory_region m_system;
+ required_shared_ptr<uint32_t> m_ram;
+ memory_passthrough_handler m_boot_mph;
+
+ // PCC registers
+ uint8_t m_genpurp_stat = 0;
+
+ // VME chip registers
+ uint8_t m_vc_cntl_conf = 0;
+};
+
+DECLARE_DEVICE_TYPE(VME_MVME147, vme_mvme147_card_device)
+
+#endif // MAME_BUS_VME_MVME147_H
diff --git a/src/devices/bus/vme/mvme180.cpp b/src/devices/bus/vme/mvme180.cpp
new file mode 100644
index 00000000000..2e95c4b5962
--- /dev/null
+++ b/src/devices/bus/vme/mvme180.cpp
@@ -0,0 +1,132 @@
+// license:BSD-3-Clause
+// copyright-holders:Patrick Mackinlay
+
+/*
+ * Motorola MVME180
+ *
+ * Sources:
+ * - OpenBSD 5.5 source code
+ *
+ * TODO:
+ * - skeleton only
+ */
+
+#include "emu.h"
+#include "mvme180.h"
+
+#define VERBOSE 0
+#include "logmacro.h"
+
+DEFINE_DEVICE_TYPE(VME_MVME180, vme_mvme180_card_device, "mvme180", "Motorola MVME180")
+
+vme_mvme180_card_device::vme_mvme180_card_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, VME_MVME180, tag, owner, clock)
+ , device_vme_card_interface(mconfig, *this)
+ , m_cpu(*this, "cpu")
+ , m_mmu(*this, "mmu%u", 0U)
+ , m_duart(*this, "duart")
+ , m_serial(*this, "serial%u", 0U)
+ , m_boot(*this, "boot")
+{
+}
+
+ROM_START(mvme180)
+ ROM_REGION32_BE(0x40000, "eprom", 0)
+ ROM_SYSTEM_BIOS(0, "v25", "180bug version 2.5 copyright 1988 Motorola")
+ ROMX_LOAD("51_w5110b19_u34__8846__180bug_2.5.u34", 0x0003, 0x10000, CRC(9b4e483a) SHA1(c9b1e9e1735a015c38eb223ab126c40c40a9f89d), ROM_SKIP(3) | ROM_BIOS(0))
+ ROMX_LOAD("51_w5110b20_u35__8846__180bug_2.5.u35", 0x0002, 0x10000, CRC(1170b048) SHA1(ab8e2917c7150e4f74be600507690aa35444244c), ROM_SKIP(3) | ROM_BIOS(0))
+ ROMX_LOAD("51_w5110b21_u36__8846__180bug_2.5.u36", 0x0001, 0x10000, CRC(270fbc7b) SHA1(a61b8701c5f1133f930320f313309008ff5d5504), ROM_SKIP(3) | ROM_BIOS(0))
+ ROMX_LOAD("51_w5110b22_u37__8846__180bug_2.5.u37", 0x0000, 0x10000, CRC(67a60a6c) SHA1(0105317abf0105216078c94c02c223dd1cd61068), ROM_SKIP(3) | ROM_BIOS(0))
+ROM_END
+
+static INPUT_PORTS_START(mvme180)
+INPUT_PORTS_END
+
+const tiny_rom_entry *vme_mvme180_card_device::device_rom_region() const
+{
+ return ROM_NAME(mvme180);
+}
+
+ioport_constructor vme_mvme180_card_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(mvme180);
+}
+
+void vme_mvme180_card_device::device_start()
+{
+ m_isr = 0;
+ m_imr = 0;
+}
+
+void vme_mvme180_card_device::device_reset()
+{
+ m_boot.select(0);
+}
+
+void vme_mvme180_card_device::device_add_mconfig(machine_config &config)
+{
+ MC88100(config, m_cpu, 40_MHz_XTAL / 2);
+ m_cpu->set_addrmap(AS_PROGRAM, &vme_mvme180_card_device::cpu_mem);
+
+ MC88200(config, m_mmu[0], 40_MHz_XTAL / 2, 0x7e);
+ m_mmu[0]->set_mbus(m_cpu, AS_PROGRAM);
+ m_cpu->set_cmmu_i(m_mmu[0]);
+
+ MC88200(config, m_mmu[1], 40_MHz_XTAL / 2, 0x7f);
+ m_mmu[1]->set_mbus(m_cpu, AS_PROGRAM);
+ m_cpu->set_cmmu_d(m_mmu[1]);
+
+ SCN2681(config, m_duart, 3.6864_MHz_XTAL);
+ m_duart->irq_cb().set(FUNC(vme_mvme180_card_device::irq_w<6>));
+ m_duart->outport_cb().set([this](u8 data) { LOG("port 0x%02x\n", data); });
+
+ RS232_PORT(config, m_serial[0], default_rs232_devices, "terminal");
+ RS232_PORT(config, m_serial[1], default_rs232_devices, nullptr);
+
+ // TODO: dsr, dtr
+ m_duart->a_tx_cb().set(m_serial[0], FUNC(rs232_port_device::write_txd));
+ m_duart->b_tx_cb().set(m_serial[1], FUNC(rs232_port_device::write_txd));
+ m_serial[0]->rxd_handler().set(m_duart, FUNC(scn2681_device::rx_a_w));
+ m_serial[1]->rxd_handler().set(m_duart, FUNC(scn2681_device::rx_b_w));
+}
+
+void vme_mvme180_card_device::cpu_mem(address_map &map)
+{
+ map(0x0000'0000, 0x007f'ffff).view(m_boot);
+ m_boot[0](0x0000'0000, 0x0003'ffff).rom().region("eprom", 0);
+ m_boot[1](0x0000'0000, 0x007f'ffff).ram();
+
+ map(0xff80'0000, 0xff83'ffff).rom().region("eprom", 0);
+ // 0xff81'0000 // ds1287 rtc?
+ map(0xffe1'0000, 0xffe1'0003).lr32([this]() { return m_isr; }, "isr");
+ map(0xffe2'0000, 0xffe2'0003).lw32(
+ [this](u32 data)
+ {
+ LOG("imr 0x%08x (%s)\n", data, machine().describe_context());
+ m_imr = data;
+
+ m_boot.select(1);
+
+ interrupt();
+ }, "imr");
+ // 0xffe3'0000 // clear parity error interrupt?
+ map(0xffe4'0000, 0xffe4'003f).rw(m_duart, FUNC(scn2681_device::read), FUNC(scn2681_device::write)).umask32(0x000000ff);
+ // 0xffe8'0000 // vme vector register?
+ // 0xffee'0000 // clear abort interrupt?
+}
+
+template <unsigned N> void vme_mvme180_card_device::irq_w(int state)
+{
+ LOG("irq_w<%d> %d\n", N, state);
+ if (state)
+ m_isr |= 1U << N;
+ else
+ m_isr &= ~(1U << N);
+
+ interrupt();
+}
+
+void vme_mvme180_card_device::interrupt()
+{
+ m_cpu->set_input_line(INPUT_LINE_IRQ0, bool(m_isr & m_imr));
+}
diff --git a/src/devices/bus/vme/mvme180.h b/src/devices/bus/vme/mvme180.h
new file mode 100644
index 00000000000..494678de61b
--- /dev/null
+++ b/src/devices/bus/vme/mvme180.h
@@ -0,0 +1,52 @@
+// license:BSD-3-Clause
+// copyright-holders:Patrick Mackinlay
+
+#ifndef MAME_BUS_VME_MVME180_H
+#define MAME_BUS_VME_MVME180_H
+
+#pragma once
+
+#include "bus/vme/vme.h"
+
+#include "cpu/m88000/m88000.h"
+#include "machine/mc68681.h"
+#include "machine/mc88200.h"
+
+#include "bus/rs232/rs232.h"
+
+class vme_mvme180_card_device
+ : public device_t
+ , public device_vme_card_interface
+{
+public:
+ vme_mvme180_card_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+protected:
+ // device_t overrides
+ virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual ioport_constructor device_input_ports() const override;
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+private:
+ void cpu_mem(address_map &map);
+
+ template <unsigned N> void irq_w(int state);
+ void interrupt();
+
+ required_device<mc88100_device> m_cpu;
+ required_device_array<mc88200_device, 2> m_mmu;
+
+ required_device<scn2681_device> m_duart;
+ required_device_array<rs232_port_device, 2> m_serial;
+
+ memory_view m_boot;
+
+ u8 m_isr; // interrupt status register
+ u8 m_imr; // interrupt mask register
+};
+
+DECLARE_DEVICE_TYPE(VME_MVME180, vme_mvme180_card_device)
+
+#endif // MAME_BUS_VME_MVME180_H
diff --git a/src/devices/bus/vme/mvme181.cpp b/src/devices/bus/vme/mvme181.cpp
new file mode 100644
index 00000000000..998959cbc32
--- /dev/null
+++ b/src/devices/bus/vme/mvme181.cpp
@@ -0,0 +1,162 @@
+// license:BSD-3-Clause
+// copyright-holders:Patrick Mackinlay
+
+/*
+ * Motorola MVME181
+ *
+ * Sources:
+ * - OpenBSD 5.5 source code
+ *
+ * TODO:
+ * - skeleton only
+ */
+/*
+ * dip function
+ * 1 system controller enable
+ * 2 VMEbus request level 0
+ * 3 VMEbus request level 1
+ * 4 VMEbus request level 2
+ * 5 VMEbus request level 3
+ * 6 system mode/board select
+ * 7 onboard memory base address (0x00000000, 0x00800000, 0x01000000, 0x01800000)
+ * 8 onboard memory base address
+ */
+
+#include "emu.h"
+#include "mvme181.h"
+
+#define VERBOSE 0
+#include "logmacro.h"
+
+DEFINE_DEVICE_TYPE(VME_MVME181, vme_mvme181_card_device, "mvme181", "Motorola MVME181")
+
+vme_mvme181_card_device::vme_mvme181_card_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, VME_MVME181, tag, owner, clock)
+ , device_vme_card_interface(mconfig, *this)
+ , m_cpu(*this, "cpu")
+ , m_mmu(*this, "mmu%u", 0U)
+ , m_rtc(*this, "rtc")
+ , m_duart(*this, "duart")
+ , m_serial(*this, "serial%u", 0U)
+ , m_boot(*this, "boot")
+{
+}
+
+ROM_START(mvme181)
+ ROM_REGION32_BE(0x80000, "eprom", 0)
+ ROM_SYSTEM_BIOS(0, "v301", "181bug Release Version 3.01 - 08/17/89")
+ ROMX_LOAD("181bug_a0.read.bin", 0x0000, 0x20000, CRC(79018bdb) SHA1(c52bfea145a56d2ad8765a508292557f096c4208), ROM_SKIP(3) | ROM_BIOS(0))
+ ROMX_LOAD("181bug_a1.read.bin", 0x0001, 0x20000, CRC(a5ac2d78) SHA1(feb16d3767cd382094de78b1043c702e29cde2ee), ROM_SKIP(3) | ROM_BIOS(0))
+ ROMX_LOAD("181bug_a2.read.bin", 0x0002, 0x20000, CRC(ddb90610) SHA1(30bd0cba86436689f8994c448515dd409e66d895), ROM_SKIP(3) | ROM_BIOS(0))
+ ROMX_LOAD("181bug_a3.read.bin", 0x0003, 0x20000, CRC(646d301f) SHA1(5871b5194e7fc623923f5df005b0463002e85626), ROM_SKIP(3) | ROM_BIOS(0))
+ROM_END
+
+static INPUT_PORTS_START(mvme181)
+INPUT_PORTS_END
+
+const tiny_rom_entry *vme_mvme181_card_device::device_rom_region() const
+{
+ return ROM_NAME(mvme181);
+}
+
+ioport_constructor vme_mvme181_card_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(mvme181);
+}
+
+void vme_mvme181_card_device::device_start()
+{
+ m_isr = 0;
+ m_imr = 0;
+
+ // memory tap offers a tidy solution for the "phantom" rtc
+ m_cpu->space(AS_PROGRAM).install_read_tap(0xff820000, 0xff82001f, "rtc",
+ [this](offs_t offset, u32 &data, u32 mem_mask)
+ {
+ if (!m_rtc->chip_enable())
+ {
+ if (BIT(offset, 2))
+ m_rtc->read_1();
+ else
+ m_rtc->read_0();
+ }
+ else if (BIT(offset, 4))
+ data = u32(m_rtc->read_data()) << 24;
+ else
+ m_rtc->write_data(BIT(offset, 2));
+ });
+}
+
+void vme_mvme181_card_device::device_reset()
+{
+ m_boot.select(0);
+}
+
+void vme_mvme181_card_device::device_add_mconfig(machine_config &config)
+{
+ MC88100(config, m_cpu, 40_MHz_XTAL / 2);
+ m_cpu->set_addrmap(AS_PROGRAM, &vme_mvme181_card_device::cpu_mem);
+
+ MC88200(config, m_mmu[0], 40_MHz_XTAL / 2, 0x7e);
+ m_mmu[0]->set_mbus(m_cpu, AS_PROGRAM);
+ m_cpu->set_cmmu_i(m_mmu[0]);
+
+ MC88200(config, m_mmu[1], 40_MHz_XTAL / 2, 0x7f);
+ m_mmu[1]->set_mbus(m_cpu, AS_PROGRAM);
+ m_cpu->set_cmmu_d(m_mmu[1]);
+
+ DS1315(config, m_rtc, 0); // DS1216
+
+ SCN2681(config, m_duart, 3.6864_MHz_XTAL); // SCC68692C1A44
+ m_duart->irq_cb().set(FUNC(vme_mvme181_card_device::irq_w<6>));
+ m_duart->outport_cb().set([this](u8 data) { LOG("port 0x%02x\n", data); });
+
+ RS232_PORT(config, m_serial[0], default_rs232_devices, "terminal");
+ RS232_PORT(config, m_serial[1], default_rs232_devices, nullptr);
+
+ // TODO: dsr, dtr
+ m_duart->a_tx_cb().set(m_serial[0], FUNC(rs232_port_device::write_txd));
+ m_duart->b_tx_cb().set(m_serial[1], FUNC(rs232_port_device::write_txd));
+ m_serial[0]->rxd_handler().set(m_duart, FUNC(scn2681_device::rx_a_w));
+ m_serial[1]->rxd_handler().set(m_duart, FUNC(scn2681_device::rx_b_w));
+}
+
+void vme_mvme181_card_device::cpu_mem(address_map &map)
+{
+ map(0x0000'0000, 0x007f'ffff).view(m_boot);
+ m_boot[0](0x0000'0000, 0x0007'ffff).rom().region("eprom", 0);
+ m_boot[1](0x0000'0000, 0x007f'ffff).ram();
+
+ map(0xff80'0000, 0xff87'ffff).rom().region("eprom", 0);
+ map(0xffe1'0000, 0xffe1'0003).lr32([this]() { return m_isr; }, "isr");
+ map(0xffe2'0000, 0xffe2'0003).lw32(
+ [this](u32 data)
+ {
+ LOG("imr 0x%08x (%s)\n", data, machine().describe_context());
+ m_imr = data;
+
+ m_boot.select(1);
+
+ interrupt();
+ }, "imr");
+ // 0xffe3'0000 // clear parity error interrupt?
+ map(0xffe4'0000, 0xffe4'003f).rw(m_duart, FUNC(scn2681_device::read), FUNC(scn2681_device::write)).umask32(0x000000ff);
+ // 0xffe8'0000 // vme vector register?
+ // 0xffee'0000 // clear abort interrupt?
+}
+
+template <unsigned N> void vme_mvme181_card_device::irq_w(int state)
+{
+ LOG("irq_w<%d> %d\n", N, state);
+ if (state)
+ m_isr |= 1U << N;
+ else
+ m_isr &= ~(1U << N);
+
+ interrupt();
+}
+
+void vme_mvme181_card_device::interrupt()
+{
+ m_cpu->set_input_line(INPUT_LINE_IRQ0, bool(m_isr & m_imr));
+}
diff --git a/src/devices/bus/vme/mvme181.h b/src/devices/bus/vme/mvme181.h
new file mode 100644
index 00000000000..e558be23e8f
--- /dev/null
+++ b/src/devices/bus/vme/mvme181.h
@@ -0,0 +1,52 @@
+// license:BSD-3-Clause
+// copyright-holders:Patrick Mackinlay
+
+#ifndef MAME_BUS_VME_MVME181_H
+#define MAME_BUS_VME_MVME181_H
+
+#pragma once
+
+#include "cpu/m88000/m88000.h"
+#include "machine/ds1315.h"
+#include "machine/mc68681.h"
+#include "machine/mc88200.h"
+
+#include "bus/vme/vme.h"
+#include "bus/rs232/rs232.h"
+
+class vme_mvme181_card_device
+ : public device_t
+ , public device_vme_card_interface
+{
+public:
+ vme_mvme181_card_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual ioport_constructor device_input_ports() const override;
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+private:
+ void cpu_mem(address_map &map);
+
+ template <unsigned N> void irq_w(int state);
+ void interrupt();
+
+ required_device<mc88100_device> m_cpu;
+ required_device_array<mc88200_device, 2> m_mmu;
+
+ required_device<ds1315_device> m_rtc;
+ required_device<scn2681_device> m_duart;
+ required_device_array<rs232_port_device, 2> m_serial;
+
+ memory_view m_boot;
+
+ u8 m_isr; // interrupt status register
+ u8 m_imr; // interrupt mask register
+};
+
+DECLARE_DEVICE_TYPE(VME_MVME181, vme_mvme181_card_device)
+
+#endif // MAME_BUS_VME_MVME181_H
diff --git a/src/devices/bus/vme/mvme187.cpp b/src/devices/bus/vme/mvme187.cpp
new file mode 100644
index 00000000000..96e8b54eb0d
--- /dev/null
+++ b/src/devices/bus/vme/mvme187.cpp
@@ -0,0 +1,138 @@
+// license:BSD-3-Clause
+// copyright-holders:Patrick Mackinlay
+
+/*
+ * Motorola MVME187
+ *
+ * Sources:
+ * - MVME187 RISC Single Board Computer Installation Guide (MVME187IG/D4), Motorola 1997
+ * - Single Board Computers Programmer's Reference Guide (VMESBCA1/PG1), Motorola 1996
+ *
+ * TODO:
+ * - skeleton only
+ *
+ * Skeleton is based on the variant of the MVME187 used in the Motorola M8120 system.
+ *
+ * M8120 variant
+ * - no SRAM
+ * - two additional serial ports (total 6)
+ * - no parallel port
+ * - only two ROM sockets
+ */
+
+/*
+ * M8120 parts
+ * -----------
+ * MC88100RC25
+ * MC88200RC25 x 2
+ * DS1643-150 8Kx8 NVRAM with RTC (MK48T08 compatible)
+ * 53C710 SCSI controller
+ * TL-SCSI285N SCSI voltage regulator
+ * DS1232S MicroMonitor chip
+ * KU82596CA-33 Ethernet controller
+ * D82C501AD Ethernet serial interface
+ * CL-CD2401-10QC-I x 2 Four-channel multi-protocol communications controller
+ * MC145406DW x 9 RS-232-D driver/receiver
+ *
+ * 51-W6281B01 1444F0011 Motorola custom ASIC (PCCChip2 or VMEChip2?)
+ * 51-W6280B02 16H7Y0005 Motorola custom ASIC (PCCChip2 or VMEChip2?)
+ * M5M27C202JK x 2 131072 word x 16 bit CMOS EEPROM
+ *
+ * DS1 run LED (green)
+ * DS2 stat LED (yellow)
+ * DS3 scsi LED (yellow)
+ * DS4 fail LED (red)
+ * abort switch
+ * reset switch
+ *
+ * 50.000MHz
+ * 20.0000MHz
+ *
+ * RAM mezzanine board has MEMC040 or MCECC memory controller ASIC
+ */
+
+#include "emu.h"
+#include "mvme187.h"
+
+#define VERBOSE 0
+#include "logmacro.h"
+
+DEFINE_DEVICE_TYPE(VME_MVME187, vme_mvme187_card_device, "mvme187", "Motorola MVME187")
+
+vme_mvme187_card_device::vme_mvme187_card_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, VME_MVME187, tag, owner, clock)
+ , device_vme_card_interface(mconfig, *this)
+ , m_cpu(*this, "cpu")
+ , m_mmu(*this, "mmu%u", 0U)
+ , m_rtc(*this, "rtc")
+ //, m_uart(*this, "uart")
+ , m_serial(*this, "serial%u", 0U)
+ //, m_scsi(*this, "scsi")
+ , m_lan(*this, "lan")
+ , m_boot(*this, "boot")
+{
+}
+
+ROM_START(mvme187)
+ ROM_REGION32_BE(0x8'0000, "eprom", 0)
+ ROM_SYSTEM_BIOS(0, "m8120", "M8120 Debugger/Diagnostics Release Version 1.2 - 04/14/93")
+ ROMX_LOAD("6631b05c__03_08_94__8120.u1", 0x0002, 0x4'0000, CRC(d31cc388) SHA1(c2e613ded8d66102d3afa41ca763e997d9829d28), ROM_REVERSE | ROM_GROUPWORD | ROM_SKIP(2) | ROM_BIOS(0)) // M5M27C202JK
+ ROMX_LOAD("6631b06c__03_08_94__8120.u4", 0x0000, 0x4'0000, CRC(c62923e9) SHA1(62515c6e0dbeca6d18f373ad33e185096f10d2fc), ROM_REVERSE | ROM_GROUPWORD | ROM_SKIP(2) | ROM_BIOS(0)) // M5M27C202JK
+ROM_END
+
+static INPUT_PORTS_START(mvme187)
+INPUT_PORTS_END
+
+const tiny_rom_entry *vme_mvme187_card_device::device_rom_region() const
+{
+ return ROM_NAME(mvme187);
+}
+
+ioport_constructor vme_mvme187_card_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(mvme187);
+}
+
+void vme_mvme187_card_device::device_start()
+{
+}
+
+void vme_mvme187_card_device::device_reset()
+{
+ m_boot.select(0);
+}
+
+void vme_mvme187_card_device::device_add_mconfig(machine_config &config)
+{
+ MC88100(config, m_cpu, 50_MHz_XTAL / 2);
+ m_cpu->set_addrmap(AS_PROGRAM, &vme_mvme187_card_device::cpu_mem);
+
+ MC88200(config, m_mmu[0], 50_MHz_XTAL / 2, 0x77);
+ m_mmu[0]->set_mbus(m_cpu, AS_PROGRAM);
+ m_cpu->set_cmmu_i(m_mmu[0]);
+
+ MC88200(config, m_mmu[1], 50_MHz_XTAL / 2, 0x7f);
+ m_mmu[1]->set_mbus(m_cpu, AS_PROGRAM);
+ m_cpu->set_cmmu_d(m_mmu[1]);
+
+ DS1643(config, m_rtc);
+
+ RS232_PORT(config, m_serial[0], default_rs232_devices, "terminal");
+ RS232_PORT(config, m_serial[1], default_rs232_devices, nullptr);
+ RS232_PORT(config, m_serial[2], default_rs232_devices, nullptr);
+ RS232_PORT(config, m_serial[3], default_rs232_devices, nullptr);
+ RS232_PORT(config, m_serial[4], default_rs232_devices, nullptr);
+ RS232_PORT(config, m_serial[5], default_rs232_devices, nullptr);
+
+ //NCR53C7XX(config, m_scsi, 0);
+ I82596_BE32(config, m_lan, 20'000'000);
+}
+
+void vme_mvme187_card_device::cpu_mem(address_map &map)
+{
+ map(0x0000'0000, 0x00ff'ffff).view(m_boot);
+ m_boot[0](0x0000'0000, 0x0007'ffff).rom().region("eprom", 0);
+ m_boot[1](0x0000'0000, 0x00ff'ffff).ram();
+
+ map(0xff80'0000, 0xff87'ffff).rom().region("eprom", 0);
+}
diff --git a/src/devices/bus/vme/mvme187.h b/src/devices/bus/vme/mvme187.h
new file mode 100644
index 00000000000..cfac9cfef05
--- /dev/null
+++ b/src/devices/bus/vme/mvme187.h
@@ -0,0 +1,51 @@
+// license:BSD-3-Clause
+// copyright-holders:Patrick Mackinlay
+
+#ifndef MAME_BUS_VME_MVME187_H
+#define MAME_BUS_VME_MVME187_H
+
+#pragma once
+
+#include "cpu/m88000/m88000.h"
+
+#include "machine/53c7xx.h"
+//#include "machine/cd2400.h"
+#include "machine/i82586.h"
+#include "machine/mc88200.h"
+#include "machine/timekpr.h"
+
+#include "bus/vme/vme.h"
+#include "bus/rs232/rs232.h"
+
+class vme_mvme187_card_device
+ : public device_t
+ , public device_vme_card_interface
+{
+public:
+ vme_mvme187_card_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual ioport_constructor device_input_ports() const override;
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+private:
+ void cpu_mem(address_map &map);
+
+ required_device<mc88100_device> m_cpu;
+ required_device_array<mc88200_device, 2> m_mmu;
+
+ required_device<ds1643_device> m_rtc;
+ //required_device_array<cd2401, 2> m_uart;
+ required_device_array<rs232_port_device, 6> m_serial;
+ //required_device<ncr53c7xx_device> m_scsi;
+ required_device<i82596_device> m_lan;
+
+ memory_view m_boot;
+};
+
+DECLARE_DEVICE_TYPE(VME_MVME187, vme_mvme187_card_device)
+
+#endif // MAME_BUS_VME_MVME187_H
diff --git a/src/devices/bus/vme/mvme327a.cpp b/src/devices/bus/vme/mvme327a.cpp
new file mode 100644
index 00000000000..dc64a89f85f
--- /dev/null
+++ b/src/devices/bus/vme/mvme327a.cpp
@@ -0,0 +1,129 @@
+// license:BSD-3-Clause
+// copyright-holders:Patrick Mackinlay
+
+/*
+ * Motorola MVME327A VMEbus To SCSI Bus Adapter
+ *
+ * Sources:
+ * - MVME327A VMEbus To SCSI Bus Adapter And MVME717 Transition Module User's Manual (MVME327A/D1)
+ *
+ * TODO:
+ * - skeleton only
+ */
+
+#include "emu.h"
+#include "mvme327a.h"
+
+#include "bus/nscsi/hd.h"
+#include "bus/nscsi/cd.h"
+
+#define VERBOSE 0
+#include "logmacro.h"
+
+DEFINE_DEVICE_TYPE(VME_MVME327A, vme_mvme327a_device, "mvme327a", "Motorola MVME327A")
+
+vme_mvme327a_device::vme_mvme327a_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, VME_MVME327A, tag, owner, clock)
+ , device_vme_card_interface(mconfig, *this)
+ , m_cpu(*this, "cpu")
+ , m_pit(*this, "pit")
+ , m_bim(*this, "bim")
+ , m_fdc(*this, "fdc")
+ , m_scsi(*this, "scsi:7:wd33c93a")
+ , m_boot(*this, "boot")
+{
+}
+
+ROM_START(mvme327a)
+ ROM_REGION16_BE(0x20000, "eprom", 0)
+ ROM_SYSTEM_BIOS(0, "v27", "327A 2.7 4/17/95")
+ ROMX_LOAD("5527c29a.u34", 0x0001, 0x10000, CRC(2ef4cc9a) SHA1(0e80e208756995cb34c006d2f1e84a5978ad17d6), ROM_SKIP(1) | ROM_BIOS(0))
+ ROMX_LOAD("5527c30a.u42", 0x0000, 0x10000, CRC(7be983d0) SHA1(ec5fc0709d8e91119d39231ace66f4fcbdb457e9), ROM_SKIP(1) | ROM_BIOS(0))
+ROM_END
+
+static INPUT_PORTS_START(mvme327a)
+INPUT_PORTS_END
+
+const tiny_rom_entry *vme_mvme327a_device::device_rom_region() const
+{
+ return ROM_NAME(mvme327a);
+}
+
+ioport_constructor vme_mvme327a_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(mvme327a);
+}
+
+void vme_mvme327a_device::device_start()
+{
+}
+
+void vme_mvme327a_device::device_reset()
+{
+ m_boot.select(0);
+}
+
+static void scsi_devices(device_slot_interface &device)
+{
+ device.option_add("cdrom", NSCSI_CDROM);
+ device.option_add("harddisk", NSCSI_HARDDISK);
+ device.option_add("wd33c93a", WD33C93A);
+}
+
+void vme_mvme327a_device::device_add_mconfig(machine_config &config)
+{
+ M68010(config, m_cpu, 20_MHz_XTAL / 2);
+ m_cpu->set_addrmap(AS_PROGRAM, &vme_mvme327a_device::cpu_mem);
+ m_cpu->set_addrmap(m68000_base_device::AS_CPU_SPACE, &vme_mvme327a_device::cpu_int);
+
+ MC68153(config, m_bim, 0);
+ PIT68230(config, m_pit, 0);
+
+ WD37C65C(config, m_fdc, 0);
+
+ NSCSI_BUS(config, "scsi", 0);
+ NSCSI_CONNECTOR(config, "scsi:0", scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi:1", scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi:2", scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi:3", scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi:4", scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi:5", scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi:6", scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi:7").option_set("wd33c93a", WD33C93A).machine_config(
+ [] (device_t *device)
+ {
+ wd33c9x_base_device &wd33c93(downcast<wd33c9x_base_device &>(*device));
+
+ wd33c93.set_clock(10000000);
+ //wd33c93.irq_cb().set(*this, ...);
+ //wd33c93.drq_cb().set(*this, ...);
+ });
+}
+
+void vme_mvme327a_device::cpu_mem(address_map &map)
+{
+ map(0x00'0000, 0x01'ffff).view(m_boot);
+ m_boot[0](0x00'0000, 0x01'ffff).rom().region("eprom", 0);
+ m_boot[1](0x00'0000, 0x01'ffff).ram();
+
+ //map(0x04'0000, 0x04'0001).rw(m_scsi, FUNC(wd33c93a_device))
+ //map(0x07'0000, 0x07'0003).m(m_fdc, &wd37c65c_device::map).umask16(0x00ff);
+ map(0x0b'0000, 0x0b'003f).rw(m_pit, FUNC(pit68230_device::read), FUNC(pit68230_device::write)).mirror(0xffc0).umask16(0x00ff);
+ map(0x0c'0000, 0x0c'000f).rw(m_bim, FUNC(bim68153_device::read), FUNC(bim68153_device::write)).mirror(0xfff0).umask16(0x00ff);
+
+ map(0x10'0000, 0x11'ffff).rom().region("eprom", 0);
+ map(0x10'0000, 0x10'0003).lw16([this](u32 data) { m_boot.select(1); }, "ram_enable");
+
+ // 0x80'0000-0xff'ffff VMEbus access
+}
+
+void vme_mvme327a_device::cpu_int(address_map &map)
+{
+ map(0xfffff3, 0xfffff3).lr8(NAME([]() { return m68000_base_device::autovector(1); }));
+ map(0xfffff5, 0xfffff5).lr8(NAME([]() { return m68000_base_device::autovector(2); }));
+ map(0xfffff7, 0xfffff7).lr8(NAME([]() { return m68000_base_device::autovector(3); }));
+ map(0xfffff9, 0xfffff9).lr8(NAME([]() { return m68000_base_device::autovector(4); }));
+ map(0xfffffb, 0xfffffb).lr8(NAME([]() { return m68000_base_device::autovector(5); }));
+ map(0xfffffd, 0xfffffd).lr8(NAME([]() { return m68000_base_device::autovector(6); }));
+ map(0xffffff, 0xffffff).lr8(NAME([]() { return m68000_base_device::autovector(7); }));
+}
diff --git a/src/devices/bus/vme/mvme327a.h b/src/devices/bus/vme/mvme327a.h
new file mode 100644
index 00000000000..26f115b9cd3
--- /dev/null
+++ b/src/devices/bus/vme/mvme327a.h
@@ -0,0 +1,48 @@
+// license:BSD-3-Clause
+// copyright-holders:Patrick Mackinlay
+
+#ifndef MAME_BUS_VME_MVME327A_H
+#define MAME_BUS_VME_MVME327A_H
+
+#pragma once
+
+#include "cpu/m68000/m68010.h"
+
+#include "machine/68230pit.h"
+#include "machine/68153bim.h"
+#include "machine/wd33c9x.h"
+#include "machine/upd765.h"
+
+#include "bus/vme/vme.h"
+
+class vme_mvme327a_device
+ : public device_t
+ , public device_vme_card_interface
+{
+public:
+ vme_mvme327a_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual ioport_constructor device_input_ports() const override;
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+private:
+ void cpu_mem(address_map &map);
+ void cpu_int(address_map &map);
+
+ required_device<m68010_device> m_cpu;
+ required_device<pit68230_device> m_pit;
+ required_device<bim68153_device> m_bim;
+
+ required_device<wd37c65c_device> m_fdc;
+ required_device<wd33c93a_device> m_scsi;
+
+ memory_view m_boot;
+};
+
+DECLARE_DEVICE_TYPE(VME_MVME327A, vme_mvme327a_device)
+
+#endif // MAME_BUS_VME_MVME327A_H
diff --git a/src/devices/bus/vme/vme_mvme350.cpp b/src/devices/bus/vme/mvme350.cpp
index a0dca46b996..bca809e3095 100644
--- a/src/devices/bus/vme/vme_mvme350.cpp
+++ b/src/devices/bus/vme/mvme350.cpp
@@ -128,26 +128,15 @@
****************************************************************************/
#include "emu.h"
-#include "vme_mvme350.h"
+#include "mvme350.h"
-#include "cpu/m68000/m68000.h"
+#include "cpu/m68000/m68010.h"
#include "machine/68230pit.h"
-#define LOG_GENERAL 0x01
-#define LOG_SETUP 0x02
-#define LOG_PRINTF 0x04
+#define VERBOSE (0) // (LOG_GENERAL)
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
-#define VERBOSE 0 //(LOG_PRINTF | LOG_SETUP | LOG_GENERAL)
-
-#define LOGMASK(mask, ...) do { if (VERBOSE & mask) logerror(__VA_ARGS__); } while (0)
-#define LOGLEVEL(mask, level, ...) do { if ((VERBOSE & mask) >= level) logerror(__VA_ARGS__); } while (0)
-
-#define LOG(...) LOGMASK(LOG_GENERAL, __VA_ARGS__)
-#define LOGSETUP(...) LOGMASK(LOG_SETUP, __VA_ARGS__)
-
-#if VERBOSE & LOG_PRINTF
-#define logerror printf
-#endif
#ifdef _MSC_VER
#define FUNCNAME __func__
@@ -155,11 +144,12 @@
#define FUNCNAME __PRETTY_FUNCTION__
#endif
+
//**************************************************************************
// GLOBAL VARIABLES
//**************************************************************************
-DEFINE_DEVICE_TYPE(VME_MVME350, vme_mvme350_card_device, "mvme350", "Motorola MVME-350 Intelligent Tape Controller")
+DEFINE_DEVICE_TYPE(VME_MVME350, vme_mvme350_card_device, "mvme350", "Motorola MVME350")
#define MVME350_CPU_TAG "mvme350_cpu"
#define MVME350_ROM "mvme350_rom"
diff --git a/src/devices/bus/vme/vme_mvme350.h b/src/devices/bus/vme/mvme350.h
index a328f3e7c53..11d767bc9ad 100644
--- a/src/devices/bus/vme/vme_mvme350.h
+++ b/src/devices/bus/vme/mvme350.h
@@ -1,7 +1,7 @@
// license:BSD-3-Clause
// copyright-holders:Joakim Larsson Edstrom
-#ifndef MAME_BUS_VME_VME_MVME350_H
-#define MAME_BUS_VME_VME_MVME350_H
+#ifndef MAME_BUS_VME_MVME350_H
+#define MAME_BUS_VME_MVME350_H
#pragma once
@@ -32,4 +32,4 @@ private:
void mvme350_mem(address_map &map);
};
-#endif // MAME_BUS_VME_VME_MVME350_H
+#endif // MAME_BUS_VME_MVME350_H
diff --git a/src/devices/bus/vme/mzr8105.cpp b/src/devices/bus/vme/mzr8105.cpp
new file mode 100644
index 00000000000..c9bc209463b
--- /dev/null
+++ b/src/devices/bus/vme/mzr8105.cpp
@@ -0,0 +1,237 @@
+// license:BSD-3-Clause
+// copyright-holders:Joakim Larsson Edstrom
+/***************************************************************************
+ *
+ * Mizar VME8105 rev D 3U SBC board driver
+ *
+ * 19/08/2015
+ *
+ * I bought this board from http://www.retrotechnology.com without documentation.
+ * It has a Motorola 68000 CPU @ 10MHz and two 27128 EPROMS with OS9 DEBUG labels
+ * and not much more except 16 or so TTLs, 2 PALs and a VME P1 connector. It is a
+ * 2 layered pcb so it shold be possible to trace the schematics quite easily.
+ * There is a date on the P1 Connector: "Feb 20 1987"
+ *
+ * ||
+ * ||
+ * ||
+ * ||
+ * ||____________________________________________________________ ___
+ * || --------------K2|U6-7432|U7-7474|U14-7405|U21-74645 | |_| |
+ * || | 2764 - low |-+-------+-------+--------+-----------+ | | |
+ * || | OS9 DEBUG U4| +---------+ +--------+---------+ | | |
+ * || -------------- | | |U13-7474|U20-74645| | | |
+ * || ______________ | | +--------+---------+ | | |
+ * || | | | | ______________K4____ | | |
+ * || | U3| | | |U12-7438|U19-74244| | |VME|
+ * || -------------- | |+------K6---------K3---+ | | |
+ * || ______________ | ||U11-PAL20L10|U18-74244| | |P1 |
+ * || | 2764 - high | | |+-----021102-+---------+ | | |
+ * || | OS9 DEBUG U2| |MC68000L10+------------+---------+ | | |
+ * || |______________| | ||U10-PAL14L4 |U17-74244| | | |
+ * || | |+-----021001-+---------+ | | |
+ * || -------------- | |+----+_______|U16-74244|+--+| | |
+ * || | | | |XTAL |U9-7410+---------+| || | |
+ * ||K1 | U1| | |FOX100-------+---------+|K5||_| |
+ * || -------------- |_________|10MHz|U8-7404|U15-74148|| || |___|
+ * ||--||--------------------------------+----+-------+---------++--+
+ * ||--||
+ * ||
+ *
+ * PAL:s
+ *------
+ * The board has two PAL:s, a PAL20L10 and a PAL14L4.
+ *
+ * _____ _____
+ * OD/CLK 1 |* \_/ | 20 VCC
+ * CPU A13 I0 2 | | 19 O0/LR A23
+ * U9 7410p12 I1 3 | | 18 O1/A0 A22
+ * CPU *AS I2 4 | | 17 02/A1 U2/U4 2764p22 *OE
+ * GND I3 5 | | 16 03/A2 U11 PAL20L10p6 I4
+ * CPU A14 I4 6 | U10 | 15 A0/O0 U11 PAL20L10p7 I5
+ * CPU A15 I5 7 | PAL14L4 | 14 A1/O1 U19 74LS244p11 I0b
+ * CPU A16 I6 8 | | 13 A2/O2 A18
+ * CPU A17 I7 9 | | 12 LR/O3 A20
+ * GND 10 |_____________| 11 CLK/OD A21
+ *
+ * _____ _____
+ * OD/CLK 1 |* \_/ | 24 VCC
+ * I0 2 | | 23 O0/LR
+ * CPU *AS I1 3 | | 22 O1/A0
+ * U10 PAL14L4p3 I2 4 | | 21 02/A1
+ * I3 5 | | 20 03/A2
+ * U10 PAL14L4p16 I4 6 | U10 | 19 04/NC
+ * U10 PAL14L4p15 I5 7 | PAL20L10 | 18 NC/O0
+ * I6 8 | | 17 A2/O1
+ * I7 9 | | 16 A1/O2
+ * I8 10 | | 15 A0/O3
+ * I9 11 | | 14 LR/O4
+ * GND 12 |_____________| 13 CLK/OD
+ *
+ * Trace is not fully completed and validated.
+ *
+ * History of Mizar
+ *-------------------
+ * Mizar was one of the first companies that released VME boards in 1982-3 together with
+ * Force Computers and Motorola. Their systems was often supported by OS9/68000 from Microware.
+ * In 1993 Mizar discontinued their OS9/CPU board product range and focused entirely on DSP
+ * boards. RTSI was founded by Mizar employees preserving the knowledge in OS9 as consultants.
+ * In 1998 Blue Wave resulted from the merger of Mizar and Loughborough Sound Images.
+ * Not much tech information availabe but I found some quotes about Mizar on the internet:
+ *
+ * From http://archive.org/stream/68micro-vol-11-num-02/V11N02_Feb1989_djvu.txt :
+ *--------------------------------------------------------------------------------
+ * " Mizar provides complete OS-9 solutions for the VMEbus. Mizar's VME CPUs
+ * offer (he functions and performance your application demands. Our single
+ * height (3U) VME processors are uniquely configurable computing engines,
+ * Through Mizar's unique MXbus expansion interface, standard and custom side
+ * modules can be added to basic processors to create double-height (6U) boards
+ * tor specific applications, 3U CPU options include 68010, 66020, and 63030
+ * microprocessors, up to one MB of DRAM, serial I/O, real-time clock, and
+ * mailbox interrupt support. Standard MXbus side modules include additional DRAM.
+ * SRAM, and I/O.
+ *
+ * Mizar's standard double-height (6U) processors provide additional features such
+ * as a high-speed cache to enhance 68030 performance, floating, point coprocessor
+ * support, up to four MB dual ported DRAM, VSB memory interface, Ethernet, and SCSI.
+ *
+ * Mizar also supports OS-9 with completely configured OS9 development systems and
+ * OS-9 application server systems. For more information, call Mizar today
+ *
+ * 800-635-0200 MIZAR 1419 Dunn Drive CarrolHon, TX 75006 214-446-2664"
+ *
+ * Known boards from Mizar:
+ *
+ * MZX 414
+ * MZ 7122
+ * MZ 7132
+ * MZ 7300 Serial I/O Board (Z8530)
+ * EMX 7320 Serial I/O Board
+ * MZ 7400 Disk Controller Board (WD 2010; WD 1772)
+ * MZ 7500 IEEE-488 (GPIB) Interface Board
+ * EMX 7550 Ethernet Controller Board (AMD 7990 Lance) MAC: 00:80:F8 MIZAR, INC.
+ * MZ 7772
+ * MZ 7810 I/O Expansion Module (6681 DUART)
+ * MZ 7831 SCSI Expansion Module (WD 33C93A)
+ * MZ 7850 Ethernet Expansion Module (WD 83C690)
+ * MZ 8000 ??
+ * MZ 8105 3U 68000 CPU board
+ * MZ 8115
+ * MZ 8300 3U serial board, 2 NEC 7201 and 1 AMD CTS9513 5 x 16 bit Counter/Timer
+ * MZ 8310 timing module 2 x AM9513
+ * MZ 8505 IEEE-488 (GPIB) Interface Board"
+ *
+ * From http://www.megalextoria.com/forum2/index.php?t=msg&goto=73945&
+ *--------------------------------------------------------------------
+ * Aug 20 1984 a report by James Jones from the OS/9 conferance in Des Moines:
+ * "...
+ * Mizar: is selling VME bus 68010 boards, running OS-9/68000; they also make
+ * various memory and I/O boards, disk controller boards, and and a NEC 7220-based
+ * graphics controller board...."
+ *
+ * Misc links about Mizar:
+ * http://www.vita.com/History
+ * http://www.verycomputer.com/154_e272024804bbe203_1.htm
+ * https://www.aihitdata.com/company/00814595/RTSI/overview
+ *
+ * Address Map
+ * --------------------------------------------------------------------------
+ * Address Range Description/Assumption
+ * --------------------------------------------------------------------------
+ * 0x000000 0x01ffff ROM because of fixed vectors
+ * 0x020000 0x03ffff RAM because bootvector stack starts at 0x21000
+ * -- VME adresses---
+ * 0xff0000 0xff0003 Bootstrap expects to find a UPD7201 serial device here
+ * --------------------------------------------------------------------------
+ *
+ * Interrupt sources
+ * ----------------------------------------------------------
+ * Description Device Lvl IRQ VME board
+ * /Board Vector Address
+ * ----------------------------------------------------------
+ * On board Sources
+ * TBD
+ * Off board Sources (other VME boards)
+ * TBD
+ * ----------------------------------------------------------
+ *
+ * TODO:
+ * - Dump the ROMs (DONE)
+ * - Setup a working address map (DONE)
+ * - Add VME bus driver (Faked one)
+ * - understand what other device is expected in VME space ff0011-13
+ *
+ ****************************************************************************/
+#include "emu.h"
+#include "mzr8105.h"
+
+#include "cpu/m68000/m68000.h"
+
+DEFINE_DEVICE_TYPE(VME_MZR8105, vme_mzr8105_card_device, "mzr8105", "Mizar VME8105")
+
+vme_mzr8105_card_device::vme_mzr8105_card_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, VME_MZR8105, tag, owner, clock)
+ , device_vme_card_interface(mconfig, *this)
+ , m_maincpu (*this, "maincpu")
+{
+}
+
+void vme_mzr8105_card_device::device_start()
+{
+}
+
+void vme_mzr8105_card_device::device_reset()
+{
+}
+
+void vme_mzr8105_card_device::mzr8105_mem(address_map &map)
+{
+ map.unmap_value_high();
+/* The ROMs contains an OS9 bootloader. It is position independent but reset vector suggests that it sits flat on adress 0 (zero) */
+ map(0x000000, 0x01ffff).rom().region("roms", 0); /* System EPROM Area 16Kb OS9 DEBUG - not verified */
+ map(0x020000, 0x03ffff).ram(); /* Not verified */
+// map(0x100000, 0xfeffff).rw(FUNC(vme_mzr8105_card_device::vme_a24_r), FUNC(vme_mzr8105_card_device::vme_a24_w)); /* VMEbus Rev B addresses (24 bits) - not verified */
+ map(0xff0000, 0xffffff).rw(FUNC(device_vme_card_interface::vme_read16<vme::AM_29>), FUNC(device_vme_card_interface::vme_write16<vme::AM_29>)); /* VMEbus Rev B addresses (16 bits) - not verified */
+}
+
+/* Input ports */
+static INPUT_PORTS_START (mzr8105)
+INPUT_PORTS_END
+
+/*
+ * Machine configuration
+ */
+void vme_mzr8105_card_device::device_add_mconfig(machine_config &config)
+{
+ M68000(config, m_maincpu, XTAL(10'000'000));
+ m_maincpu->set_addrmap(AS_PROGRAM, &vme_mzr8105_card_device::mzr8105_mem);
+}
+
+/* ROM definitions */
+/* mzr8300 UPD7201 init sequence
+ * :upd B Reg 02 <- 04 Interrupt vector
+ * :upd B Reg 06 <- 00 Sync byte
+ * :upd B Reg 07 <- 00 Sync byte
+ * :upd B Reg 03 <- c1 Rx 8 bit chars + Rx enable
+ * :upd B Reg 04 <- 44 16x clock, 1 stop bit ( == async mode), no parity
+ * :upd B Reg 05 <- 68 Tx 8 bit chars + Tx enable
+ */
+ROM_START (mzr8105)
+ ROM_REGION16_BE(0x20000, "roms", 0)
+ ROM_LOAD16_BYTE ("mzros9lb.bin", 0x000001, 0x2000, CRC (7c6a354d) SHA1 (2721eb649c8046dbcb517a36a97dc0816cd133f2))
+ ROM_LOAD16_BYTE ("mzros9hb.bin", 0x000000, 0x2000, CRC (d18e69a6) SHA1 (a00b68f4d649bcc09a29361f8692e52be12b3792))
+ROM_END
+
+const tiny_rom_entry *vme_mzr8105_card_device::device_rom_region() const
+{
+ return ROM_NAME(mzr8105);
+}
+
+ioport_constructor vme_mzr8105_card_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(mzr8105);
+}
+
+/* Driver */
+// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS
+//COMP( 1987, mzr8105, 0, 0, mzr8105, mzr8105, vme_mzr8105_card_device, empty_init, "Mizar Inc", "Mizar VME8105", MACHINE_NOT_WORKING | MACHINE_NO_SOUND_HW )
diff --git a/src/devices/bus/vme/mzr8105.h b/src/devices/bus/vme/mzr8105.h
new file mode 100644
index 00000000000..ef16d00703c
--- /dev/null
+++ b/src/devices/bus/vme/mzr8105.h
@@ -0,0 +1,32 @@
+// license:BSD-3-Clause
+// copyright-holders:Joakim Larsson Edstrom
+
+#ifndef MAME_BUS_VME_MZR8105_H
+#define MAME_BUS_VME_MZR8105_H
+
+#pragma once
+
+#include "bus/vme/vme.h"
+
+class vme_mzr8105_card_device
+ : public device_t
+ , public device_vme_card_interface
+{
+public:
+ vme_mzr8105_card_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual ioport_constructor device_input_ports() const override;
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+private:
+ void mzr8105_mem(address_map &map);
+ required_device<cpu_device> m_maincpu;
+};
+
+DECLARE_DEVICE_TYPE(VME_MZR8105, vme_mzr8105_card_device)
+
+#endif // MAME_BUS_VME_MZR8105_H
diff --git a/src/devices/bus/vme/vme_mzr8300.cpp b/src/devices/bus/vme/mzr8300.cpp
index 99e2e8c0889..d97e9c58e19 100644
--- a/src/devices/bus/vme/vme_mzr8300.cpp
+++ b/src/devices/bus/vme/mzr8300.cpp
@@ -82,27 +82,14 @@
****************************************************************************/
#include "emu.h"
-#include "vme_mzr8300.h"
+#include "mzr8300.h"
-#include "machine/am9513.h"
-#include "machine/z80sio.h"
#include "bus/rs232/rs232.h"
-#define LOG_GENERAL 0x01
-#define LOG_SETUP 0x02
-#define LOG_PRINTF 0x04
+#define VERBOSE (0) // (LOG_GENERAL)
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
-#define VERBOSE 0 // (LOG_PRINTF | LOG_SETUP | LOG_GENERAL)
-
-#define LOGMASK(mask, ...) do { if (VERBOSE & mask) logerror(__VA_ARGS__); } while (0)
-#define LOGLEVEL(mask, level, ...) do { if ((VERBOSE & mask) >= level) logerror(__VA_ARGS__); } while (0)
-
-#define LOG(...) LOGMASK(LOG_GENERAL, __VA_ARGS__)
-#define LOGSETUP(...) LOGMASK(LOG_SETUP, __VA_ARGS__)
-
-#if VERBOSE & LOG_PRINTF
-#define logerror printf
-#endif
#ifdef _MSC_VER
#define FUNCNAME __func__
@@ -110,11 +97,12 @@
#define FUNCNAME __PRETTY_FUNCTION__
#endif
+
//**************************************************************************
// GLOBAL VARIABLES
//**************************************************************************
-DEFINE_DEVICE_TYPE(VME_MZR8300, vme_mzr8300_card_device, "mzr8300", "Mizar 8300 SIO serial board")
+DEFINE_DEVICE_TYPE(VME_MZR8300, vme_mzr8300_card_device, "mzr8300", "Mizar 8300")
/* These values are borrowed just to get the terminal going and should be replaced
* once a proper serial board hardware (ie MZ 8300) is found and emulated. */
@@ -126,26 +114,26 @@ DEFINE_DEVICE_TYPE(VME_MZR8300, vme_mzr8300_card_device, "mzr8300", "Mizar 8300
void vme_mzr8300_card_device::device_add_mconfig(machine_config &config)
{
- upd7201_device& sio0(UPD7201(config, "sio0", XTAL(4'000'000)));
- sio0.out_txdb_callback().set("rs232p1", FUNC(rs232_port_device::write_txd));
- sio0.out_dtrb_callback().set("rs232p1", FUNC(rs232_port_device::write_dtr));
- sio0.out_rtsb_callback().set("rs232p1", FUNC(rs232_port_device::write_rts));
+ UPD7201(config, m_sio[0], XTAL(4'000'000));
+ m_sio[0]->out_txdb_callback().set("rs232p1", FUNC(rs232_port_device::write_txd));
+ m_sio[0]->out_dtrb_callback().set("rs232p1", FUNC(rs232_port_device::write_dtr));
+ m_sio[0]->out_rtsb_callback().set("rs232p1", FUNC(rs232_port_device::write_rts));
- UPD7201(config, "sio1", XTAL(4'000'000));
+ UPD7201(config, m_sio[1], XTAL(4'000'000));
rs232_port_device &rs232p1(RS232_PORT(config, "rs232p1", default_rs232_devices, "terminal"));
- rs232p1.rxd_handler().set("sio0", FUNC(upd7201_device::rxb_w));
- rs232p1.cts_handler().set("sio0", FUNC(upd7201_device::ctsb_w));
-
- am9513_device &stc(AM9513(config, "stc", 4_MHz_XTAL));
- stc.out1_cb().set("sio0", FUNC(upd7201_device::rxca_w));
- stc.out1_cb().append("sio0", FUNC(upd7201_device::txca_w));
- stc.out2_cb().set("sio0", FUNC(upd7201_device::rxcb_w));
- stc.out2_cb().append("sio0", FUNC(upd7201_device::txcb_w));
- stc.out3_cb().set("sio1", FUNC(upd7201_device::rxca_w));
- stc.out3_cb().append("sio1", FUNC(upd7201_device::txca_w));
- stc.out4_cb().set("sio1", FUNC(upd7201_device::rxcb_w));
- stc.out4_cb().append("sio1", FUNC(upd7201_device::txcb_w));
+ rs232p1.rxd_handler().set(m_sio[0], FUNC(upd7201_device::rxb_w));
+ rs232p1.cts_handler().set(m_sio[0], FUNC(upd7201_device::ctsb_w));
+
+ AM9513(config, m_stc, 4_MHz_XTAL);
+ m_stc->out1_cb().set(m_sio[0], FUNC(upd7201_device::rxca_w));
+ m_stc->out1_cb().append(m_sio[0], FUNC(upd7201_device::txca_w));
+ m_stc->out2_cb().set(m_sio[0], FUNC(upd7201_device::rxcb_w));
+ m_stc->out2_cb().append(m_sio[0], FUNC(upd7201_device::txcb_w));
+ m_stc->out3_cb().set(m_sio[1], FUNC(upd7201_device::rxca_w));
+ m_stc->out3_cb().append(m_sio[1], FUNC(upd7201_device::txca_w));
+ m_stc->out4_cb().set(m_sio[1], FUNC(upd7201_device::rxcb_w));
+ m_stc->out4_cb().append(m_sio[1], FUNC(upd7201_device::txcb_w));
}
@@ -153,9 +141,11 @@ void vme_mzr8300_card_device::device_add_mconfig(machine_config &config)
// LIVE DEVICE
//**************************************************************************
-vme_mzr8300_card_device::vme_mzr8300_card_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, type, tag, owner, clock),
- device_vme_card_interface(mconfig, *this)
+vme_mzr8300_card_device::vme_mzr8300_card_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, type, tag, owner, clock)
+ , device_vme_card_interface(mconfig, *this)
+ , m_sio(*this, "sio%u", 0U)
+ , m_stc(*this, "stc")
{
LOG("%s %s\n", tag, FUNCNAME);
}
@@ -170,24 +160,21 @@ void vme_mzr8300_card_device::device_start()
LOG("%s %s\n", tag(), FUNCNAME);
/* Setup r/w handlers for first SIO in A16 */
- uint32_t base = 0xFF0000;
- // m_vme->static_set_custom_spaces(*this);
-
- m_vme->install_device(vme_device::A16_SC, base + 0, base + 1, // Channel B - Data
- read8smo_delegate(*subdevice<z80sio_device>("sio0"), FUNC(z80sio_device::db_r)),
- write8smo_delegate(*subdevice<z80sio_device>("sio0"), FUNC(z80sio_device::db_w)), 0x00ff);
- m_vme->install_device(vme_device::A16_SC, base + 2, base + 3, // Channel B - Control
- read8smo_delegate(*subdevice<z80sio_device>("sio0"), FUNC(z80sio_device::cb_r)),
- write8smo_delegate(*subdevice<z80sio_device>("sio0"), FUNC(z80sio_device::cb_w)), 0x00ff);
- m_vme->install_device(vme_device::A16_SC, base + 4, base + 5, // Channel A - Data
- read8smo_delegate(*subdevice<z80sio_device>("sio0"), FUNC(z80sio_device::da_r)),
- write8smo_delegate(*subdevice<z80sio_device>("sio0"), FUNC(z80sio_device::da_w)), 0x00ff);
- m_vme->install_device(vme_device::A16_SC, base + 6, base + 7, // Channel A - Control
- read8smo_delegate(*subdevice<z80sio_device>("sio0"), FUNC(z80sio_device::ca_r)),
- write8smo_delegate(*subdevice<z80sio_device>("sio0"), FUNC(z80sio_device::ca_w)), 0x00ff);
- m_vme->install_device(vme_device::A16_SC, base + 0x10, base + 0x13, // Am9513
- read8sm_delegate(*subdevice<am9513_device>("stc"), FUNC(am9513_device::read8)),
- write8sm_delegate(*subdevice<am9513_device>("stc"), FUNC(am9513_device::write8)), 0x00ff);
+ vme_space(vme::AM_29).install_readwrite_handler(0, 1, // Channel B - Data
+ read8smo_delegate(m_sio[0], FUNC(z80sio_device::db_r)),
+ write8smo_delegate(m_sio[0], FUNC(z80sio_device::db_w)), 0x00ff);
+ vme_space(vme::AM_29).install_readwrite_handler(2, 3, // Channel B - Control
+ read8smo_delegate(m_sio[0], FUNC(z80sio_device::cb_r)),
+ write8smo_delegate(m_sio[0], FUNC(z80sio_device::cb_w)), 0x00ff);
+ vme_space(vme::AM_29).install_readwrite_handler(4, 5, // Channel A - Data
+ read8smo_delegate(m_sio[0], FUNC(z80sio_device::da_r)),
+ write8smo_delegate(m_sio[0], FUNC(z80sio_device::da_w)), 0x00ff);
+ vme_space(vme::AM_29).install_readwrite_handler(6, 7, // Channel A - Control
+ read8smo_delegate(m_sio[0], FUNC(z80sio_device::ca_r)),
+ write8smo_delegate(m_sio[0], FUNC(z80sio_device::ca_w)), 0x00ff);
+ vme_space(vme::AM_29).install_readwrite_handler(0x10, 0x13, // Am9513
+ read8sm_delegate(m_stc, FUNC(am9513_device::read8)),
+ write8sm_delegate(m_stc, FUNC(am9513_device::write8)), 0x00ff);
}
void vme_mzr8300_card_device::device_reset()
diff --git a/src/devices/bus/vme/vme_mzr8300.h b/src/devices/bus/vme/mzr8300.h
index d551bb2f077..31dc17752aa 100644
--- a/src/devices/bus/vme/vme_mzr8300.h
+++ b/src/devices/bus/vme/mzr8300.h
@@ -1,11 +1,13 @@
// license:BSD-3-Clause
// copyright-holders:Joakim Larsson Edstrom
-#ifndef MAME_BUS_VME_VME_MZR8300_H
-#define MAME_BUS_VME_VME_MZR8300_H
+#ifndef MAME_BUS_VME_MZR8300_H
+#define MAME_BUS_VME_MZR8300_H
#pragma once
#include "bus/vme/vme.h"
+#include "machine/am9513.h"
+#include "machine/z80sio.h"
DECLARE_DEVICE_TYPE(VME_MZR8300, vme_mzr8300_card_device)
@@ -25,6 +27,10 @@ protected:
// optional information overrides
virtual void device_add_mconfig(machine_config &config) override;
+
+private:
+ required_device_array<upd7201_device, 2> m_sio;
+ required_device<am9513_device> m_stc;
};
-#endif // MAME_BUS_VME_VME_MZR8300_H
+#endif // MAME_BUS_VME_MZR8300_H
diff --git a/src/devices/bus/vme/vme_smvme2000.cpp b/src/devices/bus/vme/smvme2000.cpp
index ddce242739a..76948574f74 100644
--- a/src/devices/bus/vme/vme_smvme2000.cpp
+++ b/src/devices/bus/vme/smvme2000.cpp
@@ -16,14 +16,14 @@
*/
#include "emu.h"
-#include "vme_smvme2000.h"
+#include "smvme2000.h"
#define VERBOSE 0
#include "logmacro.h"
-DEFINE_DEVICE_TYPE(VME_SMVME2000, vme_smvme2000_device, "smvme2000", "Signetics SMVME2000")
+DEFINE_DEVICE_TYPE(VME_SMVME2000, vme_smvme2000_card_device, "smvme2000", "Signetics SMVME2000")
-vme_smvme2000_device::vme_smvme2000_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
+vme_smvme2000_card_device::vme_smvme2000_card_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
: device_t(mconfig, VME_SMVME2000, tag, owner, clock)
, device_vme_card_interface(mconfig, *this)
, m_cpu(*this, "cpu")
@@ -49,22 +49,22 @@ ROM_END
static INPUT_PORTS_START(smvme2000)
INPUT_PORTS_END
-const tiny_rom_entry *vme_smvme2000_device::device_rom_region() const
+const tiny_rom_entry *vme_smvme2000_card_device::device_rom_region() const
{
return ROM_NAME(smvme2000);
}
-ioport_constructor vme_smvme2000_device::device_input_ports() const
+ioport_constructor vme_smvme2000_card_device::device_input_ports() const
{
return INPUT_PORTS_NAME(smvme2000);
}
-void vme_smvme2000_device::device_start()
+void vme_smvme2000_card_device::device_start()
{
m_fail.resolve();
}
-void vme_smvme2000_device::device_reset()
+void vme_smvme2000_card_device::device_reset()
{
/*
* FIXME: EPROM is mapped at the start of memory during reset to allow the
@@ -87,11 +87,11 @@ void vme_smvme2000_device::device_reset()
});
}
-void vme_smvme2000_device::device_add_mconfig(machine_config &config)
+void vme_smvme2000_card_device::device_add_mconfig(machine_config &config)
{
M68000(config, m_cpu, 16_MHz_XTAL / 2);
- m_cpu->set_addrmap(AS_PROGRAM, &vme_smvme2000_device::cpu_mem);
- m_cpu->set_addrmap(m68000_base_device::AS_CPU_SPACE, &vme_smvme2000_device::cpu_int);
+ m_cpu->set_addrmap(AS_PROGRAM, &vme_smvme2000_card_device::cpu_mem);
+ m_cpu->set_addrmap(m68000_base_device::AS_CPU_SPACE, &vme_smvme2000_card_device::cpu_int);
SCN2681(config, m_duart, 3.6864_MHz_XTAL);
m_duart->irq_cb().set(m_pit, FUNC(pit68230_device::h3_w)); // TODO: verify destination
@@ -114,7 +114,7 @@ void vme_smvme2000_device::device_add_mconfig(machine_config &config)
m_serial[1]->rxd_handler().set(m_duart, FUNC(scn2681_device::rx_b_w));
}
-void vme_smvme2000_device::cpu_mem(address_map &map)
+void vme_smvme2000_card_device::cpu_mem(address_map &map)
{
map(0x000000, 0x000fff).ram().share("ram");
@@ -126,7 +126,7 @@ void vme_smvme2000_device::cpu_mem(address_map &map)
//map(0xf90000, 0xf9ffff).mirror(0x060000); // VMEbus short I/O space
}
-void vme_smvme2000_device::cpu_int(address_map &map)
+void vme_smvme2000_card_device::cpu_int(address_map &map)
{
map(0xfffff3, 0xfffff3).lr8(NAME([]() { return m68000_base_device::autovector(1); }));
map(0xfffff5, 0xfffff5).lr8(NAME([]() { return m68000_base_device::autovector(2); }));
diff --git a/src/devices/bus/vme/vme_smvme2000.h b/src/devices/bus/vme/smvme2000.h
index cffea3cb469..8f60abc0739 100644
--- a/src/devices/bus/vme/vme_smvme2000.h
+++ b/src/devices/bus/vme/smvme2000.h
@@ -15,12 +15,12 @@
#include "bus/rs232/rs232.h"
-class vme_smvme2000_device
+class vme_smvme2000_card_device
: public device_t
, public device_vme_card_interface
{
public:
- vme_smvme2000_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+ vme_smvme2000_card_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
protected:
// device_t overrides
@@ -49,6 +49,6 @@ private:
memory_passthrough_handler m_boot;
};
-DECLARE_DEVICE_TYPE(VME_SMVME2000, vme_smvme2000_device)
+DECLARE_DEVICE_TYPE(VME_SMVME2000, vme_smvme2000_card_device)
#endif // MAME_BUS_VME_SMVME2000_H
diff --git a/src/devices/bus/vme/sys68k_cpu1.cpp b/src/devices/bus/vme/sys68k_cpu1.cpp
new file mode 100644
index 00000000000..090701cfb2f
--- /dev/null
+++ b/src/devices/bus/vme/sys68k_cpu1.cpp
@@ -0,0 +1,670 @@
+// license:BSD-3-Clause
+// copyright-holders:Joakim Larsson Edstrom
+/***************************************************************************
+ *
+ * Force SYS68K CPU-1/CPU-6 VME SBC drivers, initially based on the 68ksbc.c
+ *
+ * 13/06/2015
+ *
+ * The info found on the links below is for a later revisions of the board I have
+ * but it is somewhat compatible so I got the system ROM up and running in terminal.
+ * My CPU-1 board has proms from 1983 and the PCB has no rev markings so probably
+ * the original or a very early design. The board real estate differs from the later
+ * CPU-1:s I found pictures of but has the same main chips and functions.
+ *
+ * http://bitsavers.trailing-edge.com/pdf/forceComputers/1988_Force_VMEbus_Products.pdf
+ * http://www.artisantg.com/info/P_wUovN.pdf
+ *
+ * Some info from those documents:
+ *
+ * Address Map
+ * ----------------------------------------------------------
+ * Address Range Description
+ * ----------------------------------------------------------
+ * 000 000 - 000 007 Initialisation vectors from system EPROM
+ * 000 008 - 01F FFF Dynamic RAM on CPU-1 B
+ * 000 008 - 07F FFF Dynamic RAM on CPU-1 D
+ * 080 008 - 09F FFF SYSTEM EPROM Area
+ * OAO 000 - OBF FFF USER EPROMArea
+ * 0C0 041 - 0C0 043 ACIA (P3) Host
+ * 0C0 080 - 0C0 082 ACIA (P4) Terminal
+ * 0C0 101 - 0C0 103 ACIA (P5) Remote device (eg serial printer)
+ * 0C0 401 - 0C0 42F RTC
+ * OEO 001 - 0E0 035 PI/T (eg centronics printer)
+ * OEO 200 - 0E0 2FF FPU
+ * OEO 300 - 0E0 300 Reset Off
+ * OEO 380 - 0E0 380 Reset On
+ * 100 000 - FEF FFF VMEbus addresses (A24)
+ * FFO 000 - FFF FFF VMEbus Short I/O (A16)
+ * ----------------------------------------------------------
+ *
+ * Interrupt sources
+ * ----------------------------------------------------------
+ * Description Device Lvl IRQ VME board
+ * /Board Vector Address
+ * ----------------------------------------------------------
+ * On board Sources
+ * ABORT Switch 7 31
+ * Real Time Clock (RTC) 58167A 6 30
+ * Parallel/Timer (PI/T) 68230 5 29
+ * Terminal ACIA 6850 4 28
+ * Remote ACIA 6850 3 27
+ * Host ACIA 6850 2 26
+ * ACFAIL, SYSFAIL VME 5 29
+ * Off board Sources (other VME boards)
+ * 6 Port Serial I/O board SIO 4 64-75 0xb00000
+ * 8 Port Serial I/O board ISIO 4 76-83 0x960000
+ * Disk Controller WFC 3 119 0xb01000
+ * SCSI Controller ISCSI 4 119 0xa00000
+ * Slot 1 Controller Board ASCU 7 31 0xb02000
+ * ----------------------------------------------------------
+ *
+ * TODO:
+ * - Add internal layout with switches and leds
+ *
+ ****************************************************************************/
+
+#include "emu.h"
+#include "sys68k_cpu1.h"
+
+#include "bus/rs232/rs232.h"
+#include "cpu/m68000/m68000.h"
+#include "machine/clock.h"
+#include "softlist.h"
+
+/*
+ * The baudrate on the Force68k CPU-1 to CPU-6 is generated by a Motorola 14411 bitrate generator
+ * The CPU-6 documents matches the circuits that I could find on the CPU-1 board.
+ *
+ * From the documents:
+ *
+ * 3 RS232C interfaces, strap selectable baud rate from 110-9600 or 600-19200 baud (CPU-1B datasheet)
+ * or
+ * 3 RS232C interfaces, strap selectable baud rate from 60-9600 or 240-38400 baud (CPU-6 Users manual)
+ *
+ * Default Jumper Settings of B7:
+ * --------------------------------
+ * GND 10 - 11 RSA input on 14411
+ * F1 on 14411 1 - 20 Baud selector of the terminal port
+ * F1 on 14411 3 - 18 Baud selector of the host port
+ * F1 on 14411 5 - 16 Baud selector of the remote port
+ *
+ * The RSB input on the 14411 is kept high always so RSA=0, RSB=1 and a 1.8432MHz crystal
+ * generates 153600 on the F1 output pin which by default strapping is connected to all
+ * three 6850 acias on the board. These can be strapped separatelly to speedup downloads.
+ *
+ * The selectable outputs from 14411, F1-F16:
+ * X16 RSA=0,RSB=1: 153600, 115200, 76800, 57600, 38400, 28800, 19200, 9600, 4800, 3200, 2153.3, 1758.8, 1200, 921600, 1843000
+ * X64 RSA=1,RSB=1: 614400, 460800, 307200, 230400, 153600, 115200, 76800, 57600, 38400, 28800, 19200, 9600, 4800, 921600, 1843000
+ *
+ * However, the datasheet says baudrate is strapable for 110-9600 but the output is 153600
+ * so the system rom MUST setup the acia to divide by 16 to generate the correct baudrate.
+ *
+ * There are multiple ways to achieve some of the baud rates and we have only seen a CPU-6 users manual so
+ * emulation mimics a CPU-6 board at the moment until further information has been gathered.
+ */
+
+//**************************************************************************
+// CONFIGURABLE LOGGING
+//**************************************************************************
+
+#define LOG_SETUP (1U << 1)
+
+//#define VERBOSE (LOG_GENERAL | LOG_SETUP)
+//#define LOG_OUTPUT_FUNC printf
+#include "logmacro.h"
+
+// #define LOG(...) LOGMASKED(LOG_SETUP, __VA_ARGS__) // defined in logmacro.h
+#define LOGSETUP(...) LOGMASKED(LOG_SETUP, __VA_ARGS__)
+
+//**************************************************************************
+// MACROS / CONSTANTS
+//**************************************************************************
+
+#ifdef _MSC_VER
+#define FUNCNAME __func__
+#else
+#define FUNCNAME __PRETTY_FUNCTION__
+#endif
+
+
+DEFINE_DEVICE_TYPE(VME_SYS68K_CPU1, vme_sys68k_cpu1_card_device, "sys68k_cpu1", "Force Computers SYS68K/CPU-1")
+
+vme_sys68k_cpu1_card_device::vme_sys68k_cpu1_card_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, VME_SYS68K_CPU1, tag, owner, clock)
+ , device_vme_card_interface(mconfig, *this)
+ , m_maincpu(*this, "maincpu")
+ , m_rtc(*this, "rtc")
+ , m_pit(*this, "pit")
+ , m_brg(*this, "brg")
+ , m_aciahost(*this, "aciahost")
+ , m_aciaterm(*this, "aciaterm")
+ , m_aciaremt(*this, "aciaremt")
+ , m_centronics(*this, "centronics")
+ , m_centronics_ack(0)
+ , m_centronics_busy(0)
+ , m_centronics_perror(0)
+ , m_centronics_select(0)
+ , m_serial_brf(*this, "SERIAL_BRF")
+ , m_serial_p3(*this, "SERIAL_P3")
+ , m_serial_p4(*this, "SERIAL_P4")
+ , m_serial_p5(*this, "SERIAL_P5")
+ , m_cart(*this, "exp_rom1")
+ , m_eprom(*this, "eprom")
+ , m_ram(*this, "ram")
+{
+}
+
+void vme_sys68k_cpu1_card_device::force68k_mem(address_map &map)
+{
+ map.unmap_value_high();
+ map(0x000000, 0x01ffff).ram().share("ram"); /* DRAM CPU-1B */
+// map(0x020000, 0x07ffff).ram(); /* Additional DRAM CPU-1D */
+ map(0x080000, 0x09ffff).rom().region("eprom", 0); /* System EPROM Area 128Kb DEBUGGER supplied as default on CPU-1B/D */
+ //map(0x0a0000, 0x0bffff).rom().region("user", 0); /* User EPROM/SRAM Area, max 128Kb mapped by a cartslot */
+ map(0x0c0040, 0x0c0043).rw(m_aciahost, FUNC(acia6850_device::read), FUNC(acia6850_device::write)).umask16(0x00ff);
+ map(0x0c0080, 0x0c0083).rw(m_aciaterm, FUNC(acia6850_device::read), FUNC(acia6850_device::write)).umask16(0xff00);
+ map(0x0c0100, 0x0c0103).rw(m_aciaremt, FUNC(acia6850_device::read), FUNC(acia6850_device::write)).umask16(0x00ff);
+ map(0x0c0400, 0x0c042f).rw(m_rtc, FUNC(mm58167_device::read), FUNC(mm58167_device::write)).umask16(0x00ff);
+ map(0x0e0000, 0x0e0035).rw(m_pit, FUNC(pit68230_device::read), FUNC(pit68230_device::write)).umask16(0x00ff);
+// map(0x0e0200, 0x0e0380).rw(FUNC(vme_sys68k_cpu1_card_device::fpu_r), FUNC(vme_sys68k_cpu1_card_device::fpu_w)); /* optional FPCP 68881 FPU interface */
+ map(0x100000, 0xfeffff).rw(FUNC(vme_sys68k_cpu1_card_device::vme_a24_r), FUNC(vme_sys68k_cpu1_card_device::vme_a24_w)); /* VMEbus Rev B addresses (24 bits) */
+ map(0xff0000, 0xffffff).rw(FUNC(vme_sys68k_cpu1_card_device::vme_a16_r), FUNC(vme_sys68k_cpu1_card_device::vme_a16_w)); /* VMEbus Rev B addresses (16 bits) */
+}
+
+/* Input ports */
+static INPUT_PORTS_START (sys68k_cpu1)
+
+ PORT_START("SERIAL_BRF")
+ PORT_CONFNAME(0x80 , 0x00 , "Baud Rate Factor") // RSA pin on MC14411
+ PORT_CONFSETTING(0x00, "1x (Lo)")
+ PORT_CONFSETTING(0x80, "4x (Hi)")
+
+ PORT_START("SERIAL_P3")
+ PORT_CONFNAME(0x0F , 0x00 , "P3 Host Baud Lo/Hi") // F1-Fx pins on MC14411
+ PORT_CONFSETTING(mc14411_device::TIMER_F1, "9600/38400") // RSA=1x/16x
+ PORT_CONFSETTING(mc14411_device::TIMER_F3, "4800/19200")
+ PORT_CONFSETTING(mc14411_device::TIMER_F5, "2400/9600")
+ PORT_CONFSETTING(mc14411_device::TIMER_F7, "1200/4800")
+ PORT_CONFSETTING(mc14411_device::TIMER_F8, "600/2400")
+ PORT_CONFSETTING(mc14411_device::TIMER_F9, "300/1200")
+ PORT_CONFSETTING(mc14411_device::TIMER_F11, "150/600")
+ PORT_CONFSETTING(mc14411_device::TIMER_F13, "110/440")
+ PORT_CONFSETTING(mc14411_device::TIMER_F15, "60/240")
+
+ PORT_START("SERIAL_P4")
+ PORT_CONFNAME(0x0F , 0x00 , "P4 Terminal Baud Lo/Hi") // F1-Fx pins on MC14411
+ PORT_CONFSETTING(mc14411_device::TIMER_F1, "9600/38400") // RSA=1x/16x
+ PORT_CONFSETTING(mc14411_device::TIMER_F3, "4800/19200")
+ PORT_CONFSETTING(mc14411_device::TIMER_F5, "2400/9600")
+ PORT_CONFSETTING(mc14411_device::TIMER_F7, "1200/4800")
+ PORT_CONFSETTING(mc14411_device::TIMER_F8, "600/2400")
+ PORT_CONFSETTING(mc14411_device::TIMER_F9, "300/1200")
+ PORT_CONFSETTING(mc14411_device::TIMER_F11, "150/600")
+ PORT_CONFSETTING(mc14411_device::TIMER_F13, "110/440")
+ PORT_CONFSETTING(mc14411_device::TIMER_F15, "60/240")
+
+ PORT_START("SERIAL_P5")
+ PORT_CONFNAME(0x0F , 0x00 , "P5 Remote Baud Lo/Hi") // F1-Fx pins on MC14411
+ PORT_CONFSETTING(mc14411_device::TIMER_F1, "9600/38400") // RSA=1x/16x
+ PORT_CONFSETTING(mc14411_device::TIMER_F3, "4800/19200")
+ PORT_CONFSETTING(mc14411_device::TIMER_F5, "2400/9600")
+ PORT_CONFSETTING(mc14411_device::TIMER_F7, "1200/4800")
+ PORT_CONFSETTING(mc14411_device::TIMER_F8, "600/2400")
+ PORT_CONFSETTING(mc14411_device::TIMER_F9, "300/1200")
+ PORT_CONFSETTING(mc14411_device::TIMER_F11, "150/600")
+ PORT_CONFSETTING(mc14411_device::TIMER_F13, "110/440")
+ PORT_CONFSETTING(mc14411_device::TIMER_F15, "60/240")
+
+INPUT_PORTS_END
+
+/*
+ * Centronics support
+ *
+ * The system ROMs has support for a parallel printer interface but the signals are just routed to row A
+ * of the VME P2 connector so no on board Centronics connector is available but assumed to be added on a
+ * separate I/O board. After some detective work I found that the ROM works as follows:
+ *
+ * The 'PA' (Printer Attach) command issues a <cr> on Port A and sends a strobe on H2 it then loops over
+ * the select signal, bit 0 on Port B, and the ack signal on HS1, both to be non zero. The support is really
+ * flawed as the strobe signal goes high instead of low ( this might assume an inverting driver on the
+ * P2 board ) and the busy signal is not checked at all. Or I might have assumed it all wrong, but it now
+ * works with the generic centronics printer driver. Need the printer board documentation to improve further.
+ *
+ * When the 'PA' command is successful everything printed to screen is mirrored on the printer. Use the
+ * 'NOPA' command to stop mirroring. I had no printer ROMs so could not test it with a "real" printer.
+ *
+ * Force CPU-1 init sequence for MC68230 PIT
+ * -----------------------------------------
+ * 0801E6 0E0000 W 00 -> PGCR Mode 0 (uni8), H34 dis, H12 dis, H1234 HZ
+ * 0801E6 0E0002 W 00 -> PSRR PC4, PC5, H1S>H2S>H3S>H4S
+ * 0801E6 0E0004 W FF -> PADDR Port A all Outputs
+ * 0801E6 0E0006 W 00 -> PBDDR Port B all Inputs
+ * 0801EA 0E000C W 60 -> PACR Port A Mode 01, pin def, dbfr H1 data rec, H2 status/int, H2 output neg, H2S clrd
+ * 0801F0 0E000E W A0 -> PBCR Port B mode 1x, H4 output neg, H4S clrd, H3 int dis, H3 edg input, H3S set by assrt edg
+ * 0801F6 0E0000 W 30 -> PGCR H34 enable, H12enable
+ * 0801FC 0E000E W A8 -> PBCR +H4 asserted
+ * 08020A 0E000E W A0 -> PBCR +H4 negated
+ *
+ * Upon PA (Printer Attach) command enabling the Centronics printer mode
+ * ---------------------------------------------------------------------
+ * 081DB4 0E0011 W D0 -> PADR Data to Port A
+ * 081DB8 0E000D W 68 -> PACR H2 output asserted Centronics Strobe
+ * 081DC0 0E000D W 60 -> PACR H2 output negated
+ * 081DD0 0E0013 R 00 <- PBDR Port B polled for 01 (data) & 03 (mask)
+ *
+ */
+
+/* Centronics ACK handler
+ * The centronics ack signal is expected by the ROM to arrive at H1 input line
+ */
+void vme_sys68k_cpu1_card_device::centronics_ack_w(int state)
+{
+ LOG("%s(%d)\n", FUNCNAME, state);
+ m_centronics_ack = state;
+ m_pit->h1_set (state);
+}
+
+/* Centronics BUSY handler
+ * The centronics busy signal is not used by the ROM driver afaik
+ */
+void vme_sys68k_cpu1_card_device::centronics_busy_w(int state)
+{
+ LOG("%s(%d)\n", FUNCNAME, state);
+ m_centronics_busy = state;
+}
+
+/* Centronics PERROR handler
+ * The centronics perror signal is not used by the ROM driver afaik
+ */
+void vme_sys68k_cpu1_card_device::centronics_perror_w(int state)
+{
+ LOG("%s(%d)\n", FUNCNAME, state);
+ m_centronics_perror = state;
+}
+
+/* Centronics SELECT handler
+ * The centronics select signal is expected by the ROM on Port B bit 0
+ */
+void vme_sys68k_cpu1_card_device::centronics_select_w(int state)
+{
+ LOG("%s(%d)\n", FUNCNAME, state);
+ m_centronics_select = state;
+ m_pit->portb_setbit (0, state);
+}
+
+/* Start it up */
+void vme_sys68k_cpu1_card_device::device_start ()
+{
+ LOG("%s\n", FUNCNAME);
+
+ save_item (NAME (m_centronics_busy));
+ save_item (NAME (m_centronics_ack));
+ save_item (NAME (m_centronics_select));
+ save_item (NAME (m_centronics_perror));
+
+ /* Map user ROM/RAM socket(s) */
+ if (m_cart->exists())
+ {
+ m_usrrom = (uint16_t*)m_cart->get_rom_base();
+#if 0 // This should be the correct way but produces odd and even bytes swapped
+ m_maincpu->space(AS_PROGRAM).install_read_handler(0xa0000, 0xbffff, read16sm_delegate(*m_cart, FUNC(generic_slot_device::read16_rom)));
+#else // So we install a custom very inefficient handler for now until we understand how to solve the problem better
+ m_maincpu->space(AS_PROGRAM).install_read_handler(0xa0000, 0xbffff, read16sm_delegate(*this, FUNC(vme_sys68k_cpu1_card_device::read16_rom)));
+#endif
+ }
+}
+
+/* Reset it */
+void vme_sys68k_cpu1_card_device::device_reset ()
+{
+ LOG("%s\n", FUNCNAME);
+
+ // Set up the BRG divider. RSA is a jumper setting and RSB is always set High
+ m_brg->rsa_w( m_serial_brf->read() == 0x80 ? ASSERT_LINE : CLEAR_LINE );
+ m_brg->rsb_w( ASSERT_LINE);
+
+ // Disable all configured timers, only enabling the used ones
+ m_brg->timer_disable_all();
+ m_brg->timer_enable((mc14411_device::timer_id) m_serial_p3->read(), true);
+ m_brg->timer_enable((mc14411_device::timer_id) m_serial_p4->read(), true);
+ m_brg->timer_enable((mc14411_device::timer_id) m_serial_p5->read(), true);
+
+ m_maincpu->space(AS_PROGRAM).install_rom(0, m_eprom->bytes() - 1, m_eprom->base());
+
+ m_boot_mph = m_maincpu->space(AS_PROGRAM).install_read_tap(0x000006, 0x000007, "boot",
+ [this](offs_t offset, uint16_t &data, uint16_t mem_mask)
+ {
+ if (!machine().side_effects_disabled() && ACCESSING_BITS_0_7)
+ {
+ m_maincpu->space(AS_PROGRAM).install_ram(0, m_ram.bytes() - 1, m_ram.target());
+ m_boot_mph.remove();
+ }
+ });
+}
+
+/* A very inefficient User cart emulation of two 8 bit sockets (odd and even) */
+uint16_t vme_sys68k_cpu1_card_device::read16_rom(offs_t offset){
+ offset = offset % m_cart->common_get_size("rom"); // Don't read outside buffer...
+ return swapendian_int16(m_usrrom [offset]);
+}
+
+/* 10. The VMEbus (text from board documentation)
+ * ---------------
+ * The implemented VMEbus Interface includes 24 address, 16 data,
+ * 6 address modifier and the asynchronous control signals.
+ * A single level bus arbiter is provided to build multi master
+ * systems. In addition to the bus arbiter, a separate slave bus
+ * arbitration allows selection of the arbitration level (0-3).
+ *
+ * The address modifier range .,Short 110 Access can be selected
+ * via a jumper for variable system generation. The 7 interrupt
+ * request levels of the VMEbus are fully supported from the
+ * SYS68K1CPU-1 B/D. For multi-processing, each IRQ signal can be
+ * enabled/disabled via a jumper field.
+ *
+ * Additionally, the SYS68K1CPU-1 B/D supports the ACFAIL, SYSRESET,
+ * SYSFAIL and SYSCLK signal (16 MHz).
+ */
+
+/* Dummy VME access methods until the VME bus device is ready for use */
+uint16_t vme_sys68k_cpu1_card_device::vme_a24_r()
+{
+ LOG("%s\n", FUNCNAME);
+ return (uint16_t) 0;
+}
+
+void vme_sys68k_cpu1_card_device::vme_a24_w(uint16_t data)
+{
+ LOG("%s\n", FUNCNAME);
+}
+
+uint16_t vme_sys68k_cpu1_card_device::vme_a16_r()
+{
+ LOG("%s\n", FUNCNAME);
+ return (uint16_t) 0;
+}
+
+void vme_sys68k_cpu1_card_device::vme_a16_w(uint16_t data)
+{
+ LOG("%s\n", FUNCNAME);
+}
+
+/*
+ * Serial port clock sources can all be driven by different or the same output(s) of the MC14411
+ */
+void vme_sys68k_cpu1_card_device::write_acia_clocks(int id, int state)
+{
+ if (id == m_serial_p3->read())
+ {
+ m_aciahost->write_txc(state);
+ m_aciahost->write_rxc(state);
+ }
+ if (id == m_serial_p4->read())
+ {
+ m_aciaterm->write_txc(state);
+ m_aciaterm->write_rxc(state);
+ }
+ if (id == m_serial_p5->read())
+ {
+ m_aciaremt->write_txc(state);
+ m_aciaremt->write_rxc(state);
+ }
+}
+
+/*
+ * 4. The USER Area (Text from the board manual)
+ The USER area contains two 28 pin sockets with JEDEC compatible pin out.
+ To allow the usage of static RAM's, the access to the USER area is byte
+ oriented. Table 3. lists the usable device types.
+
+ Bits Bytes EPROM SRAM
+ --------------------------
+ 2Kx16 4 Kbyte 2716 6116
+ 4Kx16 8 Kbyte 2732
+ 8Kx16 16 Kbyte 2764 6264
+ 16Kx16 32 Kbyte 27128
+ 32Kx16 64 Kbyte 27256
+ --------------------------
+*/
+// Implementation of static 2 x 64K EPROM in sockets J10/J11 as 16 bit wide cartridge for easier
+// software handling. TODO: make configurable according to table above.
+void vme_sys68k_cpu1_card_device::fccpu1_eprom_sockets(machine_config &config)
+{
+ generic_cartslot_device &exp_rom1(GENERIC_CARTSLOT(config, "exp_rom1", generic_plain_slot, "fccpu1_cart", "bin,rom"));
+ exp_rom1.set_width(GENERIC_ROM16_WIDTH);
+ exp_rom1.set_endian(ENDIANNESS_BIG);
+ exp_rom1.set_device_load(FUNC(vme_sys68k_cpu1_card_device::exp1_load));
+// SOFTWARE_LIST(config, "cart_list").set_original("fccpu1_cart");
+}
+
+/***************************
+ Rom loading functions
+****************************/
+std::pair<std::error_condition, std::string> vme_sys68k_cpu1_card_device::force68k_load_cart(device_image_interface &image, generic_slot_device *slot)
+{
+ uint32_t size = slot->common_get_size("rom");
+
+ if (size > 0x2'0000) // Max 128Kb
+ {
+ return std::make_pair(
+ image_error::INVALIDLENGTH,
+ util::string_format("Cartridge size %d exceeds max size (128K)", size));
+ }
+
+ slot->rom_alloc(size, GENERIC_ROM16_WIDTH, ENDIANNESS_BIG);
+ slot->common_load_rom(slot->get_rom_base(), size, "rom");
+
+ return std::make_pair(std::error_condition(), std::string());
+}
+
+/*
+ * Machine configuration
+ */
+void vme_sys68k_cpu1_card_device::device_add_mconfig(machine_config &config)
+{
+ /* basic machine hardware */
+ M68000(config, m_maincpu, XTAL(16'000'000) / 2);
+ m_maincpu->set_addrmap(AS_PROGRAM, &vme_sys68k_cpu1_card_device::force68k_mem);
+
+ /* P3/Host Port config
+ * LO command causes ROM monitor to expect S-records on HOST port by default
+ * Implementation through nullmodem currently does not support handshakes so
+ * the ROM monitor is over-run while checking for checksums etc if used with
+ * UI mount <file> feature.
+ */
+ ACIA6850(config, m_aciahost, 0);
+ m_aciahost->txd_handler().set("rs232host", FUNC(rs232_port_device::write_txd));
+ m_aciahost->rts_handler().set("rs232host", FUNC(rs232_port_device::write_rts));
+
+ rs232_port_device &rs232host(RS232_PORT(config, "rs232host", default_rs232_devices, "null_modem"));
+ rs232host.rxd_handler().set(m_aciahost, FUNC(acia6850_device::write_rxd));
+ rs232host.cts_handler().set(m_aciahost, FUNC(acia6850_device::write_cts));
+
+ /* P4/Terminal Port config */
+ ACIA6850(config, m_aciaterm, 0);
+ m_aciaterm->txd_handler().set("rs232trm", FUNC(rs232_port_device::write_txd));
+ m_aciaterm->rts_handler().set("rs232trm", FUNC(rs232_port_device::write_rts));
+
+ rs232_port_device &rs232trm(RS232_PORT(config, "rs232trm", default_rs232_devices, "terminal"));
+ rs232trm.rxd_handler().set(m_aciaterm, FUNC(acia6850_device::write_rxd));
+ rs232trm.cts_handler().set(m_aciaterm, FUNC(acia6850_device::write_cts));
+
+ /* P5/Remote Port config */
+ ACIA6850(config, m_aciaremt, 0);
+
+ /* Bit Rate Generator */
+ MC14411(config, m_brg, XTAL(1'843'200));
+ m_brg->out_f<1>().set(FUNC(vme_sys68k_cpu1_card_device::write_f1_clock));
+ m_brg->out_f<3>().set(FUNC(vme_sys68k_cpu1_card_device::write_f3_clock));
+ m_brg->out_f<5>().set(FUNC(vme_sys68k_cpu1_card_device::write_f5_clock));
+ m_brg->out_f<7>().set(FUNC(vme_sys68k_cpu1_card_device::write_f7_clock));
+ m_brg->out_f<8>().set(FUNC(vme_sys68k_cpu1_card_device::write_f8_clock));
+ m_brg->out_f<9>().set(FUNC(vme_sys68k_cpu1_card_device::write_f9_clock));
+ m_brg->out_f<11>().set(FUNC(vme_sys68k_cpu1_card_device::write_f11_clock));
+ m_brg->out_f<13>().set(FUNC(vme_sys68k_cpu1_card_device::write_f13_clock));
+ m_brg->out_f<15>().set(FUNC(vme_sys68k_cpu1_card_device::write_f15_clock));
+
+ /* RTC Real Time Clock device */
+ MM58167(config, m_rtc, XTAL(32'768));
+
+ /* PIT Parallel Interface and Timer device, assuming strapped for on board clock */
+ PIT68230(config, m_pit, XTAL(16'000'000) / 2);
+ m_pit->pa_out_callback().set("cent_data_out", FUNC(output_latch_device::write));
+ m_pit->h2_out_callback().set(m_centronics, FUNC(centronics_device::write_strobe));
+
+ // Centronics
+ CENTRONICS(config, m_centronics, centronics_devices, "printer");
+ m_centronics->ack_handler().set(FUNC(vme_sys68k_cpu1_card_device::centronics_ack_w));
+ m_centronics->busy_handler().set(FUNC(vme_sys68k_cpu1_card_device::centronics_busy_w));
+ m_centronics->perror_handler().set(FUNC(vme_sys68k_cpu1_card_device::centronics_perror_w));
+ m_centronics->select_handler().set(FUNC(vme_sys68k_cpu1_card_device::centronics_select_w));
+
+ output_latch_device &latch(OUTPUT_LATCH(config, "cent_data_out"));
+ m_centronics->set_output_latch(latch);
+
+ // EPROM sockets
+ fccpu1_eprom_sockets(config);
+}
+
+#if 0 /*
+ * CPU-6 family is device and adressmap compatible with CPU-1 but with additions
+ * such as an optional 68881 FPU
+ */
+void vme_sys68k_cpu1_card_device::fccpu6(machine_config &config)
+{
+ M68000(config, m_maincpu, XTAL(8'000'000)); /* Jumper B10 Mode B */
+ m_maincpu->set_addrmap(AS_PROGRAM, &vme_sys68k_cpu1_card_device::force68k_mem);
+}
+
+void vme_sys68k_cpu1_card_device::fccpu6a(machine_config &config)
+{
+ M68000(config, m_maincpu, XTAL(12'500'000)); /* Jumper B10 Mode A */
+ m_maincpu->set_addrmap(AS_PROGRAM, &vme_sys68k_cpu1_card_device::force68k_mem);
+}
+
+void vme_sys68k_cpu1_card_device::fccpu6v(machine_config &config)
+{
+ M68010(config, m_maincpu, XTAL(8'000'000)); /* Jumper B10 Mode B */
+ m_maincpu->set_addrmap(AS_PROGRAM, &vme_sys68k_cpu1_card_device::force68k_mem);
+}
+
+void vme_sys68k_cpu1_card_device::fccpu6va(machine_config &config)
+{
+ M68010(config, m_maincpu, XTAL(12'500'000)); /* Jumper B10 Mode A */
+ m_maincpu->set_addrmap(AS_PROGRAM, &vme_sys68k_cpu1_card_device::force68k_mem);
+}
+
+void vme_sys68k_cpu1_card_device::fccpu6vb(machine_config &config)
+{
+ M68010(config, m_maincpu, XTAL(12'500'000)); /* Jumper B10 Mode A */
+ m_maincpu->set_addrmap(AS_PROGRAM, &vme_sys68k_cpu1_card_device::force68k_mem);
+}
+#endif
+
+/* ROM definitions */
+ROM_START (sys68k_cpu1)
+ ROM_REGION16_BE(0x20000, "eprom", 0)
+ ROM_DEFAULT_BIOS("forcebug-1.1")
+
+ ROM_SYSTEM_BIOS(0, "forcemon-1.0l", "Force Computers SYS68K/CPU-1 Force Monitor 1.0L")
+ ROMX_LOAD ("fccpu1v1.0l.j8.bin", 0x0001, 0x2000, CRC (3ac6f08f) SHA1 (502f6547b508d8732bd68bbbb2402d8c30fefc3b), ROM_SKIP(1) | ROM_BIOS(0))
+ ROMX_LOAD ("fccpu1v1.0l.j9.bin", 0x0000, 0x2000, CRC (035315fb) SHA1 (90dc44d9c25d28428233e6846da6edce2d69e440), ROM_SKIP(1) | ROM_BIOS(0))
+
+ ROM_SYSTEM_BIOS(1, "forcebug-1.1", "Force Computers SYS68K/CPU-1 Force Debugger 1.1")
+ ROMX_LOAD ("fccpu1v1.1.j8.bin", 0x0001, 0x4000, CRC (116dcbf0) SHA1 (6870b71606933f84afe27ad031c651d201b93f99), ROM_SKIP(1) | ROM_BIOS(1))
+ ROMX_LOAD ("fccpu1v1.1.j9.bin", 0x0000, 0x4000, CRC (aefd5b0b) SHA1 (1e24530a6d5dc4fb77fde67acae08d371e59fc0f), ROM_SKIP(1) | ROM_BIOS(1))
+
+/*
+ * System ROM terminal commands
+ *
+ * COMMAND SUMMARY DESCRIPTION (From CPU-1B datasheet, ROMs were dumped
+ * from a CPU-1 board so some features might be missing or different)
+ * ---------------------------------------------------------------------------
+ * BF <address1> <address2> <data> <CR> Block Fill memory - from addr1 through addr2 with data
+ * BM <address1> <address2> <address 3> <CR> Block Move - move from addr1 through addr2to addr3
+ * BR [<address> [; <count>] ... ] <CR> Set/display Breakpoint
+ * BS <address1> <address2> <data> <CR> Block Search - search addr1 through addr2 for data
+ * BT <address1> <address2> <CR> Block Test of memory
+ * DC <expression> <CR> Data Conversion
+ * DF <CR> Display Formatted registers
+ * DU [n] <address1> <address2>[<string>] <CR> Dump memory to object file
+ * GO or G [<address] <CR> Execute program.
+ * GD [<address] <CR> Go Direct
+ * GT <address> <CR> Exec prog: temporary breakpoint
+ * HE<CR> Help; display monitor commands
+ * LO [n] [;<options] <CR> Load Object file
+ * MD <address> [<count>] <CR> Memory Display
+ * MM or M <address> [<data<][;<options>] <CR> Memory Modify
+ * MS <address> <data1 > <data2> < ... <CR> Memory Set - starting at addr with data 1. data 2 ...
+ * NOBR [<address> ... ] <CR> Remove Breakpoint
+ * NOPA <CR> Printer Detach (Centronics on PIT/P2)
+ * OF <CR> Offset
+ * PA <CR> Printer Attach (Centronics on PIT/P2)
+ * PF[n] <CR> Set/display Port Format
+ * RM <CR> Register Modify
+ * TM [<exit character>] <CR> Transparent Mode
+ * TR OR T [<count] <CR> Trace
+ * TT <address> <CR> Trace: temporary breakpoint
+ * VE [n] [<string] <CR> Verify memory/object file
+ * ----------------------------------------------------------------------------
+ * .AO - .A7 [<expression] <CR> Display/set address register
+ * .00 - .07 [<expression] <CR> Display/set data register
+ * .RO - .R6 [<expression] <CR> Display/set offset register
+ * .PC [<expression] <CR> Display/set program counter
+ * .SR [<expression] <CR> Display/set status register
+ * .SS [<expression] <CR> Display/set supervisor stack
+ * .US [<expression] <CR> Display/set user stack
+ * ----------------------------------------------------------------------------
+ * MD <address> [<count>]; DI <CR> Disassemble memory location
+ * MM <address>; DI <CR> Disassemble/Assemble memory location
+ * ----------------------------------------------------------------------------
+ * Undocumented commands found in ROM table at address 0x80308
+ * .* No WHAT message displayed, no action seen.
+ */
+ROM_END
+
+/*
+ * CPU-6 ROMs were generally based om VMEPROM which contained the PDOS RTOS from Eyring Research.
+ * I don't have these but if anyone can dump them and send to me I can verify that they work as expected.
+ */
+#if 0
+ROM_START (fccpu6)
+ ROM_REGION (0x1000000, "maincpu", 0)
+ROM_END
+
+ROM_START (fccpu6a)
+ ROM_REGION (0x1000000, "maincpu", 0)
+ROM_END
+
+ROM_START (fccpu6v)
+ ROM_REGION (0x1000000, "maincpu", 0)
+ROM_END
+
+ROM_START (fccpu6va)
+ ROM_REGION (0x1000000, "maincpu", 0)
+ROM_END
+
+ROM_START (fccpu6vb)
+ ROM_REGION (0x1000000, "maincpu", 0)
+ROM_END
+#endif
+
+const tiny_rom_entry *vme_sys68k_cpu1_card_device::device_rom_region() const
+{
+ return ROM_NAME(sys68k_cpu1);
+}
+
+ioport_constructor vme_sys68k_cpu1_card_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(sys68k_cpu1);
+}
+
+/* Driver */
+/* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS */
+//COMP( 1983, fccpu1, 0, 0, fccpu1, force68k, vme_sys68k_cpu1_card_device, empty_init, "Force Computers GmbH", "SYS68K/CPU-1", MACHINE_NO_SOUND_HW )
+//COMP( 1989, fccpu6, 0, 0, fccpu6, force68k, vme_sys68k_cpu1_card_device, empty_init, "Force Computers GmbH", "SYS68K/CPU-6", MACHINE_IS_SKELETON )
+//COMP( 1989, fccpu6a, 0, 0, fccpu6a, force68k, vme_sys68k_cpu1_card_device, empty_init, "Force Computers GmbH", "SYS68K/CPU-6a", MACHINE_IS_SKELETON )
+//COMP( 1989, fccpu6v, 0, 0, fccpu6v, force68k, vme_sys68k_cpu1_card_device, empty_init, "Force Computers GmbH", "SYS68K/CPU-6v", MACHINE_IS_SKELETON )
+//COMP( 1989, fccpu6va, 0, 0, fccpu6va, force68k, vme_sys68k_cpu1_card_device, empty_init, "Force Computers GmbH", "SYS68K/CPU-6va", MACHINE_IS_SKELETON )
+//COMP( 1989, fccpu6vb, 0, 0, fccpu6vb, force68k, vme_sys68k_cpu1_card_device, empty_init, "Force Computers GmbH", "SYS68K/CPU-6vb", MACHINE_IS_SKELETON )
diff --git a/src/devices/bus/vme/sys68k_cpu1.h b/src/devices/bus/vme/sys68k_cpu1.h
new file mode 100644
index 00000000000..4f68fac5dbd
--- /dev/null
+++ b/src/devices/bus/vme/sys68k_cpu1.h
@@ -0,0 +1,97 @@
+// license:BSD-3-Clause
+// copyright-holders:Joakim Larsson Edstrom
+
+#ifndef MAME_BUS_VME_SYS68K_CPU1_H
+#define MAME_BUS_VME_SYS68K_CPU1_H
+
+#pragma once
+
+#include "bus/vme/vme.h"
+
+#include "machine/mm58167.h"
+#include "machine/68230pit.h"
+#include "machine/mc14411.h"
+#include "machine/6850acia.h"
+#include "bus/centronics/ctronics.h"
+#include "bus/generic/carts.h"
+#include "bus/generic/slot.h"
+
+class vme_sys68k_cpu1_card_device
+ : public device_t
+ , public device_vme_card_interface
+{
+public:
+ vme_sys68k_cpu1_card_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual ioport_constructor device_input_ports() const override;
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+private:
+ void fccpu1_eprom_sockets(machine_config &config);
+
+ uint16_t vme_a24_r();
+ void vme_a24_w(uint16_t data);
+ uint16_t vme_a16_r();
+ void vme_a16_w(uint16_t data);
+
+ // Clocks
+ void write_acia_clocks(int id, int state);
+ void write_f1_clock(int state) { write_acia_clocks(mc14411_device::TIMER_F1, state); }
+ void write_f3_clock(int state) { write_acia_clocks(mc14411_device::TIMER_F3, state); }
+ void write_f5_clock(int state) { write_acia_clocks(mc14411_device::TIMER_F5, state); }
+ void write_f7_clock(int state) { write_acia_clocks(mc14411_device::TIMER_F7, state); }
+ void write_f8_clock(int state) { write_acia_clocks(mc14411_device::TIMER_F8, state); }
+ void write_f9_clock(int state) { write_acia_clocks(mc14411_device::TIMER_F9, state); }
+ void write_f11_clock(int state) { write_acia_clocks(mc14411_device::TIMER_F11, state); }
+ void write_f13_clock(int state) { write_acia_clocks(mc14411_device::TIMER_F13, state); }
+ void write_f15_clock(int state) { write_acia_clocks(mc14411_device::TIMER_F15, state); }
+
+ // Centronics printer interface
+ void centronics_ack_w(int state);
+ void centronics_busy_w(int state);
+ void centronics_perror_w(int state);
+ void centronics_select_w(int state);
+
+ // User EPROM/SRAM slot(s)
+ std::pair<std::error_condition, std::string> force68k_load_cart(device_image_interface &image, generic_slot_device *slot);
+ DECLARE_DEVICE_IMAGE_LOAD_MEMBER(exp1_load) { return force68k_load_cart(image, m_cart); }
+ uint16_t read16_rom(offs_t offset);
+
+ void force68k_mem(address_map &map);
+
+ required_device<cpu_device> m_maincpu;
+ required_device<mm58167_device> m_rtc;
+ required_device<pit68230_device> m_pit;
+ required_device<mc14411_device> m_brg;
+ required_device<acia6850_device> m_aciahost;
+ required_device<acia6850_device> m_aciaterm;
+ required_device<acia6850_device> m_aciaremt;
+ optional_device<centronics_device> m_centronics;
+
+ int32_t m_centronics_ack;
+ int32_t m_centronics_busy;
+ int32_t m_centronics_perror;
+ int32_t m_centronics_select;
+
+ // fake inputs for hardware configuration and things that need rewiring
+ required_ioport m_serial_brf;
+ required_ioport m_serial_p3;
+ required_ioport m_serial_p4;
+ required_ioport m_serial_p5;
+
+ uint16_t *m_usrrom;
+
+ required_device<generic_slot_device> m_cart;
+
+ required_memory_region m_eprom;
+ required_shared_ptr<uint16_t> m_ram;
+ memory_passthrough_handler m_boot_mph;
+};
+
+DECLARE_DEVICE_TYPE(VME_SYS68K_CPU1, vme_sys68k_cpu1_card_device)
+
+#endif // MAME_BUS_VME_SYS68K_CPU1_H
diff --git a/src/devices/bus/vme/vme_fccpu20.cpp b/src/devices/bus/vme/sys68k_cpu20.cpp
index c85f6fd6a7f..2273a57920d 100644
--- a/src/devices/bus/vme/vme_fccpu20.cpp
+++ b/src/devices/bus/vme/sys68k_cpu20.cpp
@@ -183,25 +183,21 @@
* - VME bus arbiter as MAME always gets the bus
****************************************************************************/
#include "emu.h"
-#include "vme_fccpu20.h"
+#include "sys68k_cpu20.h"
-#include "cpu/m68000/m68000.h"
+#include "cpu/m68000/m68020.h"
#include "bus/rs232/rs232.h"
#include "machine/68230pit.h"
#include "machine/68153bim.h"
#include "machine/68561mpcc.h"
#include "machine/clock.h"
-//#define LOG_GENERAL (1U << 0)
-#define LOG_SETUP (1U << 1)
-#define LOG_INT (1U << 2)
+#define LOG_INT (1U << 1)
-//#define VERBOSE (LOG_GENERAL | LOG_SETUP | LOG_INT)
+#define VERBOSE (0) // (LOG_GENERAL | LOG_INT)
//#define LOG_OUTPUT_FUNC printf
-
#include "logmacro.h"
-#define LOGSETUP(...) LOGMASKED(LOG_SETUP, __VA_ARGS__)
#define LOGINT(...) LOGMASKED(LOG_INT, __VA_ARGS__)
@@ -210,27 +206,25 @@
// GLOBAL VARIABLES
//**************************************************************************
-DEFINE_DEVICE_TYPE(VME_FCCPU20, vme_fccpu20_card_device, "fccpu20", "Force Computer SYS68K/CPU-20 CPU Board")
-DEFINE_DEVICE_TYPE(VME_FCCPU21S, vme_fccpu21s_card_device, "fccpu21s", "Force Computer SYS68K/CPU-21S CPU Board")
-DEFINE_DEVICE_TYPE(VME_FCCPU21, vme_fccpu21_card_device, "fccpu21", "Force Computer SYS68K/CPU-21 CPU Board")
-DEFINE_DEVICE_TYPE(VME_FCCPU21A, vme_fccpu21a_card_device, "fccpu21a", "Force Computer SYS68K/CPU-21A CPU Board")
-DEFINE_DEVICE_TYPE(VME_FCCPU21YA, vme_fccpu21ya_card_device, "fccpu21ya", "Force Computer SYS68K/CPU-21YA CPU Board")
-DEFINE_DEVICE_TYPE(VME_FCCPU21B, vme_fccpu21b_card_device, "fccpu21b", "Force Computer SYS68K/CPU-21B CPU Board")
-DEFINE_DEVICE_TYPE(VME_FCCPU21YB, vme_fccpu21yb_card_device, "fccpu21yb", "Force Computer SYS68K/CPU-21YB CPU Board")
+DEFINE_DEVICE_TYPE(VME_SYS68K_CPU20, vme_sys68k_cpu20_card_device, "sys68k_cpu20", "Force Computers SYS68K/CPU-20")
+DEFINE_DEVICE_TYPE(VME_SYS68K_CPU21S, vme_sys68k_cpu21s_card_device, "sys68k_cpu21s", "Force Computers SYS68K/CPU-21S")
+DEFINE_DEVICE_TYPE(VME_SYS68K_CPU21, vme_sys68k_cpu21_card_device, "sys68k_cpu21", "Force Computers SYS68K/CPU-21")
+DEFINE_DEVICE_TYPE(VME_SYS68K_CPU21A, vme_sys68k_cpu21a_card_device, "sys68k_cpu21a", "Force Computers SYS68K/CPU-21A")
+DEFINE_DEVICE_TYPE(VME_SYS68K_CPU21YA, vme_sys68k_cpu21ya_card_device, "sys68k_cpu21ya", "Force Computers SYS68K/CPU-21YA")
+DEFINE_DEVICE_TYPE(VME_SYS68K_CPU21B, vme_sys68k_cpu21b_card_device, "sys68k_cpu21b", "Force Computers SYS68K/CPU-21B")
+DEFINE_DEVICE_TYPE(VME_SYS68K_CPU21YB, vme_sys68k_cpu21yb_card_device, "sys68k_cpu21yb", "Force Computers SYS68K/CPU-21YB")
#define CLOCK50 XTAL(50'000'000) /* HCJ */
#define CLOCK40 XTAL(40'000'000) /* HCJ */
#define CLOCK32 XTAL(32'000'000) /* HCJ */
-void vme_fccpu20_device::cpu20_mem(address_map &map)
+void vme_sys68k_cpu20_card_device_base::cpu20_mem(address_map &map)
{
map.unmap_value_high();
- map(0x00000000, 0x00000007).ram().w(FUNC(vme_fccpu20_device::bootvect_w)); /* After first write we act as RAM */
- map(0x00000000, 0x00000007).rom().r(FUNC(vme_fccpu20_device::bootvect_r)); /* ROM mirror just during reset */
- map(0x00000008, 0x0007ffff).ram(); /* Local SRAM */
+ map(0x00000000, 0x0007ffff).ram().share("ram"); /* Local SRAM */
map(0x00080000, 0x000fffff).ram(); /* SRAM-22 installed */
map(0xff040000, 0xff04ffff).ram();
- map(0xff000000, 0xff00ffff).rom().region("roms", 0x0000);
+ map(0xff000000, 0xff00ffff).rom().region("eprom", 0);
map(0xff800000, 0xff80001f).rw("mpcc", FUNC(mpcc68561_device::read), FUNC(mpcc68561_device::write));
map(0xff800200, 0xff80021f).rw("mpcc2", FUNC(mpcc68561_device::read), FUNC(mpcc68561_device::write));
map(0xff800600, 0xff80061f).rw("mpcc3", FUNC(mpcc68561_device::read), FUNC(mpcc68561_device::write));
@@ -247,28 +241,28 @@ static DEVICE_INPUT_DEFAULTS_START( terminal )
DEVICE_INPUT_DEFAULTS( "RS232_STOPBITS", 0xff, RS232_STOPBITS_2 )
DEVICE_INPUT_DEFAULTS_END
-void vme_fccpu20_device::cpu_space_map(address_map &map)
+void vme_sys68k_cpu20_card_device_base::cpu_space_map(address_map &map)
{
map(0xfffffff2, 0xffffffff).lr16(NAME([this](offs_t offset) -> u16 { return m_bim->iack(offset+1); }));
}
-void vme_fccpu20_device::device_add_mconfig(machine_config &config)
+void vme_sys68k_cpu20_card_device_base::device_add_mconfig(machine_config &config)
{
/* basic machine hardware */
M68020(config, m_maincpu, CLOCK50 / 3); /* Crytstal verified from picture HCI */
- m_maincpu->set_addrmap(AS_PROGRAM, &vme_fccpu20_device::cpu20_mem);
- m_maincpu->set_addrmap(m68000_base_device::AS_CPU_SPACE, &vme_fccpu20_device::cpu_space_map);
+ m_maincpu->set_addrmap(AS_PROGRAM, &vme_sys68k_cpu20_card_device_base::cpu20_mem);
+ m_maincpu->set_addrmap(m68000_base_device::AS_CPU_SPACE, &vme_sys68k_cpu20_card_device_base::cpu_space_map);
/* PIT Parallel Interface and Timer device, assumed strapped for on board clock */
PIT68230(config, m_pit, CLOCK32 / 4); /* Crystal not verified */
- m_pit->pa_in_callback().set(FUNC(vme_fccpu20_device::pita_r));
- m_pit->pb_in_callback().set(FUNC(vme_fccpu20_device::pitb_r));
- m_pit->pc_in_callback().set(FUNC(vme_fccpu20_device::pitc_r));
+ m_pit->pa_in_callback().set(FUNC(vme_sys68k_cpu20_card_device_base::pita_r));
+ m_pit->pb_in_callback().set(FUNC(vme_sys68k_cpu20_card_device_base::pitb_r));
+ m_pit->pc_in_callback().set(FUNC(vme_sys68k_cpu20_card_device_base::pitc_r));
m_pit->timer_irq_callback().set("bim", FUNC(bim68153_device::int2_w));
/* BIM */
bim68153_device &bim(MC68153(config, "bim", CLOCK32 / 8));
- bim.out_int_callback().set(FUNC(vme_fccpu20_device::bim_irq_callback));
+ bim.out_int_callback().set(FUNC(vme_sys68k_cpu20_card_device_base::bim_irq_callback));
/*INT0 - Abort switch */
/*INT1 - MPCC@8.064 MHz aswell */
/*INT2 - PI/T timer */
@@ -315,55 +309,55 @@ void vme_fccpu20_device::device_add_mconfig(machine_config &config)
rs232p3.cts_handler().set(m_mpcc3, FUNC(mpcc68561_device::cts_w));
}
-void vme_fccpu20_card_device::device_add_mconfig(machine_config &config)
+void vme_sys68k_cpu20_card_device::device_add_mconfig(machine_config &config)
{
- vme_fccpu20_device::device_add_mconfig(config);
+ vme_sys68k_cpu20_card_device_base::device_add_mconfig(config);
}
// SYS68K/CPU-21S Part No.1 01 041 - 68020 CPU board + FPU 68881 at 12.5 MHz, 512 KB RAM
-void vme_fccpu21s_card_device::device_add_mconfig(machine_config &config)
+void vme_sys68k_cpu21s_card_device::device_add_mconfig(machine_config &config)
{
- vme_fccpu20_device::device_add_mconfig(config);
+ vme_sys68k_cpu20_card_device_base::device_add_mconfig(config);
m_maincpu->set_clock(CLOCK50 / 4);
}
// SYS68K/CPU-21 Part No.1 01 001 - 68020 CPU board (CPU-20) + FPU 68881 at 16.7 MHz, 512 KB RAM
-void vme_fccpu21_card_device::device_add_mconfig(machine_config &config)
+void vme_sys68k_cpu21_card_device::device_add_mconfig(machine_config &config)
{
- vme_fccpu20_device::device_add_mconfig(config);
+ vme_sys68k_cpu20_card_device_base::device_add_mconfig(config);
m_maincpu->set_clock(CLOCK50 / 3);
}
// SYS68K/CPU-21A Part No.1 01 011 - 68020 CPU board + FPU 68881 at 20 MHz, 512 KB RAM
-void vme_fccpu21a_card_device::device_add_mconfig(machine_config &config)
+void vme_sys68k_cpu21a_card_device::device_add_mconfig(machine_config &config)
{
- vme_fccpu20_device::device_add_mconfig(config);
+ vme_sys68k_cpu20_card_device_base::device_add_mconfig(config);
m_maincpu->set_clock(CLOCK40 / 2);
}
// SYS68K/CPU-21YA Part No.1 01 061 - 68020 CPU board + FPU 68881 at 20 MHz, 2048 KB RAM
-void vme_fccpu21ya_card_device::device_add_mconfig(machine_config &config)
+void vme_sys68k_cpu21ya_card_device::device_add_mconfig(machine_config &config)
{
- vme_fccpu20_device::device_add_mconfig(config);
+ vme_sys68k_cpu20_card_device_base::device_add_mconfig(config);
m_maincpu->set_clock(CLOCK40 / 2);
}
// SYS68K/CPU-21B Part No.1 01 021 - 68020 CPU board + FPU 68881 at 25 MHz, 512 KB RAM
-void vme_fccpu21b_card_device::device_add_mconfig(machine_config &config)
+void vme_sys68k_cpu21b_card_device::device_add_mconfig(machine_config &config)
{
- vme_fccpu20_device::device_add_mconfig(config);
+ vme_sys68k_cpu20_card_device_base::device_add_mconfig(config);
m_maincpu->set_clock(CLOCK50 / 2);
}
// SYS68K/CPU-21YB Part No.1 01 071 - 68020 CPU board + FPU 68881 at 25 MHz, 2048 KB RAM
-void vme_fccpu21yb_card_device::device_add_mconfig(machine_config &config)
+void vme_sys68k_cpu21yb_card_device::device_add_mconfig(machine_config &config)
{
- vme_fccpu20_device::device_add_mconfig(config);
+ vme_sys68k_cpu20_card_device_base::device_add_mconfig(config);
m_maincpu->set_clock(CLOCK50 / 2);
}
@@ -372,7 +366,7 @@ void vme_fccpu21yb_card_device::device_add_mconfig(machine_config &config)
//**************************************************************************
// Base Device
//**************************************************************************
-vme_fccpu20_device::vme_fccpu20_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, fc_board_t board_id) :
+vme_sys68k_cpu20_card_device_base::vme_sys68k_cpu20_card_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, fc_board_t board_id) :
device_t(mconfig, type, tag, owner, clock)
, device_vme_card_interface(mconfig, *this)
, m_maincpu (*this, "maincpu")
@@ -381,73 +375,70 @@ vme_fccpu20_device::vme_fccpu20_device(const machine_config &mconfig, device_typ
, m_mpcc (*this, "mpcc")
, m_mpcc2 (*this, "mpcc2")
, m_mpcc3 (*this, "mpcc3")
+ , m_eprom (*this, "eprom")
+ , m_ram (*this, "ram")
, m_board_id(board_id)
{
- LOG("vme_fccpu20_device ctor\n");
+ LOG("vme_sys68k_cpu20_card_device_base ctor\n");
}
//**************************************************************************
// Card Devices
//**************************************************************************
-vme_fccpu20_card_device::vme_fccpu20_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : vme_fccpu20_card_device(mconfig, VME_FCCPU20, tag, owner, clock)
+vme_sys68k_cpu20_card_device::vme_sys68k_cpu20_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : vme_sys68k_cpu20_card_device(mconfig, VME_SYS68K_CPU20, tag, owner, clock)
{
- LOG("vme_fccpu20_card_device ctor: %s\n", tag);
+ LOG("vme_sys68k_cpu20_card_device ctor: %s\n", tag);
}
-vme_fccpu21s_card_device::vme_fccpu21s_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : vme_fccpu21s_card_device(mconfig, VME_FCCPU21S, tag, owner, clock)
+vme_sys68k_cpu21s_card_device::vme_sys68k_cpu21s_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : vme_sys68k_cpu21s_card_device(mconfig, VME_SYS68K_CPU21S, tag, owner, clock)
{
- LOG("vme_fccpu21s_card_device ctor: %s\n", tag);
+ LOG("vme_sys68k_cpu21s_card_device ctor: %s\n", tag);
}
-vme_fccpu21_card_device::vme_fccpu21_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : vme_fccpu21_card_device(mconfig, VME_FCCPU21, tag, owner, clock)
+vme_sys68k_cpu21_card_device::vme_sys68k_cpu21_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : vme_sys68k_cpu21_card_device(mconfig, VME_SYS68K_CPU21, tag, owner, clock)
{
- LOG("vme_fccpu21_card_device ctor: %s\n", tag);
+ LOG("vme_sys68k_cpu21_card_device ctor: %s\n", tag);
}
-vme_fccpu21a_card_device::vme_fccpu21a_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : vme_fccpu21a_card_device(mconfig, VME_FCCPU21A, tag, owner, clock)
+vme_sys68k_cpu21a_card_device::vme_sys68k_cpu21a_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : vme_sys68k_cpu21a_card_device(mconfig, VME_SYS68K_CPU21A, tag, owner, clock)
{
- LOG("vme_fccpu21a_card_device ctor: %s\n", tag);
+ LOG("vme_sys68k_cpu21a_card_device ctor: %s\n", tag);
}
// TODO: Change to 2MB on board RAM and move FLME memory and find/verify memory map
-vme_fccpu21ya_card_device::vme_fccpu21ya_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : vme_fccpu21ya_card_device(mconfig, VME_FCCPU21YA, tag, owner, clock)
+vme_sys68k_cpu21ya_card_device::vme_sys68k_cpu21ya_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : vme_sys68k_cpu21ya_card_device(mconfig, VME_SYS68K_CPU21YA, tag, owner, clock)
{
- LOG("vme_fccpu21ya_card_device ctor: %s\n", tag);
+ LOG("vme_sys68k_cpu21ya_card_device ctor: %s\n", tag);
}
-vme_fccpu21b_card_device::vme_fccpu21b_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : vme_fccpu21b_card_device(mconfig, VME_FCCPU21B, tag, owner, clock)
+vme_sys68k_cpu21b_card_device::vme_sys68k_cpu21b_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : vme_sys68k_cpu21b_card_device(mconfig, VME_SYS68K_CPU21B, tag, owner, clock)
{
- LOG("vme_fccpu21b_card_device ctor: %s\n", tag);
+ LOG("vme_sys68k_cpu21b_card_device ctor: %s\n", tag);
}
// TODO: Change to 2MB on board RAM and move FLME memory and find/verify memory map
-vme_fccpu21yb_card_device::vme_fccpu21yb_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : vme_fccpu21yb_card_device(mconfig, VME_FCCPU21YB, tag, owner, clock)
+vme_sys68k_cpu21yb_card_device::vme_sys68k_cpu21yb_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : vme_sys68k_cpu21yb_card_device(mconfig, VME_SYS68K_CPU21YB, tag, owner, clock)
{
- LOG("vme_fccpu21yb_card_device ctor: %s\n", tag);
+ LOG("vme_sys68k_cpu21yb_card_device ctor: %s\n", tag);
}
-void vme_fccpu20_device::device_start()
+void vme_sys68k_cpu20_card_device_base::device_start()
{
- LOG("vme_fccpu20_device::device_start\n");
+ LOG("vme_sys68k_cpu20_card_device::device_start\n");
- save_pointer(NAME(m_sysrom), sizeof(m_sysrom));
- save_pointer(NAME(m_sysram), sizeof(m_sysram));
// save_item(NAME(m_board_id)); // TODO: Save this "non base type" item
/* TODO: setup this RAM from (not yet) optional SRAM-2x board and also support 2MB versions */
//m_maincpu->space(AS_PROGRAM).install_ram(0x80000, m_ram->size() + 0x7ffff, m_ram->pointer());
- /* Setup pointer to bootvector in ROM for bootvector handler bootvect_r */
- m_sysrom = (uint32_t*)(memregion("roms")->base());
-
#if 0 // TODO: Setup VME access handlers for shared memory area
uint32_t base = 0xFFFF5000;
m_vme->install_device(base + 0, base + 1, // Channel B - Data
@@ -455,44 +446,41 @@ void vme_fccpu20_device::device_start()
m_vme->install_device(base + 2, base + 3, // Channel B - Control
read8_delegate(*subdevice<z80sio_device>("pit"), FUNC(z80sio_device::cb_r)), write8_delegate(*subdevice<z80sio_device>("pit"), FUNC(z80sio_device::cb_w)), 0x00ff);
#endif
- m_arbiter_start = timer_alloc(FUNC(vme_fccpu20_device::grant_bus), this);
+ m_arbiter_start = timer_alloc(FUNC(vme_sys68k_cpu20_card_device_base::grant_bus), this);
}
-void vme_fccpu20_device::device_reset()
+void vme_sys68k_cpu20_card_device_base::device_reset()
{
- LOG("vme_fccpu20_device::device_reset\n");
+ LOG("vme_sys68k_cpu20_card_device::device_reset\n");
/* We need to delay the static bus grant signal until we have it from the VME interface or MAME supports bus arbitration */
m_arbiter_start->adjust(attotime::from_msec(10));
+
+ m_maincpu->space(AS_PROGRAM).install_rom(0, m_eprom->bytes() - 1, m_eprom->base());
+
+ m_boot_mph = m_maincpu->space(AS_PROGRAM).install_read_tap(0x000004, 0x000007, "boot",
+ [this](offs_t offset, u32 &data, u32 mem_mask)
+ {
+ if (!machine().side_effects_disabled() && ACCESSING_BITS_0_15)
+ {
+ m_maincpu->space(AS_PROGRAM).install_ram(0, m_ram.bytes() - 1, m_ram.target());
+ m_boot_mph.remove();
+ }
+ });
}
//-------------------------------------------------
// grant_bus
//-------------------------------------------------
-TIMER_CALLBACK_MEMBER(vme_fccpu20_device::grant_bus)
+TIMER_CALLBACK_MEMBER(vme_sys68k_cpu20_card_device_base::grant_bus)
{
m_pit->h1_w(ASSERT_LINE); // Grant bus always
}
-/* Boot vector handler, the PCB hardwires the first 8 bytes from 0xff800000 to 0x0 at reset*/
-uint32_t vme_fccpu20_device::bootvect_r(offs_t offset)
-{
- LOG("vme_fccpu20_device::bootvect_r\n");
- return m_sysrom[offset];
-}
-
-void vme_fccpu20_device::bootvect_w(offs_t offset, uint32_t data, uint32_t mem_mask)
-{
- LOG("vme_fccpu20_device::bootvect_w\n");
- m_sysram[offset % std::size(m_sysram)] &= ~mem_mask;
- m_sysram[offset % std::size(m_sysram)] |= (data & mem_mask);
- m_sysrom = &m_sysram[0]; // redirect all upcoming accesses to masking RAM until reset.
-}
-
-WRITE_LINE_MEMBER(vme_fccpu20_device::bim_irq_callback)
+void vme_sys68k_cpu20_card_device_base::bim_irq_callback(int state)
{
- LOGINT("vme_fccpu20_device::bim_irq_callback(%02x)\n", state);
+ LOGINT("vme_sys68k_cpu20_card_device_base::bim_irq_callback(%02x)\n", state);
m_bim_irq_state = state;
m_bim_irq_level = m_bim->get_irq_level();
@@ -500,9 +488,9 @@ WRITE_LINE_MEMBER(vme_fccpu20_device::bim_irq_callback)
update_irq_to_maincpu();
}
-void vme_fccpu20_device::update_irq_to_maincpu()
+void vme_sys68k_cpu20_card_device_base::update_irq_to_maincpu()
{
- LOGINT("vme_fccpu20_device::update_irq_to_maincpu()\n");
+ LOGINT("vme_sys68k_cpu20_card_device_base::update_irq_to_maincpu()\n");
LOGINT(" - m_bim_irq_level: %02x\n", m_bim_irq_level);
LOGINT(" - m_bim_irq_state: %02x\n", m_bim_irq_state);
switch (m_bim_irq_level & 0x07)
@@ -514,7 +502,7 @@ void vme_fccpu20_device::update_irq_to_maincpu()
case 5: m_maincpu->set_input_line(M68K_IRQ_5, m_bim_irq_state); break;
case 6: m_maincpu->set_input_line(M68K_IRQ_6, m_bim_irq_state); break;
case 7: m_maincpu->set_input_line(M68K_IRQ_7, m_bim_irq_state); break;
- default: logerror("Unsupported BIM IRQ line value 0 in vme_fccpu20_device::update_irq_to_maincpu, please report\n");
+ default: logerror("Unsupported BIM IRQ line value 0 in vme_sys68k_cpu20_card_device_base::update_irq_to_maincpu, please report\n");
}
}
@@ -538,26 +526,26 @@ void vme_fccpu20_device::update_irq_to_maincpu()
#define BR8N38400 0x08
#define FORCEBUG 0x30
-uint8_t vme_fccpu20_device::pita_r()
+uint8_t vme_sys68k_cpu20_card_device_base::pita_r()
{
- LOG("vme_fccpu20_device::pita_r\n");
+ LOG("vme_sys68k_cpu20_card_device::pita_r\n");
return FORCEBUG | BR7N9600;
}
/* Enabling/Disabling of VME IRQ 1-7 */
-uint8_t vme_fccpu20_device::pitb_r()
+uint8_t vme_sys68k_cpu20_card_device_base::pitb_r()
{
- LOG("vme_fccpu20_device::pitb_r\n");
+ LOG("vme_sys68k_cpu20_card_device::pitb_r\n");
return 0xff;
}
/* VME board ID bit and bus release software settings (output) (ROR, RAT, RATAR, RATBCLR, RORAT, RORRAT */
/* Bit 4 is bus available */
-uint8_t vme_fccpu20_device::pitc_r()
+uint8_t vme_sys68k_cpu20_card_device_base::pitc_r()
{
uint8_t board_id = 0;
- LOG("vme_fccpu20_device::pitc_r Board id:%02x\n", m_board_id);
+ LOG("vme_sys68k_cpu20_card_device_base::pitc_r Board id:%02x\n", m_board_id);
switch (m_board_id)
{
@@ -581,38 +569,17 @@ uint8_t vme_fccpu20_device::pitc_r()
}
/* ROM definitions */
-ROM_START (fccpu20) /* This is an original rom dump */
- ROM_REGION32_BE(0x10000, "roms", 0)
+ROM_START (sys68k_cpu20) /* This is an original rom dump */
+ ROM_REGION32_BE(0x10000, "eprom", 0)
ROM_LOAD32_BYTE("l.bin", 0x000002, 0x4000, CRC (174ab801) SHA1 (0d7b8ed29d5fdd4bd2073005008120c5f20128dd))
ROM_LOAD32_BYTE("ll.bin", 0x000003, 0x4000, CRC (9fd9e3e4) SHA1 (e5a7c87021e6be412dd5a8166d9f62b681169eda))
ROM_LOAD32_BYTE("u.bin", 0x000001, 0x4000, CRC (d1afe4c0) SHA1 (b5baf9798d73632f7bb843cbc4b306c8c03f4296))
ROM_LOAD32_BYTE("uu.bin", 0x000000, 0x4000, CRC (b54d623b) SHA1 (49b272184a04570b09004de71fae0ed0d1bf5929))
ROM_END
-/* These cpu-21 boards are supported by the latest cpu-20 rom */
-#define rom_fccpu21s rom_fccpu20
-#define rom_fccpu21 rom_fccpu20
-#define rom_fccpu21a rom_fccpu20
-#define rom_fccpu21ya rom_fccpu20
-#define rom_fccpu21b rom_fccpu20
-#define rom_fccpu21yb rom_fccpu20
-
-const tiny_rom_entry *vme_fccpu20_device::device_rom_region() const
+const tiny_rom_entry *vme_sys68k_cpu20_card_device_base::device_rom_region() const
{
- LOG("vme_fccpu20_device::device_rom_region\n");
-
- switch (m_board_id)
- {
- case cpu20: return ROM_NAME( fccpu20 ); break;
- case cpu21a: return ROM_NAME( fccpu21a ); break;
- case cpu21ya: return ROM_NAME( fccpu21ya ); break;
- case cpu21b: return ROM_NAME( fccpu21b ); break;
- case cpu21yb: return ROM_NAME( fccpu21yb ); break;
- case cpu21s: return ROM_NAME( fccpu21s ); break;
- case cpu21: return ROM_NAME( fccpu21 ); break;
- default: logerror("Attempted to get rom set for unknown board type %02x, defaulting to CPU20\n", m_board_id);
- return ROM_NAME( fccpu20 );
- }
+ return ROM_NAME(sys68k_cpu20);
}
/*
diff --git a/src/devices/bus/vme/sys68k_cpu20.h b/src/devices/bus/vme/sys68k_cpu20.h
new file mode 100644
index 00000000000..28106623ea7
--- /dev/null
+++ b/src/devices/bus/vme/sys68k_cpu20.h
@@ -0,0 +1,188 @@
+// license:BSD-3-Clause
+// copyright-holders:Joakim Larsson Edstrom
+#ifndef MAME_BUS_VME_SYS68K_CPU20_H
+#define MAME_BUS_VME_SYS68K_CPU20_H
+
+#pragma once
+
+#include "bus/vme/vme.h"
+#include "machine/68561mpcc.h"
+#include "machine/68230pit.h"
+#include "machine/68153bim.h"
+
+DECLARE_DEVICE_TYPE(VME_SYS68K_CPU20, vme_sys68k_cpu20_card_device)
+DECLARE_DEVICE_TYPE(VME_SYS68K_CPU21S, vme_sys68k_cpu21s_card_device)
+DECLARE_DEVICE_TYPE(VME_SYS68K_CPU21, vme_sys68k_cpu21_card_device)
+DECLARE_DEVICE_TYPE(VME_SYS68K_CPU21A, vme_sys68k_cpu21a_card_device)
+DECLARE_DEVICE_TYPE(VME_SYS68K_CPU21YA, vme_sys68k_cpu21ya_card_device)
+DECLARE_DEVICE_TYPE(VME_SYS68K_CPU21B, vme_sys68k_cpu21b_card_device)
+DECLARE_DEVICE_TYPE(VME_SYS68K_CPU21YB, vme_sys68k_cpu21yb_card_device)
+
+//**************************************************************************
+// Base Device declaration
+//**************************************************************************
+class vme_sys68k_cpu20_card_device_base : public device_t, public device_vme_card_interface
+{
+protected:
+ // PIT port C Board ID bits
+ static constexpr unsigned CPU20 = 0x40;
+ static constexpr unsigned CPU21 = 0x00;
+
+ /* Board types */
+ enum fc_board_t {
+ cpu20,
+ cpu21,
+ cpu21a,
+ cpu21ya,
+ cpu21b,
+ cpu21yb,
+ cpu21s
+ };
+
+ vme_sys68k_cpu20_card_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, fc_board_t board_id);
+
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+ TIMER_CALLBACK_MEMBER(grant_bus);
+
+ int m_bim_irq_state;
+ uint8_t m_bim_irq_level;
+
+ emu_timer *m_arbiter_start; // Need a startup delay because it is hooked up to the sense inputs of the PIT
+
+ required_device<cpu_device> m_maincpu;
+
+private:
+ void bim_irq_callback(int state);
+
+ /* PIT callbacks */
+ uint8_t pita_r();
+ uint8_t pitb_r();
+ uint8_t pitc_r();
+
+ void cpu20_mem(address_map &map);
+ void cpu_space_map(address_map &map);
+
+ required_device<pit68230_device> m_pit;
+ required_device<bim68153_device> m_bim;
+ required_device<mpcc68561_device> m_mpcc;
+ required_device<mpcc68561_device> m_mpcc2;
+ required_device<mpcc68561_device> m_mpcc3;
+
+ required_memory_region m_eprom;
+ required_shared_ptr<uint32_t> m_ram;
+ memory_passthrough_handler m_boot_mph;
+
+ void update_irq_to_maincpu();
+ const fc_board_t m_board_id;
+};
+
+//**************************************************************************
+// Board Device declarations
+//**************************************************************************
+
+class vme_sys68k_cpu20_card_device : public vme_sys68k_cpu20_card_device_base
+{
+public :
+ vme_sys68k_cpu20_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ vme_sys68k_cpu20_card_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : vme_sys68k_cpu20_card_device_base(mconfig, type, tag, owner, clock, cpu20)
+ { }
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+};
+
+class vme_sys68k_cpu21s_card_device : public vme_sys68k_cpu20_card_device_base
+{
+public :
+ vme_sys68k_cpu21s_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ vme_sys68k_cpu21s_card_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : vme_sys68k_cpu20_card_device_base(mconfig, type, tag, owner, clock, cpu21s)
+ { }
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+};
+
+class vme_sys68k_cpu21_card_device : public vme_sys68k_cpu20_card_device_base
+{
+public :
+ vme_sys68k_cpu21_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ vme_sys68k_cpu21_card_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : vme_sys68k_cpu20_card_device_base(mconfig, type, tag, owner, clock, cpu21)
+ { }
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+};
+
+class vme_sys68k_cpu21a_card_device : public vme_sys68k_cpu20_card_device_base
+{
+public :
+ vme_sys68k_cpu21a_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ vme_sys68k_cpu21a_card_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : vme_sys68k_cpu20_card_device_base(mconfig, type, tag, owner, clock, cpu21a)
+ { }
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+};
+
+class vme_sys68k_cpu21ya_card_device : public vme_sys68k_cpu20_card_device_base
+{
+public :
+ vme_sys68k_cpu21ya_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ vme_sys68k_cpu21ya_card_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : vme_sys68k_cpu20_card_device_base(mconfig, type, tag, owner, clock, cpu21ya)
+ { }
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+};
+
+class vme_sys68k_cpu21b_card_device : public vme_sys68k_cpu20_card_device_base
+{
+public :
+ vme_sys68k_cpu21b_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ vme_sys68k_cpu21b_card_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : vme_sys68k_cpu20_card_device_base(mconfig, type, tag, owner, clock, cpu21b)
+ { }
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+};
+
+class vme_sys68k_cpu21yb_card_device : public vme_sys68k_cpu20_card_device_base
+{
+public :
+ vme_sys68k_cpu21yb_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ vme_sys68k_cpu21yb_card_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : vme_sys68k_cpu20_card_device_base(mconfig, type, tag, owner, clock, cpu21yb)
+ { }
+
+ // optional information overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+};
+
+
+#endif // MAME_BUS_VME_SYS68K_CPU20_H
diff --git a/src/devices/bus/vme/sys68k_cpu30.cpp b/src/devices/bus/vme/sys68k_cpu30.cpp
new file mode 100644
index 00000000000..ba726b400d0
--- /dev/null
+++ b/src/devices/bus/vme/sys68k_cpu30.cpp
@@ -0,0 +1,952 @@
+// license:BSD-3-Clause
+// copyright-holders:Joakim Larsson Edstrom
+/***************************************************************************
+ *
+ * Force SYS68K CPU-30 VME SBC drivers
+ *
+ * 21/05/2016
+ *
+ * Thanks to Al Kossow and his site http://www.bitsavers.org/ I got the information
+ * required to start the work with this driver.
+ *
+ * The driver is currently starting up and the Boot ROM asks for input do start FGA-002
+ * diagnostics and do SRAM setup, which it does. After that it jumps to zeroed memory
+ * and crashes so needs some more work to be useful
+ *
+ *
+ * ||
+ * || || CPU-30
+ * ||||--||_____________________________________________________________
+ * ||||--|| |
+ * || || _ |__
+ * || +----------------+ | | |
+ * RST O=== | | | | |
+ * || | | | | |
+ * ABT O=== | FGA-002 | | | |
+ RUN/HLT C| GREEN/RED +------------+ | | | | |
+ BUS MST C| GREEN/unlit |System flash| | | | | |
+ * || +------------+ | | | |VME|
+ * rot [O SW4 +------------+ +----------------+ | | |
+ * swtshs|| |System Flash| | |P1 |
+ * [O SW3 +------------+ +----------+ | | |
+ * || +------------+ | | | | |
+ * || |System Flash| | 68030 | | | |
+ * | || +------------+ | | | | |
+ * |--| +------------+ | | | | |
+ * AUI | | |System Flash| +----------+ | | |
+ * eth| | +------------+ |_| |
+ * | | +----------+ |___|
+ * | | +-----+ | | |
+ * |--| |SIA | | 68882 | |
+ * | || |7992 | | | |
+ * || +-----+ J28 | | |
+ * || +------+ +----------+ |
+ * || | Opt | |
+ * ||| | Boot | |
+ * +---+ | PROM | |
+ * Ser | = +----------+ +------+ +--------+ |___
+ * #3 | = | LANCE | +------+ | SCSI | _ _| |
+ * | = | 7970 | | Def | | 87034 | | | |
+ * +---+ | | | Boot | | | | | |
+ * ||| | | | PROM | +--------+ | | |
+ * || +----------+ +------+ | | |
+ * ||| +----+ J36 +------+ | |VME|
+ * +---+ |NV- | | FDC | | | |
+ * Ser | = | RAM| |37C65C| | |P2 |
+ * #2 | = | | +------+ | | |
+ * | = +----+ | 5 row |
+ * +---+ +--------+ +--------+ | conn- |
+ * ||| +-----+ | DUSCC1 | | PIT1 | | ector|
+ * || | OPT | | 68562 | | 68230 | | | |
+ * ||| |NVRAM| | | | | | | |
+ * +---+ | | +--------+ +--------+ | | |
+ * Ser | = | | ____ +--------+ +--------+ | | |
+ * #1 | = | | / \ | DUSCC2 | | PIT2 | |_ _| |
+ * | = | | BATTERY | 68562 | | 68230 | |___|
+ * || +---+ +-----+ \____/ | | | | +
+ * ||||--|| +--------+ +--------+ |
+ * ||||--||--------------------------------------------------------------+
+ * ||
+ *
+ * History of Force Computers
+ *---------------------------
+ * 1981 Force Computers was founded in San Jose, California. Over time a European headquarter was opened
+ * in Munich, Germany, and a Japanese headquarter in Tokyo
+ * 1996 Force was acquired by Solectron Corporation in 1996
+ * 2004 Force was sold off from Solectron to Motorola
+ * 2008 Force was acquired by Emerson as part of the Motorola Embedded Division
+ * 2016 Force was acquired by Platinum Equity as part of the Emerson Network Power Division
+ *
+ * Force developed and produced VME board products based on SPARC, Pentium, PowerPC and 68K.
+ *
+ * Misc links about Force Computes and this board:
+ *------------------------------------------------
+ * http://bitsavers.trailing-edge.com/pdf/forceComputers/CPU30/204030_CPU-30_R4_Technical_Reference_Oct96.pdf
+ * http://www.artisantg.com/info/P_wUovN.pdf
+ *
+ * Description(s)
+ * -------------
+ * CPU-30 has the following feature set
+ * - 16.7 or 25 MHz MC68030 enhanced 32-bit microprocessor
+ * - 16.7 or 25 MHz MC68882 floating-point coprocessor
+ * - 32-512 Kb of SRAM with battery backup
+ * - 4, 8, 16, or 32MB of shared DRAM, with byte parity
+ * - Up to 8Mb Flash memory
+ * - 128,256 or 512 Mb boot flash or upto 1Mb of boot OTP PROM
+ * - Double High (6U) VMEmodule
+ * - A32/D32 VMEbus master/slave interface with system controller function (VMEchip ASIC)
+ * - Ethernet transceiver interface (AM79C90)
+ * - SCSI bus interface with independent data bus on P2 connector (MB87033/34)
+ * - Floppy disk interface on P2 connector (FCD37C65C)
+ * - Four serial ports (DUSCC SCN68562 x 2)
+ * - 20 bit digital i/o for user applications( 2 x 68230 PI/T )
+ * - Real-Time Clock with interrupt (72423)
+ * - 4-level requester, 7-level interrupter, and 7-level interrupt handler for VMEbus (VMEchip ASIC)
+ *
+ * NOTE: This driver currently mimics the CPU-30xyz configuration: 16MHz, 4Mb RAM, no parity, no ethernet (See TODO)
+ *
+ * Address Map
+ * --------------------------------------------------------------------------
+ * Range Desccription
+ * --------------------------------------------------------------------------
+ * 00000000-0xxFFFFF Shared DRAM D8-D32 xx=0x1F-0x03 for 32Mb-4Mb
+ * 0yy00000-FAFFFFFF VME A32 D8-D32 yy=xx+1
+ * FB000000-FBFEFFFF VME A24 D8-D32
+ * FBFF0000-FBFFFFFF VME A16 D8-D32
+ * FC000000-FCFEFFFF VME A24 D8-D16
+ * FCFF0000-FCFFFFFF VME A16 D8-D16
+ * FD000000-FEEFFFFF Reserved
+ * FEF00000-FEF7FFFF LAN RAM D8-D32
+ * FEF80000-FEFFFFFF LAN Controller D16 (AM79C90)
+ * FF000000-FF7FFFFF System PROM D8-D32 (read) D32 (flash write)
+ * FF800000-FF800BFF Reserved
+ * FF800C00-FF800DFF PIT1 D8 (68230)
+ * FF800E00-FF800FFF PIT2 D8 (68230)
+ * FF801000-FF801FFF Reserved
+ * FF802000-FF8021FF DUSCC1 D8 (SCN68562)
+ * FF802200-FF8023FF DUSCC2 D8 (SCN68562)
+ * FF802400-FF802FFF Reserved
+ * FF803000-FF8031FF RTC (72423) D8
+ * FF803200-FF8033FF Reserved
+ * FF803400-FF8035FF SCSI controller (MB87033/34) D8
+ * FF803600-FF8037FF Reserved
+ * FF803800-FF80397F Floppy controller (FDC37C65C) D8
+ * FF803980-FF8039FF Slot 1 status register (read) D8
+ * FFC00000-FFCFFFFF Local SRAM D8-D32
+ * FFD00000-FFDFFFFF FGA-002 Gate Array D8-D32
+ * FFE00000-FFEFFFFF Boot PROM D8-D32
+ * FFF00000-FFFFFFFF Reserved
+ * --------------------------------------------------------------------------
+ *
+ * Interrupt sources CPU30
+ * ----------------------------------------------------------
+ * Description Device Lvl IRQ VME board
+ * /Board Vector Address
+ * ----------------------------------------------------------
+ * On board Sources
+ *
+ * Off board Sources (other VME boards)
+ *
+ * ----------------------------------------------------------
+ *
+ * PIT #1 hardware wiring
+ * ----------------------------------------------------------
+ * PA0-PA3 Rotary Switch 1 input
+ * PA4-PA7 Rotary Switch 2 input
+ * H1-H4 User I/O via optional B5 or optional 5-row VME P2 connector
+ * PB0-PB2 Floppy Disk Drive Control output
+ * PB3-PB4 Floppy Disk Drive Control input
+ * PB5 Floppy Disk Drive Control output
+ * PB6-PB7 DMAC control
+ * PC0,PC1 User I/O via optional B5 or optional 5-row VME P2 connector
+ * PC4,PC7 User I/O via optional B5 or optional 5-row VME P2 connector
+ * PC2 Reserved
+ * PC3 Timer interrupt request
+ * PC5 Port Interrupt Request
+ * PC6 68882 FPCP Sense
+ *
+ * PIT #2 hardware setup wiring
+ * ----------------------------------------------------------
+ * PA0-PA7 User I/O via optional B5 or optional 5-row VME P2 connector
+ * H1-H4 User I/O via optional B5 or optional 5-row VME P2 connector
+ * PB0-PB2 Memory Size
+ * PB3-PB7 Board ID
+ * PC0-PC1 Hardware ID
+ * PC2 Status of write protection for (default and optional) Boot PROMs
+ * PC3 Timer Interrupt request
+ * PC4 Status of write protection for SYSTEM-Flash Memory
+ * PC5 DMA control
+ * PC6 Flash programming voltage control
+ * PC7 Reserved
+ *
+ * DMAC Channel Assignments
+ * ----------------------------------------------------------
+ * Channel SYS68K/CPU30
+ * ----------------------------------------------------------
+ *
+ *
+ * TODO:
+ * - Investigate and fix crash
+ * - Add VxWorks proms
+ * - Add more devices
+ * - Write VME device
+ * - Add variants of boards
+ *
+ ****************************************************************************/
+
+#include "emu.h"
+#include "sys68k_cpu30.h"
+
+#include "machine/nvram.h"
+#include "bus/rs232/rs232.h"
+#include "machine/clock.h"
+//#include "machine/timekpr.h"
+
+#define LOG_SETUP (1U << 1)
+#define LOG_READ (1U << 2)
+#define LOG_INT (1U << 3)
+#define LOG_INIT (1U << 4)
+
+//#define VERBOSE (LOG_GENERAL | LOG_SETUP)
+//#define LOG_OUTPUT_FUNC printf
+
+#include "logmacro.h"
+
+#define LOGSETUP(...) LOGMASKED(LOG_SETUP, __VA_ARGS__)
+#define LOGR(...) LOGMASKED(LOG_READ, __VA_ARGS__)
+#define LOGINT(...) LOGMASKED(LOG_INT, __VA_ARGS__)
+#define LOGINIT(...) LOGMASKED(LOG_INIT, __VA_ARGS__)
+
+#ifdef _MSC_VER
+#define FUNCNAME __func__
+#else
+#define FUNCNAME __PRETTY_FUNCTION__
+#endif
+
+
+#define DUSCC_CLOCK XTAL(14'745'600) /* Verified */
+
+DEFINE_DEVICE_TYPE(VME_SYS68K_CPU30, vme_sys68k_cpu30_card_device, "sys68k_cpu30", "Force Computers SYS68K/CPU-30")
+DEFINE_DEVICE_TYPE(VME_SYS68K_CPU30X, vme_sys68k_cpu30x_card_device, "sys68k_cpu30x", "Force Computers SYS68K/CPU-30X")
+DEFINE_DEVICE_TYPE(VME_SYS68K_CPU30XA, vme_sys68k_cpu30xa_card_device, "sys68k_cpu30xa", "Force Computers SYS68K/CPU-30XA")
+DEFINE_DEVICE_TYPE(VME_SYS68K_CPU30ZA, vme_sys68k_cpu30za_card_device, "sys68k_cpu30za", "Force Computers SYS68K/CPU-30ZA")
+DEFINE_DEVICE_TYPE(VME_SYS68K_CPU30BE, vme_sys68k_cpu30be_card_device, "sys68k_cpu30be", "Force Computers SYS68K/CPU-30BE")
+DEFINE_DEVICE_TYPE(VME_SYS68K_CPU30LITE, vme_sys68k_cpu30lite_card_device, "sys68k_cpu30lite", "Force Computers SYS68K/CPU-30Lite")
+DEFINE_DEVICE_TYPE(VME_SYS68K_CPU33, vme_sys68k_cpu33_card_device, "sys68k_cpu33", "Force Computers SYS68K/CPU-33")
+
+sys68k_cpu30_device_base::sys68k_cpu30_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock, uint8_t board_id)
+ : device_t(mconfig, type, tag, owner, clock)
+ , device_vme_card_interface(mconfig, *this)
+ , m_maincpu (*this, "maincpu")
+ , m_ram(*this, RAM_TAG)
+ , m_dusccterm(*this, "duscc")
+ , m_pit1 (*this, "pit1")
+ , m_pit2 (*this, "pit2")
+ , m_fga002 (*this, "fga002")
+ , m_rtc (*this, "rtc")
+ , m_boot(*this, "boot")
+ , m_board_id(board_id)
+{
+}
+
+vme_sys68k_cpu30_card_device::vme_sys68k_cpu30_card_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
+ : sys68k_cpu30_device_base(mconfig, VME_SYS68K_CPU30, tag, owner, clock, 0x50)
+{
+}
+vme_sys68k_cpu30x_card_device::vme_sys68k_cpu30x_card_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
+ : sys68k_cpu30_device_base(mconfig, VME_SYS68K_CPU30X, tag, owner, clock, 0x50)
+{
+}
+vme_sys68k_cpu30xa_card_device::vme_sys68k_cpu30xa_card_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
+ : sys68k_cpu30_device_base(mconfig, VME_SYS68K_CPU30XA, tag, owner, clock, 0x50)
+{
+}
+vme_sys68k_cpu30za_card_device::vme_sys68k_cpu30za_card_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
+ : sys68k_cpu30_device_base(mconfig, VME_SYS68K_CPU30ZA, tag, owner, clock, 0x50)
+{
+}
+vme_sys68k_cpu30be_card_device::vme_sys68k_cpu30be_card_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
+ : sys68k_cpu30_device_base(mconfig, VME_SYS68K_CPU30BE, tag, owner, clock, 0x50)
+{
+}
+vme_sys68k_cpu30lite_card_device::vme_sys68k_cpu30lite_card_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
+ : sys68k_cpu30_device_base(mconfig, VME_SYS68K_CPU30LITE, tag, owner, clock, 0x50)
+{
+}
+vme_sys68k_cpu33_card_device::vme_sys68k_cpu33_card_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
+ : sys68k_cpu30_device_base(mconfig, VME_SYS68K_CPU33, tag, owner, clock, 0x68) // 0x60 skips FGA prompt
+{
+}
+
+void sys68k_cpu30_device_base::cpu30_mem(address_map &map)
+{
+ map.unmap_value_high();
+
+// map(0x00000008, 0x003fffff).ram(); /* RAM installed in machine start */
+ map(0xff000000, 0xff7fffff).rom().region("system", 0);
+ map(0xff800c00, 0xff800dff).rw(m_pit1, FUNC(pit68230_device::read), FUNC(pit68230_device::write));
+ map(0xff800e00, 0xff800fff).rw(m_pit2, FUNC(pit68230_device::read), FUNC(pit68230_device::write));
+ map(0xff802000, 0xff8021ff).rw(m_dusccterm, FUNC(duscc68562_device::read), FUNC(duscc68562_device::write)); /* Port 1&2 - Dual serial port DUSCC */
+ map(0xff802200, 0xff8023ff).rw("duscc2", FUNC(duscc68562_device::read), FUNC(duscc68562_device::write)); /* Port 3&4 - Dual serial port DUSCC */
+ map(0xff803000, 0xff8031ff).rw(m_rtc, FUNC(rtc72423_device::read), FUNC(rtc72423_device::write));
+// map(0xff803400, 0xff8035ff).rw("scsi", FUNC(mb87033_device::read), FUNC(mb87033_device::write)); /* TODO: implement MB87344 SCSI device */
+ map(0xff803400, 0xff8035ff).rw(FUNC(sys68k_cpu30_device_base::scsi_r), FUNC(sys68k_cpu30_device_base::scsi_w)).umask32(0x000000ff); /* mock driver to log calls to device */
+// map(0xff803800, 0xff80397f).rw("fdc", FUNC(wd37c65c_device::read), FUNC(wd37c65c_device::write)); /* TODO: implement WD3/C65C fdc controller */
+ map(0xff803800, 0xff80397f).rw(FUNC(sys68k_cpu30_device_base::fdc_r), FUNC(sys68k_cpu30_device_base::fdc_w)).umask32(0x000000ff); /* mock driver to log calls to device */
+ map(0xff803980, 0xff8039ff).r(FUNC(sys68k_cpu30_device_base::slot1_status_r)).umask32(0x000000ff);
+ map(0xffc00000, 0xffcfffff).ram().share("nvram"); /* On-board SRAM with battery backup (nvram) */
+ map(0xffd00000, 0xffdfffff).rw(m_fga002, FUNC(fga002_device::read), FUNC(fga002_device::write)); /* FGA-002 Force Gate Array */
+ map(0xffe00000, 0xffe0ffff).rom().region("boot", 0);
+
+ //map(0x100000, 0xfeffff).rw(FUNC(sys68k_cpu30_device_base::vme_a24_r), FUNC(sys68k_cpu30_device_base::vme_a24_w)); /* VMEbus Rev B addresses (24 bits) - not verified */
+ //map(0xff0000, 0xffffff).rw(FUNC(sys68k_cpu30_device_base::vme_a16_r), FUNC(sys68k_cpu30_device_base::vme_a16_w)); /* VMEbus Rev B addresses (16 bits) - not verified */
+}
+
+/* Input ports */
+static INPUT_PORTS_START (sys68k_cpu30)
+INPUT_PORTS_END
+
+/* Start it up */
+void sys68k_cpu30_device_base::device_start ()
+{
+ LOGINIT("%s\n", FUNCNAME);
+}
+
+void sys68k_cpu30_device_base::device_reset()
+{
+ LOGINIT("%s\n", FUNCNAME);
+
+ m_maincpu->space(AS_PROGRAM).install_rom(0, m_boot->bytes() - 1, m_boot->base());
+
+ m_boot_mph = m_maincpu->space(AS_PROGRAM).install_read_tap(0x000004, 0x000007, "boot",
+ [this](offs_t offset, u32 &data, u32 mem_mask)
+ {
+ if (!machine().side_effects_disabled() && ACCESSING_BITS_0_15)
+ {
+ m_maincpu->space(AS_PROGRAM).install_ram(0, m_ram->size() - 1, m_ram->pointer());
+ m_boot_mph.remove();
+ }
+ });
+}
+
+/* Mock FDC driver */
+uint8_t sys68k_cpu30_device_base::fdc_r(offs_t offset){
+ LOG("%s\n * FDC read Offset: %04x\n", FUNCNAME, offset);
+ return 1;
+}
+
+void sys68k_cpu30_device_base::fdc_w(offs_t offset, uint8_t data){
+ LOG("%s\n * FDC write Offset: %04x Data: %02x\n", FUNCNAME, offset, data);
+}
+
+/* Mock SCSI driver */
+uint8_t sys68k_cpu30_device_base::scsi_r(offs_t offset){
+ LOG("%s\n * SCSI read Offset: %04x\n", FUNCNAME, offset);
+ return 1;
+}
+
+void sys68k_cpu30_device_base::scsi_w(offs_t offset, uint8_t data){
+ LOG("%s\n * SCSI write Offset: %04x Data: %02x\n", FUNCNAME, offset, data);
+}
+
+/* 1 = board is in slot 1, 0 = board is NOT in slot 1 */
+uint8_t sys68k_cpu30_device_base::slot1_status_r(){
+ LOG("%s\n", FUNCNAME);
+ return 1;
+}
+
+/*
+ * Rotary Switches - to configure the board
+ *
+ * Table 25: PI/T #1 Interface Signals
+ * Pin Function In/Out
+ * PA0-PA3 SW1 In
+ * PA4 PA7 SW2 In
+ *
+ * Table 38: Upper Rotary Switch (SW2)
+ * Bit 3: This bit indicates whether the RAM disk should be initialized after reset. If this bit is set to "0" (settings 0-7),
+ * the RAM disk is initialized as defined by bit 0 and 1. When the disk is initialized, all data on the disk is lost.
+ * Bit 2: This bit defines the default data size on the VMEbus. If the bit is set to "0", 16 bits are selected, if it is set
+ * to "1", 32 bits are selected.
+ * Bit 1 and Bit 0: These two bits define the default RAM disk. See Table 40, "RAM Disk Usage," a detailed description.
+ * If AUTOBOOT is set by bit 2 and 3 of SW1, bit 1 and 0 of SW2 define which operating system will be booted. See Table 42,
+ * "Boot an Operating System (if AUTOBOOT is selected)," on page 129 for detailed description.
+ *
+ * Table 39: Lower Rotary Switch (SW1)
+ * Bit 3 and Bit 2: These two bits define which program is to be invoked after reset. Please refer
+ * to Table 41, "Program After Reset," on page 129 for a detailed description.
+ * Bit 1: If this switch is "0" (settings 0,1,4,5,8,9,C,D), VMEPROM tries to execute a start-up file after reset. The default
+ * filename is SY$STRT. If the bit is "1", VMEPROM comes up with the default banner.
+ * Bit 0: If this switch is set to "0" (settings 0,2,4,6,8,A,C,E), VMEPROM checks the VMEbus for available hardware after reset.
+ * In addition VMEPROM waits for SYSFAIL to disappear from the VMEbus. The following hardware can be detected:
+ * - Contiguous memory
+ * - ASCU-1/2
+ * - ISIO-1/2
+ * - SIO-1/2
+ * - ISCSI-1
+ * - WFC-1
+ *
+ * Table 40: RAM Disk Usage
+ * Bit 1 Bit 0 Upper Switch (SW 2) selected on
+ * 1 1 RAM DISK AT TOP OF MEMORY (32 Kbytes) 3,7,B,F
+ * 1 0 RAM DISK AT 0xFC80 0000 (512 Kbytes) 2,6,A,E
+ * 0 1 RAM DISK AT 0x4070 0000 (512 Kbytes) 1,5,9,D
+ * 0 0 RAM DISK AT 0x4080 0000 (512 Kbytes) 0,4,8,C
+ *
+ * Table 41: Program After Reset
+ * Bit 3 Bit 2 Lower Switch (SW 1) selected on
+ * 1 1 VMEPROM C,D,E,F
+ * 1 0 USER PROGRAM AT 0x4070 0000 8,9,A,B
+ * 0 1 AUTOBOOT SYSTEM 4,5,6,7
+ * 0 0 USER PROGRAM AT 4080.000016 0,1,2,3
+ *
+ * Table 42: Boot an Operating System (if AUTOBOOT is selected)
+ * Bit 1 Bit 0 Upper Switch (SW 2) selected on
+ * 1 1 reserved 3,7,B,F
+ * 1 0 Boot UNIX/PDOS 4.x 2,6,A,E
+ * 0 1 Boot another operating system 1,5,9,D
+ * 0 0 Setup for UNIX mailbox driver 0,4,8,C
+ *
+ * "To start VMEPROM, the rotary switches must both be set to 'F':" Hmm...
+ */
+uint8_t sys68k_cpu30_device_base::rotary_rd(){
+ LOG("%s\n", FUNCNAME);
+ return 0xff; // TODO: make this configurable from commandline or artwork
+}
+
+// PIT#1 Port B TODO: implement floppy and dma control
+uint8_t sys68k_cpu30_device_base::flop_dmac_r(){
+ LOG("%s\n", FUNCNAME);
+ return 0xff;
+}
+
+void sys68k_cpu30_device_base::flop_dmac_w(uint8_t data){
+ LOG("%s(%02x)\n", FUNCNAME, data);
+}
+
+#define FPCP_SENSE 0x40 /* Port C bit 6 is low if a Floating Point Co Processor is installed */
+// PIT#1 Port C TODO: implement timer+port interrupts
+// TODO: Connect PC0, PC1, PC4 and PC7 to B5 and/or P2 connector
+uint8_t sys68k_cpu30_device_base::pit1c_r(){
+ LOG("%s\n", FUNCNAME);
+ m_maincpu->set_fpu_enable(1); // Lets assume the FPCP is always installed ( which is default for 68030 atm )
+ return 0xff & ~FPCP_SENSE; // Should really be command line for the edge cases...
+}
+
+void sys68k_cpu30_device_base::pit1c_w(uint8_t data){
+ LOG("%s(%02x)\n", FUNCNAME, data);
+}
+
+// PIT#2 Port A TODO: Connect to B5 and /or P2 connector
+uint8_t sys68k_cpu30_device_base::pit2a_r(){
+ LOG("%s\n", FUNCNAME);
+ logerror("Unsupported user i/o on PIT2 port A detected\n");
+ return 0xff;
+}
+
+void sys68k_cpu30_device_base::pit2a_w(uint8_t data){
+ LOG("%s(%02x)\n", FUNCNAME, data);
+ logerror("Unsupported user i/o on PIT2 port A detected\n");
+}
+
+/*
+ * PI/T #2 Factory settings
+ * B2 B1 B0 Shared Memory Size - From these lines, the on-board Shared RAM capacity can be read in by software.
+ * 0 0 0 32 Mb
+ * 0 0 1 16 Mb
+ * 0 1 0 8 Mb
+ * 0 1 1 4 Mb
+ * 1 x x Reserved
+ * B3-B7 Board ID(s) - From these lines, the CPU board identification number can be read in by
+ * 0 1 0 1 0 CPU-30 R4 software. Every CPU board has a unique number. Different versions of
+ * (fill in more) one CPU board (i.e. different speeds, capacity of memory, or modules)
+ * contain the same identification number. In the case of the CPU-30 R4, the
+ * number is 0x0a
+ *
+ * The speed of the board is measured by looping some instructions and measure the time it takes with a timer
+ * Currently this doesn't work so the wrong speed is displayed on the screen. To fix this timing needs to be more exact.
+ * Speed measure subroutine is at address 0xffe033c4 in the FGA-002 firmware with CRC (faa38972) (for example)
+ */
+uint8_t sys68k_cpu30_device_base::board_mem_id_rd()
+{
+ int sz;
+ LOG("%s\n", FUNCNAME);
+ switch (m_ram->size())
+ {
+ case (1024 * 1024 * 32): sz = 0; break;
+ case (1024 * 1024 * 16): sz = 1; break;
+ case (1024 * 1024 * 8): sz = 2; break;
+ case (1024 * 1024 * 4): sz = 3; break;
+ case (1024 * 1024 * 2): sz = 4; break;
+ case (1024 * 1024 * 1): sz = 5; break;
+ case (1024 * 512 * 1): sz = 6; break;
+ case (1024 * 256 * 1): sz = 7; break;
+ default:
+ logerror("No supported RAM size, telling VMEPROM 4Mb\n");
+ sz = 4;
+ }
+ // return 0x6A; // CPU-30 R4 with 4Mb of shared RAM. TODO: make this configurable from commandline or artwork
+ // return 0x57; // blankt 53 56
+ // return 0x36; // CPU-26 1Mb 36 MHz
+ // return 0x35; // CPU-26 1Mb 36 MHz
+ // calculate response from m_ram (default 4M or command line -ramsize) Bit 2 is reserved and always 0 on CPU-30
+ // return 0x6B;// CPU-33, 4Mb, 36MHz p4
+ // return 0x6B;// CPU-33, 4Mb, 36MHz p4
+ // return 0x99;// CPU-26, 4Mb, 36MHz p4
+ // return 0x33;// CPU-26, 4Mb, 36MHz p4
+ // return 0x37;// CPU-26, 4Mb, 36MHz p4
+ // return 0x35;// CPU-26, 1Mb, 36MHz p4
+ // return 0x36;// CPU-26, 1Mb, 36MHz p4
+ // return 0x55;// CPU-30, 1Mb, 36MHz
+ // return 0x56;// CPU-30, 1Mb, 36MHz
+ // return 0x53;// CPU-30, 4Mb, 36MHz
+ // return 0x57;// CPU-30, 4Mb, 36MHz
+ // return 0x48 + sz;// none
+ // return 0x38 + sz;// none
+ // return 0x28 + sz;// none
+ // return 0x18 + sz;// CPU-23 p1
+ // return 0x10 + sz;// CPU-22 p4
+ // return 0x20 + sz;// p1: Wait until hard disk is up to speed
+ // printf("SIZE:%02x\n", sz);
+ LOG("- Board ID:%02x Size:%02x\n", m_board_id, sz);
+ return m_board_id + sz;
+}
+
+// PIT#2 Port C TODO: implement timer interrupt, DMA i/o, memory control and Hardware ID
+uint8_t sys68k_cpu30_device_base::pit2c_r(){
+ LOG("%s\n", FUNCNAME);
+ return 0xfe;
+}
+
+void sys68k_cpu30_device_base::pit2c_w(uint8_t data){
+ LOG("%s(%02x)\n", FUNCNAME, data);
+}
+
+#if 0
+/* Dummy VME access methods until the VME bus device is ready for use */
+uint16_t sys68k_cpu30_device_base::vme_a24_r(){
+ LOG("%s\n", FUNCNAME);
+ return (uint16_t) 0;
+}
+
+void sys68k_cpu30_device_base::vme_a24_w(uint16_t data){
+ LOG("%s(%02x)\n", FUNCNAME, data);
+}
+
+uint16_t sys68k_cpu30_device_base::vme_a16_r(){
+ LOG("%s\n", FUNCNAME);
+ return (uint16_t) 0;
+}
+
+void sys68k_cpu30_device_base::vme_a16_w(uint16_t data){
+ LOG("%s(%02x)\n", FUNCNAME, data);
+}
+#endif
+
+void sys68k_cpu30_device_base::fga_irq_callback(int state)
+{
+ LOGINT("%s(%02x)\n", FUNCNAME, state);
+
+ fga_irq_state = state;
+ fga_irq_level = m_fga002->get_irq_level();
+ LOGINT(" - FGA irq level %02x\n", fga_irq_level);
+ update_irq_to_maincpu();
+}
+
+void sys68k_cpu30_device_base::update_irq_to_maincpu()
+{
+ LOGINT("%s()\n", FUNCNAME);
+ LOGINT(" - fga_irq_level: %02x\n", fga_irq_level);
+ LOGINT(" - fga_irq_state: %02x\n", fga_irq_state);
+ switch (fga_irq_level & 0x07)
+ {
+ case 1: m_maincpu->set_input_line(M68K_IRQ_1, fga_irq_state); break;
+ case 2: m_maincpu->set_input_line(M68K_IRQ_2, fga_irq_state); break;
+ case 3: m_maincpu->set_input_line(M68K_IRQ_3, fga_irq_state); break;
+ case 4: m_maincpu->set_input_line(M68K_IRQ_4, fga_irq_state); break;
+ case 5: m_maincpu->set_input_line(M68K_IRQ_5, fga_irq_state); break;
+ case 6: m_maincpu->set_input_line(M68K_IRQ_6, fga_irq_state); break;
+ case 7: m_maincpu->set_input_line(M68K_IRQ_7, fga_irq_state); break;
+ default: logerror("Programmatic error in %s, please report\n", FUNCNAME);
+ }
+}
+
+/*
+ * Machine configuration
+ */
+
+void sys68k_cpu30_device_base::cpu_space_map(address_map &map)
+{
+ map(0xfffffff2, 0xffffffff).lr16(NAME([this] (offs_t offset) -> u16 { return m_fga002->iack(); }));
+}
+
+void sys68k_cpu30_device_base::sys68k_cpu30(machine_config &config, XTAL clock, char const *const ram_default, char const *const ram_options)
+{
+ /* basic machine hardware */
+ M68030(config, m_maincpu, clock);
+ m_maincpu->set_addrmap(AS_PROGRAM, &sys68k_cpu30_device_base::cpu30_mem);
+ m_maincpu->set_addrmap(m68000_base_device::AS_CPU_SPACE, &sys68k_cpu30_device_base::cpu_space_map);
+ NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0);
+
+ /* Terminal Port config */
+ /* Force CPU30 series of boards has up to four serial ports, p1-p4, the FGA boot uses p4 as console and subsequent
+ firmware uses p1 as console and in an operating system environment there may be user login shells on the other.
+
+ In order to use more than just one terminal MAME supports serial socket servers to which it is possible to
+ connect a telnet terminal to. The general syntax to open a socket server from the command prompts is:
+
+ mame cpu30 -window -rs232p4 null_modem -bitbngr socket.127.0.0.1:1001
+
+ At the opening screen, before the board starts to execute code, start up the telnet client and give 127.0.0.1:1001 as host
+ It is also possible to enumerate more than one terminal server in order to have several terminal session attached.
+
+ mame cpu30 -window -rs232p4 null_modem -bitbngr1 socket.127.0.0.1:1001 -rs232p1 null_modem -bitbngr2 socket.127.0.0.1:1002
+
+ Now just start up the telnet clients with 127.0.0.1:1001 and 127.0.0.1:1002 as hosts and you have control of input for each port.
+ */
+
+#define RS232P1_TAG "rs232p1"
+#define RS232P2_TAG "rs232p2"
+#define RS232P3_TAG "rs232p3"
+#define RS232P4_TAG "rs232p4"
+
+ DUSCC68562(config, m_dusccterm, DUSCC_CLOCK);
+ m_dusccterm->configure_channels(0, 0, 0, 0);
+ /* Port 1 on Port B */
+ m_dusccterm->out_txdb_callback().set(RS232P1_TAG, FUNC(rs232_port_device::write_txd));
+ m_dusccterm->out_dtrb_callback().set(RS232P1_TAG, FUNC(rs232_port_device::write_dtr));
+ m_dusccterm->out_rtsb_callback().set(RS232P1_TAG, FUNC(rs232_port_device::write_rts));
+ /* Port 4 on Port A */
+ m_dusccterm->out_txda_callback().set(RS232P4_TAG, FUNC(rs232_port_device::write_txd));
+ m_dusccterm->out_dtra_callback().set(RS232P4_TAG, FUNC(rs232_port_device::write_dtr));
+ m_dusccterm->out_rtsa_callback().set(RS232P4_TAG, FUNC(rs232_port_device::write_rts));
+ /* DUSCC1 interrupt signal REQN is connected to LOCAL IRQ4 of the FGA-002 and level is programmable */
+ m_dusccterm->out_int_callback().set(m_fga002, FUNC(fga002_device::lirq4_w));
+
+ duscc68562_device &duscc2(DUSCC68562(config, "duscc2", DUSCC_CLOCK));
+ duscc2.configure_channels(0, 0, 0, 0);
+ /* Port 2 on Port A */
+ duscc2.out_txda_callback().set(RS232P2_TAG, FUNC(rs232_port_device::write_txd));
+ duscc2.out_dtra_callback().set(RS232P2_TAG, FUNC(rs232_port_device::write_dtr));
+ duscc2.out_rtsa_callback().set(RS232P2_TAG, FUNC(rs232_port_device::write_rts));
+ /* Port 3 on Port B */
+ duscc2.out_txdb_callback().set(RS232P3_TAG, FUNC(rs232_port_device::write_txd));
+ duscc2.out_dtrb_callback().set(RS232P3_TAG, FUNC(rs232_port_device::write_dtr));
+ duscc2.out_rtsb_callback().set(RS232P3_TAG, FUNC(rs232_port_device::write_rts));
+ /* DUSCC2 interrupt signal REQN is connected to LOCAL IRQ5 of the FGA-002 and level is programmable */
+ duscc2.out_int_callback().set(m_fga002, FUNC(fga002_device::lirq5_w));
+
+ rs232_port_device &rs232p1(RS232_PORT(config, RS232P1_TAG, default_rs232_devices, "terminal"));
+ rs232p1.rxd_handler().set(m_dusccterm, FUNC(duscc68562_device::rxb_w));
+ rs232p1.cts_handler().set(m_dusccterm, FUNC(duscc68562_device::ctsb_w));
+
+ rs232_port_device &rs232p2(RS232_PORT(config, RS232P2_TAG, default_rs232_devices, nullptr));
+ rs232p2.rxd_handler().set("duscc2", FUNC(duscc68562_device::rxa_w));
+ rs232p2.cts_handler().set("duscc2", FUNC(duscc68562_device::ctsa_w));
+
+ rs232_port_device &rs232p3(RS232_PORT(config, RS232P3_TAG, default_rs232_devices, nullptr));
+ rs232p3.rxd_handler().set("duscc2", FUNC(duscc68562_device::rxb_w));
+ rs232p3.cts_handler().set("duscc2", FUNC(duscc68562_device::ctsb_w));
+
+ rs232_port_device &rs232p4(RS232_PORT(config, RS232P4_TAG, default_rs232_devices, "terminal"));
+ rs232p4.rxd_handler().set(m_dusccterm, FUNC(duscc68562_device::rxa_w));
+ rs232p4.cts_handler().set(m_dusccterm, FUNC(duscc68562_device::ctsa_w));
+
+ /* PIT Parallel Interface and Timer device, assumed strapped for on board clock */
+ PIT68230(config, m_pit1, XTAL(16'000'000) / 2); // The PIT clock is not verified on schema but reversed from behaviour
+ m_pit1->pa_in_callback().set(FUNC(sys68k_cpu30_device_base::rotary_rd));
+ m_pit1->pb_in_callback().set(FUNC(sys68k_cpu30_device_base::flop_dmac_r));
+ m_pit1->pb_out_callback().set(FUNC(sys68k_cpu30_device_base::flop_dmac_w));
+ m_pit1->pc_in_callback().set(FUNC(sys68k_cpu30_device_base::pit1c_r));
+ m_pit1->pc_out_callback().set(FUNC(sys68k_cpu30_device_base::pit1c_w));
+// m_pit1->timer_irq_callback().set(m_fga002, FUNC(fga002_device::lirq2_w)); // The timer interrupt seems to silence the terminal interrupt, needs invectigation
+
+ PIT68230(config, m_pit2, XTAL(16'000'000) / 2); // Th PIT clock is not verified on schema but reversed from behaviour
+ m_pit2->pb_in_callback().set(FUNC(sys68k_cpu30_device_base::board_mem_id_rd));
+ m_pit2->pa_in_callback().set(FUNC(sys68k_cpu30_device_base::pit2a_r));
+ m_pit2->pa_out_callback().set(FUNC(sys68k_cpu30_device_base::pit2a_w));
+ m_pit2->pc_in_callback().set(FUNC(sys68k_cpu30_device_base::pit2c_r));
+ m_pit2->pc_out_callback().set(FUNC(sys68k_cpu30_device_base::pit2c_w));
+// m_pit2->timer_irq_callback().set(m_fga002, FUNC(fga002_device::lirq3_w)); // The timer interrupt seems to silence the terminal interrupt, needs invectigation
+
+ /* FGA-002, Force Gate Array */
+ FGA002(config, m_fga002, 0);
+ m_fga002->out_int().set(FUNC(sys68k_cpu30_device_base::fga_irq_callback));
+ m_fga002->liack4().set("duscc", FUNC(duscc_device::iack));
+ m_fga002->liack5().set("duscc2", FUNC(duscc_device::iack));
+
+ // RTC
+ RTC72423(config, m_rtc, XTAL(32'768)); // Fake crystal value, the 72423 uses it own internal crystal
+ m_rtc->out_int_handler().set(m_fga002, FUNC(fga002_device::lirq0_w));
+
+ // dual ported ram
+ RAM(config, m_ram).set_default_size(ram_default).set_extra_options(ram_options);
+}
+
+void vme_sys68k_cpu30_card_device::device_add_mconfig(machine_config &config)
+{
+ sys68k_cpu30(config, XTAL(25'000'000), "4M", "4M, 8M, 16M, 32M");
+}
+
+/* SYS68K/CPU-30X Part No.1 01300: 16.7 MHz 68030 based CPU board with 68882 FPCP, DMAC, 1 Mbyte Dual Ported RAM capacity and VMEPROM. */
+void vme_sys68k_cpu30x_card_device::device_add_mconfig(machine_config &config)
+{
+ sys68k_cpu30(config, XTAL(16'777'216), "1M", "1M, 2M, 4M"); // 16.7 MHz from description, crystal needs verification
+}
+
+/* SYS68K/CPU-30XA Part No.1 01301: 20.0 MHz 68030 based CPU board with 68882 FPCP, DMAC, 1 Mbyte Dual Ported RAM capacity and VMEPROM. Documentation included.*/
+void vme_sys68k_cpu30xa_card_device::device_add_mconfig(machine_config &config)
+{
+ sys68k_cpu30(config, XTAL(20'000'000), "1M", "1M, 2M, 4M"); // 20.0 MHz from description, crystal needs verification
+}
+
+/* SYS68K/CPU-30ZA Part No.1 01302: 20.0 MHz 68030 based CPU board with 68882 FPCP, DMAC, 4 Mbyte Dual Ported RAM capacity and VMEPROM. Documentation included.*/
+void vme_sys68k_cpu30za_card_device::device_add_mconfig(machine_config &config)
+{
+ sys68k_cpu30(config, XTAL(20'000'000), "4M", "1M, 2M, 4M"); // 20.0 MHz from description, crystal needs verification
+}
+
+/* SYS68K/CPU-30ZBE 68030/68882 CPU, 25 MHz, 4/8/16 Mbyte shared DRAM, 4 Mbyte Flash, SCSI, Ethernet, Floppy disk, 4 serial I/O ports, 32-bit VMEbus interface */
+void vme_sys68k_cpu30be_card_device::device_add_mconfig(machine_config &config)
+{
+ sys68k_cpu30(config, XTAL(25'000'000), "4M", "256K, 512K, 1M, 2M, 4M, 8M, 16M, 32M"); // 25.0 MHz from description, crystal needs verification
+}
+
+/* SYS68K/CPU-33 */
+void vme_sys68k_cpu33_card_device::device_add_mconfig(machine_config &config)
+{
+ sys68k_cpu30(config, XTAL(25'000'000), "4M", "256K, 512K, 1M, 2M, 4M, 8M, 16M, 32M"); // 25.0 MHz from description, crystal needs verification
+}
+
+/* SYS68K/CPU-30Lite 68030 CPU, 25 MHz, 4/8 Mbyte shared DRAM, 4 Mbyte Flash, 4 serial ports, 32-bit VMEbus interface, VMEPROM firmware. */
+void vme_sys68k_cpu30lite_card_device::device_add_mconfig(machine_config &config)
+{
+ sys68k_cpu30(config, XTAL(25'000'000), "4M", "256K, 512K, 1M, 2M, 4M, 8M, 16M, 32M");
+
+// Enable these when added to main config
+// config.device_remove("fpu");
+// config.device_remove("scsi");
+// config.device_remove("eth");
+// config.device_remove("fdc");
+}
+
+/* ROM definitions */
+ROM_START (sys68k_cpu30) /* This is an original rom dump */
+ ROM_REGION32_BE(0x800000, "system", 0)
+// Boots with Board ID set to: 0x36 (FGA002 BOOT on terminal P4, "Wait until harddisk is up to speed " on terminal P1)
+ ROM_LOAD32_BYTE("cpu30ll-ubr-v2.1.rom", 0x000003, 0x20000, CRC (a03ebf46) SHA1 (48fa0268cb10e20679c093e02574dbd9925f95d1))
+ ROM_LOAD32_BYTE("cpu30lo-ubr-v2.1.rom", 0x000002, 0x20000, CRC (fefa88ed) SHA1 (71a9ad807c0c2da5c6f6a6dc68c73ad8b52f3ea9))
+ ROM_LOAD32_BYTE("cpu30up-ubr-v2.1.rom", 0x000001, 0x20000, CRC (dfed1f68) SHA1 (71478a77d5ab5da0fabcd78e69537919b560e3b8))
+ ROM_LOAD32_BYTE("cpu30uu-ubr-v2.1.rom", 0x000000, 0x20000, CRC (66e95cc2) SHA1 (acdb468a3a5974295b81271d617de7f101098891))
+// Same binary for many boards, attempts to detect CPU speed etc, currently failing detection but boots system roms anyway
+
+ ROM_REGION32_BE(0x10000, "boot", 0)
+ ROM_LOAD ("fga002-3.1.rom", 0x000000, 0x10000, CRC (faa38972) SHA1 (651dfc2f9a865fc6adf49dad90f9e705f2889919) )
+ROM_END
+
+ROM_START (sys68k_cpu33) /* This is an original rom dump */
+ ROM_REGION32_BE(0x800000, "system", 0)
+// Boots with Board ID set to: 0x36 (FGA002 BOOT and VMEPROM on terminal P4)
+ ROM_LOAD16_BYTE("cpu33lo-ubr-v1.01.rom", 0x000001, 0x40000, CRC (49895fdf) SHA1 (733abd144c95225a2faf920490e31df2a27f8e03))
+ ROM_LOAD16_BYTE("cpu33up-ubr-v1.01.rom", 0x000000, 0x40000, CRC (cfe75e94) SHA1 (d40e0635a48607be25f7c58c74b53b7e58fe735d))
+
+// Same binary for many boards, attempts to detect CPU speed etc, currently failing detection but boots system roms anyway
+ ROM_REGION32_BE(0x10000, "boot", 0)
+ ROM_LOAD ("fga002-3.1.rom", 0x000000, 0x10000, CRC (faa38972) SHA1 (651dfc2f9a865fc6adf49dad90f9e705f2889919) )
+ROM_END
+
+ROM_START (nodump)
+ ROM_REGION32_BE(0x800000, "system", 0)
+ ROM_LOAD("system.bin", 0x000000, 0x800000, NO_DUMP)
+ ROM_REGION32_BE(0x10000, "boot", 0)
+ ROM_LOAD("boot.bin", 0x000000, 0x10000, NO_DUMP)
+ROM_END
+
+const tiny_rom_entry *vme_sys68k_cpu30_card_device::device_rom_region() const { return ROM_NAME(sys68k_cpu30); }
+
+/* These needs reality check as they has 1Mb of RAM which is not a suitable size for later CPU_30:s */
+const tiny_rom_entry *vme_sys68k_cpu30x_card_device::device_rom_region() const { return ROM_NAME(sys68k_cpu30); }
+const tiny_rom_entry *vme_sys68k_cpu30xa_card_device::device_rom_region() const { return ROM_NAME(sys68k_cpu30); }
+const tiny_rom_entry *vme_sys68k_cpu30za_card_device::device_rom_region() const { return ROM_NAME(sys68k_cpu30); }
+
+const tiny_rom_entry *vme_sys68k_cpu30be_card_device::device_rom_region() const { return ROM_NAME(sys68k_cpu30); }
+
+/* These needs dumps */
+const tiny_rom_entry *vme_sys68k_cpu30lite_card_device::device_rom_region() const { return ROM_NAME(nodump); }
+
+const tiny_rom_entry *vme_sys68k_cpu33_card_device::device_rom_region() const { return ROM_NAME(sys68k_cpu33); }
+
+ioport_constructor sys68k_cpu30_device_base::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(sys68k_cpu30);
+}
+
+/*
+ * System ROM information
+ *
+ * FGA-002 Bootprom version 3.1 is released May 28, 1990, coprighted by FORCE Computers GmbH
+ *
+ * Bootprom PIT setup sequence - To start VMEPROM, the rotary switches must both be set to 'F' (PI/T #1 port A)
+ * --------------------------------------------------------------------------------------------------------------
+ * :pit1 Reg 10 -> ff PAAR - read port A of PIT1 without side effects
+
+ * :pit2 Reg 10 -> 36 PBAR - read port B of PIT2 without side effects
+ * :pit2 Reg 10 <- 00 TCR - PC3/PC7 is I/O, PC2 is I/O, CLK and x32 prescaler, Preload timer on 0 (zero), Timer disabled
+ * :pit2 Reg 13 <- ff CPRH - Counter Preload Regsiter High
+ * :pit2 Reg 14 <- ff CPRM - Counter Preload Regsiter Mid
+ * :pit2 Reg 15 <- ff CPRL - Counter Preload Regsiter Low
+ * :pit2 Reg 10 <- 01 TCR - PC3/PC7 is I/O, PC2 is I/O, CLK and x32 prescaler, Preload timer on 0 (zero), Timer enabled
+ * :pit2 Reg 10 <- 00 TCR - PC3/PC7 is I/O, PC2 is I/O, CLK and x32 prescaler, Preload timer on 0 (zero), Timer disabled
+ * :pit2 Reg -> ff CNTRH - Current value of timer high byte
+ * :pit2 Reg -> b3 CNTRM - Current value of timer mid byte
+ * :pit2 Reg -> 70 CNTRL - Current value of timer low byte
+
+ * :pit1 Reg 10 <- e0 TCR - PC3 is TOUT, PC7 is I/O, Interrupts enabled, PC2 is I/O, CLK and x32 prescaler, Preload timer on 0 (zero), Timer disabled
+ * :pit1 Reg 00 <- 20 PGCR -
+ * :pit1 Reg 01 <- 08 PSRR -
+ * :pit1 Reg 06 <- c0 PACR -
+ * :pit1 Reg 02 <- 00 PADDR -
+ * :pit1 Reg 07 <- c0 PBCR -
+ * :pit1 Reg 09 <- 00 PBDR -
+ * :pit1 Reg 03 <- 00 PBDDR -
+ * :pit1 Reg 0c <- 17 PCDR -
+ * :pit1 Reg 04 <- 17 PCDDR -
+ * :pit1 Reg 15 <- e2 CPRL -
+ * :pit1 Reg 14 <- 04 CPRM -
+ * :pit1 Reg 13 <- 00 CPRH -
+ * :pit1 Reg 11 <- f2 TIVR -
+ * :pit1 Reg 10 <- 41 TCR - PC3 is SQW at TOUT, PC7 is I/O, PC2 is I/O, CLK and x32 prescaler, Preload timer on 0 (zero), Timer enabled
+
+ * :pit2 Reg 10 <- e2 PC3 is TOUT, PC7 is I/O, Interrupts enabled, PC2 is timer enable/disable, CLK and prescaler, Preload timer on 0 (zero), Timer disabled
+ * :pit2 Reg 00 <- 1e PGCR
+ * :pit2 Reg 01 <- 08 PSRR
+ * :pit2 Reg 06 <- c0 PACR
+ * :pit2 Reg 02 <- 00 PADDR
+ * :pit2 Reg 07 <- c0 PBCR
+ * :pit2 Reg 03 <- 00 PBDDR
+ * :pit2 Reg 04 <- 00 PCDDR
+ * :pit2 Reg 15 <- 08 CPRL
+ * :pit2 Reg 14 <- 00 CPRM
+ * :pit2 Reg 13 <- 00 CPRH
+ * :pit2 Reg 11 <- f3 TIVR
+ * :pit2 Reg 10 <- e3 PC3 is TOUT, PC7 is I/O, Interrupts enabled, PC2 is timer enable/disable, CLK and prescaler, Preload timer on 0 (zero), Timer enabled
+
+ * DUSCC #1 channel A setup 1 sequence FGA-002 firmware (polled i/o)
+ * A Reg 0f <- 00 - reset Tx Command
+ * A Reg 0f <- 40 - reset Rx Command
+ * A Reg 00 <- 07 - Async mode
+ * A Reg 01 <- 38 - Normal polled or interrupt mode, no DMA
+ * A Reg 04 <- 7f - Tx 8 bits, CTS and RTS, 1 STOP bit
+ * A Reg 06 <- 1b - Rx RTS, 8 bits, no DCD, no parity
+ * A Reg 05 <- 3d - Tx BRG 9600 (assuming a 14.7456 crystal)
+ * A Reg 07 <- 2d - Rx BRG 9600 (assuming a 14.7456 crystal)
+ * A Reg 0e <- 27 - TRxC = RxCLK 1x, RTxC is input, RTS, GPO2, crystal oscillator connected to X2
+ * A Reg 0b <- f1 - RTS low, OUT1 = OUT2 = high, RxRdy asserted on FIFO not empty
+ * TxRdy asserted on FIFO not empty, Same Tx Residual Character Length as for REG_TPR
+ * A Reg 0f <- 00 - reset Tx Command
+ * A Reg 0f <- 40 - reset Rx Command
+ * A Reg 0f <- 02 - enable Tx Command
+ * A Reg 0f <- 42 - enable Rx Command
+ *--- end of setup sequence ---
+ * loop:
+ * read <- REG_GSR
+ * until something needs attention
+ *
+ * DUSCC #1 channel A & B setup 2 sequence CPU-33 VMEPROM with PDOS (interrupt driven i/o)
+ * A Reg 0f <- 00 - reset Tx Command
+ * A Reg 0f <- 40 - reset Rx Command
+ * A Reg 00 <- 07 - Async mode
+ * A Reg 01 <- 38 - Normal polled or interrupt mode, no DMA
+ * A Reg 04 <- 7f - Tx 8 bits, CTS and RTS, 1 STOP bit
+ * A Reg 06 <- 1b - Rx RTS, 8 bits, no DCD, no parity
+ * A Reg 0b <- e1 - RTS low, OUT1 = OUT2 = high, RxRdy asserted on FIFO not empty
+ * TxRdy asserted on FIFO not full, Same Tx Residual Character Length as for REG_TPR
+ * A Reg 0e <- 27 - TRxC = RxCLK 1x, RTxC is input, RTS, GPO2, crystal oscillator connected to X2
+ * A Reg 07 <- 2d - Rx BRG 9600 (assuming a 14.7456 crystal)
+ * A Reg 05 <- 3d - Tx BRG 9600 (assuming a 14.7456 crystal)
+ * A Reg 1c <- 10 - RXRDY interrupts enabled
+ * A Reg 1e <- 1c - Interrupt vector
+ * A Reg 1f <- 83 - Interleaved prio with A high, no status in vector, enable interrupts for A & B channel
+ * A Reg 0f <- 00 - reset Tx Command
+ * A Reg 0f <- 02 - enable Tx Command
+ * A Reg 0f <- 40 - reset Rx Command
+ * A Reg 0f <- 42 - enable Rx Command
+ * Repeated setup for channel B
+ *
+ * FGA setup
+void fga002_device::do_fga002reg_icrtim0_w(uint8_t)(00)
+void fga002_device::do_fga002reg_ctl3_w(uint8_t)(0c)
+void fga002_device::do_fga002reg_icrlocal0_w(uint8_t)(00)
+void fga002_device::do_fga002reg_icrlocal1_w(uint8_t)(00)
+void fga002_device::do_fga002reg_icrlocal2_w(uint8_t)(00)
+void fga002_device::do_fga002reg_icrlocal3_w(uint8_t)(00)
+void fga002_device::do_fga002reg_icrlocal4_w(uint8_t)(00)
+void fga002_device::do_fga002reg_icrlocal5_w(uint8_t)(00)
+void fga002_device::do_fga002reg_icrlocal6_w(uint8_t)(00)
+void fga002_device::do_fga002reg_icrlocal7_w(uint8_t)(00)
+
+ * A Reg 10 <- 20
+uint8_t duscc_channel::do_dusccreg_rxfifo_r()
+ - RX rp:0 wp:1 sz:4
+ - RX reading out data:6e 'n'
+
+uint8_t duscc_channel::do_dusccreg_rxfifo_r()
+ - RX rp:1 wp:2 sz:4
+ - RX reading out data:6e 'n'
+ * A Reg 10 <- 6e
+ * A Reg 10 <- 0d
+ * A Reg 10 <- 0a
+void fga002_device::do_fga002reg_icrlocal2_w(uint8_t)(4d)
+void fga002_device::do_fga002reg_icrlocal4_w(uint8_t)(1c)
+ * A Reg 0f <- 00
+ * A Reg 0f <- 40
+ * A Reg 00 <- 07
+ * A Reg 01 <- 38
+ * A Reg 04 <- 7f
+ * A Reg 06 <- 1b
+ * A Reg 0b <- e1
+ * A Reg 0e <- 27
+ * A Reg 07 <- 2d
+ * A Reg 05 <- 3d
+ * A Reg 1c <- 10
+void duscc_channel::do_dusccreg_ier_w(uint8_t)(10)
+- RXRDY interrupts enabled
+:duscc void duscc_device::check_interrupts()()
+:duscc virtual int duscc_device::z80daisy_irq_state() A:[00][00][00][00] B:[00][00][00][00] Interrupt State 00
+void fga002_device::trigger_interrupt(uint8_t)(34)
+Interrupt Level 4, caused by ICR 1c with vector 34
+void fga002_device::check_interrupts()()
+:fga002 virtual int fga002_device::z80daisy_irq_state() Level 0-7:[00][00] [00][00] [01][00] [00][00]
+void sys68k_cpu30_device_base::fga_irq_callback(int)(01)
+void fga002_device::check_interrupts()()
+ */
+
+
+/* Driver */
+/* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS */
+//COMP( 1988, sys68k_cpu30, 0, 0, cpu30, cpu30, sys68k_cpu30_device_base, empty_init, "Force Computers GmbH", "SYS68K/CPU-30", MACHINE_NOT_WORKING | MACHINE_NO_SOUND_HW )
+//COMP( 1988, sys68k_cpu30x, sys68k_cpu30, 0, cpu30x, cpu30, sys68k_cpu30_device_base, init_cpu30x, "Force Computers GmbH", "SYS68K/CPU-30X", MACHINE_NOT_WORKING | MACHINE_NO_SOUND_HW )
+//COMP( 1988, sys68k_cpu30xa, sys68k_cpu30, 0, cpu30xa, cpu30, sys68k_cpu30_device_base, init_cpu30xa, "Force Computers GmbH", "SYS68K/CPU-30XA", MACHINE_NOT_WORKING | MACHINE_NO_SOUND_HW )
+//COMP( 1988, sys68k_cpu30za, sys68k_cpu30, 0, cpu30za, cpu30, sys68k_cpu30_device_base, init_cpu30za, "Force Computers GmbH", "SYS68K/CPU-30ZA", MACHINE_NOT_WORKING | MACHINE_NO_SOUND_HW )
+//COMP( 1996, sys68k_cpu30zbe, sys68k_cpu30, 0, cpu30zbe, cpu30, sys68k_cpu30_device_base, init_cpu30zbe, "Force Computers GmbH", "SYS68K/CPU-30ZBE", MACHINE_NOT_WORKING | MACHINE_NO_SOUND_HW )
+//COMP( 1996, sys68k_cpu30be8, sys68k_cpu30, 0, cpu30be8, cpu30, sys68k_cpu30_device_base, init_cpu30be8, "Force Computers GmbH", "SYS68K/CPU-30BE/8", MACHINE_NOT_WORKING | MACHINE_NO_SOUND_HW )
+//COMP( 1996, sys68k_cpu30be16, sys68k_cpu30, 0, cpu30be16, cpu30, sys68k_cpu30_device_base, init_cpu30be16, "Force Computers GmbH", "SYS68K/CPU-30BE/16", MACHINE_NOT_WORKING | MACHINE_NO_SOUND_HW )
+//COMP( 1996, sys68k_cpu30lite4, sys68k_cpu30, 0, cpu30lite4, cpu30, sys68k_cpu30_device_base, init_cpu30lite4, "Force Computers GmbH", "SYS68K/CPU-30Lite/4", MACHINE_NOT_WORKING | MACHINE_NO_SOUND_HW )
+//COMP( 1996, sys68k_cpu30lite8, sys68k_cpu30, 0, cpu30lite8, cpu30, sys68k_cpu30_device_base, init_cpu30lite8, "Force Computers GmbH", "SYS68K/CPU-30Lite/8", MACHINE_NOT_WORKING | MACHINE_NO_SOUND_HW )
+//COMP( 199?, sys68k_cpu33, sys68k_cpu30, 0, cpu33, cpu30, sys68k_cpu30_device_base, init_cpu33, "Force Computers GmbH", "SYS68K/CPU-33", MACHINE_NOT_WORKING | MACHINE_NO_SOUND_HW )
+
+/* Below are not fully configured variants defaulting to generic cpu30 */
+
+/* The following boards were manufactured for Ericsson to be used in their fixed network switches. They support hot swap and the Ericsson APNbus */
+/* SYS68K/CPU-30SEN-R/32 assumed as generic until spec is found. 25 MHz 68030 based CPU board with DMAC, 32 MByte Shared RAM capacity and VMEPROM.
+ 4 MByte System Flash memory, SCSI via on-board EAGLE Controller FC68165 with DMA, 2 serial I/O ports, APNbus interface, VMEPROM firmware */
+//COMP( 1997, sys68k_cpu30senr, 0, 0, cpu30, cpu30, sys68k_cpu30_device_base, empty_init, "Force Computers GmbH", "SYS68K/CPU-30SEN-R", MACHINE_NOT_WORKING | MACHINE_NO_SOUND_HW )
+/* SYS68K/CPU-30SEN-R-501/4 assumed as generic until spec is found. 25 MHz 68030 based CPU board with DMAC, 4 MByte Shared RAM capacity and VMEPROM.
+ 48V DC/DC onboard, metric backplane connectors, BYB501 PCB formfactor (TVJ807). 4 MByte System Flash memory, SCSI via onboard EAGLEController
+ FC68165 with DMA, 2 serial I/O ports, APNbus interface, VMEPROM firmware*/
+//COMP( 1997, sys68k_cpu30senr501, 0, 0, cpu30, cpu30, sys68k_cpu30_device_base, empty_init, "Force Computers GmbH", "SYS68K/CPU-30SEN-R-501", MACHINE_NOT_WORKING | MACHINE_NO_SOUND_HW )
+
+/*CPU-33XB MC68030 25MHz CPU, 68882 FPC, 1MB, 2 SERIAL, RS-232, VME BOARD*/
+//COMP( 1990, cpu33xb, 0, 0, cpu30, cpu30, sys68k_cpu30_device_base, 0, "Force Computers GmbH", "SYS68K/CPU-33XB", MACHINE_NOT_WORKING | MACHINE_NO_SOUND_HW )
+/*CPU-33B/4 MC68030 25MHz CPU, 68882 FPC, 1MB, 2 SERIAL, RS-232, VME BOARD*/
+//COMP( 1990, cpu30b4, 0, 0, cpu30, cpu30, sys68k_cpu30_device_base, 0, "Force Computers GmbH", "SYS68K/CPU-33B/4", MACHINE_NOT_WORKING | MACHINE_NO_SOUND_HW )
diff --git a/src/devices/bus/vme/sys68k_cpu30.h b/src/devices/bus/vme/sys68k_cpu30.h
new file mode 100644
index 00000000000..28691cbc4e9
--- /dev/null
+++ b/src/devices/bus/vme/sys68k_cpu30.h
@@ -0,0 +1,157 @@
+// license:BSD-3-Clause
+// copyright-holders:Joakim Larsson Edstrom
+
+#ifndef MAME_BUS_VME_SYS68K_CPU30_H
+#define MAME_BUS_VME_SYS68K_CPU30_H
+
+#pragma once
+
+#include "bus/vme/vme.h"
+#include "cpu/m68000/m68030.h"
+#include "machine/ram.h" // For variants that only differs in amount of RAM
+#include "machine/scnxx562.h"
+#include "machine/68230pit.h"
+#include "machine/msm6242.h"
+#include "machine/fga002.h"
+
+class sys68k_cpu30_device_base
+ : public device_t
+ , public device_vme_card_interface
+{
+public:
+ sys68k_cpu30_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock, uint8_t board_id);
+
+protected:
+ virtual ioport_constructor device_input_ports() const override;
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ void sys68k_cpu30(machine_config &config, XTAL clock, char const *const ram_default, char const *const ram_options);
+
+ void fdc_w(offs_t offset, uint8_t data);
+ uint8_t fdc_r(offs_t offset);
+ void scsi_w(offs_t offset, uint8_t data);
+ uint8_t scsi_r(offs_t offset);
+ uint8_t slot1_status_r();
+
+ /* Interrupt support */
+ void cpu_space_map(address_map &map);
+ void fga_irq_callback(int state);
+ uint8_t fga_irq_state = 0;
+ // int fga_irq_vector = 0;
+ int fga_irq_level = 0;
+
+ /* Rotary switch PIT input */
+ uint8_t rotary_rd();
+ uint8_t flop_dmac_r();
+ void flop_dmac_w(uint8_t data);
+ uint8_t pit1c_r();
+ void pit1c_w(uint8_t data);
+ uint8_t pit2a_r();
+ void pit2a_w(uint8_t data);
+ uint8_t board_mem_id_rd();
+ uint8_t pit2c_r();
+ void pit2c_w(uint8_t data);
+
+ /* VME bus accesses */
+ //uint16_t vme_a24_r();
+ //void vme_a24_w(uint16_t data);
+ //uint16_t vme_a16_r();
+ //void vme_a16_w(uint16_t data);
+
+ void cpu30_mem(address_map &map);
+
+ required_device<m68000_musashi_device> m_maincpu;
+ required_device<ram_device> m_ram;
+
+ required_device<duscc68562_device> m_dusccterm;
+
+ required_device<pit68230_device> m_pit1;
+ required_device<pit68230_device> m_pit2;
+
+ required_device<fga002_device> m_fga002;
+
+ required_device<rtc72423_device> m_rtc;
+
+ required_memory_region m_boot;
+ memory_passthrough_handler m_boot_mph;
+
+ // Helper functions
+ void update_irq_to_maincpu();
+
+ uint8_t const m_board_id;
+};
+
+class vme_sys68k_cpu30_card_device : public sys68k_cpu30_device_base
+{
+public:
+ vme_sys68k_cpu30_card_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override;
+};
+class vme_sys68k_cpu30x_card_device : public sys68k_cpu30_device_base
+{
+public:
+ vme_sys68k_cpu30x_card_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override;
+};
+class vme_sys68k_cpu30xa_card_device : public sys68k_cpu30_device_base
+{
+public:
+ vme_sys68k_cpu30xa_card_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override;
+};
+class vme_sys68k_cpu30za_card_device : public sys68k_cpu30_device_base
+{
+public:
+ vme_sys68k_cpu30za_card_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override;
+};
+class vme_sys68k_cpu30be_card_device : public sys68k_cpu30_device_base
+{
+public:
+ vme_sys68k_cpu30be_card_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override;
+};
+class vme_sys68k_cpu30lite_card_device : public sys68k_cpu30_device_base
+{
+public:
+ vme_sys68k_cpu30lite_card_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override;
+};
+class vme_sys68k_cpu33_card_device : public sys68k_cpu30_device_base
+{
+public:
+ vme_sys68k_cpu33_card_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override;
+};
+
+DECLARE_DEVICE_TYPE(VME_SYS68K_CPU30, vme_sys68k_cpu30_card_device)
+DECLARE_DEVICE_TYPE(VME_SYS68K_CPU30X, vme_sys68k_cpu30x_card_device)
+DECLARE_DEVICE_TYPE(VME_SYS68K_CPU30XA, vme_sys68k_cpu30xa_card_device)
+DECLARE_DEVICE_TYPE(VME_SYS68K_CPU30ZA, vme_sys68k_cpu30za_card_device)
+DECLARE_DEVICE_TYPE(VME_SYS68K_CPU30BE, vme_sys68k_cpu30be_card_device)
+DECLARE_DEVICE_TYPE(VME_SYS68K_CPU30LITE, vme_sys68k_cpu30lite_card_device)
+DECLARE_DEVICE_TYPE(VME_SYS68K_CPU33, vme_sys68k_cpu33_card_device)
+
+#endif // MAME_BUS_VME_SYS68K_CPU30_H
diff --git a/src/devices/bus/vme/vme_fcscsi.cpp b/src/devices/bus/vme/sys68k_iscsi.cpp
index 320d1ad77c5..2d0ee64b605 100644
--- a/src/devices/bus/vme/vme_fcscsi.cpp
+++ b/src/devices/bus/vme/sys68k_iscsi.cpp
@@ -143,30 +143,18 @@
*
****************************************************************************/
#include "emu.h"
-#include "vme_fcscsi.h"
+#include "sys68k_iscsi.h"
-#include "cpu/m68000/m68000.h"
+#include "cpu/m68000/m68010.h"
#include "machine/68230pit.h"
#include "machine/wd_fdc.h"
#include "machine/hd63450.h" // compatible with MC68450
#include "machine/clock.h"
-#include "formats/pc_dsk.h"
-#define LOG_GENERAL 0x01
-#define LOG_SETUP 0x02
-#define LOG_PRINTF 0x04
+#define VERBOSE (0) // (LOG_GENERAL)
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
-#define VERBOSE 0 //(LOG_PRINTF | LOG_SETUP | LOG_GENERAL)
-
-#define LOGMASK(mask, ...) do { if (VERBOSE & mask) logerror(__VA_ARGS__); } while (0)
-#define LOGLEVEL(mask, level, ...) do { if ((VERBOSE & mask) >= level) logerror(__VA_ARGS__); } while (0)
-
-#define LOG(...) LOGMASK(LOG_GENERAL, __VA_ARGS__)
-#define LOGSETUP(...) LOGMASK(LOG_SETUP, __VA_ARGS__)
-
-#if VERBOSE & LOG_PRINTF
-#define logerror printf
-#endif
#ifdef _MSC_VER
#define FUNCNAME __func__
@@ -180,24 +168,23 @@
// GLOBAL VARIABLES
//**************************************************************************
-DEFINE_DEVICE_TYPE(VME_FCSCSI1, vme_fcscsi1_card_device, "fcscsi1", "Force Computer SYS68K/ISCSI-1 Intelligent Mass Storage Controller Board")
+DEFINE_DEVICE_TYPE(VME_SYS68K_ISCSI1, vme_sys68k_iscsi1_card_device, "sys68k_iscsi1", "Force Computers SYS68K/ISCSI-1")
#define CPU_CRYSTAL 20_MHz_XTAL /* Jauch */
#define PIT_CRYSTAL 16_MHz_XTAL /* Jauch */
-void vme_fcscsi1_card_device::fcscsi1_mem(address_map &map)
+void vme_sys68k_iscsi1_card_device::fcscsi1_mem(address_map &map)
{
map.unmap_value_high();
- map(0x000000, 0x000007).rom().r(FUNC(vme_fcscsi1_card_device::bootvect_r)); /* Vectors mapped from System EPROM */
- map(0x000008, 0x001fff).ram(); /* SRAM */
- map(0x002000, 0x01ffff).ram(); /* Dual Ported RAM */
- map(0xe00000, 0xe7ffff).rom(); /* System EPROM Area 32Kb DEBUGGER supplied */
+
+ map(0x000000, 0x01ffff).ram(); /* SRAM */
+ map(0xe00000, 0xe1ffff).rom().region("eprom", 0); /* System EPROM Area 32Kb DEBUGGER supplied */
map(0xd00000, 0xd0003f).rw("pit", FUNC(pit68230_device::read), FUNC(pit68230_device::write)).umask16(0x00ff);
// map(0xc40000, 0xc4001f).rw("scsi", FUNC(ncr5386_device::read), FUNC(ncr5386_device::write)).umask16(0x00ff); /* SCSI Controller interface - device support not yet available*/
- map(0xc40000, 0xc4001f).rw(FUNC(vme_fcscsi1_card_device::scsi_r), FUNC(vme_fcscsi1_card_device::scsi_w)).umask16(0x00ff);
+ map(0xc40000, 0xc4001f).rw(FUNC(vme_sys68k_iscsi1_card_device::scsi_r), FUNC(vme_sys68k_iscsi1_card_device::scsi_w)).umask16(0x00ff);
map(0xc80000, 0xc800ff).rw("mc68450", FUNC(hd63450_device::read), FUNC(hd63450_device::write)); /* DMA Controller interface */
map(0xcc0000, 0xcc0007).rw("fdc", FUNC(wd1772_device::read), FUNC(wd1772_device::write)).umask16(0x00ff); /* Floppy Controller interface */
- map(0xcc0009, 0xcc0009).rw(FUNC(vme_fcscsi1_card_device::tcr_r), FUNC(vme_fcscsi1_card_device::tcr_w)); /* The Control Register, SCSI ID and FD drive select bits */
+ map(0xcc0009, 0xcc0009).rw(FUNC(vme_sys68k_iscsi1_card_device::tcr_r), FUNC(vme_sys68k_iscsi1_card_device::tcr_w)); /* The Control Register, SCSI ID and FD drive select bits */
}
/*
@@ -223,7 +210,7 @@ elapses and/or if the VMEbus interrupt trigger call occurs.
/* TODO: Add configurable B41 jumper */
#define B41 0
-void vme_fcscsi1_card_device::update_irq_to_maincpu() {
+void vme_sys68k_iscsi1_card_device::update_irq_to_maincpu() {
if (fdc_irq_state) {
m_maincpu->set_input_line(M68K_IRQ_3, ASSERT_LINE);
m_maincpu->set_input_line(M68K_IRQ_2, CLEAR_LINE);
@@ -239,10 +226,10 @@ void vme_fcscsi1_card_device::update_irq_to_maincpu() {
}
}
-void vme_fcscsi1_card_device::cpu_space_map(address_map &map)
+void vme_sys68k_iscsi1_card_device::cpu_space_map(address_map &map)
{
map(0xfffff0, 0xffffff).m(m_maincpu, FUNC(m68000_base_device::autovectors_map));
- map(0xfffff5, 0xfffff5).r(FUNC(vme_fcscsi1_card_device::dma_iack));
+ map(0xfffff5, 0xfffff5).r(FUNC(vme_sys68k_iscsi1_card_device::dma_iack));
}
static void fcscsi_floppies(device_slot_interface &device)
@@ -252,32 +239,32 @@ static void fcscsi_floppies(device_slot_interface &device)
/* ROM definitions */
-ROM_START (fcscsi1)
- ROM_REGION (0x1000000, "maincpu", 0)
+ROM_START (sys68k_iscsi1)
+ ROM_REGION16_BE (0x20000, "eprom", 0)
/* Besta ROM:s - apparantly patched Force ROM:s */
ROM_SYSTEM_BIOS(0, "besta88", "Besta 88")
- ROMX_LOAD ("besta88_scsi_lower.rom", 0xe00001, 0x4000, CRC (fb3ab364) SHA1 (d79112100f1c4beaf358e006efd4dde5e300b0ba), ROM_SKIP(1) | ROM_BIOS(0))
- ROMX_LOAD ("besta88_scsi_upper.rom", 0xe00000, 0x4000, CRC (41f9cdf4) SHA1 (66b998bbf9459f0a613718260e05e97749532073), ROM_SKIP(1) | ROM_BIOS(0))
+ ROMX_LOAD ("besta88_scsi_lower.rom", 0x00001, 0x4000, CRC (fb3ab364) SHA1 (d79112100f1c4beaf358e006efd4dde5e300b0ba), ROM_SKIP(1) | ROM_BIOS(0))
+ ROMX_LOAD ("besta88_scsi_upper.rom", 0x00000, 0x4000, CRC (41f9cdf4) SHA1 (66b998bbf9459f0a613718260e05e97749532073), ROM_SKIP(1) | ROM_BIOS(0))
/* Force ROM:s */
ROM_SYSTEM_BIOS(1, "iscsi-1_v3.7", "Force Computer SYS68K/ISCSI-1 firmware v3.7")
- ROMX_LOAD ("iscsi-1_v3.7_l.bin", 0xe00001, 0x4000, CRC (83d95ab7) SHA1 (bf249910bcb6cb0b04dda2a95a38a0f90b553352), ROM_SKIP(1) | ROM_BIOS(1))
- ROMX_LOAD ("iscsi-1_v3.7_u.bin", 0xe00000, 0x4000, CRC (58815831) SHA1 (074085ef96e1fe2a551938bdeee6a9cab40ff09c), ROM_SKIP(1) | ROM_BIOS(1))
+ ROMX_LOAD ("iscsi-1_v3.7_l.bin", 0x00001, 0x4000, CRC (83d95ab7) SHA1 (bf249910bcb6cb0b04dda2a95a38a0f90b553352), ROM_SKIP(1) | ROM_BIOS(1))
+ ROMX_LOAD ("iscsi-1_v3.7_u.bin", 0x00000, 0x4000, CRC (58815831) SHA1 (074085ef96e1fe2a551938bdeee6a9cab40ff09c), ROM_SKIP(1) | ROM_BIOS(1))
ROM_END
-void vme_fcscsi1_card_device::device_add_mconfig(machine_config &config)
+void vme_sys68k_iscsi1_card_device::device_add_mconfig(machine_config &config)
{
/* basic machine hardware */
M68010(config, m_maincpu, CPU_CRYSTAL / 2); /* 7474 based frequency divide by 2 */
- m_maincpu->set_addrmap(AS_PROGRAM, &vme_fcscsi1_card_device::fcscsi1_mem);
- m_maincpu->set_addrmap(m68000_base_device::AS_CPU_SPACE, &vme_fcscsi1_card_device::cpu_space_map);
+ m_maincpu->set_addrmap(AS_PROGRAM, &vme_sys68k_iscsi1_card_device::fcscsi1_mem);
+ m_maincpu->set_addrmap(m68000_base_device::AS_CPU_SPACE, &vme_sys68k_iscsi1_card_device::cpu_space_map);
/* FDC */
WD1772(config, m_fdc, PIT_CRYSTAL / 2);
- m_fdc->intrq_wr_callback().set(FUNC(vme_fcscsi1_card_device::fdc_irq));
+ m_fdc->intrq_wr_callback().set(FUNC(vme_sys68k_iscsi1_card_device::fdc_irq));
m_fdc->drq_wr_callback().set("mc68450", FUNC(hd63450_device::drq1_w));
FLOPPY_CONNECTOR(config, "fdc:0", fcscsi_floppies, "525qd", floppy_image_device::default_pc_floppy_formats);
FLOPPY_CONNECTOR(config, "fdc:1", fcscsi_floppies, "525qd", floppy_image_device::default_pc_floppy_formats);
@@ -286,53 +273,52 @@ void vme_fcscsi1_card_device::device_add_mconfig(machine_config &config)
/* PIT Parallel Interface and Timer device */
PIT68230(config, m_pit, PIT_CRYSTAL / 2); /* 7474 based frequency divide by 2 */
- m_pit->pb_out_callback().set(FUNC(vme_fcscsi1_card_device::led_w));
+ m_pit->pb_out_callback().set(FUNC(vme_sys68k_iscsi1_card_device::led_w));
/* DMAC it is really a M68450 but the HD63850 is upwards compatible */
HD63450(config, m_dmac, CPU_CRYSTAL / 2, "maincpu"); // MC68450 compatible
m_dmac->set_clocks(attotime::from_usec(32), attotime::from_nsec(450), attotime::from_usec(4), attotime::from_hz(15625/2));
m_dmac->set_burst_clocks(attotime::from_usec(32), attotime::from_nsec(450), attotime::from_nsec(50), attotime::from_nsec(50));
- m_dmac->irq_callback().set(FUNC(vme_fcscsi1_card_device::dma_irq));
- //m_dmac->dma_read<0>().set(FUNC(vme_fcscsi1_card_device::scsi_read_byte)); // ch 0 = SCSI
- //m_dmac->dma_write<0>().set(FUNC(vme_fcscsi1_card_device::scsi_write_byte));
- m_dmac->dma_read<1>().set(FUNC(vme_fcscsi1_card_device::fdc_read_byte)); // ch 1 = fdc
- m_dmac->dma_write<1>().set(FUNC(vme_fcscsi1_card_device::fdc_write_byte));
+ m_dmac->irq_callback().set(FUNC(vme_sys68k_iscsi1_card_device::dma_irq));
+ //m_dmac->dma_read<0>().set(FUNC(vme_sys68k_iscsi1_card_device::scsi_read_byte)); // ch 0 = SCSI
+ //m_dmac->dma_write<0>().set(FUNC(vme_sys68k_iscsi1_card_device::scsi_write_byte));
+ m_dmac->dma_read<1>().set(FUNC(vme_sys68k_iscsi1_card_device::fdc_read_byte)); // ch 1 = fdc
+ m_dmac->dma_write<1>().set(FUNC(vme_sys68k_iscsi1_card_device::fdc_write_byte));
}
-const tiny_rom_entry *vme_fcscsi1_card_device::device_rom_region() const
+const tiny_rom_entry *vme_sys68k_iscsi1_card_device::device_rom_region() const
{
LOG("%s\n", FUNCNAME);
- return ROM_NAME( fcscsi1 );
+ return ROM_NAME(sys68k_iscsi1);
}
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
-vme_fcscsi1_card_device::vme_fcscsi1_card_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+vme_sys68k_iscsi1_card_device::vme_sys68k_iscsi1_card_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, type, tag, owner, clock)
, device_vme_card_interface(mconfig, *this)
, m_maincpu(*this, "maincpu")
, m_fdc(*this, "fdc")
, m_pit(*this, "pit")
, m_dmac(*this, "mc68450")
+ , m_eprom(*this, "eprom")
+ , m_ram(*this, "ram")
, m_tcr(0)
{
LOG("%s\n", FUNCNAME);
}
-vme_fcscsi1_card_device::vme_fcscsi1_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : vme_fcscsi1_card_device(mconfig, VME_FCSCSI1, tag, owner, clock)
+vme_sys68k_iscsi1_card_device::vme_sys68k_iscsi1_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : vme_sys68k_iscsi1_card_device(mconfig, VME_SYS68K_ISCSI1, tag, owner, clock)
{
}
/* Start it up */
-void vme_fcscsi1_card_device::device_start()
+void vme_sys68k_iscsi1_card_device::device_start()
{
LOG("%s\n", FUNCNAME);
- /* Setup pointer to bootvector in ROM for bootvector handler bootvect_r */
- m_sysrom = (uint16_t*)(memregion ("maincpu")->base () + 0xe00000);
-
#if 0 // TODO: Setup VME access handlers for shared memory area
uint32_t base = 0x00A00000;
m_vme->install_device(base + 0, base + 1, // Channel B - Data
@@ -343,14 +329,21 @@ void vme_fcscsi1_card_device::device_start()
}
-void vme_fcscsi1_card_device::device_reset()
+void vme_sys68k_iscsi1_card_device::device_reset()
{
LOG("%s\n", FUNCNAME);
-}
-/* Boot vector handler, the PCB hardwires the first 8 bytes from 0x80000 to 0x0 */
-uint16_t vme_fcscsi1_card_device::bootvect_r(offs_t offset){
- return m_sysrom [offset];
+ m_maincpu->space(AS_PROGRAM).install_rom(0, m_eprom->bytes() - 1, m_eprom->base());
+
+ m_boot_mph = m_maincpu->space(AS_PROGRAM).install_read_tap(0x000006, 0x000007, "boot",
+ [this](offs_t offset, uint16_t &data, uint16_t mem_mask)
+ {
+ if (!machine().side_effects_disabled() && ACCESSING_BITS_0_7)
+ {
+ m_maincpu->space(AS_PROGRAM).install_ram(0, m_ram.bytes() - 1, m_ram.target());
+ m_boot_mph.remove();
+ }
+ });
}
/* The Control Register - discretely implemented on the PCB
@@ -365,12 +358,12 @@ Bit #: 7 6 5 4 3 2 1 0
\ ISCSI-l 1.D. Bit #2
*/
-uint8_t vme_fcscsi1_card_device::tcr_r(){
+uint8_t vme_sys68k_iscsi1_card_device::tcr_r(){
LOG("%s\n", FUNCNAME);
return (uint8_t) m_tcr;
}
-void vme_fcscsi1_card_device::tcr_w(uint8_t data){
+void vme_sys68k_iscsi1_card_device::tcr_w(uint8_t data){
floppy_image_device *floppy0 = m_fdc->subdevice<floppy_connector>("0")->get_device();
floppy_image_device *floppy1 = m_fdc->subdevice<floppy_connector>("1")->get_device();
floppy_image_device *floppy2 = m_fdc->subdevice<floppy_connector>("2")->get_device();
@@ -401,7 +394,7 @@ void vme_fcscsi1_card_device::tcr_w(uint8_t data){
return;
}
-void vme_fcscsi1_card_device::led_w(uint8_t data) {
+void vme_sys68k_iscsi1_card_device::led_w(uint8_t data) {
LOG("%s [%02x]\n", FUNCNAME, data);
m_fdc->dden_w(BIT(data, 7));
@@ -409,7 +402,7 @@ void vme_fcscsi1_card_device::led_w(uint8_t data) {
return;
}
-WRITE_LINE_MEMBER(vme_fcscsi1_card_device::dma_irq)
+void vme_sys68k_iscsi1_card_device::dma_irq(int state)
{
if(state != CLEAR_LINE)
{
@@ -424,7 +417,7 @@ WRITE_LINE_MEMBER(vme_fcscsi1_card_device::dma_irq)
update_irq_to_maincpu();
}
-uint8_t vme_fcscsi1_card_device::dma_iack()
+uint8_t vme_sys68k_iscsi1_card_device::dma_iack()
{
if (B41)
return m_dmac->iack();
@@ -432,7 +425,7 @@ uint8_t vme_fcscsi1_card_device::dma_iack()
return m68000_base_device::autovector(2);
}
-WRITE_LINE_MEMBER(vme_fcscsi1_card_device::fdc_irq)
+void vme_sys68k_iscsi1_card_device::fdc_irq(int state)
{
if (state != 0)
{
@@ -445,17 +438,17 @@ WRITE_LINE_MEMBER(vme_fcscsi1_card_device::fdc_irq)
update_irq_to_maincpu();
}
-uint8_t vme_fcscsi1_card_device::fdc_read_byte()
+uint8_t vme_sys68k_iscsi1_card_device::fdc_read_byte()
{
return m_fdc->data_r();
}
-void vme_fcscsi1_card_device::fdc_write_byte(uint8_t data)
+void vme_sys68k_iscsi1_card_device::fdc_write_byte(uint8_t data)
{
m_fdc->data_w(data & 0xff);
}
-uint8_t vme_fcscsi1_card_device::scsi_r(offs_t offset)
+uint8_t vme_sys68k_iscsi1_card_device::scsi_r(offs_t offset)
{
uint8_t data = 0;
@@ -468,12 +461,12 @@ uint8_t vme_fcscsi1_card_device::scsi_r(offs_t offset)
return data;
}
-void vme_fcscsi1_card_device::scsi_w(offs_t offset, uint8_t data)
+void vme_sys68k_iscsi1_card_device::scsi_w(offs_t offset, uint8_t data)
{
LOG("scsi W %02x <- %02x\n", offset, data);
}
-uint8_t vme_fcscsi1_card_device::not_implemented_r(){
+uint8_t vme_sys68k_iscsi1_card_device::not_implemented_r(){
static int been_here = 0;
if (!been_here++){
logerror(TODO);
@@ -482,7 +475,7 @@ uint8_t vme_fcscsi1_card_device::not_implemented_r(){
return (uint8_t) 0;
}
-void vme_fcscsi1_card_device::not_implemented_w(uint8_t data){
+void vme_sys68k_iscsi1_card_device::not_implemented_w(uint8_t data){
static int been_here = 0;
if (!been_here++){
logerror(TODO);
diff --git a/src/devices/bus/vme/vme_fcscsi.h b/src/devices/bus/vme/sys68k_iscsi.h
index 58c57c88fdc..489d8600306 100644
--- a/src/devices/bus/vme/vme_fcscsi.h
+++ b/src/devices/bus/vme/sys68k_iscsi.h
@@ -1,7 +1,7 @@
// license:BSD-3-Clause
// copyright-holders:Joakim Larsson Edstrom
-#ifndef MAME_BUS_VME_VME_FCSCSI_H
-#define MAME_BUS_VME_VME_FCSCSI_H
+#ifndef MAME_BUS_VME_SYS68K_ISCSI_H
+#define MAME_BUS_VME_SYS68K_ISCSI_H
#pragma once
@@ -11,15 +11,15 @@
#include "machine/hd63450.h" // compatible with MC68450
#include "bus/vme/vme.h"
-DECLARE_DEVICE_TYPE(VME_FCSCSI1, vme_fcscsi1_card_device)
+DECLARE_DEVICE_TYPE(VME_SYS68K_ISCSI1, vme_sys68k_iscsi1_card_device)
-class vme_fcscsi1_card_device : public device_t, public device_vme_card_interface
+class vme_sys68k_iscsi1_card_device : public device_t, public device_vme_card_interface
{
public:
- vme_fcscsi1_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ vme_sys68k_iscsi1_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
- vme_fcscsi1_card_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+ vme_sys68k_iscsi1_card_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
virtual void device_start() override;
virtual void device_reset() override;
@@ -35,15 +35,14 @@ protected:
private:
//dmac
- DECLARE_WRITE_LINE_MEMBER(dma_irq);
+ void dma_irq(int state);
uint8_t dma_iack();
//fdc
- DECLARE_WRITE_LINE_MEMBER(fdc_irq);
+ void fdc_irq(int state);
uint8_t fdc_read_byte();
void fdc_write_byte(uint8_t data);
- uint16_t bootvect_r(offs_t offset);
uint8_t tcr_r();
void tcr_w(uint8_t data);
void led_w(uint8_t data);
@@ -63,10 +62,11 @@ private:
required_device<pit68230_device> m_pit;
required_device<hd63450_device> m_dmac;
- uint8_t m_tcr;
+ required_memory_region m_eprom;
+ required_shared_ptr<uint16_t> m_ram;
+ memory_passthrough_handler m_boot_mph;
- // Pointer to System ROMs needed by bootvect_r
- uint16_t *m_sysrom;
+ uint8_t m_tcr;
};
-#endif // MAME_BUS_VME_VME_FCSCSI_H
+#endif // MAME_BUS_VME_SYS68K_ISCSI_H
diff --git a/src/devices/bus/vme/vme_fcisio.cpp b/src/devices/bus/vme/sys68k_isio.cpp
index 4b454df22d7..36369dc45c5 100644
--- a/src/devices/bus/vme/vme_fcisio.cpp
+++ b/src/devices/bus/vme/sys68k_isio.cpp
@@ -125,25 +125,19 @@
*
****************************************************************************/
#include "emu.h"
-#include "vme_fcisio.h"
+#include "sys68k_isio.h"
-#include "cpu/m68000/m68000.h"
+#include "cpu/m68000/m68010.h"
#include "machine/scnxx562.h"
#include "machine/68230pit.h"
#include "machine/68153bim.h"
#include "bus/rs232/rs232.h"
#include "machine/clock.h"
-//#define LOG_GENERAL (1U << 0)
-#define LOG_SETUP (1U << 1)
-
-//#define VERBOSE (LOG_GENERAL | LOG_SETUP)
+#define VERBOSE (0) // (LOG_GENERAL)
//#define LOG_OUTPUT_FUNC printf
-
#include "logmacro.h"
-#define LOGSETUP(...) LOGMASKED(LOG_SETUP, __VA_ARGS__)
-
#ifdef _MSC_VER
#define FUNCNAME __func__
#else
@@ -156,28 +150,27 @@
// GLOBAL VARIABLES
//**************************************************************************
-DEFINE_DEVICE_TYPE(VME_FCISIO1, vme_fcisio1_card_device, "fcisio1", "Force Computer SYS68K/ISIO-1/2 Intelligent Serial I/O Board")
+DEFINE_DEVICE_TYPE(VME_SYS68K_ISIO1, vme_sys68k_isio1_card_device, "sys68k_isio1", "Force Computers SYS68K/ISIO-1")
#define CPU_CLOCK XTAL(20'000'000) /* HCJ */
#define DUSCC_CLOCK XTAL(14'745'600) /* HCJ */
-void vme_fcisio1_card_device::fcisio1_mem(address_map &map)
+void vme_sys68k_isio1_card_device::fcisio1_mem(address_map &map)
{
map.unmap_value_high();
- map(0x000000, 0x01ffff).ram(); /* SRAM */
- map(0x000000, 0x000007).rom().r(FUNC(vme_fcisio1_card_device::bootvect_r)); /* Vectors mapped from System EPROM */
+ map(0x000000, 0x01ffff).ram().share("ram"); /* SRAM */
map(0xe00000, 0xe001ff).rw("duscc0", FUNC(duscc68562_device::read), FUNC(duscc68562_device::write)).umask16(0x00ff);
map(0xe20000, 0xe201ff).rw("duscc1", FUNC(duscc68562_device::read), FUNC(duscc68562_device::write)).umask16(0x00ff);
map(0xe40000, 0xe401ff).rw("duscc2", FUNC(duscc68562_device::read), FUNC(duscc68562_device::write)).umask16(0x00ff);
map(0xe60000, 0xe601ff).rw("duscc3", FUNC(duscc68562_device::read), FUNC(duscc68562_device::write)).umask16(0x00ff);
map(0xe80000, 0xe80dff).rw("pit", FUNC(pit68230_device::read), FUNC(pit68230_device::write)).umask16(0x00ff);
- map(0xf00000, 0xf7ffff).rom(); /* System EPROM Area 32Kb DEBUGGER supplied */
-// map(0xc40000, 0xc800ff).rw(FUNC(vme_fcisio1_card_device::not_implemented_r), FUNC(vme_fcisio1_card_device::not_implemented_w)); /* Dummy mapping af address area to display message */
+ map(0xf00000, 0xf1ffff).rom().region("eprom", 0); /* System EPROM Area 32Kb DEBUGGER supplied */
+// map(0xc40000, 0xc800ff).rw(FUNC(vme_sys68k_isio1_card_device::not_implemented_r), FUNC(vme_sys68k_isio1_card_device::not_implemented_w)); /* Dummy mapping af address area to display message */
}
/* ROM definitions */
-ROM_START (fcisio1)
- ROM_REGION (0x1000000, "maincpu", 0)
+ROM_START (sys68k_isio1)
+ ROM_REGION16_BE (0x20000, "eprom", 0)
/* ISIO ROM:s v2.1 information
* PIT setup sequence
@@ -271,15 +264,15 @@ ROM_START (fcisio1)
* 1e 1a -> DUSCC2 REG_IVR
* 1e 19 -> DUSCC3 REG_IVR
*/
- ROM_LOAD16_BYTE ("isio-1_v2.1_l.bin", 0xf00001, 0x4000, CRC (0d47d80f) SHA1 (541b55966f464c1cf686e36998650720950a2242))
- ROM_LOAD16_BYTE ("isio-1_v2.1_u.bin", 0xf00000, 0x4000, CRC (67986768) SHA1 (215f7ff90d9dbe2bea54510e3722fb33d4e54193))
+ ROM_LOAD16_BYTE ("isio-1_v2.1_l.bin", 0x0001, 0x4000, CRC (0d47d80f) SHA1 (541b55966f464c1cf686e36998650720950a2242))
+ ROM_LOAD16_BYTE ("isio-1_v2.1_u.bin", 0x0000, 0x4000, CRC (67986768) SHA1 (215f7ff90d9dbe2bea54510e3722fb33d4e54193))
ROM_END
-void vme_fcisio1_card_device::device_add_mconfig(machine_config &config)
+void vme_sys68k_isio1_card_device::device_add_mconfig(machine_config &config)
{
/* basic machine hardware */
M68010(config, m_maincpu, CPU_CLOCK / 2);
- m_maincpu->set_addrmap(AS_PROGRAM, &vme_fcisio1_card_device::fcisio1_mem);
+ m_maincpu->set_addrmap(AS_PROGRAM, &vme_sys68k_isio1_card_device::fcisio1_mem);
/* DUSCC channels */
#define RS232P1_TAG "rs232p1"
@@ -368,21 +361,21 @@ void vme_fcisio1_card_device::device_add_mconfig(machine_config &config)
rs232p8.cts_handler().set(m_duscc3, FUNC(duscc68562_device::ctsb_w));
PIT68230(config, m_pit, XTAL(20'000'000) / 2);
- m_pit->pb_in_callback().set(FUNC(vme_fcisio1_card_device::config_rd));
+ m_pit->pb_in_callback().set(FUNC(vme_sys68k_isio1_card_device::config_rd));
MC68153(config, m_bim, XTAL(20'000'000) / 2);
}
-const tiny_rom_entry *vme_fcisio1_card_device::device_rom_region() const
+const tiny_rom_entry *vme_sys68k_isio1_card_device::device_rom_region() const
{
LOG("%s\n", FUNCNAME);
- return ROM_NAME( fcisio1 );
+ return ROM_NAME(sys68k_isio1);
}
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
-vme_fcisio1_card_device::vme_fcisio1_card_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+vme_sys68k_isio1_card_device::vme_sys68k_isio1_card_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, type, tag, owner, clock)
, device_vme_card_interface(mconfig, *this)
, m_maincpu (*this, "maincpu")
@@ -392,23 +385,22 @@ vme_fcisio1_card_device::vme_fcisio1_card_device(const machine_config &mconfig,
, m_duscc3(*this, "duscc3")
, m_pit (*this, "pit")
, m_bim (*this, "bim")
+ , m_eprom (*this, "eprom")
+ , m_ram (*this, "ram")
{
LOG("%s\n", FUNCNAME);
}
-vme_fcisio1_card_device::vme_fcisio1_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : vme_fcisio1_card_device(mconfig, VME_FCISIO1, tag, owner, clock)
+vme_sys68k_isio1_card_device::vme_sys68k_isio1_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : vme_sys68k_isio1_card_device(mconfig, VME_SYS68K_ISIO1, tag, owner, clock)
{
}
/* Start it up */
-void vme_fcisio1_card_device::device_start()
+void vme_sys68k_isio1_card_device::device_start()
{
LOG("%s\n", FUNCNAME);
- /* Setup pointer to bootvector in ROM for bootvector handler bootvect_r */
- m_sysrom = (uint16_t*)(memregion ("maincpu")->base () + 0xf00000);
-
#if 0 // TODO: Setup VME access handlers for shared memory area
uint32_t base = 0xFFFF5000;
m_vme->install_device(base + 0, base + 1, // Channel B - Data
@@ -419,17 +411,24 @@ void vme_fcisio1_card_device::device_start()
}
-void vme_fcisio1_card_device::device_reset()
+void vme_sys68k_isio1_card_device::device_reset()
{
LOG("%s\n", FUNCNAME);
-}
-/* Boot vector handler, the PCB hardwires the first 8 bytes from 0x80000 to 0x0 */
-uint16_t vme_fcisio1_card_device::bootvect_r(offs_t offset){
- return m_sysrom [offset];
+ m_maincpu->space(AS_PROGRAM).install_rom(0, m_eprom->bytes() - 1, m_eprom->base());
+
+ m_boot_mph = m_maincpu->space(AS_PROGRAM).install_read_tap(0x000006, 0x000007, "boot",
+ [this](offs_t offset, uint16_t &data, uint16_t mem_mask)
+ {
+ if (!machine().side_effects_disabled() && ACCESSING_BITS_0_7)
+ {
+ m_maincpu->space(AS_PROGRAM).install_ram(0, m_ram.bytes() - 1, m_ram.target());
+ m_boot_mph.remove();
+ }
+ });
}
-uint8_t vme_fcisio1_card_device::not_implemented_r(){
+uint8_t vme_sys68k_isio1_card_device::not_implemented_r(){
static int been_here = 0;
if (!been_here++){
logerror(TODO);
@@ -438,7 +437,7 @@ uint8_t vme_fcisio1_card_device::not_implemented_r(){
return (uint8_t) 0;
}
-void vme_fcisio1_card_device::not_implemented_w(uint8_t data){
+void vme_sys68k_isio1_card_device::not_implemented_w(uint8_t data){
static int been_here = 0;
if (!been_here++){
logerror(TODO);
@@ -448,7 +447,7 @@ void vme_fcisio1_card_device::not_implemented_w(uint8_t data){
}
// TODO: Get a manual to understand the config options for real
-uint8_t vme_fcisio1_card_device::config_rd(){
+uint8_t vme_sys68k_isio1_card_device::config_rd(){
uint8_t ret = 0;
LOG("%s\n", FUNCNAME);
@@ -461,4 +460,4 @@ uint8_t vme_fcisio1_card_device::config_rd(){
// This info isn't kept in a card driver atm so storing it as a comment for later use
// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS
-//COMP( 1986, fcisio1, 0, 0, fcisio1, fcisio1, driver_device, 0, "Force Computers Gmbh", "SYS68K/ISIO-1", MACHINE_NOT_WORKING | MACHINE_NO_SOUND_HW | MACHINE_TYPE_COMPUTER )
+//COMP( 1986, fcisio1, 0, 0, fcisio1, fcisio1, driver_device, 0, "Force Computers Gmbh", "SYS68K/ISIO-1", MACHINE_NOT_WORKING | MACHINE_NO_SOUND_HW )
diff --git a/src/devices/bus/vme/vme_fcisio.h b/src/devices/bus/vme/sys68k_isio.h
index 6ffecb0e6af..d31580c064d 100644
--- a/src/devices/bus/vme/vme_fcisio.h
+++ b/src/devices/bus/vme/sys68k_isio.h
@@ -1,7 +1,7 @@
// license:BSD-3-Clause
// copyright-holders:Joakim Larsson Edstrom
-#ifndef MAME_BUS_VME_VME_FCISIO_H
-#define MAME_BUS_VME_VME_FCISIO_H
+#ifndef MAME_BUS_VME_SYS68K_ISIO_H
+#define MAME_BUS_VME_SYS68K_ISIO_H
#pragma once
@@ -10,15 +10,15 @@
#include "machine/68153bim.h"
#include "bus/vme/vme.h"
-DECLARE_DEVICE_TYPE(VME_FCISIO1, vme_fcisio1_card_device)
+DECLARE_DEVICE_TYPE(VME_SYS68K_ISIO1, vme_sys68k_isio1_card_device)
-class vme_fcisio1_card_device : public device_t, public device_vme_card_interface
+class vme_sys68k_isio1_card_device : public device_t, public device_vme_card_interface
{
public:
- vme_fcisio1_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ vme_sys68k_isio1_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
- vme_fcisio1_card_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+ vme_sys68k_isio1_card_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
virtual void device_start() override;
virtual void device_reset() override;
@@ -30,8 +30,6 @@ protected:
private:
uint8_t config_rd();
- uint16_t bootvect_r(offs_t offset);
-
/* Dummy driver routines */
uint8_t not_implemented_r();
void not_implemented_w(uint8_t data);
@@ -47,8 +45,9 @@ private:
required_device<pit68230_device> m_pit;
required_device<bim68153_device> m_bim;
- // Pointer to System ROMs needed by bootvect_r
- uint16_t *m_sysrom;
+ required_memory_region m_eprom;
+ required_shared_ptr<uint16_t> m_ram;
+ memory_passthrough_handler m_boot_mph;
};
-#endif // MAME_BUS_VME_VME_FCISIO_H
+#endif // MAME_BUS_VME_SYS68K_ISIO_H
diff --git a/src/devices/bus/vme/tp881v.cpp b/src/devices/bus/vme/tp881v.cpp
new file mode 100644
index 00000000000..e4cac6ef524
--- /dev/null
+++ b/src/devices/bus/vme/tp881v.cpp
@@ -0,0 +1,349 @@
+// license:BSD-3-Clause
+// copyright-holders:Patrick Mackinlay
+
+/*
+ * Tadpole Technology TP881V
+ *
+ * Sources:
+ * - TPROM/88K User Manual, Monitor/Debugger For 88000 Boards, Issue: 1.3, 26 June 1990, Part No. DS-1003
+ * - TPIX/88K version 1.06 source code
+ *
+ * TODO:
+ * - scsi dma controllers
+ * - serial dma
+ * - vme interface
+ * - interrupt enables/masking
+ * - multiprocessor configurations
+ */
+
+#include "emu.h"
+#include "tp881v.h"
+
+#include "machine/input_merger.h"
+
+#include "bus/nscsi/hd.h"
+#include "bus/nscsi/cd.h"
+
+#define VERBOSE 0
+#include "logmacro.h"
+
+DEFINE_DEVICE_TYPE(VME_TP881V, vme_tp881v_card_device, "tp881v", "Tadpole Technology TP881V")
+
+vme_tp881v_card_device::vme_tp881v_card_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, VME_TP881V, tag, owner, clock)
+ , device_vme_card_interface(mconfig, *this)
+ , m_cpu(*this, "cpu")
+ , m_mmu(*this, "mmu%u", 0U)
+ , m_cio(*this, "cio%u", 0U)
+ , m_rtc(*this, "rtc")
+ , m_scsi(*this, "scsi%u:7:ncr53c90a", 0U)
+ , m_net(*this, "net")
+ , m_scc(*this, "scc%u", 0U)
+ , m_scc_dma(*this, "scc_dma")
+ , m_vcs(*this, "vcs")
+ , m_gcs(*this, "gcs%u", 0U)
+ , m_eeprom(*this, "eeprom")
+ , m_serial(*this, "serial%u", 0U)
+{
+}
+
+ROM_START(tp881v)
+ ROM_REGION32_BE(0x40000, "eprom", 0)
+ ROM_SYSTEM_BIOS(0, "v504", "TP881 Multiprocessor Monitor V5.04")
+ ROMX_LOAD("881v__5.04l.bin", 0x0002, 0x20000, CRC(d9027c64) SHA1(88cca011dee005d273a1cd7048480ff3fac9c06a), ROM_REVERSE | ROM_GROUPWORD | ROM_SKIP(2) | ROM_BIOS(0))
+ ROMX_LOAD("881v__5.04h.bin", 0x0000, 0x20000, CRC(74de0772) SHA1(8e5bfd427c0bdea4ab350333fd5a814712014302), ROM_REVERSE | ROM_GROUPWORD | ROM_SKIP(2) | ROM_BIOS(0))
+ROM_END
+
+static INPUT_PORTS_START(tp881v)
+INPUT_PORTS_END
+
+const tiny_rom_entry *vme_tp881v_card_device::device_rom_region() const
+{
+ return ROM_NAME(tp881v);
+}
+
+ioport_constructor vme_tp881v_card_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(tp881v);
+}
+
+void vme_tp881v_card_device::device_start()
+{
+}
+
+void vme_tp881v_card_device::device_reset()
+{
+}
+
+static void scsi_devices(device_slot_interface &device)
+{
+ device.option_add("cdrom", NSCSI_CDROM);
+ device.option_add("harddisk", NSCSI_HARDDISK);
+ device.option_add("ncr53c90a", NCR53C90A);
+}
+
+void vme_tp881v_card_device::device_add_mconfig(machine_config &config)
+{
+ MC88100(config, m_cpu, 40_MHz_XTAL / 2);
+ m_cpu->set_addrmap(AS_PROGRAM, &vme_tp881v_card_device::cpu_mem);
+
+ MC88200(config, m_mmu[0], 40_MHz_XTAL / 2, 0x00);
+ m_mmu[0]->set_mbus(m_cpu, AS_PROGRAM);
+ m_cpu->set_cmmu_i(m_mmu[0]);
+
+ MC88200(config, m_mmu[1], 40_MHz_XTAL / 2, 0x01);
+ m_mmu[1]->set_mbus(m_cpu, AS_PROGRAM);
+ m_cpu->set_cmmu_d(m_mmu[1]);
+
+ // per-jp interrupt controllers
+ // 4MHz input clock, ct3 gives 100Hz clock, ct2 counts at 10kHz
+ Z8036(config, m_cio[0], 4'000'000); // Z0803606VSC
+ /*
+ * port a bit mode ddr 0xff
+ * bit i/o function
+ * 0 i porta int?
+ * 1 i ethernet
+ * 2 i scc dma
+ * 3 i scsi0
+ * 4 i scsi1
+ * 5 i scc
+ * 6 i acfail
+ * 7 i parity
+ *
+ * port b bit mode ddr 0xbf
+ * bit i/o function
+ * 0 i port b
+ * 1 i mbus err
+ * 2 i port b err
+ * 3 i vme
+ * 4 i vme mailbox
+ * 5 i port b err
+ * 6 o software interrupt
+ * 7 i vsb
+ *
+ * port c ? ddr 0xf
+ * bit i/o function
+ * 0 i
+ * 1 i
+ * 2 i
+ * 3 i
+ */
+ m_cio[0]->irq_wr_cb().set_inputline(m_cpu, INPUT_LINE_IRQ0);
+
+ Z8036(config, m_cio[1], 4'000'000); // Z0803606VSC
+ Z8036(config, m_cio[2], 4'000'000); // Z0803606VSC
+ Z8036(config, m_cio[3], 4'000'000); // Z0803606VSC
+ Z8036(config, m_cio[4], 4'000'000); // Z0803606VSC
+ Z8036(config, m_cio[5], 4'000'000); // Z0803606VSC
+ Z8036(config, m_cio[6], 4'000'000); // Z0803606VSC
+ Z8036(config, m_cio[7], 4'000'000); // Z0803606VSC
+
+ M48T02(config, m_rtc, 0);
+
+ NSCSI_BUS(config, "scsi0", 0);
+ NSCSI_CONNECTOR(config, "scsi0:0", scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi0:1", scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi0:2", scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi0:3", scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi0:4", scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi0:5", scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi0:6", scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi0:7").option_set("ncr53c90a", NCR53C90A).machine_config(
+ [this](device_t *device)
+ {
+ ncr53c90a_device &ncr53c90a(downcast<ncr53c90a_device &>(*device));
+
+ ncr53c90a.set_clock(20'000'000);
+ ncr53c90a.irq_handler_cb().set(m_cio[0], FUNC(z8036_device::pa3_w));
+ //ncr53c90a.drq_cb().set(*this, ...);
+ });
+
+ NSCSI_BUS(config, "scsi1", 0);
+ NSCSI_CONNECTOR(config, "scsi1:0", scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi1:1", scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi1:2", scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi1:3", scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi1:4", scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi1:5", scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi1:6", scsi_devices, nullptr, false);
+ NSCSI_CONNECTOR(config, "scsi1:7").option_set("ncr53c90a", NCR53C90A).machine_config(
+ [this](device_t *device)
+ {
+ ncr53c90a_device &ncr53c90a(downcast<ncr53c90a_device &>(*device));
+
+ ncr53c90a.set_clock(20'000'000);
+ ncr53c90a.irq_handler_cb().set(m_cio[0], FUNC(z8036_device::pa4_w));
+ //ncr53c90a.drq_cb().set(*this, ...);
+ });
+
+ I82596_BE32(config, m_net, 20'000'000); // A82596DX-25
+ m_net->out_irq_cb().set(m_cio[0], FUNC(z8036_device::pa1_w));
+ m_net->set_addrmap(0, &vme_tp881v_card_device::net_mem);
+
+ input_merger_any_high_device &scc_irq(INPUT_MERGER_ANY_HIGH(config, "scc_irq"));
+ scc_irq.output_handler().set(m_cio[0], FUNC(z8036_device::pa5_w));
+
+ SCC8030(config, m_scc[0], 3.6864_MHz_XTAL); // Z0803006VSC
+ m_scc[0]->configure_channels(m_scc[0]->clock(), m_scc[0]->clock(), m_scc[0]->clock(), m_scc[0]->clock());
+ m_scc[0]->out_int_callback().set(scc_irq, FUNC(input_merger_any_high_device::in_w<0>));
+
+ SCC8030(config, m_scc[1], 3.6864_MHz_XTAL); // Z0803006VSC
+ m_scc[1]->configure_channels(m_scc[1]->clock(), m_scc[1]->clock(), m_scc[1]->clock(), m_scc[1]->clock());
+ m_scc[1]->out_int_callback().set(scc_irq, FUNC(input_merger_any_high_device::in_w<1>));
+
+ RS232_PORT(config, m_serial[0], default_rs232_devices, "terminal");
+ RS232_PORT(config, m_serial[1], default_rs232_devices, nullptr);
+
+ m_scc[0]->out_txda_callback().set(m_serial[0], FUNC(rs232_port_device::write_txd));
+ m_scc[0]->out_dtra_callback().set(m_serial[0], FUNC(rs232_port_device::write_dtr));
+ m_scc[0]->out_rtsa_callback().set(m_serial[0], FUNC(rs232_port_device::write_rts));
+ m_scc[0]->out_txdb_callback().set(m_serial[1], FUNC(rs232_port_device::write_txd));
+ m_scc[0]->out_dtrb_callback().set(m_serial[1], FUNC(rs232_port_device::write_dtr));
+ m_scc[0]->out_rtsb_callback().set(m_serial[1], FUNC(rs232_port_device::write_rts));
+
+ m_serial[0]->rxd_handler().set(m_scc[0], FUNC(z80scc_device::rxa_w));
+ m_serial[0]->dcd_handler().set(m_scc[0], FUNC(z80scc_device::dcda_w));
+ m_serial[0]->cts_handler().set(m_scc[0], FUNC(z80scc_device::ctsa_w));
+ m_serial[1]->rxd_handler().set(m_scc[0], FUNC(z80scc_device::rxb_w));
+ m_serial[1]->dcd_handler().set(m_scc[0], FUNC(z80scc_device::dcdb_w));
+ m_serial[1]->cts_handler().set(m_scc[0], FUNC(z80scc_device::ctsb_w));
+
+ RS232_PORT(config, m_serial[2], default_rs232_devices, nullptr);
+ RS232_PORT(config, m_serial[3], default_rs232_devices, nullptr);
+
+ m_scc[1]->out_txda_callback().set(m_serial[2], FUNC(rs232_port_device::write_txd));
+ m_scc[1]->out_dtra_callback().set(m_serial[2], FUNC(rs232_port_device::write_dtr));
+ m_scc[1]->out_rtsa_callback().set(m_serial[2], FUNC(rs232_port_device::write_rts));
+ m_scc[1]->out_txdb_callback().set(m_serial[3], FUNC(rs232_port_device::write_txd));
+ m_scc[1]->out_dtrb_callback().set(m_serial[3], FUNC(rs232_port_device::write_dtr));
+ m_scc[1]->out_rtsb_callback().set(m_serial[3], FUNC(rs232_port_device::write_rts));
+
+ m_serial[2]->rxd_handler().set(m_scc[1], FUNC(z80scc_device::rxa_w));
+ m_serial[2]->dcd_handler().set(m_scc[1], FUNC(z80scc_device::dcda_w));
+ m_serial[2]->cts_handler().set(m_scc[1], FUNC(z80scc_device::ctsa_w));
+ m_serial[3]->rxd_handler().set(m_scc[1], FUNC(z80scc_device::rxb_w));
+ m_serial[3]->dcd_handler().set(m_scc[1], FUNC(z80scc_device::dcdb_w));
+ m_serial[3]->cts_handler().set(m_scc[1], FUNC(z80scc_device::ctsb_w));
+
+ // TODO: MC68440 is function and pin compatible with MC68450/HD63450, but
+ // has only two DMA channels instead of four.
+ HD63450(config, m_scc_dma, 10'000'000); // MC68440FN10
+ m_scc_dma->set_cpu_tag(m_cpu);
+ m_scc_dma->irq_callback().set(m_cio[0], FUNC(z8036_device::pa2_w));
+
+ // VME control and status CIO
+ Z8036(config, m_vcs, 4'000'000); // Z0803606VSC
+ /*
+ * port a
+ * bit i/o function
+ * 0 i vme dram address bit 25
+ * 1 i vme dram address bit 26
+ * 2 i vme dram address bit 27
+ * 3 i vme dram address bit 28
+ * 4 i vme dram address bit 29
+ * 5 i vme dram address bit 30
+ * 6 i vme dram address bit 31
+ * 7 ?
+ */
+
+ // general control and status CIO 0
+ Z8036(config, m_gcs[0], 4'000'000); // Z0803606VSC
+ /*
+ * port a ddr 0x01
+ * bit i/o function
+ * 0 i
+ * 1 o
+ * 2 o
+ * 3 o fail led
+ * 4 o user led
+ * 5 o
+ * 6 o
+ * 7 o
+ *
+ * port b ddr 0x00
+ * bit i/o function
+ * 0 o
+ * 1 o
+ * 2 o
+ * 3 o
+ * 4 o
+ * 5 o
+ * 6 o scsi1 dma memory->device
+ * 7 o scsi0 dma memory->device
+ *
+ * port c 0xe
+ * bit i/o function
+ * 0 o
+ * 1 i vme irq level bit 0
+ * 2 i vme irq level bit 1
+ * 3 i vme irq level bit 2
+ */
+ // back panel has scsi0, scsi1, vme, net, sysfail, user,
+
+ // general control and status CIO 1
+ Z8036(config, m_gcs[1], 4'000'000); // Z0803606VSC
+ /*
+ * port c ddr 0x1
+ * bit i/o function
+ * 0 i eeprom data in
+ * 1 o eeprom data out
+ * 2 o eeprom chip select
+ * 3 o eeprom clock
+ */
+ m_gcs[1]->pc_wr_cb().set(
+ [this](u8 data)
+ {
+ // chip select
+ if (!BIT(data, 6))
+ m_eeprom->cs_w(BIT(data, 2));
+
+ // data out
+ if (!BIT(data, 5))
+ m_eeprom->di_w(BIT(data, 1));
+
+ // clock
+ if (!BIT(data, 4))
+ m_eeprom->sk_w(BIT(data, 3));
+ });
+ m_gcs[1]->pc_rd_cb().set(m_eeprom, FUNC(nmc9306_device::do_r));
+
+ NMC9306(config, m_eeprom, 0);
+}
+
+void vme_tp881v_card_device::cpu_mem(address_map &map)
+{
+ map(0x0000'0000, 0x0003'ffff).rom().region("eprom", 0);
+ //map(0x2000'0000, 0x20ff'ffff); // vme short space (a24 d32)
+
+ map(0x4000'0000, 0x41ff'ffff).ram().share("ram");
+ //map(0x8000'0000, 0xbfff'ffff); // vme extended space (a32 d32)
+ //map(0xc000'0000, 0xc0ff'ffff); // vsb space
+
+ map(0xfff3'0000, 0xfff3'003f).m(m_scsi[0], FUNC(ncr53c90a_device::map)).umask32(0x000000ff);
+ //0xfff30080; // dmac scsi0
+ map(0xfff3'8000, 0xfff3'803f).m(m_scsi[1], FUNC(ncr53c90a_device::map)).umask32(0x000000ff);
+ //0xfff38080; // dmac scsi1
+ //0xfff40000; // vme a16 d16 base
+ map(0xfff5'2000, 0xfff5'207f).rw(m_scc[1], FUNC(z80scc_device::zbus_r), FUNC(z80scc_device::zbus_w)).umask32(0x000000ff);
+ map(0xfff5'4000, 0xfff5'407f).rw(m_scc[0], FUNC(z80scc_device::zbus_r), FUNC(z80scc_device::zbus_w)).umask32(0x000000ff);
+ map(0xfff5'6000, 0xfff5'60bf).rw(m_gcs[0], FUNC(z8036_device::read), FUNC(z8036_device::write)).umask32(0x000000ff);
+ map(0xfff5'8000, 0xfff5'80bf).rw(m_gcs[1], FUNC(z8036_device::read), FUNC(z8036_device::write)).umask32(0x000000ff);
+ map(0xfff5'a000, 0xfff5'a0bf).rw(m_vcs, FUNC(z8036_device::read), FUNC(z8036_device::write)).umask32(0x000000ff);
+ map(0xfff5'e000, 0xfff5'ffff).rw(m_rtc, FUNC(m48t02_device::read), FUNC(m48t02_device::write)).umask32(0x000000ff);
+ //0xfff60000; // vme iack
+ //map(0xfff7'8002, 0xfff7'8003).w(m_net, FUNC(i82596_device::port));
+ //map(0xfff7'c000, 0xfffc'0000).lw8([this](u8 data) { m_net->ca(1); }, "net_ca");
+ map(0xfff8'0000, 0xfff8'00bf).rw(m_cio[0], FUNC(z8036_device::read), FUNC(z8036_device::write)).umask32(0x000000ff);
+ map(0xfff8'0400, 0xfff8'04bf).rw(m_cio[1], FUNC(z8036_device::read), FUNC(z8036_device::write)).umask32(0x000000ff);
+ map(0xfff8'0800, 0xfff8'08bf).rw(m_cio[2], FUNC(z8036_device::read), FUNC(z8036_device::write)).umask32(0x000000ff);
+ map(0xfff8'0c00, 0xfff8'0cbf).rw(m_cio[3], FUNC(z8036_device::read), FUNC(z8036_device::write)).umask32(0x000000ff);
+ map(0xfff9'0000, 0xfff9'00bf).rw(m_cio[4], FUNC(z8036_device::read), FUNC(z8036_device::write)).umask32(0x000000ff);
+ map(0xfff9'0400, 0xfff9'04bf).rw(m_cio[5], FUNC(z8036_device::read), FUNC(z8036_device::write)).umask32(0x000000ff);
+ map(0xfff9'0800, 0xfff9'08bf).rw(m_cio[6], FUNC(z8036_device::read), FUNC(z8036_device::write)).umask32(0x000000ff);
+ map(0xfff9'0c00, 0xfff9'0cbf).rw(m_cio[7], FUNC(z8036_device::read), FUNC(z8036_device::write)).umask32(0x000000ff);
+}
+
+void vme_tp881v_card_device::net_mem(address_map &map)
+{
+ map(0x4000'0000, 0x41ff'ffff).ram().share("ram");
+}
diff --git a/src/devices/bus/vme/tp881v.h b/src/devices/bus/vme/tp881v.h
new file mode 100644
index 00000000000..f7e58980b2d
--- /dev/null
+++ b/src/devices/bus/vme/tp881v.h
@@ -0,0 +1,59 @@
+// license:BSD-3-Clause
+// copyright-holders:Patrick Mackinlay
+
+#ifndef MAME_BUS_VME_TP881V_H
+#define MAME_BUS_VME_TP881V_H
+
+#pragma once
+
+#include "cpu/m88000/m88000.h"
+#include "machine/i82586.h"
+#include "machine/hd63450.h"
+#include "machine/mc88200.h"
+#include "machine/ncr53c90.h"
+#include "machine/nmc9306.h"
+#include "machine/timekpr.h"
+#include "machine/z80scc.h"
+#include "machine/z8536.h"
+
+#include "bus/vme/vme.h"
+#include "bus/rs232/rs232.h"
+
+class vme_tp881v_card_device
+ : public device_t
+ , public device_vme_card_interface
+{
+public:
+ vme_tp881v_card_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual ioport_constructor device_input_ports() const override;
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+private:
+ void cpu_mem(address_map &map);
+ void net_mem(address_map &map);
+
+ required_device<mc88100_device> m_cpu;
+ required_device_array<mc88200_device, 2> m_mmu;
+ required_device_array<z8036_device, 8> m_cio;
+
+ required_device<m48t02_device> m_rtc;
+ required_device_array<ncr53c90a_device, 2> m_scsi;
+ required_device<i82596_device> m_net;
+ required_device_array<scc8030_device, 2> m_scc;
+ required_device<hd63450_device> m_scc_dma;
+
+ required_device<z8036_device> m_vcs; // vme control and status cio
+ required_device_array<z8036_device, 2> m_gcs; // global control and status cio
+ required_device<nmc9306_device> m_eeprom;
+
+ required_device_array<rs232_port_device, 4> m_serial;
+};
+
+DECLARE_DEVICE_TYPE(VME_TP881V, vme_tp881v_card_device)
+
+#endif // MAME_BUS_VME_TP881V_H
diff --git a/src/devices/bus/vme/vme.cpp b/src/devices/bus/vme/vme.cpp
index 1353f36ae22..d154edaf310 100644
--- a/src/devices/bus/vme/vme.cpp
+++ b/src/devices/bus/vme/vme.cpp
@@ -66,409 +66,277 @@
interfaced to the incoming AC power source and may also be located remotely.
*/
+/*
+ * TODO:
+ * - bus arbitration
+ * - block, rmw and address-only cycles
+ * - utility bus (serial clock/data, acfail, sysreset, sysfail)
+ * - variants (16-bit backplanes, VME64)
+ * - location monitors
+ */
+
#include "emu.h"
#include "vme.h"
-//#include "bus/vme/vme_mzr8105.h"
-#include "bus/vme/vme_mzr8300.h"
-#include "bus/vme/vme_mvme350.h"
-#include "bus/vme/vme_fcisio.h"
-#include "bus/vme/vme_fcscsi.h"
-
-#define LOG_GENERAL 0x01
-#define LOG_SETUP 0x02
-
-//#define VERBOSE (LOG_SETUP | LOG_GENERAL)
-
-#define LOG_OUTPUT_FUNC printf // logerror is not available here
+#define VERBOSE 0
#include "logmacro.h"
-#define LOG(...) LOGMASKED(LOG_GENERAL, __VA_ARGS__)
-#define LOGSETUP(...) LOGMASKED(LOG_SETUP, __VA_ARGS__)
-
-#ifdef _MSC_VER
-#define FUNCNAME __func__
-#else
-#define FUNCNAME __PRETTY_FUNCTION__
-#endif
-
-//**************************************************************************
-// GLOBAL VARIABLES
-//**************************************************************************
-
+DEFINE_DEVICE_TYPE(VME, vme_bus_device, "vme", "VME bus")
DEFINE_DEVICE_TYPE(VME_SLOT, vme_slot_device, "vme_slot", "VME slot")
-//-------------------------------------------------
-// vme_slot_device - constructor
-//-------------------------------------------------
-vme_slot_device::vme_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : vme_slot_device(mconfig, VME_SLOT, tag, owner, clock)
-{
-}
-
-vme_slot_device::vme_slot_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, type, tag, owner, clock)
- , device_slot_interface(mconfig, *this)
- , m_vme(*this, finder_base::DUMMY_TAG)
- , m_slot_nbr(0)
- , m_vme_j1_callback(*this)
-{
- LOG("%s %s\n", tag, FUNCNAME);
-}
-
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-void vme_slot_device::device_start()
-{
- // m_card = dynamic_cast<device_vme_card_interface *>(get_card_device());
-}
-
-//-------------------------------------------------
-// device_resolve_objects - resolve objects that
-// may be needed for other devices to set
-// initial conditions at start time
-//-------------------------------------------------
-void vme_slot_device::device_resolve_objects()
-{
- device_vme_card_interface *dev = dynamic_cast<device_vme_card_interface *>(get_card_device());
- LOG("%s %s - %s\n", tag(), FUNCNAME, m_vme.finder_tag());
- if (dev)
+vme_bus_device::vme_bus_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock, u8 datawidth)
+ : device_t(mconfig, VME, tag, owner, clock)
+ , device_memory_interface(mconfig, *this)
+ , m_asc
{
- dev->set_vme_bus(*m_vme, m_slot_nbr);
+ { "iack", ENDIANNESS_BIG, datawidth, 4, -2, address_map_constructor(FUNC(vme_bus_device::iack), this) },
+ {}, {}, {}, {}, {}, {}, {}, {},
+ { "a32_09", ENDIANNESS_BIG, datawidth, 32, 0, address_map_constructor(FUNC(vme_bus_device::a32), this) },
+ { "a32_0a", ENDIANNESS_BIG, datawidth, 32, 0, address_map_constructor(FUNC(vme_bus_device::a32), this) },
+ { "a32_0b", ENDIANNESS_BIG, datawidth, 32, 0, address_map_constructor(FUNC(vme_bus_device::a32), this) },
+ {},
+ { "a32_0d", ENDIANNESS_BIG, datawidth, 32, 0, address_map_constructor(FUNC(vme_bus_device::a32), this) },
+ { "a32_0e", ENDIANNESS_BIG, datawidth, 32, 0, address_map_constructor(FUNC(vme_bus_device::a32), this) },
+ { "a32_0f", ENDIANNESS_BIG, datawidth, 32, 0, address_map_constructor(FUNC(vme_bus_device::a32), this) },
+ {}, {}, {}, {}, {}, {}, {}, {},
+ {}, {}, {}, {}, {}, {}, {}, {},
+ {}, {}, {}, {}, {}, {}, {}, {},
+ {},
+ { "a16_29", ENDIANNESS_BIG, datawidth, 16, 0, address_map_constructor(FUNC(vme_bus_device::a16), this) },
+ {}, {}, {},
+ { "a16_2d", ENDIANNESS_BIG, datawidth, 16, 0, address_map_constructor(FUNC(vme_bus_device::a16), this) },
+ {}, {},
+ {}, {}, {}, {}, {}, {}, {}, {},
+ {},
+ { "a24_39", ENDIANNESS_BIG, datawidth, 24, 0, address_map_constructor(FUNC(vme_bus_device::a24), this) },
+ { "a24_3a", ENDIANNESS_BIG, datawidth, 24, 0, address_map_constructor(FUNC(vme_bus_device::a24), this) },
+ { "a24_3b", ENDIANNESS_BIG, datawidth, 24, 0, address_map_constructor(FUNC(vme_bus_device::a24), this) },
+ {},
+ { "a24_3d", ENDIANNESS_BIG, datawidth, 24, 0, address_map_constructor(FUNC(vme_bus_device::a24), this) },
+ { "a24_3e", ENDIANNESS_BIG, datawidth, 24, 0, address_map_constructor(FUNC(vme_bus_device::a24), this) },
+ { "a24_3f", ENDIANNESS_BIG, datawidth, 24, 0, address_map_constructor(FUNC(vme_bus_device::a24), this) },
}
-}
-
-//-------------------------------------------------
-// P1 D8 read
-//-------------------------------------------------
-uint8_t vme_slot_device::read8(offs_t offset)
+ , m_irq(*this)
+ , m_berr(*this)
+ , m_irq_count{}
+ , m_iack(false)
{
- uint16_t result = 0x00;
- LOG("%s %s\n", tag(), FUNCNAME);
- // printf("%s %s\n", tag(), FUNCNAME);
- // if (m_card) result = m_card->read8(offset);
- return result;
}
-//-------------------------------------------------
-// P1 D8 write
-//-------------------------------------------------
-void vme_slot_device::write8(offs_t offset, uint8_t data)
+void vme_bus_device::device_start()
{
- LOG("%s %s\n", tag(), FUNCNAME);
- // printf("%s %s\n", tag(), FUNCNAME);
- // if (m_card) m_card->write8(offset, data);
+ save_item(NAME(m_irq_count));
+ save_item(NAME(m_iack));
}
-#if 0 // Disabled until we know how to make a board driver also a slot device
-/* The following two slot collections be combined once we intriduce capabilities for each board */
-/* Usually a VME firmware supports only a few boards so it will have its own slot collection defined */
-// Controller capable boards that can go into slot1 ( or has an embedded VME bus )
-void vme_slot1(device_slot_interface &device)
+device_memory_interface::space_config_vector vme_bus_device::memory_space_config() const
{
-// device.option_add("mzr8105", VME_MZR8105);
-}
-#endif
-
-// All boards that can be non-controller boards, eg not driving the VME CLK etc
-void vme_slots(device_slot_interface &device)
-{
- device.option_add("mzr8300", VME_MZR8300);
- device.option_add("mvme350", VME_MVME350);
- device.option_add("fcisio1", VME_FCISIO1);
- device.option_add("fcscsi1", VME_FCSCSI1);
-}
-
-//
-// VME device P1
-//
-
-DEFINE_DEVICE_TYPE(VME, vme_device, "vme", "VME bus")
-
-device_memory_interface::space_config_vector vme_device::memory_space_config() const
-{
- return space_config_vector {
- std::make_pair(AS_PROGRAM, &m_a32_config)
+ return space_config_vector{
+ std::make_pair(vme::IACK, &m_asc[vme::IACK]),
+
+ std::make_pair(vme::AM_09, &m_asc[vme::AM_09]),
+ std::make_pair(vme::AM_0a, &m_asc[vme::AM_0a]),
+ std::make_pair(vme::AM_0b, &m_asc[vme::AM_0b]),
+ std::make_pair(vme::AM_0d, &m_asc[vme::AM_0d]),
+ std::make_pair(vme::AM_0e, &m_asc[vme::AM_0e]),
+ std::make_pair(vme::AM_0f, &m_asc[vme::AM_0f]),
+
+ std::make_pair(vme::AM_29, &m_asc[vme::AM_29]),
+ std::make_pair(vme::AM_2d, &m_asc[vme::AM_2d]),
+
+ std::make_pair(vme::AM_39, &m_asc[vme::AM_39]),
+ std::make_pair(vme::AM_3a, &m_asc[vme::AM_3a]),
+ std::make_pair(vme::AM_3b, &m_asc[vme::AM_3b]),
+ std::make_pair(vme::AM_3d, &m_asc[vme::AM_3d]),
+ std::make_pair(vme::AM_3e, &m_asc[vme::AM_3e]),
+ std::make_pair(vme::AM_3f, &m_asc[vme::AM_3f]),
};
}
-// set_use_owner_spaces - disables use of the memory interface and use the address spaces
-// of the owner instead. This is useful for VME buses where no address modifiers or arbitration is
-// being used and gives some gain in performance.
-void vme_device::use_owner_spaces()
+u32 vme_bus_device::read_iack(address_space &space, offs_t offset, u32 mem_mask)
{
- LOG("%s %s\n", tag(), FUNCNAME);
+ if (!device().machine().side_effects_disabled())
+ {
+ LOG("read_iack 0x%08x mem_mask 0x%08x (%s)\n", offset, mem_mask, machine().describe_context());
- m_allocspaces = false;
-}
+ // enable interrupt acknowledge daisy chain
+ m_iack = true;
+ }
-vme_device::vme_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : vme_device(mconfig, VME, tag, owner, clock)
-{
+ return space.unmap();
}
-vme_device::vme_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, type, tag, owner, clock)
- , device_memory_interface(mconfig, *this)
- , m_a32_config("a32", ENDIANNESS_BIG, 32, 32, 0, address_map_constructor())
- , m_allocspaces(true)
- , m_cputag("maincpu")
+// generate bus errors on unmapped read cycles
+u32 vme_bus_device::read_berr(address_space &space, offs_t offset, u32 mem_mask)
{
- LOG("%s %s\n", tag, FUNCNAME);
-}
+ if (!device().machine().side_effects_disabled())
+ {
+ LOG("read_berr 0x%08x mem_mask 0x%08x (%s)\n", offset << 2, mem_mask, machine().describe_context());
-vme_device::~vme_device()
-{
- LOG("%s %s\n", tag(), FUNCNAME);
- m_device_list.detach_all();
+ m_berr(0);
+ }
+
+ return space.unmap();
}
-void vme_device::device_start()
+// generate bus errors on unmapped write cycles
+void vme_bus_device::write_berr(offs_t offset, u32 data, u32 mem_mask)
{
- LOG("%s %s %s\n", owner()->tag(), tag(), FUNCNAME);
- if (m_allocspaces)
+ if (!device().machine().side_effects_disabled())
{
- LOG(" - using my own memory spaces\n");
- m_prgspace = &space(AS_PROGRAM);
- m_prgwidth = m_prgspace->data_width();
- LOG(" - Done at %d width\n", m_prgwidth);
- }
- else // use host CPU's spaces directly
- {
- LOG(" - using owner memory spaces for %s\n", m_cputag);
- m_maincpu = owner()->subdevice<cpu_device>(m_cputag);
- m_prgspace = &m_maincpu->space(AS_PROGRAM);
- m_prgwidth = m_maincpu->space_config(AS_PROGRAM)->data_width();
- LOG(" - Done at %d width\n", m_prgwidth);
+ LOG("write_berr 0x%08x data 0x%08x mem_mask 0x%08x (%s)\n", offset << 2, data, mem_mask, machine().describe_context());
+
+ m_berr(0);
}
}
-void vme_device::device_reset()
+void vme_bus_device::iack(address_map &map)
{
- LOG("%s %s\n", tag(), FUNCNAME);
+ map(0x0, 0xf).r(FUNC(vme_bus_device::read_iack));
}
-void vme_device::add_vme_card(device_vme_card_interface *card)
+void vme_bus_device::a16(address_map &map)
{
- LOG("%s %s\n", tag(), FUNCNAME);
- m_device_list.append(*card);
+ map(0x0000, 0xffff).rw(FUNC(vme_bus_device::read_berr), FUNC(vme_bus_device::write_berr));
}
-#if 0
-/*
- * Install UB (Utility Bus) handlers for this board
- *
- * The Utility Bus signal lines
- *------------------------------
- * System Clock (SYSCLK)
- * Serial Clock (SERCLK)
- * Serial Data (SERDAT*)
- * AC Fail (ACFAIL*)
- * System Reset (SYSRESET*)
- * System Failure (SYSFAIL*)
- *------------------------------
- */
-void vme_device::install_ub_handler(offs_t start, offs_t end, read8_delegate rhandler, write8_delegate whandler, uint32_t mask)
+void vme_bus_device::a24(address_map &map)
{
+ map(0x00'0000, 0xff'ffff).rw(FUNC(vme_bus_device::read_berr), FUNC(vme_bus_device::write_berr));
}
-#endif
-
-/*
- * Install DTB (Data Transfer Bus) handlers for this board
- */
-// D8 bit devices in A16, A24 and A32
-void vme_device::install_device(vme_amod_t amod, offs_t start, offs_t end, read8_delegate rhandler, write8_delegate whandler, uint32_t mask)
+void vme_bus_device::a32(address_map &map)
{
- LOG("%s %s AM%d D%02x\n", tag(), FUNCNAME, amod, m_prgwidth);
-
- LOG(" - width:%d\n", m_prgwidth);
-
- // TODO: support address modifiers and buscycles other than single access cycles
- switch(amod)
- {
- case A16_SC: break;
- case A24_SC: break;
- case A32_SC: break;
- default: fatalerror("VME D8: Non supported Address modifier: AM%02x\n", amod);
- }
-
- switch(m_prgwidth)
- {
- case 16:
- m_prgspace->install_readwrite_handler(start, end, rhandler, whandler, (uint16_t)(mask & 0x0000ffff));
- break;
- case 24:
- m_prgspace->install_readwrite_handler(start, end, rhandler, whandler, (uint32_t)(mask & 0x00ffffff));
- break;
- case 32:
- m_prgspace->install_readwrite_handler(start, end, rhandler, whandler, mask);
- break;
- default: fatalerror("VME D8: Bus width %d not supported\n", m_prgwidth);
- }
+ map(0x0000'0000, 0xffff'ffff).rw(FUNC(vme_bus_device::read_berr), FUNC(vme_bus_device::write_berr));
}
-void vme_device::install_device(vme_amod_t amod, offs_t start, offs_t end, read8sm_delegate rhandler, write8sm_delegate whandler, uint32_t mask)
+template <unsigned I> void vme_bus_device::irq_w(int state)
{
- LOG("%s %s AM%d D%02x\n", tag(), FUNCNAME, amod, m_prgwidth);
+ bool const irq_active = m_irq_count[I - 1];
- LOG(" - width:%d\n", m_prgwidth);
+ // count assertions
+ if (!state)
+ m_irq_count[I - 1]++;
+ else if (irq_active)
+ m_irq_count[I - 1]--;
- // TODO: support address modifiers and buscycles other than single access cycles
- switch(amod)
+ // update line state
+ if (irq_active ^ bool(m_irq_count[I - 1]))
{
- case A16_SC: break;
- case A24_SC: break;
- case A32_SC: break;
- default: fatalerror("VME D8: Non supported Address modifier: AM%02x\n", amod);
- }
-
- switch(m_prgwidth)
- {
- case 16:
- m_prgspace->install_readwrite_handler(start, end, rhandler, whandler, (uint16_t)(mask & 0x0000ffff));
- break;
- case 24:
- m_prgspace->install_readwrite_handler(start, end, rhandler, whandler, (uint32_t)(mask & 0x00ffffff));
- break;
- case 32:
- m_prgspace->install_readwrite_handler(start, end, rhandler, whandler, mask);
- break;
- default: fatalerror("VME D8: Bus width %d not supported\n", m_prgwidth);
+ LOG("irq %d state %d\n", I, state);
+ m_irq[I - 1](state);
}
}
-void vme_device::install_device(vme_amod_t amod, offs_t start, offs_t end, read8smo_delegate rhandler, write8smo_delegate whandler, uint32_t mask)
-{
- LOG("%s %s AM%d D%02x\n", tag(), FUNCNAME, amod, m_prgwidth);
-
- LOG(" - width:%d\n", m_prgwidth);
-
- // TODO: support address modifiers and buscycles other than single access cycles
- switch(amod)
- {
- case A16_SC: break;
- case A24_SC: break;
- case A32_SC: break;
- default: fatalerror("VME D8: Non supported Address modifier: AM%02x\n", amod);
- }
-
- switch(m_prgwidth)
- {
- case 16:
- m_prgspace->install_readwrite_handler(start, end, rhandler, whandler, (uint16_t)(mask & 0x0000ffff));
- break;
- case 24:
- m_prgspace->install_readwrite_handler(start, end, rhandler, whandler, (uint32_t)(mask & 0x00ffffff));
- break;
- case 32:
- m_prgspace->install_readwrite_handler(start, end, rhandler, whandler, mask);
- break;
- default: fatalerror("VME D8: Bus width %d not supported\n", m_prgwidth);
- }
-}
+template void vme_bus_device::irq_w<1>(int state);
+template void vme_bus_device::irq_w<2>(int state);
+template void vme_bus_device::irq_w<3>(int state);
+template void vme_bus_device::irq_w<4>(int state);
+template void vme_bus_device::irq_w<5>(int state);
+template void vme_bus_device::irq_w<6>(int state);
+template void vme_bus_device::irq_w<7>(int state);
-// D16 bit devices in A16, A24 and A32
-void vme_device::install_device(vme_amod_t amod, offs_t start, offs_t end, read16_delegate rhandler, write16_delegate whandler, uint32_t mask)
+vme_slot_device::vme_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, VME_SLOT, tag, owner, clock)
+ , device_slot_interface(mconfig, *this)
+ , m_bus(*this, owner->tag())
{
- LOG("%s %s AM%d D%02x\n", tag(), FUNCNAME, amod, m_prgwidth);
-
- LOG(" - width:%d\n", m_prgwidth);
-
- // TODO: support address modifiers and buscycles other than single access cycles
- switch(amod)
- {
- case A16_SC: break;
- case A24_SC: break;
- case A32_SC: break;
- default: fatalerror("VME D16: Non supported Address modifier: %02x\n", amod);
- }
-
- switch(m_prgwidth)
- {
- case 16:
- m_prgspace->install_readwrite_handler(start, end, rhandler, whandler, (uint16_t)(mask & 0x0000ffff));
- break;
- case 24:
- m_prgspace->install_readwrite_handler(start, end, rhandler, whandler, (uint32_t)(mask & 0x00ffffff));
- break;
- case 32:
- m_prgspace->install_readwrite_handler(start, end, rhandler, whandler, mask);
- break;
- default: fatalerror("VME D16: Bus width %d not supported\n", m_prgwidth);
- }
}
-// D32 bit devices in A16, A24 and A32
-void vme_device::install_device(vme_amod_t amod, offs_t start, offs_t end, read32_delegate rhandler, write32_delegate whandler, uint32_t mask)
+void vme_slot_device::device_start()
{
- LOG("%s %s AM%d D%02x\n", tag(), FUNCNAME, amod, m_prgwidth);
-
- LOG(" - width:%d\n", m_prgwidth);
-
- // TODO: support address modifiers and buscycles other than single access cycles
- switch(amod)
- {
- case A16_SC: break;
- case A24_SC: break;
- case A32_SC: break;
- default: fatalerror("VME D32: Non supported Address modifier: %02x\n", amod);
- }
-
- switch(m_prgwidth)
- {
- case 16:
- m_prgspace->install_readwrite_handler(start, end, rhandler, whandler, (uint16_t)(mask & 0x0000ffff));
- break;
- case 24:
- m_prgspace->install_readwrite_handler(start, end, rhandler, whandler, (uint32_t)(mask & 0x00ffffff));
- break;
- case 32:
- m_prgspace->install_readwrite_handler(start, end, rhandler, whandler, mask);
- break;
- default: fatalerror("VME D32: Bus width %d not supported\n", m_prgwidth);
- }
}
-//
-// Card interface
-//
-device_vme_card_interface::device_vme_card_interface(const machine_config &mconfig, device_t &device)
+#undef LOG_OUTPUT_FUNC
+#define LOG_OUTPUT_FUNC device().logerror
+
+device_vme_card_interface::device_vme_card_interface(machine_config const &mconfig, device_t &device)
: device_interface(device, "vme")
- , m_vme(nullptr)
- , m_slot(0)
- , m_next(nullptr)
+ , m_slot(dynamic_cast<vme_slot_device *>(device.owner()))
+ , m_berr(*this)
+ , m_iack(*this, 0)
+ , m_irq_active(0)
+ , m_master(false)
{
- m_device = &device;
- LOG("%s %s\n", m_device->tag(), FUNCNAME);
}
-device_vme_card_interface::~device_vme_card_interface()
+void device_vme_card_interface::interface_config_complete()
{
- LOG("%s %s\n", m_device->tag(), FUNCNAME);
+ // route bus errors to the card when it is the bus master
+ if (m_slot) // HACK: avoid breaking listxml until proper fix can be identified
+ m_slot->berr().append(
+ [this](int state)
+ {
+ if (m_master)
+ {
+ LOG("vme berr %d\n", state);
+ m_berr(state);
+ }
+ });
}
void device_vme_card_interface::interface_post_start()
{
- LOG("%s %s\n", m_device->tag(), FUNCNAME);
- // printf("*** %s %sfound\n", m_vme_tag, m_vme ? "" : "not ");
- if (m_vme) m_vme->add_vme_card(this);
+ device().save_item(NAME(m_irq_active));
+ device().save_item(NAME(m_master));
+
+ /*
+ * Install a read tap into the bus interrupt acknowledge address space,
+ * simulating a daisy chain and giving each card an opportunity to respond
+ * to the interrupt acknowledge cycle in slot sequence. Empty slots do not
+ * respond, acting as if they have /IACKIN jumpered to /IACKOUT.
+ */
+ vme_space(vme::IACK).install_read_tap(0x0, 0xf, "iack",
+ [this](offs_t offset, u32 &data, u32 mem_mask)
+ {
+ // decode the interrupt number from address lines A03-A01
+ unsigned const irq = BIT(offset, 1, 3);
+
+ /*
+ * An interrupt acknowledge cycle is being asserted. This device
+ * will only respond if the upstream interrupt acknowledge daisy
+ * chain input (/IACKIN) is asserted and this device is asserting
+ * the interrupt number being acknowledged.
+ */
+ if (m_slot->iackin_r() && BIT(m_irq_active, irq))
+ {
+ // deassert interrupt acknowledge daisy chain output
+ m_slot->iackout_w(1);
+
+ // read and return the interrupting device status/ID
+ data = m_iack(irq);
+
+ LOG("vme iack irq %d status 0x%08x (%s)\n", irq, data, device().machine().describe_context());
+ }
+ });
}
-/* VME D8 accesses */
-uint8_t device_vme_card_interface::read8(offs_t offset)
+template <unsigned I> void device_vme_card_interface::vme_irq_w(int state)
{
- uint8_t result = 0x00;
- LOG("%s %s Offset:%08x\n", m_device->tag(), FUNCNAME, offset);
- return result;
-}
+ // check whether the interrupt state has changed
+ if (BIT(m_irq_active, I) == state)
+ {
+ LOG("vme irq %d state %d\n", I, state);
-void device_vme_card_interface::write8(offs_t offset, uint8_t data)
-{
- LOG("%s %s Offset:%08x\n", m_device->tag(), FUNCNAME, offset);
+ // record device interrupt state
+ if (!state)
+ m_irq_active |= 1U << I;
+ else
+ m_irq_active &= ~(1U << I);
+
+ // update the bus irq state
+ m_slot->irq_w<I>(state);
+ }
}
+template void device_vme_card_interface::vme_irq_w<1>(int state);
+template void device_vme_card_interface::vme_irq_w<2>(int state);
+template void device_vme_card_interface::vme_irq_w<3>(int state);
+template void device_vme_card_interface::vme_irq_w<4>(int state);
+template void device_vme_card_interface::vme_irq_w<5>(int state);
+template void device_vme_card_interface::vme_irq_w<6>(int state);
+template void device_vme_card_interface::vme_irq_w<7>(int state);
+
//--------------- P2 connector below--------------------------
/*
The VME P2 connector only specifies the mid row B of the connector
diff --git a/src/devices/bus/vme/vme.h b/src/devices/bus/vme/vme.h
index e49b23cbbbe..298f623112b 100644
--- a/src/devices/bus/vme/vme.h
+++ b/src/devices/bus/vme/vme.h
@@ -50,192 +50,175 @@
#pragma once
-
-//**************************************************************************
-// CONSTANTS
-//**************************************************************************
-
-//void vme_slot1(device_slot_interface &device); // Disabled until we know how to combine a board driver and a slot device.
-void vme_slots(device_slot_interface &device);
-
-class device_vme_card_interface; // This interface is standardized
-class vme_device;
-
-class vme_slot_device : public device_t,
- public device_slot_interface
+namespace vme
{
-public:
- // VME BUS signals driven to or drived by the VME bus
- enum class control
- {
- AS,
- DS0,
- DS1,
- BERR,
- DTACK,
- WRITE
- };
-
- enum class address
+ enum address_modifier : u8
{
- DS0,
- DS1,
- LWORD
+ IACK = 0x00, // interrupt acknowledge
+
+ AM_09 = 0x09, // a32, non-privileged, data
+ AM_0a = 0x0a, // a32, non-privileged, instruction
+ AM_0b = 0x0b, // a32, non-privileged, block transfer
+ AM_0d = 0x0d, // a32, privileged, data
+ AM_0e = 0x0e, // a32, privileged, instruction
+ AM_0f = 0x0f, // a32, privileged, block transfer
+
+ AM_29 = 0x29, // a16, non-privileged
+ AM_2d = 0x2d, // a16, privileged
+
+ AM_39 = 0x39, // a24, non-privileged, data
+ AM_3a = 0x3a, // a24, non-privileged, instruction
+ AM_3b = 0x3b, // a24, non-privileged, block transfer
+ AM_3d = 0x3d, // a24, privileged, data
+ AM_3e = 0x3e, // a24, privileged, instruction
+ AM_3f = 0x3f, // a24, privileged, block transfer
};
+}
- // construction/destruction
- template <typename T, typename U>
- vme_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts, char const *dflt, uint32_t slot_nbr, U &&bus_tag)
- : vme_slot_device(mconfig, tag, owner, 0)
- {
- option_reset();
- opts(*this);
- set_default_option(dflt);
- set_fixed(false);
- set_vme_slot(std::forward<U>(bus_tag), slot_nbr);
- }
-
- vme_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- // Callbacks to the board from the VME bus comes through here
- auto vme_j1_callback() { return m_vme_j1_callback.bind(); }
+class vme_bus_device
+ : public device_t
+ , public device_memory_interface
+{
+public:
+ vme_bus_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock = 16'000'000, u8 datawidth = 32);
- template <typename T> void set_vme_slot(T &&tag, uint32_t slot_nbr) { m_vme.set_tag(std::forward<T>(tag)); m_slot_nbr = slot_nbr; }
+ // configuration
+ auto berr() { return m_berr.bind(); }
+ template <unsigned I> auto irq() { return m_irq[I - 1].bind(); }
- virtual uint8_t read8(offs_t offset);
- virtual void write8(offs_t offset, uint8_t data);
+ // runtime
+ void berr_w(int state) { m_berr(state); }
+ int iackin_r() { return m_iack; }
+ void iackout_w(int state) { m_iack = !state; }
+ template <unsigned I> void irq_w(int state);
protected:
- vme_slot_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
-
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
- virtual void device_resolve_objects() override;
- // configuration
- required_device<vme_device> m_vme;
- uint32_t m_slot_nbr;
+ // device_memory_interface implementation
+ virtual space_config_vector memory_space_config() const override;
- // callbacks
- devcb_write_line m_vme_j1_callback;
- device_vme_card_interface *m_card;
-};
+private:
+ void iack(address_map &map);
+ void a16(address_map &map);
+ void a24(address_map &map);
+ void a32(address_map &map);
-DECLARE_DEVICE_TYPE(VME, vme_device)
+ u32 read_iack(address_space &space, offs_t offset, u32 mem_mask);
+ u32 read_berr(address_space &space, offs_t offset, u32 mem_mask);
+ void write_berr(offs_t offset, u32 data, u32 mem_mask);
+ address_space_config const m_asc[64];
-class vme_card_interface;
+ devcb_write_line::array<7> m_irq;
+ devcb_write_line m_berr;
-class vme_device : public device_t,
- public device_memory_interface
+ u8 m_irq_count[7];
+ bool m_iack;
+};
+
+class vme_slot_device
+ : public device_t
+ , public device_slot_interface
{
public:
- vme_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- ~vme_device();
-
- // inline configuration
- void set_cputag(const char *tag) { m_cputag = tag; }
- void use_owner_spaces();
-
- const address_space_config m_a32_config;
-
- void add_vme_card(device_vme_card_interface *card);
-
- //
- // Address Modifiers
- //
- /* There are 6 address modifier lines. They allow the MASTER to pass additional binary
- information to the SLAVE during data transfers. Table 2-3 lists all of the 64 possible
- address modifier (AM) codes and classifies each into one of three categories:
- - Defined
- - Reserved
- - User defined
- The defined address modifier codes can be further classified into three categories:
- Short addressing AM codes indicate that address lines A02-A15 are being used to select a BYTE(0-3) group.
- Standard addressing AM codes ,indicate that address lines A02-A23 are being used to select a BYTE(0-3) group.
- Extended addressing AM codes indicate that address lines A02-A31 are being used to select a BYTE(0-3) group.*/
-
- enum vme_amod_t
- { // Defined and User Defined Address Modifier Values (long bnames from VME standard text. please use short)
- AMOD_EXTENDED_NON_PRIV_DATA = 0x09, //A32 SC (Single Cycle)
- A32_SC = 0x09, //A32 SC (Single Cycle)
- AMOD_EXTENDED_NON_PRIV_PRG = 0x0A,
- AMOD_EXTENDED_NON_PRIV_BLK = 0x0B,
- AMOD_EXTENDED_SUPERVIS_DATA = 0x0D,
- AMOD_EXTENDED_SUPERVIS_PRG = 0x0E,
- AMOD_EXTENDED_SUPERVIS_BLK = 0x0F,
- AMOD_USER_DEFINED_FIRST = 0x10,
- AMOD_USER_DEFINED_LAST = 0x1F,
- AMOD_SHORT_NON_PRIV_ACCESS = 0x29, //A16 SC
- A16_SC = 0x29, //A16 SC
- AMOD_SHORT_SUPERVIS_ACCESS = 0x2D,
- AMOD_STANDARD_NON_PRIV_DATA = 0x39, //A24 SC
- A24_SC = 0x39, //A24 SC
- AMOD_STANDARD_NON_PRIV_PRG = 0x3A,
- AMOD_STANDARD_NON_PRIV_BLK = 0x3B, //A24 BLT
- AMOD_STANDARD_SUPERVIS_DATA = 0x3D,
- AMOD_STANDARD_SUPERVIS_PRG = 0x3E,
- AMOD_STANDARD_SUPERVIS_BLK = 0x3F
- };
- void install_device(vme_amod_t amod, offs_t start, offs_t end, read8_delegate rhandler, write8_delegate whandler, uint32_t mask);
- void install_device(vme_amod_t amod, offs_t start, offs_t end, read8sm_delegate rhandler, write8sm_delegate whandler, uint32_t mask);
- void install_device(vme_amod_t amod, offs_t start, offs_t end, read8smo_delegate rhandler, write8smo_delegate whandler, uint32_t mask);
- // void install_device(vme_amod_t amod, offs_t start, offs_t end, read8_delegate rhandler, write8_delegate whandler);
- void install_device(vme_amod_t amod, offs_t start, offs_t end, read16_delegate rhandler, write16_delegate whandler, uint32_t mask);
- void install_device(vme_amod_t amod, offs_t start, offs_t end, read32_delegate rhandler, write32_delegate whandler, uint32_t mask);
+ vme_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock = DERIVED_CLOCK(1, 1));
-protected:
- vme_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
-
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- simple_list<device_vme_card_interface> m_device_list;
+ template <typename T>
+ vme_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&slot_options, char const *default_option, bool const fixed = false)
+ : vme_slot_device(mconfig, tag, owner, DERIVED_CLOCK(1, 1))
+ {
+ option_reset();
+ slot_options(*this);
+ set_default_option(default_option);
+ set_fixed(fixed);
+ }
- virtual space_config_vector memory_space_config() const override;
+ // configuration
+ template <unsigned I> auto irq() { return m_bus.lookup()->irq<I>(); }
+ auto berr() { return m_bus.lookup()->berr(); }
- // internal state
- cpu_device *m_maincpu;
+ // runtime
+ void berr_w(int state) { m_bus->berr_w(state); }
+ int iackin_r() { return m_bus->iackin_r(); }
+ void iackout_w(int state) { m_bus->iackout_w(state); }
+ template <unsigned I> void irq_w(int state) { m_bus->irq_w<I>(state); }
- // address spaces
- address_space *m_prgspace;
- int m_prgwidth;
- bool m_allocspaces;
+ address_space &space(vme::address_modifier am) const { return m_bus->space(am); }
- const char *m_cputag;
+protected:
+ // device_t implementation
+ virtual void device_start() override;
+private:
+ required_device<vme_bus_device> m_bus;
};
-
-
-// device type definition
-DECLARE_DEVICE_TYPE(VME_SLOT, vme_slot_device)
-
class device_vme_card_interface : public device_interface
{
- template <class ElementType> friend class simple_list;
public:
- // inline configuration
- void set_vme_bus(vme_device &vme, int slot) { m_vme = &vme; m_slot = slot; }
+ template <vme::address_modifier AM, offs_t base = 0> u32 vme_read32(offs_t offset, u32 mem_mask)
+ {
+ m_master = true;
+ u32 const data = m_slot->space(AM).read_dword(base + (offset << 2), mem_mask);
+ m_master = false;
- // construction/destruction
- virtual ~device_vme_card_interface();
+ return data;
+ }
+ template <vme::address_modifier AM, offs_t base = 0> u16 vme_read16(offs_t offset, u16 mem_mask)
+ {
+ m_master = true;
+ u16 const data = m_slot->space(AM).read_word(base + (offset << 1), mem_mask);
+ m_master = false;
- virtual uint8_t read8(offs_t offset);
- virtual void write8(offs_t offset, uint8_t data);
+ return data;
+ }
+ template <vme::address_modifier AM, offs_t base = 0> void vme_write32(offs_t offset, u32 data, u32 mem_mask)
+ {
+ m_master = true;
+ m_slot->space(AM).write_dword(base + (offset << 2), data, mem_mask);
+ m_master = false;
+ }
+ template <vme::address_modifier AM, offs_t base = 0> void vme_write16(offs_t offset, u16 data, u16 mem_mask)
+ {
+ m_master = true;
+ m_slot->space(AM).write_word(base + (offset << 1), data, mem_mask);
+ m_master = false;
+ }
+ u32 vme_iack_r(offs_t offset)
+ {
+ return m_slot->space(vme::IACK).read_dword(offset);
+ }
protected:
- device_vme_card_interface(const machine_config &mconfig, device_t &device);
+ device_vme_card_interface(machine_config const &mconfig, device_t &device);
+
+ // configuration
+ template <unsigned I> auto vme_irq() { return m_slot->irq<I>(); }
+ auto vme_berr() { return m_berr.bind(); }
+ auto vme_iack() { return m_iack.bind(); }
+ // device_interface implementation
+ virtual void interface_config_complete() override;
virtual void interface_post_start() override;
- device_t *m_device;
+ // runtime
+ template <unsigned I> void vme_irq_w(int state);
+ void vme_berr_w(int state) { m_slot->berr_w(state); }
- vme_device *m_vme;
- int m_slot;
+ address_space &vme_space(vme::address_modifier am) const { return m_slot->space(am); }
private:
- device_vme_card_interface *m_next;
+ vme_slot_device *m_slot;
+ devcb_write_line m_berr;
+ devcb_read32 m_iack;
+
+ u8 m_irq_active;
+ bool m_master;
};
+DECLARE_DEVICE_TYPE(VME, vme_bus_device)
+DECLARE_DEVICE_TYPE(VME_SLOT, vme_slot_device)
+
#endif // MAME_BUS_VME_VME_H
diff --git a/src/devices/bus/vme/vme_cards.cpp b/src/devices/bus/vme/vme_cards.cpp
new file mode 100644
index 00000000000..e66cf8d322a
--- /dev/null
+++ b/src/devices/bus/vme/vme_cards.cpp
@@ -0,0 +1,65 @@
+// license:BSD-3-Clause
+// copyright-holders:Patrick Mackinlay
+
+#include "emu.h"
+#include "vme_cards.h"
+
+#include "cp31.h"
+#include "enp10.h"
+#include "hcpu30.h"
+#include "hk68v10.h"
+#include "mvme120.h"
+#include "mvme147.h"
+#include "mvme180.h"
+#include "mvme181.h"
+#include "mvme187.h"
+#include "mvme327a.h"
+#include "mvme350.h"
+#include "mzr8105.h"
+#include "mzr8300.h"
+#include "smvme2000.h"
+#include "sys68k_cpu1.h"
+#include "sys68k_cpu20.h"
+#include "sys68k_cpu30.h"
+#include "sys68k_iscsi.h"
+#include "sys68k_isio.h"
+#include "tp881v.h"
+
+void vme_cards(device_slot_interface &device)
+{
+ device.option_add("cp31", VME_CP31);
+ device.option_add("enp10", VME_ENP10);
+ device.option_add("hcpu30", VME_HCPU30);
+ device.option_add("hk68v10", VME_HK68V10);
+ device.option_add("mvme120", VME_MVME120);
+ device.option_add("mvme121", VME_MVME121);
+ device.option_add("mvme122", VME_MVME122);
+ device.option_add("mvme123", VME_MVME123);
+ device.option_add("mvme147", VME_MVME147);
+ device.option_add("mvme180", VME_MVME180);
+ device.option_add("mvme181", VME_MVME181);
+ device.option_add("mvme187", VME_MVME187);
+ device.option_add("mvme327a", VME_MVME327A);
+ device.option_add("mvme350", VME_MVME350);
+ device.option_add("mzr8105", VME_MZR8105);
+ device.option_add("mzr8300", VME_MZR8300);
+ device.option_add("smvme2000", VME_SMVME2000);
+ device.option_add("sys68k_cpu1", VME_SYS68K_CPU1);
+ device.option_add("sys68k_cpu20", VME_SYS68K_CPU20);
+ device.option_add("sys68k_cpu21", VME_SYS68K_CPU21);
+ device.option_add("sys68k_cpu21a", VME_SYS68K_CPU21A);
+ device.option_add("sys68k_cpu21b", VME_SYS68K_CPU21B);
+ device.option_add("sys68k_cpu21s", VME_SYS68K_CPU21S);
+ device.option_add("sys68k_cpu21ya", VME_SYS68K_CPU21YA);
+ device.option_add("sys68k_cpu21yb", VME_SYS68K_CPU21YB);
+ device.option_add("sys68k_cpu30", VME_SYS68K_CPU30);
+ device.option_add("sys68k_cpu30x", VME_SYS68K_CPU30X);
+ device.option_add("sys68k_cpu30xa", VME_SYS68K_CPU30XA);
+ device.option_add("sys68k_cpu30za", VME_SYS68K_CPU30ZA);
+ device.option_add("sys68k_cpu30be", VME_SYS68K_CPU30BE);
+ device.option_add("sys68k_cpu30lite", VME_SYS68K_CPU30LITE);
+ device.option_add("sys68k_cpu33", VME_SYS68K_CPU33);
+ device.option_add("sys68k_iscsi1", VME_SYS68K_ISCSI1),
+ device.option_add("sys68k_isio1", VME_SYS68K_ISIO1),
+ device.option_add("tp881v", VME_TP881V);
+}
diff --git a/src/devices/bus/vme/vme_cards.h b/src/devices/bus/vme/vme_cards.h
new file mode 100644
index 00000000000..196c96c77e2
--- /dev/null
+++ b/src/devices/bus/vme/vme_cards.h
@@ -0,0 +1,11 @@
+// license:BSD-3-Clause
+// copyright-holders:Patrick Mackinlay
+
+#ifndef MAME_BUS_VME_CARDS_H
+#define MAME_BUS_VME_CARDS_H
+
+#pragma once
+
+void vme_cards(device_slot_interface &device);
+
+#endif // MAME_BUS_VME_CARDS_H
diff --git a/src/devices/bus/vme/vme_fccpu20.h b/src/devices/bus/vme/vme_fccpu20.h
deleted file mode 100644
index 42569041f87..00000000000
--- a/src/devices/bus/vme/vme_fccpu20.h
+++ /dev/null
@@ -1,191 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Joakim Larsson Edstrom
-#ifndef MAME_BUS_VME_VME_FCCPU20_H
-#define MAME_BUS_VME_VME_FCCPU20_H
-
-#pragma once
-
-#include "bus/vme/vme.h"
-#include "machine/68561mpcc.h"
-#include "machine/68230pit.h"
-#include "machine/68153bim.h"
-
-DECLARE_DEVICE_TYPE(VME_FCCPU20, vme_fccpu20_card_device)
-DECLARE_DEVICE_TYPE(VME_FCCPU21S, vme_fccpu21s_card_device)
-DECLARE_DEVICE_TYPE(VME_FCCPU21, vme_fccpu21_card_device)
-DECLARE_DEVICE_TYPE(VME_FCCPU21A, vme_fccpu21a_card_device)
-DECLARE_DEVICE_TYPE(VME_FCCPU21YA, vme_fccpu21ya_card_device)
-DECLARE_DEVICE_TYPE(VME_FCCPU21B, vme_fccpu21b_card_device)
-DECLARE_DEVICE_TYPE(VME_FCCPU21YB, vme_fccpu21yb_card_device)
-
-//**************************************************************************
-// Base Device declaration
-//**************************************************************************
-class vme_fccpu20_device : public device_t, public device_vme_card_interface
-{
-protected:
- // PIT port C Board ID bits
- static constexpr unsigned CPU20 = 0x40;
- static constexpr unsigned CPU21 = 0x00;
-
- /* Board types */
- enum fc_board_t {
- cpu20,
- cpu21,
- cpu21a,
- cpu21ya,
- cpu21b,
- cpu21yb,
- cpu21s
- };
-
- vme_fccpu20_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, fc_board_t board_id);
-
- virtual void device_start() override;
- virtual void device_reset() override;
-
- // optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
-
- TIMER_CALLBACK_MEMBER(grant_bus);
-
- int m_bim_irq_state;
- uint8_t m_bim_irq_level;
-
- emu_timer *m_arbiter_start; // Need a startup delay because it is hooked up to the sense inputs of the PIT
-
- required_device<cpu_device> m_maincpu;
-
-private:
- DECLARE_WRITE_LINE_MEMBER(bim_irq_callback);
-
- /* PIT callbacks */
- uint8_t pita_r();
- uint8_t pitb_r();
- uint8_t pitc_r();
-
- // Below are duplicated declarations from src/mame/drivers/fccpu20.cpp
- uint32_t bootvect_r(offs_t offset);
- void bootvect_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
-
- void cpu20_mem(address_map &map);
- void cpu_space_map(address_map &map);
-
- required_device<pit68230_device> m_pit;
- required_device<bim68153_device> m_bim;
- required_device<mpcc68561_device> m_mpcc;
- required_device<mpcc68561_device> m_mpcc2;
- required_device<mpcc68561_device> m_mpcc3;
-
- // Pointer to System ROMs needed by bootvect_r and masking RAM buffer for post reset accesses
- uint32_t *m_sysrom;
- uint32_t m_sysram[2];
- void update_irq_to_maincpu();
- const fc_board_t m_board_id;
-};
-
-//**************************************************************************
-// Board Device declarations
-//**************************************************************************
-
-class vme_fccpu20_card_device : public vme_fccpu20_device
-{
-public :
- vme_fccpu20_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- vme_fccpu20_card_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
- : vme_fccpu20_device(mconfig, type, tag, owner, clock, cpu20)
- { }
-
- // optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
-};
-
-class vme_fccpu21s_card_device : public vme_fccpu20_device
-{
-public :
- vme_fccpu21s_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- vme_fccpu21s_card_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
- : vme_fccpu20_device(mconfig, type, tag, owner, clock, cpu21s)
- { }
-
- // optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
-};
-
-class vme_fccpu21_card_device : public vme_fccpu20_device
-{
-public :
- vme_fccpu21_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- vme_fccpu21_card_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
- : vme_fccpu20_device(mconfig, type, tag, owner, clock, cpu21)
- { }
-
- // optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
-};
-
-class vme_fccpu21a_card_device : public vme_fccpu20_device
-{
-public :
- vme_fccpu21a_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- vme_fccpu21a_card_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
- : vme_fccpu20_device(mconfig, type, tag, owner, clock, cpu21a)
- { }
-
- // optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
-};
-
-class vme_fccpu21ya_card_device : public vme_fccpu20_device
-{
-public :
- vme_fccpu21ya_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- vme_fccpu21ya_card_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
- : vme_fccpu20_device(mconfig, type, tag, owner, clock, cpu21ya)
- { }
-
- // optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
-};
-
-class vme_fccpu21b_card_device : public vme_fccpu20_device
-{
-public :
- vme_fccpu21b_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- vme_fccpu21b_card_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
- : vme_fccpu20_device(mconfig, type, tag, owner, clock, cpu21b)
- { }
-
- // optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
-};
-
-class vme_fccpu21yb_card_device : public vme_fccpu20_device
-{
-public :
- vme_fccpu21yb_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- vme_fccpu21yb_card_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
- : vme_fccpu20_device(mconfig, type, tag, owner, clock, cpu21yb)
- { }
-
- // optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
-};
-
-
-#endif // MAME_BUS_VME_VME_FCCPU20_H
diff --git a/src/devices/bus/vme/vme_mzr8105.cpp b/src/devices/bus/vme/vme_mzr8105.cpp
deleted file mode 100644
index fe63e92ee28..00000000000
--- a/src/devices/bus/vme/vme_mzr8105.cpp
+++ /dev/null
@@ -1,70 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Joakim Larsson Edstrom
-
-#include "emu.h"
-#include "vme_mzr8105.h"
-
-#define LOG_GENERAL 0x01
-#define LOG_SETUP 0x02
-#define LOG_PRINTF 0x04
-
-#define VERBOSE 0 // (LOG_PRINTF | LOG_SETUP | LOG_GENERAL)
-
-#define LOGMASK(mask, ...) do { if (VERBOSE & mask) logerror(__VA_ARGS__); } while (0)
-#define LOGLEVEL(mask, level, ...) do { if ((VERBOSE & mask) >= level) logerror(__VA_ARGS__); } while (0)
-
-#define LOG(...) LOGMASK(LOG_GENERAL, __VA_ARGS__)
-#define LOGSETUP(...) LOGMASK(LOG_SETUP, __VA_ARGS__)
-
-#if VERBOSE & LOG_PRINTF
-#define logerror printf
-#endif
-
-#ifdef _MSC_VER
-#define FUNCNAME __func__
-#else
-#define FUNCNAME __PRETTY_FUNCTION__
-#endif
-
-//**************************************************************************
-// GLOBAL VARIABLES
-//**************************************************************************
-
-DEFINE_DEVICE_TYPE(VME_MZR8105, vme_mzr8105_card_device, "mzr8105", "Mizar 8105 68K CPU board")
-
-//-------------------------------------------------
-// device_add_mconfig - add device configuration
-//-------------------------------------------------
-
-void vme_mzr8105_card_device::device_add_mconfig(machine_config &config)
-{
- M68000(config, m_maincpu, XTAL(10'000'000))
- m_maincpu->set_addrmap(AS_PROGRAM, &vme_mzr8105_card_device::mzr8105_mem);
-
- VME(config, "vme", 0).use_owner_spaces();
- VME_SLOT(config, "slot1", mzr8105_vme_cards, "mzr8300", 1, "vme");
-}
-
-vme_mzr8105_card_device::vme_mzr8105_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- vme_mzr8105_card_device(mconfig, VME_MZR8105, tag, owner, clock)
-{
- m_slot = 1;
- LOG("%s %s\n", tag, FUNCNAME);
-}
-
-vme_mzr8105_card_device::vme_mzr8105_card_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, type, tag, owner, clock),
- device_vme_card_interface(mconfig, *this)
-{
- LOG("%s %s\n", tag, FUNCNAME);
-}
-
-void vme_mzr8105_card_device::device_start()
-{
- LOG("%s %s\n", tag(), FUNCNAME);
-}
-
-void vme_mzr8105_card_device::device_reset()
-{
- LOG("%s %s\n", tag(), FUNCNAME);
-}
diff --git a/src/devices/bus/vme/vme_mzr8105.h b/src/devices/bus/vme/vme_mzr8105.h
deleted file mode 100644
index 9d5e371b47f..00000000000
--- a/src/devices/bus/vme/vme_mzr8105.h
+++ /dev/null
@@ -1,27 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Joakim Larsson Edstrom
-#ifndef MAME_BUS_VME_VME_MZR8105_H
-#define MAME_BUS_VME_VME_MZR8105_H
-
-#pragma once
-
-#include "bus/vme/vme.h"
-
-DECLARE_DEVICE_TYPE(VME_MZR8105, vme_mzr8105_card_device)
-
-class vme_mzr8105_card_device : public device_t, public device_vme_card_interface
-{
-public:
- vme_mzr8105_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- vme_mzr8105_card_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
-
- virtual void device_start() override;
- virtual void device_reset() override;
-
- // optional information overrides
- virtual void device_add_mconfig(machine_config &config) override;
-};
-
-#endif // MAME_BUS_VME_VME_MZR8105_H
diff --git a/src/devices/bus/vsmile/vsmile_ctrl.cpp b/src/devices/bus/vsmile/vsmile_ctrl.cpp
index f253e800fab..8fc8e0e678b 100644
--- a/src/devices/bus/vsmile/vsmile_ctrl.cpp
+++ b/src/devices/bus/vsmile/vsmile_ctrl.cpp
@@ -73,9 +73,6 @@ vsmile_ctrl_port_device::~vsmile_ctrl_port_device()
void vsmile_ctrl_port_device::device_resolve_objects()
{
m_device = get_card_device();
-
- m_rts_cb.resolve_safe();
- m_data_cb.resolve_safe();
}
void vsmile_ctrl_port_device::device_start()
diff --git a/src/devices/bus/vsmile/vsmile_slot.cpp b/src/devices/bus/vsmile/vsmile_slot.cpp
index f7a44c3014a..1e743c5f393 100644
--- a/src/devices/bus/vsmile/vsmile_slot.cpp
+++ b/src/devices/bus/vsmile/vsmile_slot.cpp
@@ -44,12 +44,12 @@ device_vsmile_cart_interface::~device_vsmile_cart_interface()
// rom_alloc - alloc the space for the cart
//-------------------------------------------------
-void device_vsmile_cart_interface::rom_alloc(uint32_t size, const char *tag)
+void device_vsmile_cart_interface::rom_alloc(uint32_t size)
{
if (m_rom == nullptr)
{
// We always alloc 8MB of ROM region
- m_rom = (uint16_t *)device().machine().memory().region_alloc(std::string(tag).append(VSMILE_SLOT_ROM_REGION_TAG).c_str(), size, 2, ENDIANNESS_BIG)->base();
+ m_rom = (uint16_t *)device().machine().memory().region_alloc(device().subtag("^cart:rom"), size, 2, ENDIANNESS_BIG)->base();
m_rom_size = size;
}
}
@@ -132,19 +132,16 @@ static int vsmile_get_pcb_id(const char *slot)
call load
-------------------------------------------------*/
-image_init_result vsmile_cart_slot_device::call_load()
+std::pair<std::error_condition, std::string> vsmile_cart_slot_device::call_load()
{
if (m_cart)
{
- uint32_t size = loaded_through_softlist() ? get_software_region_length("rom") : length();
- if (size > 0x1000000)
- {
- seterror(image_error::INVALIDIMAGE, "Attempted loading a cart larger than 16MB");
- return image_init_result::FAIL;
- }
+ uint32_t const size = loaded_through_softlist() ? get_software_region_length("rom") : length();
+ if (size > 0x100'0000)
+ return std::make_pair(image_error::INVALIDLENGTH, "Cartridges larger than 16MB are not supported");
- m_cart->rom_alloc(size, tag());
- uint8_t *rom = (uint8_t *)m_cart->get_rom_base();
+ m_cart->rom_alloc(size);
+ uint8_t *const rom = (uint8_t *)m_cart->get_rom_base();
if (!loaded_through_softlist())
{
@@ -160,23 +157,17 @@ image_init_result vsmile_cart_slot_device::call_load()
if (pcb_name)
m_type = vsmile_get_pcb_id(pcb_name);
- osd_printf_info("V.Smile: Detected (XML) %s\n", pcb_name ? pcb_name : "NONE");
+ osd_printf_verbose("V.Smile: Detected (XML) %s\n", pcb_name ? pcb_name : "NONE");
}
if (m_type == VSMILE_NVRAM)
- {
- m_cart->nvram_alloc(0x200000);
- }
+ m_cart->nvram_alloc(0x20'0000);
if (m_cart->get_nvram_size())
- {
battery_load(m_cart->get_nvram_base(), m_cart->get_nvram_size(), 0x00);
- }
-
- return image_init_result::PASS;
}
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
diff --git a/src/devices/bus/vsmile/vsmile_slot.h b/src/devices/bus/vsmile/vsmile_slot.h
index 910e352db21..627fb8ac4ad 100644
--- a/src/devices/bus/vsmile/vsmile_slot.h
+++ b/src/devices/bus/vsmile/vsmile_slot.h
@@ -12,8 +12,6 @@
TYPE DEFINITIONS
***************************************************************************/
-#define VSMILE_SLOT_ROM_REGION_TAG ":cart:rom"
-
enum
{
VSMILE_STD = 0,
@@ -41,7 +39,7 @@ public:
// banking
virtual void set_cs2(bool cs2) = 0;
- void rom_alloc(uint32_t size, const char *tag);
+ void rom_alloc(uint32_t size);
void nvram_alloc(uint32_t size);
uint16_t* get_rom_base() { return m_rom; }
uint16_t* get_nvram_base() { return &m_nvram[0]; }
@@ -81,15 +79,15 @@ public:
vsmile_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual ~vsmile_cart_slot_device();
- // image-level overrides
- virtual image_init_result call_load() override;
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
virtual void call_unload() override;
virtual bool is_reset_on_load() const noexcept override { return true; }
virtual const char *image_interface() const noexcept override { return "vsmile_cart"; }
virtual const char *file_extensions() const noexcept override { return "u1,u3,bin"; }
- // slot interface overrides
+ // device_slot_interface implementation
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
void save_nvram() { if (m_cart && m_cart->get_nvram_size()) m_cart->save_nvram(); }
@@ -109,11 +107,11 @@ public:
void set_cs2(bool cs2);
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
int m_type;
- device_vsmile_cart_interface* m_cart;
+ device_vsmile_cart_interface *m_cart;
};
// device type definition
diff --git a/src/devices/bus/vtech/ioexp/printer.cpp b/src/devices/bus/vtech/ioexp/printer.cpp
index b5eaa4e8a4b..ba549b22a5e 100644
--- a/src/devices/bus/vtech/ioexp/printer.cpp
+++ b/src/devices/bus/vtech/ioexp/printer.cpp
@@ -80,7 +80,7 @@ void vtech_printer_interface_device::device_start()
// IMPLEMENTATION
//**************************************************************************
-WRITE_LINE_MEMBER( vtech_printer_interface_device::busy_w )
+void vtech_printer_interface_device::busy_w(int state)
{
m_centronics_busy = state;
}
diff --git a/src/devices/bus/vtech/ioexp/printer.h b/src/devices/bus/vtech/ioexp/printer.h
index be25c7fd614..c45dfd9c836 100644
--- a/src/devices/bus/vtech/ioexp/printer.h
+++ b/src/devices/bus/vtech/ioexp/printer.h
@@ -39,7 +39,7 @@ private:
required_device<centronics_device> m_centronics;
required_device<output_latch_device> m_latch;
- DECLARE_WRITE_LINE_MEMBER( busy_w );
+ void busy_w(int state);
uint8_t busy_r();
void strobe_w(uint8_t data);
diff --git a/src/devices/bus/vtech/memexp/floppy.cpp b/src/devices/bus/vtech/memexp/floppy.cpp
index 4e641947aaf..7fdfd30a65a 100644
--- a/src/devices/bus/vtech/memexp/floppy.cpp
+++ b/src/devices/bus/vtech/memexp/floppy.cpp
@@ -11,8 +11,11 @@
#include "emu.h"
#include "floppy.h"
-#include "formats/vt_dsk.h"
+
#include "formats/fs_vtech.h"
+#include "formats/vt_dsk.h"
+
+#include <algorithm>
//**************************************************************************
@@ -82,8 +85,8 @@ void vtech_floppy_controller_device::device_add_mconfig(machine_config &config)
m_memexp->set_memspace(m_mem, AS_PROGRAM);
m_memexp->set_iospace(m_io, AS_PROGRAM);
- FLOPPY_CONNECTOR(config, m_floppy0, laser_floppies, "525", floppy_formats);
- FLOPPY_CONNECTOR(config, m_floppy1, laser_floppies, "525", floppy_formats);
+ for (auto &floppy : m_floppy)
+ FLOPPY_CONNECTOR(config, floppy, laser_floppies, "525", floppy_formats);
}
@@ -98,9 +101,8 @@ void vtech_floppy_controller_device::device_add_mconfig(machine_config &config)
vtech_floppy_controller_device::vtech_floppy_controller_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
vtech_memexp_device(mconfig, VTECH_FLOPPY_CONTROLLER, tag, owner, clock),
m_memexp(*this, "mem"),
- m_floppy0(*this, "0"),
- m_floppy1(*this, "1"),
- m_floppy(nullptr), m_latch(0), m_shifter(0), m_latching_inverter(false), m_current_cyl(0), m_write_position(0)
+ m_floppy(*this, "%u", 0U),
+ m_selected_floppy(nullptr), m_latch(0), m_shifter(0), m_latching_inverter(false), m_current_cyl(0), m_write_position(0)
{
}
@@ -121,7 +123,7 @@ void vtech_floppy_controller_device::device_start()
save_item(NAME(m_write_start_time));
save_item(NAME(m_write_position));
- // TODO: save m_write_buffer and rebuild m_floppy after load
+ // TODO: save m_write_buffer and rebuild m_selected_floppy after load
// Obvious bugs... must have worked by sheer luck and very subtle
// timings. Our current z80 is not subtle enough.
@@ -137,14 +139,14 @@ void vtech_floppy_controller_device::device_start()
void vtech_floppy_controller_device::device_reset()
{
m_latch = 0x00;
- m_floppy = nullptr;
+ m_selected_floppy = nullptr;
m_current_cyl = 0;
m_shifter = 0x00;
m_latching_inverter = false;
m_last_latching_inverter_update_time = machine().time();
m_write_start_time = attotime::never;
m_write_position = 0;
- memset(m_write_buffer, 0, sizeof(m_write_buffer));
+ std::fill(std::begin(m_write_buffer), std::end(m_write_buffer), attotime::zero);
}
@@ -165,26 +167,26 @@ void vtech_floppy_controller_device::latch_w(uint8_t data)
floppy_image_device *newflop = nullptr;
if(m_latch & 0x10)
- newflop = m_floppy0->get_device();
+ newflop = m_floppy[0]->get_device();
else if(m_latch & 0x80)
- newflop = m_floppy1->get_device();
+ newflop = m_floppy[1]->get_device();
- if(newflop != m_floppy) {
+ if(newflop != m_selected_floppy) {
update_latching_inverter();
flush_writes();
- if(m_floppy) {
- m_floppy->mon_w(1);
- m_floppy->setup_index_pulse_cb(floppy_image_device::index_pulse_cb());
+ if(m_selected_floppy) {
+ m_selected_floppy->mon_w(1);
+ m_selected_floppy->setup_index_pulse_cb(floppy_image_device::index_pulse_cb());
}
if(newflop) {
newflop->mon_w(0);
newflop->setup_index_pulse_cb(floppy_image_device::index_pulse_cb(&vtech_floppy_controller_device::index_callback, this));
m_current_cyl = newflop->get_cyl() << 1;
}
- m_floppy = newflop;
+ m_selected_floppy = newflop;
}
- if(m_floppy) {
+ if(m_selected_floppy) {
int cph = m_current_cyl & 3;
int pcyl = m_current_cyl;
if(!(m_latch & (1 << cph))) {
@@ -193,10 +195,10 @@ void vtech_floppy_controller_device::latch_w(uint8_t data)
if(m_current_cyl && (m_latch & (1 << ((cph+3) & 3))))
m_current_cyl--;
if(m_current_cyl != pcyl && !(m_current_cyl & 1)) {
- m_floppy->dir_w(m_current_cyl < pcyl);
- m_floppy->stp_w(true);
- m_floppy->stp_w(false);
- m_floppy->stp_w(true);
+ m_selected_floppy->dir_w(m_current_cyl < pcyl);
+ m_selected_floppy->stp_w(true);
+ m_selected_floppy->stp_w(false);
+ m_selected_floppy->stp_w(true);
}
}
}
@@ -205,8 +207,8 @@ void vtech_floppy_controller_device::latch_w(uint8_t data)
if(!(m_latch & 0x40)) {
m_write_start_time = machine().time();
m_write_position = 0;
- if(m_floppy)
- m_floppy->set_write_splice(m_write_start_time);
+ if(m_selected_floppy)
+ m_selected_floppy->set_write_splice(m_write_start_time);
} else {
update_latching_inverter();
@@ -256,20 +258,20 @@ uint8_t vtech_floppy_controller_device::rd_r()
// Linked to wp signal on bit 7, rest is floating
uint8_t vtech_floppy_controller_device::wpt_r()
{
- return m_floppy && m_floppy->wpt_r() ? 0x80 : 0x00;
+ return m_selected_floppy && m_selected_floppy->wpt_r() ? 0x80 : 0x00;
}
void vtech_floppy_controller_device::update_latching_inverter()
{
attotime now = machine().time();
- if(!m_floppy) {
+ if(!m_selected_floppy) {
m_last_latching_inverter_update_time = now;
return;
}
attotime when = m_last_latching_inverter_update_time;
for(;;) {
- when = m_floppy->get_next_transition(when);
+ when = m_selected_floppy->get_next_transition(when);
if(when == attotime::never || when > now)
break;
m_latching_inverter = !m_latching_inverter;
@@ -285,7 +287,7 @@ void vtech_floppy_controller_device::index_callback(floppy_image_device *floppy,
void vtech_floppy_controller_device::flush_writes(bool keep_margin)
{
- if(!m_floppy || m_write_start_time == attotime::never)
+ if(!m_selected_floppy || m_write_start_time == attotime::never)
return;
// Beware of time travel. Index pulse callback (which flushes)
@@ -310,13 +312,13 @@ void vtech_floppy_controller_device::flush_writes(bool keep_margin)
m_write_position -= kept_count;
if(m_write_position && m_write_buffer[0] == m_write_start_time) {
if(m_write_position)
- memmove(m_write_buffer, m_write_buffer+1, sizeof(m_write_buffer[0])*(m_write_position-1));
+ std::copy_n(m_write_buffer + 1, m_write_position - 1, m_write_buffer);
m_write_position--;
}
- m_floppy->write_flux(m_write_start_time, limit, m_write_position, m_write_buffer);
+ m_selected_floppy->write_flux(m_write_start_time, limit, m_write_position, m_write_buffer);
m_write_start_time = limit;
if(kept_count != 0)
- memmove(m_write_buffer, m_write_buffer+kept_pos, kept_count*sizeof(m_write_buffer[0]));
+ std::copy_n(m_write_buffer + kept_pos, kept_count, m_write_buffer);
m_write_position = kept_count;
}
diff --git a/src/devices/bus/vtech/memexp/floppy.h b/src/devices/bus/vtech/memexp/floppy.h
index 167cbf5ba63..df208c0ef0a 100644
--- a/src/devices/bus/vtech/memexp/floppy.h
+++ b/src/devices/bus/vtech/memexp/floppy.h
@@ -41,8 +41,8 @@ protected:
private:
required_device<vtech_memexp_slot_device> m_memexp;
- required_device<floppy_connector> m_floppy0, m_floppy1;
- floppy_image_device *m_floppy;
+ required_device_array<floppy_connector, 2> m_floppy;
+ floppy_image_device *m_selected_floppy;
static void floppy_formats(format_registration &fr);
diff --git a/src/devices/bus/vtech/memexp/memexp.cpp b/src/devices/bus/vtech/memexp/memexp.cpp
index 74d2213009a..984849fe9ab 100644
--- a/src/devices/bus/vtech/memexp/memexp.cpp
+++ b/src/devices/bus/vtech/memexp/memexp.cpp
@@ -86,11 +86,6 @@ void vtech_memexp_slot_device::device_start()
m_module->iorq_w(offset, data);
}
);
-
- // resolve callbacks
- m_int_handler.resolve_safe();
- m_nmi_handler.resolve_safe();
- m_reset_handler.resolve_safe();
}
diff --git a/src/devices/bus/vtech/memexp/memexp.h b/src/devices/bus/vtech/memexp/memexp.h
index 5fd3ee6a449..6dc44bdba25 100644
--- a/src/devices/bus/vtech/memexp/memexp.h
+++ b/src/devices/bus/vtech/memexp/memexp.h
@@ -73,9 +73,9 @@ public:
auto reset_handler() { return m_reset_handler.bind(); }
// called from cart device
- DECLARE_WRITE_LINE_MEMBER( int_w ) { m_int_handler(state); }
- DECLARE_WRITE_LINE_MEMBER( nmi_w ) { m_nmi_handler(state); }
- DECLARE_WRITE_LINE_MEMBER( reset_w ) { m_reset_handler(state); }
+ void int_w(int state) { m_int_handler(state); }
+ void nmi_w(int state) { m_nmi_handler(state); }
+ void reset_w(int state) { m_reset_handler(state); }
protected:
// device-level overrides
diff --git a/src/devices/bus/vtech/memexp/sdloader.cpp b/src/devices/bus/vtech/memexp/sdloader.cpp
index 84df085c86a..5992c66cb49 100644
--- a/src/devices/bus/vtech/memexp/sdloader.cpp
+++ b/src/devices/bus/vtech/memexp/sdloader.cpp
@@ -21,7 +21,6 @@
#include "emu.h"
#include "sdloader.h"
-#define LOG_GENERAL (1U << 0)
#define LOG_SPI (1U << 1)
#define VERBOSE (LOG_GENERAL)
#include "logmacro.h"
diff --git a/src/devices/bus/wangpc/lvc.cpp b/src/devices/bus/wangpc/lvc.cpp
index 2eb45e47db0..66b86493051 100644
--- a/src/devices/bus/wangpc/lvc.cpp
+++ b/src/devices/bus/wangpc/lvc.cpp
@@ -104,7 +104,7 @@ MC6845_UPDATE_ROW( wangpc_lvc_device::crtc_update_row )
}
}
-WRITE_LINE_MEMBER( wangpc_lvc_device::vsync_w )
+void wangpc_lvc_device::vsync_w(int state)
{
if (OPTION_VSYNC && state)
{
diff --git a/src/devices/bus/wangpc/lvc.h b/src/devices/bus/wangpc/lvc.h
index 7f0cb5ac816..48e271f91ef 100644
--- a/src/devices/bus/wangpc/lvc.h
+++ b/src/devices/bus/wangpc/lvc.h
@@ -43,7 +43,7 @@ protected:
private:
MC6845_UPDATE_ROW( crtc_update_row );
- DECLARE_WRITE_LINE_MEMBER( vsync_w );
+ void vsync_w(int state);
inline void set_irq(int state);
diff --git a/src/devices/bus/wangpc/mvc.cpp b/src/devices/bus/wangpc/mvc.cpp
index 12aae997900..65985890f82 100644
--- a/src/devices/bus/wangpc/mvc.cpp
+++ b/src/devices/bus/wangpc/mvc.cpp
@@ -126,7 +126,7 @@ MC6845_UPDATE_ROW( wangpc_mvc_device::crtc_update_row )
}
}
-WRITE_LINE_MEMBER( wangpc_mvc_device::vsync_w )
+void wangpc_mvc_device::vsync_w(int state)
{
if (OPTION_VSYNC && state)
{
diff --git a/src/devices/bus/wangpc/mvc.h b/src/devices/bus/wangpc/mvc.h
index 9911952f6ac..9e0d6cd5b44 100644
--- a/src/devices/bus/wangpc/mvc.h
+++ b/src/devices/bus/wangpc/mvc.h
@@ -43,7 +43,7 @@ protected:
private:
MC6845_UPDATE_ROW( crtc_update_row );
- DECLARE_WRITE_LINE_MEMBER( vsync_w );
+ void vsync_w(int state);
inline void set_irq(int state);
diff --git a/src/devices/bus/wangpc/wangpc.cpp b/src/devices/bus/wangpc/wangpc.cpp
index 7f209465d2d..c03f84d9372 100644
--- a/src/devices/bus/wangpc/wangpc.cpp
+++ b/src/devices/bus/wangpc/wangpc.cpp
@@ -41,7 +41,7 @@ wangpcbus_slot_device::wangpcbus_slot_device(const machine_config &mconfig, cons
void wangpcbus_slot_device::device_start()
{
- device_wangpcbus_card_interface *dev = get_card_device();
+ device_wangpcbus_card_interface *const dev = get_card_device();
if (dev)
m_bus->add_card(*dev, m_sid);
}
@@ -66,6 +66,10 @@ wangpcbus_device::wangpcbus_device(const machine_config &mconfig, const char *ta
{
}
+wangpcbus_device::~wangpcbus_device()
+{
+}
+
//-------------------------------------------------
// device_start - device-specific startup
@@ -73,17 +77,6 @@ wangpcbus_device::wangpcbus_device(const machine_config &mconfig, const char *ta
void wangpcbus_device::device_start()
{
- // resolve callbacks
- m_write_irq2.resolve_safe();
- m_write_irq3.resolve_safe();
- m_write_irq4.resolve_safe();
- m_write_irq5.resolve_safe();
- m_write_irq6.resolve_safe();
- m_write_irq7.resolve_safe();
- m_write_drq1.resolve_safe();
- m_write_drq2.resolve_safe();
- m_write_drq3.resolve_safe();
- m_write_ioerror.resolve_safe();
}
@@ -93,7 +86,7 @@ void wangpcbus_device::device_start()
void wangpcbus_device::add_card(device_wangpcbus_card_interface &card, int sid)
{
- m_device_list.append(card);
+ m_device_list.emplace_back(card);
card.m_bus = this;
card.m_sid = sid;
@@ -108,13 +101,8 @@ uint16_t wangpcbus_device::mrdc_r(offs_t offset, uint16_t mem_mask)
{
uint16_t data = 0xffff;
- device_wangpcbus_card_interface *entry = m_device_list.first();
-
- while (entry)
- {
- data &= entry->wangpcbus_mrdc_r(offset + 0x40000/2, mem_mask);
- entry = entry->next();
- }
+ for (device_wangpcbus_card_interface &entry : m_device_list)
+ data &= entry.wangpcbus_mrdc_r(offset + 0x40000/2, mem_mask);
return data;
}
@@ -126,13 +114,8 @@ uint16_t wangpcbus_device::mrdc_r(offs_t offset, uint16_t mem_mask)
void wangpcbus_device::amwc_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
- device_wangpcbus_card_interface *entry = m_device_list.first();
-
- while (entry)
- {
- entry->wangpcbus_amwc_w(offset + 0x40000/2, mem_mask, data);
- entry = entry->next();
- }
+ for (device_wangpcbus_card_interface &entry : m_device_list)
+ entry.wangpcbus_amwc_w(offset + 0x40000/2, mem_mask, data);
}
@@ -144,13 +127,8 @@ uint16_t wangpcbus_device::sad_r(offs_t offset, uint16_t mem_mask)
{
uint16_t data = 0xffff;
- device_wangpcbus_card_interface *entry = m_device_list.first();
-
- while (entry)
- {
- data &= entry->wangpcbus_iorc_r(offset + 0x1100/2, mem_mask);
- entry = entry->next();
- }
+ for (device_wangpcbus_card_interface &entry : m_device_list)
+ data &= entry.wangpcbus_iorc_r(offset + 0x1100/2, mem_mask);
return data;
}
@@ -162,13 +140,8 @@ uint16_t wangpcbus_device::sad_r(offs_t offset, uint16_t mem_mask)
void wangpcbus_device::sad_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
- device_wangpcbus_card_interface *entry = m_device_list.first();
-
- while (entry)
- {
- entry->wangpcbus_aiowc_w(offset + 0x1100/2, mem_mask, data);
- entry = entry->next();
- }
+ for (device_wangpcbus_card_interface &entry : m_device_list)
+ entry.wangpcbus_aiowc_w(offset + 0x1100/2, mem_mask, data);
}
@@ -179,17 +152,14 @@ void wangpcbus_device::sad_w(offs_t offset, uint16_t data, uint16_t mem_mask)
uint8_t wangpcbus_device::dack_r(int line)
{
uint8_t retVal = 0xff;
- device_wangpcbus_card_interface *entry = m_device_list.first();
- while (entry)
+ for (device_wangpcbus_card_interface &entry : m_device_list)
{
- if (entry->wangpcbus_have_dack(line))
+ if (entry.wangpcbus_have_dack(line))
{
- retVal = entry->wangpcbus_dack_r(line);
+ retVal = entry.wangpcbus_dack_r(line);
break;
}
-
- entry = entry->next();
}
return retVal;
@@ -202,16 +172,10 @@ uint8_t wangpcbus_device::dack_r(int line)
void wangpcbus_device::dack_w(int line, uint8_t data)
{
- device_wangpcbus_card_interface *entry = m_device_list.first();
-
- while (entry)
+ for (device_wangpcbus_card_interface &entry : m_device_list)
{
- if (entry->wangpcbus_have_dack(line))
- {
- entry->wangpcbus_dack_w(line, data);
- }
-
- entry = entry->next();
+ if (entry.wangpcbus_have_dack(line))
+ entry.wangpcbus_dack_w(line, data);
}
}
@@ -220,15 +184,10 @@ void wangpcbus_device::dack_w(int line, uint8_t data)
// tc_w - terminal count
//-------------------------------------------------
-WRITE_LINE_MEMBER( wangpcbus_device::tc_w )
+void wangpcbus_device::tc_w(int state)
{
- device_wangpcbus_card_interface *entry = m_device_list.first();
-
- while (entry)
- {
- entry->wangpcbus_tc_w(state);
- entry = entry->next();
- }
+ for (device_wangpcbus_card_interface &entry : m_device_list)
+ entry.wangpcbus_tc_w(state);
}
@@ -242,9 +201,11 @@ WRITE_LINE_MEMBER( wangpcbus_device::tc_w )
//-------------------------------------------------
device_wangpcbus_card_interface::device_wangpcbus_card_interface(const machine_config &mconfig, device_t &device) :
- device_interface(device, "wangpcbus"), m_bus(nullptr), m_sid(0), m_next(nullptr)
+ device_interface(device, "wangpcbus"),
+ m_bus(nullptr),
+ m_slot(dynamic_cast<wangpcbus_slot_device *>(device.owner())),
+ m_sid(0)
{
- m_slot = dynamic_cast<wangpcbus_slot_device *>(device.owner());
}
diff --git a/src/devices/bus/wangpc/wangpc.h b/src/devices/bus/wangpc/wangpc.h
index 05ca1908f75..8da788e1398 100644
--- a/src/devices/bus/wangpc/wangpc.h
+++ b/src/devices/bus/wangpc/wangpc.h
@@ -14,6 +14,8 @@
#pragma once
+#include <functional>
+#include <vector>
@@ -49,7 +51,7 @@ public:
void set_bus_slot(int sid) { m_sid = sid; }
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
private:
@@ -70,7 +72,7 @@ class wangpcbus_device : public device_t
public:
// construction/destruction
wangpcbus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- ~wangpcbus_device() { m_device_list.detach_all(); }
+ ~wangpcbus_device();
auto irq2_wr_callback() { return m_write_irq2.bind(); }
auto irq3_wr_callback() { return m_write_irq3.bind(); }
@@ -104,25 +106,27 @@ public:
uint8_t dack3_r() { return dack_r(3); }
void dack3_w(uint8_t data) { dack_w(3, data); }
- DECLARE_WRITE_LINE_MEMBER( tc_w );
+ void tc_w(int state);
// peripheral interface
- DECLARE_WRITE_LINE_MEMBER( irq2_w ) { m_write_irq2(state); }
- DECLARE_WRITE_LINE_MEMBER( irq3_w ) { m_write_irq3(state); }
- DECLARE_WRITE_LINE_MEMBER( irq4_w ) { m_write_irq4(state); }
- DECLARE_WRITE_LINE_MEMBER( irq5_w ) { m_write_irq5(state); }
- DECLARE_WRITE_LINE_MEMBER( irq6_w ) { m_write_irq6(state); }
- DECLARE_WRITE_LINE_MEMBER( irq7_w ) { m_write_irq7(state); }
- DECLARE_WRITE_LINE_MEMBER( drq1_w ) { m_write_drq1(state); }
- DECLARE_WRITE_LINE_MEMBER( drq2_w ) { m_write_drq2(state); }
- DECLARE_WRITE_LINE_MEMBER( drq3_w ) { m_write_drq3(state); }
- DECLARE_WRITE_LINE_MEMBER( ioerror_w ) { m_write_ioerror(state); }
+ void irq2_w(int state) { m_write_irq2(state); }
+ void irq3_w(int state) { m_write_irq3(state); }
+ void irq4_w(int state) { m_write_irq4(state); }
+ void irq5_w(int state) { m_write_irq5(state); }
+ void irq6_w(int state) { m_write_irq6(state); }
+ void irq7_w(int state) { m_write_irq7(state); }
+ void drq1_w(int state) { m_write_drq1(state); }
+ void drq2_w(int state) { m_write_drq2(state); }
+ void drq3_w(int state) { m_write_drq3(state); }
+ void ioerror_w(int state) { m_write_ioerror(state); }
protected:
- // device-level overrides
+ // devicedevice_t implementation
virtual void device_start() override;
private:
+ using card_vector = std::vector<std::reference_wrapper<device_wangpcbus_card_interface> >;
+
devcb_write_line m_write_irq2;
devcb_write_line m_write_irq3;
devcb_write_line m_write_irq4;
@@ -134,7 +138,7 @@ private:
devcb_write_line m_write_drq3;
devcb_write_line m_write_ioerror;
- simple_list<device_wangpcbus_card_interface> m_device_list;
+ card_vector m_device_list;
};
@@ -148,11 +152,8 @@ DECLARE_DEVICE_TYPE(WANGPC_BUS, wangpcbus_device)
class device_wangpcbus_card_interface : public device_interface
{
friend class wangpcbus_device;
- template <class ElementType> friend class simple_list;
public:
- device_wangpcbus_card_interface *next() const { return m_next; }
-
// memory access
virtual uint16_t wangpcbus_mrdc_r(offs_t offset, uint16_t mem_mask) { return 0; }
virtual void wangpcbus_amwc_w(offs_t offset, uint16_t mem_mask, uint16_t data) { }
@@ -175,12 +176,9 @@ protected:
virtual void interface_pre_start() override;
wangpcbus_device *m_bus;
- wangpcbus_slot_device *m_slot;
+ wangpcbus_slot_device *const m_slot;
int m_sid;
-
-private:
- device_wangpcbus_card_interface *m_next;
};
diff --git a/src/devices/bus/waveblaster/db50xg.cpp b/src/devices/bus/waveblaster/db50xg.cpp
new file mode 100644
index 00000000000..76cf8a47330
--- /dev/null
+++ b/src/devices/bus/waveblaster/db50xg.cpp
@@ -0,0 +1,104 @@
+// license:BSD-3-Clause
+// copyright-holders: Olivier Galibert
+
+// Yamaha DB50XG
+
+// PCB name: XQ791
+
+// It's in large part a mu50 on a board, same swp00, same wave ROMs.
+// CPU and program are different though, and obviously there's no
+// LCD. There are also no analog inputs, which were half-assed in the
+// mu50 anyway.
+
+#include "emu.h"
+#include "db50xg.h"
+
+#include "cpu/h8/h83002.h"
+#include "sound/swp00.h"
+
+
+namespace {
+
+class db50xg_device : public device_t, public device_waveblaster_interface
+{
+public:
+ db50xg_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
+ virtual ~db50xg_device();
+
+ virtual void midi_rx(int state) override;
+
+protected:
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override;
+
+private:
+ required_device<h83002_device> m_cpu;
+ required_device<swp00_device> m_swp00;
+
+ void map(address_map &map);
+};
+
+db50xg_device::db50xg_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, DB50XG, tag, owner, clock),
+ device_waveblaster_interface(mconfig, *this),
+ m_cpu(*this, "cpu"),
+ m_swp00(*this, "swp00")
+{
+}
+
+db50xg_device::~db50xg_device()
+{
+}
+
+void db50xg_device::midi_rx(int state)
+{
+ m_cpu->sci_rx_w<0>(state);
+}
+
+void db50xg_device::map(address_map &map)
+{
+ map(0x000000, 0x07ffff).rom().region("cpu", 0);
+ map(0x400000, 0x4007ff).m(m_swp00, FUNC(swp00_device::map));
+ map(0x600000, 0x607fff).ram();
+}
+
+void db50xg_device::device_add_mconfig(machine_config &config)
+{
+ H83002(config, m_cpu, 12_MHz_XTAL);
+ m_cpu->set_addrmap(AS_PROGRAM, &db50xg_device::map);
+ m_cpu->write_sci_tx<0>().set([this] (int state) { m_connector->do_midi_tx(state); });
+
+ SWP00(config, m_swp00);
+ m_swp00->add_route(0, DEVICE_SELF_OWNER, 1.0, AUTO_ALLOC_INPUT, 0);
+ m_swp00->add_route(1, DEVICE_SELF_OWNER, 1.0, AUTO_ALLOC_INPUT, 1);
+}
+
+ROM_START( db50xg )
+ ROM_REGION( 0x80000, "cpu", 0 )
+ ROM_LOAD16_WORD_SWAP( "xr253a0.ic7", 0x000000, 0x080000, CRC(6c2a2c49) SHA1(61a80e066c7ff40dcba01b796d9faff3b9952a5b) )
+
+ ROM_REGION( 0x400000, "swp00", 0 )
+ ROM_LOAD( "xq730b0.ic9", 0x000000, 0x200000, CRC(d4adbc7e) SHA1(32f653c7644d060f5a6d63a435ae3a7412386d92) )
+ ROM_LOAD( "xq731b0.ic10", 0x200000, 0x200000, CRC(7b68f475) SHA1(adf68689b4842ec5bc9b0ea1bb99cf66d2dec4de) )
+ROM_END
+
+void db50xg_device::device_start()
+{
+}
+
+void db50xg_device::device_reset()
+{
+ // Active-low, wired to gnd
+ m_cpu->set_input_line(0, ASSERT_LINE);
+}
+
+const tiny_rom_entry *db50xg_device::device_rom_region() const
+{
+ return ROM_NAME(db50xg);
+}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(DB50XG, device_waveblaster_interface, db50xg_device, "db50xg", "Yamaha DB50XG")
diff --git a/src/devices/bus/waveblaster/db50xg.h b/src/devices/bus/waveblaster/db50xg.h
new file mode 100644
index 00000000000..8f6779db170
--- /dev/null
+++ b/src/devices/bus/waveblaster/db50xg.h
@@ -0,0 +1,15 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+
+#ifndef MAME_BUS_WAVEBLASTER_DB50XG_H
+#define MAME_BUS_WAVEBLASTER_DB50XG_H
+
+// Yamaha DB50XG
+
+#pragma once
+
+#include "waveblaster.h"
+
+DECLARE_DEVICE_TYPE(DB50XG, device_waveblaster_interface)
+
+#endif // MAME_BUS_WAVEBLASTER_DB50XG_H
diff --git a/src/devices/bus/waveblaster/db60xg.cpp b/src/devices/bus/waveblaster/db60xg.cpp
new file mode 100644
index 00000000000..8ccd724e320
--- /dev/null
+++ b/src/devices/bus/waveblaster/db60xg.cpp
@@ -0,0 +1,102 @@
+// license:BSD-3-Clause
+// copyright-holders: Olivier Galibert
+
+// Yamaha DB60XG / NEC XR385
+
+// PCB name: XR712, XR385 (NEC)
+
+// It's a revision of the db50xg which brings the half-assed analog
+// input back and has a system program upgrade. The NEC variant is in fact identical
+
+#include "emu.h"
+#include "db60xg.h"
+
+#include "cpu/h8/h83002.h"
+#include "sound/swp00.h"
+
+
+namespace {
+
+class db60xg_device : public device_t, public device_waveblaster_interface
+{
+public:
+ db60xg_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
+ virtual ~db60xg_device();
+
+ virtual void midi_rx(int state) override;
+
+protected:
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override;
+
+private:
+ required_device<h83002_device> m_cpu;
+ required_device<swp00_device> m_swp00;
+
+ void map(address_map &map);
+};
+
+db60xg_device::db60xg_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, DB60XG, tag, owner, clock),
+ device_waveblaster_interface(mconfig, *this),
+ m_cpu(*this, "cpu"),
+ m_swp00(*this, "swp00")
+{
+}
+
+db60xg_device::~db60xg_device()
+{
+}
+
+void db60xg_device::midi_rx(int state)
+{
+ m_cpu->sci_rx_w<0>(state);
+}
+
+void db60xg_device::map(address_map &map)
+{
+ map(0x000000, 0x07ffff).rom().region("cpu", 0);
+ map(0x400000, 0x4007ff).m(m_swp00, FUNC(swp00_device::map));
+ map(0x600000, 0x607fff).ram();
+}
+
+void db60xg_device::device_add_mconfig(machine_config &config)
+{
+ H83002(config, m_cpu, 12_MHz_XTAL);
+ m_cpu->set_addrmap(AS_PROGRAM, &db60xg_device::map);
+ m_cpu->write_sci_tx<0>().set([this] (int state) { m_connector->do_midi_tx(state); });
+
+ SWP00(config, m_swp00);
+ m_swp00->add_route(0, DEVICE_SELF_OWNER, 1.0, AUTO_ALLOC_INPUT, 0);
+ m_swp00->add_route(1, DEVICE_SELF_OWNER, 1.0, AUTO_ALLOC_INPUT, 1);
+}
+
+ROM_START( db60xg )
+ ROM_REGION( 0x80000, "cpu", 0 )
+ ROM_LOAD16_WORD_SWAP( "xr560b0.ic7", 0x000000, 0x080000, CRC(d9cad989) SHA1(d17e4ac0fc0e50a06d9d505bc87af155356436eb) )
+
+ ROM_REGION( 0x400000, "swp00", 0 )
+ ROM_LOAD( "xq730b0.ic9", 0x000000, 0x200000, CRC(d4adbc7e) SHA1(32f653c7644d060f5a6d63a435ae3a7412386d92) )
+ ROM_LOAD( "xq731b0.ic10", 0x200000, 0x200000, CRC(7b68f475) SHA1(adf68689b4842ec5bc9b0ea1bb99cf66d2dec4de) )
+ROM_END
+
+void db60xg_device::device_start()
+{
+}
+
+void db60xg_device::device_reset()
+{
+ // Active-low, wired to gnd
+ m_cpu->set_input_line(0, ASSERT_LINE);
+}
+
+const tiny_rom_entry *db60xg_device::device_rom_region() const
+{
+ return ROM_NAME(db60xg);
+}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(DB60XG, device_waveblaster_interface, db60xg_device, "db60xg", "Yamaha DB60XG")
diff --git a/src/devices/bus/waveblaster/db60xg.h b/src/devices/bus/waveblaster/db60xg.h
new file mode 100644
index 00000000000..4cbcbc5a14e
--- /dev/null
+++ b/src/devices/bus/waveblaster/db60xg.h
@@ -0,0 +1,15 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+
+#ifndef MAME_BUS_WAVEBLASTER_DB60XG_H
+#define MAME_BUS_WAVEBLASTER_DB60XG_H
+
+// Yamaha DB60XG / NEC XR385
+
+#pragma once
+
+#include "waveblaster.h"
+
+DECLARE_DEVICE_TYPE(DB60XG, device_waveblaster_interface)
+
+#endif // MAME_BUS_WAVEBLASTER_DB60XG_H
diff --git a/src/devices/bus/waveblaster/omniwave.cpp b/src/devices/bus/waveblaster/omniwave.cpp
new file mode 100644
index 00000000000..913c85a6d38
--- /dev/null
+++ b/src/devices/bus/waveblaster/omniwave.cpp
@@ -0,0 +1,71 @@
+// license:BSD-3-Clause
+// copyright-holders: Olivier Galibert
+
+// Samsung Omniwave
+
+#include "emu.h"
+#include "omniwave.h"
+
+#include "sound/ks0164.h"
+
+
+namespace {
+
+class omniwave_device : public device_t, public device_waveblaster_interface
+{
+public:
+ omniwave_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
+ virtual ~omniwave_device();
+
+ virtual void midi_rx(int state) override;
+
+protected:
+ virtual void device_start() override;
+ const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override;
+
+private:
+ required_device<ks0164_device> m_ks0164;
+};
+
+omniwave_device::omniwave_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, OMNIWAVE, tag, owner, clock),
+ device_waveblaster_interface(mconfig, *this),
+ m_ks0164(*this, "ks0164")
+{
+}
+
+omniwave_device::~omniwave_device()
+{
+}
+
+void omniwave_device::midi_rx(int state)
+{
+ m_ks0164->midi_rx(state);
+}
+
+void omniwave_device::device_add_mconfig(machine_config &config)
+{
+ KS0164(config, m_ks0164, 16.9344_MHz_XTAL);
+ m_ks0164->add_route(0, DEVICE_SELF_OWNER, 1.0, AUTO_ALLOC_INPUT, 0);
+ m_ks0164->add_route(1, DEVICE_SELF_OWNER, 1.0, AUTO_ALLOC_INPUT, 1);
+ m_ks0164->midi_tx().set([this] (int state) { m_connector->do_midi_tx(state); });
+}
+
+ROM_START( omniwave )
+ ROM_REGION16_BE( 0x100000, "ks0164", 0)
+ ROM_LOAD16_WORD_SWAP("ks0174-1m04.bin", 0, 0x100000, CRC(3cabaa2f) SHA1(1e894c0345eaf0ea713f36a75b065f7ee419c63c))
+ROM_END
+
+void omniwave_device::device_start()
+{
+}
+
+const tiny_rom_entry *omniwave_device::device_rom_region() const
+{
+ return ROM_NAME(omniwave);
+}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(OMNIWAVE, device_waveblaster_interface, omniwave_device, "omniwave", "Samsung Omniwave")
diff --git a/src/devices/bus/waveblaster/omniwave.h b/src/devices/bus/waveblaster/omniwave.h
new file mode 100644
index 00000000000..6196ff561dd
--- /dev/null
+++ b/src/devices/bus/waveblaster/omniwave.h
@@ -0,0 +1,15 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+
+#ifndef MAME_BUS_WAVEBLASTER_OMNIWAVE_H
+#define MAME_BUS_WAVEBLASTER_OMNIWAVE_H
+
+// Samsung Omniwave
+
+#pragma once
+
+#include "waveblaster.h"
+
+DECLARE_DEVICE_TYPE(OMNIWAVE, device_waveblaster_interface)
+
+#endif // MAME_BUS_WAVEBLASTER_OMNIWAVE_H
diff --git a/src/devices/bus/waveblaster/waveblaster.cpp b/src/devices/bus/waveblaster/waveblaster.cpp
new file mode 100644
index 00000000000..c280a2fd083
--- /dev/null
+++ b/src/devices/bus/waveblaster/waveblaster.cpp
@@ -0,0 +1,56 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+
+#include "emu.h"
+#include "waveblaster.h"
+
+#include "omniwave.h"
+#include "db50xg.h"
+#include "db60xg.h"
+#include "wg130.h"
+
+
+DEFINE_DEVICE_TYPE(WAVEBLASTER_CONNECTOR, waveblaster_connector, "waveblaster_connector", "Waveblaster extension connector")
+
+waveblaster_connector::waveblaster_connector(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, WAVEBLASTER_CONNECTOR, tag, owner, clock),
+ device_single_card_slot_interface<device_waveblaster_interface>(mconfig, *this),
+ device_mixer_interface(mconfig, *this, 2),
+ m_midi_tx(*this)
+{
+}
+
+void waveblaster_connector::device_start()
+{
+ save_item(NAME(m_state_system_is_annoying));
+}
+
+void waveblaster_connector::midi_rx(int state)
+{
+ auto card = get_card_device();
+ if(card)
+ card->midi_rx(state);
+}
+
+void waveblaster_intf(device_slot_interface &device)
+{
+ device.option_add("omniwave", OMNIWAVE);
+ device.option_add("db50xg", DB50XG);
+ device.option_add("db60xg", DB60XG);
+ device.option_add("wg130", WG130);
+}
+
+device_waveblaster_interface::device_waveblaster_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "waveblaster"),
+ m_connector(nullptr)
+{
+}
+
+device_waveblaster_interface::~device_waveblaster_interface()
+{
+}
+
+void device_waveblaster_interface::interface_pre_start()
+{
+ m_connector = downcast<waveblaster_connector *>(device().owner());
+}
diff --git a/src/devices/bus/waveblaster/waveblaster.h b/src/devices/bus/waveblaster/waveblaster.h
new file mode 100644
index 00000000000..342dfce9bcc
--- /dev/null
+++ b/src/devices/bus/waveblaster/waveblaster.h
@@ -0,0 +1,60 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+
+// Waveblaster midi extension cards
+
+#ifndef MAME_BUS_WAVEBLASTER_WAVEBLASTER_H
+#define MAME_BUS_WAVEBLASTER_WAVEBLASTER_H
+
+#pragma once
+
+class device_waveblaster_interface;
+
+class waveblaster_connector: public device_t, public device_single_card_slot_interface<device_waveblaster_interface>, public device_mixer_interface
+{
+public:
+ template <typename T>
+ waveblaster_connector(const machine_config &mconfig, const char *tag, device_t *owner, T &&opts, const char *dflt)
+ : waveblaster_connector(mconfig, tag, owner, (uint32_t)0)
+ {
+ option_reset();
+ opts(*this);
+ set_default_option(dflt);
+ set_fixed(false);
+ }
+
+ waveblaster_connector(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ void midi_rx(int state);
+ auto midi_tx() { return m_midi_tx.bind(); }
+
+ void do_midi_tx(int state) { m_midi_tx(state); }
+
+protected:
+ bool m_state_system_is_annoying = true;
+ devcb_write_line m_midi_tx;
+
+ virtual void device_start() override;
+};
+
+class device_waveblaster_interface: public device_interface
+{
+public:
+ virtual ~device_waveblaster_interface();
+
+ virtual void midi_rx(int state) = 0;
+
+protected:
+ waveblaster_connector *m_connector;
+
+ device_waveblaster_interface(const machine_config &mconfig, device_t &device);
+
+ virtual void interface_pre_start() override;
+};
+
+DECLARE_DEVICE_TYPE(WAVEBLASTER_CONNECTOR, waveblaster_connector)
+
+void waveblaster_intf(device_slot_interface &device);
+
+#endif // MAME_BUS_WAVEBLASTER_WAVEBLASTER_H
+
diff --git a/src/devices/bus/waveblaster/wg130.cpp b/src/devices/bus/waveblaster/wg130.cpp
new file mode 100644
index 00000000000..385a39581f3
--- /dev/null
+++ b/src/devices/bus/waveblaster/wg130.cpp
@@ -0,0 +1,117 @@
+// license:BSD-3-Clause
+// copyright-holders: Devin Acker
+/*
+ Casio WG-130
+
+ This is the daughterboard version of the GZ-30M and GZ-70SP modules, using the same ROM.
+*/
+#include "emu.h"
+#include "wg130.h"
+
+#include "cpu/h8/gt913.h"
+
+
+namespace {
+
+class wg130_device : public device_t, public device_waveblaster_interface
+{
+public:
+ wg130_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
+ virtual ~wg130_device();
+
+ virtual void midi_rx(int state) override;
+
+protected:
+ virtual void device_start() override;
+ const tiny_rom_entry *device_rom_region() const override;
+ virtual ioport_constructor device_input_ports() const override;
+ virtual void device_add_mconfig(machine_config &config) override;
+
+private:
+ required_device<gt913_device> m_gt913;
+
+ void map(address_map &map);
+};
+
+INPUT_PORTS_START(wg130)
+ PORT_START("gt913:kbd:FI0")
+ PORT_START("gt913:kbd:FI1")
+ PORT_START("gt913:kbd:FI2")
+ PORT_START("gt913:kbd:FI3")
+ PORT_START("gt913:kbd:FI4")
+ PORT_START("gt913:kbd:FI5")
+ PORT_START("gt913:kbd:FI6")
+ PORT_START("gt913:kbd:FI7")
+ PORT_START("gt913:kbd:FI8")
+ PORT_START("gt913:kbd:FI9")
+ PORT_START("gt913:kbd:FI10")
+ PORT_START("gt913:kbd:KI0")
+ PORT_START("gt913:kbd:KI1")
+ PORT_START("gt913:kbd:KI2")
+INPUT_PORTS_END
+
+wg130_device::wg130_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, WG130, tag, owner, clock),
+ device_waveblaster_interface(mconfig, *this),
+ m_gt913(*this, "gt913")
+{
+}
+
+wg130_device::~wg130_device()
+{
+}
+
+void wg130_device::midi_rx(int state)
+{
+ m_gt913->sci_rx_w<1>(state);
+}
+
+void wg130_device::map(address_map &map)
+{
+ map(0x000000, 0x1fffff).rom().region("gt913", 0);
+ map(0x300000, 0x301fff).ram().mirror(0x07e000);
+ map(0x380000, 0x380003).noprw(); // DSP is mapped here, but not actually present
+}
+
+void wg130_device::device_add_mconfig(machine_config &config)
+{
+ GT913(config, m_gt913, 30_MHz_XTAL / 2);
+ m_gt913->set_addrmap(AS_DATA, &wg130_device::map);
+ m_gt913->add_route(0, DEVICE_SELF_OWNER, 1.0, AUTO_ALLOC_INPUT, 0);
+ m_gt913->add_route(1, DEVICE_SELF_OWNER, 1.0, AUTO_ALLOC_INPUT, 1);
+ m_gt913->read_port1().set_constant(0xff);
+ m_gt913->write_port1().set_nop();
+ m_gt913->read_port2().set_constant(0xff);
+ m_gt913->write_port2().set_nop();
+ m_gt913->write_sci_tx<1>().set([this] (int state) { m_connector->do_midi_tx(state); });
+}
+
+ROM_START( wg130 )
+ ROM_REGION(0x200000, "gt913", 0)
+ ROM_LOAD("romsxgm.bin", 0x000000, 0x200000, CRC(c392cf89) SHA1(93ebe213ea7a085c67d88974ed39ac3e9bf8059b)) // from the SW-10 softsynth
+ROM_END
+
+void wg130_device::device_start()
+{
+ /*
+ the version of this ROM bundled with the SW-10 softsynth has little endian samples, so byteswap them
+ (and stop at the end of sample data, not the end of the whole ROM, otherwise the ROM test fails)
+ */
+ uint16_t *const rom = reinterpret_cast<uint16_t *>(memregion("gt913")->base());
+ for (uint32_t addr = 0x2f000 >> 1; addr < 0x1fe8c2 >> 1; addr++)
+ rom[addr] = swapendian_int16(rom[addr]);
+}
+
+const tiny_rom_entry *wg130_device::device_rom_region() const
+{
+ return ROM_NAME(wg130);
+}
+
+ioport_constructor wg130_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(wg130);
+}
+
+} // anonymous namespace
+
+DEFINE_DEVICE_TYPE_PRIVATE(WG130, device_waveblaster_interface, wg130_device, "wg130", "Casio WG-130")
diff --git a/src/devices/bus/waveblaster/wg130.h b/src/devices/bus/waveblaster/wg130.h
new file mode 100644
index 00000000000..30113ef8971
--- /dev/null
+++ b/src/devices/bus/waveblaster/wg130.h
@@ -0,0 +1,15 @@
+// license:BSD-3-Clause
+// copyright-holders: Devin Acker
+
+#ifndef MAME_BUS_WAVEBLASTER_WG130_H
+#define MAME_BUS_WAVEBLASTER_WG130_H
+
+// Casio WG130
+
+#pragma once
+
+#include "waveblaster.h"
+
+DECLARE_DEVICE_TYPE(WG130, device_waveblaster_interface)
+
+#endif // MAME_BUS_WAVEBLASTER_WG130_H
diff --git a/src/devices/bus/wswan/slot.cpp b/src/devices/bus/wswan/slot.cpp
index 6062540b4cf..31edbc6d971 100644
--- a/src/devices/bus/wswan/slot.cpp
+++ b/src/devices/bus/wswan/slot.cpp
@@ -47,11 +47,11 @@ device_ws_cart_interface::~device_ws_cart_interface()
// rom_alloc - alloc the space for the cart
//-------------------------------------------------
-void device_ws_cart_interface::rom_alloc(u32 size, const char *tag)
+void device_ws_cart_interface::rom_alloc(u32 size)
{
if (m_rom == nullptr)
{
- m_rom = (u16 *)device().machine().memory().region_alloc(std::string(tag).append(WSSLOT_ROM_REGION_TAG).c_str(), size, 2, ENDIANNESS_LITTLE)->base();
+ m_rom = (u16 *)device().machine().memory().region_alloc(device().subtag("^cart:rom"), size, 2, ENDIANNESS_LITTLE)->base();
m_rom_size = size;
m_bank_mask = ((m_rom_size >> 16) - 1);
}
@@ -150,22 +150,21 @@ static const char *ws_get_slot(int type)
call load
-------------------------------------------------*/
-image_init_result ws_cart_slot_device::call_load()
+std::pair<std::error_condition, std::string> ws_cart_slot_device::call_load()
{
if (m_cart)
{
- u16 *ROM;
- u32 size = !loaded_through_softlist() ? length() : get_software_region_length("rom");
- u32 nvram_size = 0;
+ u32 const size = !loaded_through_softlist() ? length() : get_software_region_length("rom");
- m_cart->rom_alloc(size, tag());
- ROM = m_cart->get_rom_base();
+ m_cart->rom_alloc(size);
+ u16 *const ROM = m_cart->get_rom_base();
if (!loaded_through_softlist())
fread(ROM, size);
else
memcpy(ROM, get_software_region("rom"), size);
+ u32 nvram_size = 0;
if (!loaded_through_softlist())
{
// get cart type and nvram length
@@ -203,7 +202,7 @@ image_init_result ws_cart_slot_device::call_load()
internal_header_logging(ROM, ((size >> 16) - 1) << 16, size);
}
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
/*-------------------------------------------------
@@ -291,8 +290,7 @@ std::string ws_cart_slot_device::get_default_card_software(get_default_card_soft
int type;
u32 nvram;
- size_t actual;
- hook.image_file()->read(&rom[0], size, actual);
+ /*[err, actual] =*/ read(*hook.image_file(), &rom[0], size);
// nvram size is not really used here, but we set it up nevertheless
type = get_cart_type(&rom[0], size, nvram);
diff --git a/src/devices/bus/wswan/slot.h b/src/devices/bus/wswan/slot.h
index 8a743a2ac07..6c84f093450 100644
--- a/src/devices/bus/wswan/slot.h
+++ b/src/devices/bus/wswan/slot.h
@@ -101,7 +101,7 @@ public:
virtual u16 read_io(offs_t offset, u16 mem_mask) { return 0xffff; }
virtual void write_io(offs_t offset, u16 data, u16 mem_mask) { }
- void rom_alloc(u32 size, const char *tag);
+ void rom_alloc(u32 size);
void nvram_alloc(u32 size);
u16* get_rom_base() { return m_rom; }
uint8_t* get_nvram_base() { return &m_nvram[0]; }
@@ -145,15 +145,15 @@ public:
ws_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
virtual ~ws_cart_slot_device();
- // image-level overrides
- virtual image_init_result call_load() override;
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
virtual void call_unload() override;
virtual bool is_reset_on_load() const noexcept override { return true; }
virtual const char *image_interface() const noexcept override { return "wswan_cart"; }
virtual const char *file_extensions() const noexcept override { return "ws,wsc,bin"; }
- // slot interface overrides
+ // device_slot_interface implementation
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
int get_type() { return m_type; }
@@ -172,11 +172,11 @@ public:
virtual void write_io(offs_t offset, u16 data, u16 mem_mask);
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
int m_type;
- device_ws_cart_interface* m_cart;
+ device_ws_cart_interface *m_cart;
};
@@ -184,11 +184,4 @@ protected:
// device type definition
DECLARE_DEVICE_TYPE(WS_CART_SLOT, ws_cart_slot_device)
-
-/***************************************************************************
- DEVICE CONFIGURATION MACROS
- ***************************************************************************/
-
-#define WSSLOT_ROM_REGION_TAG ":cart:rom"
-
#endif // MAME_BUS_WSWAN_SLOT_H
diff --git a/src/devices/bus/wysekbd/wysegakb.cpp b/src/devices/bus/wysekbd/wysegakb.cpp
new file mode 100644
index 00000000000..4ec409ce118
--- /dev/null
+++ b/src/devices/bus/wysekbd/wysegakb.cpp
@@ -0,0 +1,730 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/***************************************************************************
+
+ Wyse gate array-based terminal keyboards
+
+***************************************************************************/
+
+#include "emu.h"
+#include "wysegakb.h"
+
+
+//**************************************************************************
+// DEVICE TYPE DEFINITIONS
+//**************************************************************************
+
+// device type definitions
+DEFINE_DEVICE_TYPE(WY60_ASCII_KEYBOARD, wy60_ascii_keyboard_device, "wy60_ascii_kbd", "WY-60 ASCII Keyboard")
+DEFINE_DEVICE_TYPE(WYSE_AT_KEYBOARD, wyse_at_keyboard_device, "wyse_at_kbd", "Wyse AT-Style Keyboard")
+DEFINE_DEVICE_TYPE(WYSE_316X_KEYBOARD, wyse_316x_keyboard_device, "wyse_316x_kbd", "Wyse IBM 316X-Style Keyboard")
+DEFINE_DEVICE_TYPE(WYSE_PCE_KEYBOARD, wyse_pce_keyboard_device, "wyse_pce_kbd", "Wyse Enhanced PC-Style Keyboard")
+DEFINE_DEVICE_TYPE(WYSE_PCEINT_KEYBOARD, wyse_pceint_keyboard_device, "wyse_pceint_kbd", "Wyse Enhanced PC-Style International Keyboard")
+
+
+//**************************************************************************
+// WYSE GATE ARRAY KEYBOARD EMULATION
+//**************************************************************************
+
+wyse_gate_array_keyboard_device::wyse_gate_array_keyboard_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, type, tag, owner, clock)
+ , wyse_keyboard_interface(mconfig, *this)
+ , m_r(*this, "R%u", 0U)
+ , m_key_index(0)
+ , m_clock_state(true)
+ , m_reset_time(attotime::zero)
+{
+}
+
+void wyse_gate_array_keyboard_device::device_start()
+{
+ save_item(NAME(m_key_index));
+ save_item(NAME(m_clock_state));
+ save_item(NAME(m_reset_time));
+}
+
+bool wyse_gate_array_keyboard_device::wysekbd_read_data()
+{
+ if (machine().time() >= m_reset_time)
+ return true;
+ else if (m_key_index < 0x68)
+ {
+ auto &r = m_r[m_key_index >> 3];
+ return !r.found() || BIT(r->read(), m_key_index & 0x07);
+ }
+ else if ((m_key_index & 0xf8) == 0x90)
+ return BIT(wysekbd_get_id(), m_key_index & 0x07);
+ else
+ return true;
+}
+
+void wyse_gate_array_keyboard_device::wysekbd_write_cmd(bool state)
+{
+ if (m_clock_state == state)
+ return;
+
+ constexpr attotime RESET_TIMEOUT = attotime::from_usec(50);
+ if (state)
+ {
+ if (machine().time() >= m_reset_time)
+ m_key_index = 0;
+ else if (m_key_index == 0xff)
+ m_key_index = 0xc0;
+ else
+ ++m_key_index;
+ m_reset_time = attotime::never;
+ }
+ else
+ {
+ m_reset_time = machine().time() + RESET_TIMEOUT;
+ if (m_key_index >= 0x90)
+ wysekbd_update_leds(m_key_index);
+ }
+
+ m_clock_state = state;
+}
+
+void wyse_gate_array_keyboard_device::wysekbd_update_leds(u8 index)
+{
+}
+
+
+//**************************************************************************
+// KEYBOARD DEVICES
+//**************************************************************************
+
+wy60_ascii_keyboard_device::wy60_ascii_keyboard_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : wyse_gate_array_keyboard_device(mconfig, WY60_ASCII_KEYBOARD, tag, owner, clock)
+{
+}
+
+static INPUT_PORTS_START(wy60_ascii_keyboard)
+ PORT_START("R0")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("SetUp") PORT_CODE(KEYCODE_ESC)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Funct") PORT_CHAR(UCHAR_MAMEKEY(LALT)) PORT_CODE(KEYCODE_LALT)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Esc") PORT_CHAR(0x1b) PORT_CODE(KEYCODE_TILDE)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Break") PORT_CHAR(UCHAR_MAMEKEY(PAUSE)) PORT_CODE(KEYCODE_PAUSE)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Y") PORT_CHAR('y') PORT_CHAR('Y') PORT_CODE(KEYCODE_Y)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(MINUS_PAD)) PORT_CODE(KEYCODE_MINUS_PAD)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(',') PORT_CHAR('<') PORT_CODE(KEYCODE_COMMA)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('\'') PORT_CHAR('"') PORT_CODE(KEYCODE_QUOTE)
+
+ PORT_START("R1")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Shift (Left)") PORT_CHAR(UCHAR_SHIFT_1) PORT_CODE(KEYCODE_LSHIFT)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(CAPSLOCK)) PORT_CODE(KEYCODE_LCONTROL)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Shift (Right)") PORT_CHAR(UCHAR_MAMEKEY(RSHIFT)) PORT_CODE(KEYCODE_RSHIFT)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(']') PORT_CHAR('}') PORT_CODE(KEYCODE_CLOSEBRACE)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(';') PORT_CHAR(':') PORT_CODE(KEYCODE_COLON)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Ins Char Ins Line") PORT_CHAR(UCHAR_MAMEKEY(INSERT)) PORT_CODE(KEYCODE_INSERT)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(UP)) PORT_CODE(KEYCODE_UP)
+
+ PORT_START("R2")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Space Bar") PORT_CHAR(' ') PORT_CODE(KEYCODE_SPACE)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Ctrl") PORT_CHAR(UCHAR_MAMEKEY(LCONTROL)) PORT_CODE(KEYCODE_CAPSLOCK)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("O") PORT_CHAR('o') PORT_CHAR('O') PORT_CODE(KEYCODE_O)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Clr Line Clr Scrn") PORT_CHAR(UCHAR_MAMEKEY(SLASH_PAD)) PORT_CODE(KEYCODE_SLASH_PAD)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Return") PORT_CHAR(0x0d) PORT_CODE(KEYCODE_ENTER)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Next Page Prev Page") PORT_CHAR(UCHAR_MAMEKEY(PGDN)) PORT_CODE(KEYCODE_PGDN)
+
+ PORT_START("R3")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(COMMA_PAD)) PORT_CODE(KEYCODE_PLUS_PAD)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Del Char Del Line") PORT_CHAR(UCHAR_MAMEKEY(END)) PORT_CODE(KEYCODE_END)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(ENTER_PAD)) PORT_CODE(KEYCODE_ENTER_PAD)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(DEL_PAD)) PORT_CODE(KEYCODE_DEL_PAD)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(9_PAD)) PORT_CODE(KEYCODE_9_PAD)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('[') PORT_CHAR('{') PORT_CODE(KEYCODE_OPENBRACE)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('`') PORT_CHAR('~') PORT_CODE(KEYCODE_BACKSLASH)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Send Print") PORT_CHAR(UCHAR_MAMEKEY(PRTSCR)) PORT_CODE(KEYCODE_PRTSCR)
+
+ PORT_START("R4")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('2') PORT_CHAR('@') PORT_CODE(KEYCODE_2)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('1') PORT_CHAR('!') PORT_CODE(KEYCODE_1)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Repl Ins") PORT_CODE(KEYCODE_ASTERISK)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('-') PORT_CHAR('_') PORT_CODE(KEYCODE_MINUS)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("I") PORT_CHAR('i') PORT_CHAR('I') PORT_CODE(KEYCODE_I)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("L") PORT_CHAR('l') PORT_CHAR('L') PORT_CODE(KEYCODE_L)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Z") PORT_CHAR('z') PORT_CHAR('Z') PORT_CODE(KEYCODE_Z)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(8_PAD)) PORT_CODE(KEYCODE_8_PAD)
+
+ PORT_START("R5")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F7)) PORT_CODE(KEYCODE_F7)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F14)) PORT_CODE(KEYCODE_F14)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('0') PORT_CHAR(')') PORT_CODE(KEYCODE_0)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('\\') PORT_CHAR('|') PORT_CODE(KEYCODE_RALT)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("U") PORT_CHAR('u') PORT_CHAR('U') PORT_CODE(KEYCODE_U)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("K") PORT_CHAR('k') PORT_CHAR('K') PORT_CODE(KEYCODE_K)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('.') PORT_CHAR('>') PORT_CODE(KEYCODE_STOP)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(7_PAD)) PORT_CODE(KEYCODE_7_PAD)
+
+ PORT_START("R6")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F6)) PORT_CODE(KEYCODE_F6)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F13)) PORT_CODE(KEYCODE_F13)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('9') PORT_CHAR('(') PORT_CODE(KEYCODE_9)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(HOME)) PORT_CODE(KEYCODE_HOME)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("T") PORT_CHAR('t') PORT_CHAR('T') PORT_CODE(KEYCODE_T)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("J") PORT_CHAR('j') PORT_CHAR('J') PORT_CODE(KEYCODE_J)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("B") PORT_CHAR('b') PORT_CHAR('B') PORT_CODE(KEYCODE_B)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(6_PAD)) PORT_CODE(KEYCODE_6_PAD)
+
+ PORT_START("R7")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F5)) PORT_CODE(KEYCODE_F5)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F12)) PORT_CODE(KEYCODE_F12)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('8') PORT_CHAR('*') PORT_CODE(KEYCODE_8)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(DOWN)) PORT_CODE(KEYCODE_DOWN)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("P") PORT_CHAR('p') PORT_CHAR('P') PORT_CODE(KEYCODE_P)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("H") PORT_CHAR('h') PORT_CHAR('H') PORT_CODE(KEYCODE_H)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("M") PORT_CHAR('m') PORT_CHAR('M') PORT_CODE(KEYCODE_M)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(5_PAD)) PORT_CODE(KEYCODE_5_PAD)
+
+ PORT_START("R8")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F4)) PORT_CODE(KEYCODE_F4)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F11)) PORT_CODE(KEYCODE_F11)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('7') PORT_CHAR('&') PORT_CODE(KEYCODE_7)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(RIGHT)) PORT_CODE(KEYCODE_RIGHT)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("R") PORT_CHAR('r') PORT_CHAR('R') PORT_CODE(KEYCODE_R)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("G") PORT_CHAR('g') PORT_CHAR('G') PORT_CODE(KEYCODE_G)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("N") PORT_CHAR('n') PORT_CHAR('N') PORT_CODE(KEYCODE_N)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(4_PAD)) PORT_CODE(KEYCODE_4_PAD)
+
+ PORT_START("R9")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F3)) PORT_CODE(KEYCODE_F3)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F10)) PORT_CODE(KEYCODE_F10)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('6') PORT_CHAR('^') PORT_CODE(KEYCODE_6)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(LEFT)) PORT_CODE(KEYCODE_LEFT)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("W") PORT_CHAR('w') PORT_CHAR('W') PORT_CODE(KEYCODE_W)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("D") PORT_CHAR('d') PORT_CHAR('D') PORT_CODE(KEYCODE_D)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("V") PORT_CHAR('v') PORT_CHAR('V') PORT_CODE(KEYCODE_V)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(3_PAD)) PORT_CODE(KEYCODE_3_PAD)
+
+ PORT_START("R10")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F2)) PORT_CODE(KEYCODE_F2)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F9)) PORT_CODE(KEYCODE_F9)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('5') PORT_CHAR('%') PORT_CODE(KEYCODE_5)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F16)) PORT_CODE(KEYCODE_F16)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("E") PORT_CHAR('e') PORT_CHAR('E') PORT_CODE(KEYCODE_E)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F") PORT_CHAR('f') PORT_CHAR('F') PORT_CODE(KEYCODE_F)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("X") PORT_CHAR('x') PORT_CHAR('X') PORT_CODE(KEYCODE_X)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(2_PAD)) PORT_CODE(KEYCODE_2_PAD)
+
+ PORT_START("R11")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F1)) PORT_CODE(KEYCODE_F1)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F8)) PORT_CODE(KEYCODE_F8)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('4') PORT_CHAR('$') PORT_CODE(KEYCODE_4)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F15)) PORT_CODE(KEYCODE_F15)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Q") PORT_CHAR('q') PORT_CHAR('Q') PORT_CODE(KEYCODE_Q)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("S") PORT_CHAR('s') PORT_CHAR('S') PORT_CODE(KEYCODE_S)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C") PORT_CHAR('c') PORT_CHAR('C') PORT_CODE(KEYCODE_C)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(1_PAD)) PORT_CODE(KEYCODE_1_PAD)
+
+ PORT_START("R12")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Del") PORT_CHAR(UCHAR_MAMEKEY(DEL)) PORT_CODE(KEYCODE_DEL)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('=') PORT_CHAR('+') PORT_CODE(KEYCODE_EQUALS)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('3') PORT_CHAR('#') PORT_CODE(KEYCODE_3)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Back Space") PORT_CHAR(0x08) PORT_CODE(KEYCODE_BACKSPACE)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Tab") PORT_CHAR(0x09) PORT_CODE(KEYCODE_TAB)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("A") PORT_CHAR('a') PORT_CHAR('A') PORT_CODE(KEYCODE_A)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('/') PORT_CHAR('?') PORT_CODE(KEYCODE_SLASH)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(0_PAD)) PORT_CODE(KEYCODE_0_PAD)
+INPUT_PORTS_END
+
+ioport_constructor wy60_ascii_keyboard_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(wy60_ascii_keyboard);
+}
+
+u8 wy60_ascii_keyboard_device::wysekbd_get_id()
+{
+ return 0x41 ^ 0xff;
+}
+
+
+wyse_at_keyboard_device::wyse_at_keyboard_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
+ : wyse_gate_array_keyboard_device(mconfig, type, tag, owner, clock)
+ , m_caps_led(*this, "caps_led")
+ , m_num_led(*this, "num_led")
+ , m_scroll_led(*this, "scroll_led")
+{
+}
+
+wyse_at_keyboard_device::wyse_at_keyboard_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : wyse_at_keyboard_device(mconfig, WYSE_AT_KEYBOARD, tag, owner, clock)
+{
+}
+
+void wyse_at_keyboard_device::device_resolve_objects()
+{
+ wyse_gate_array_keyboard_device::device_resolve_objects();
+
+ m_caps_led.resolve();
+ m_num_led.resolve();
+ m_scroll_led.resolve();
+}
+
+static INPUT_PORTS_START(wyse_at_keyboard)
+ PORT_START("R0")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Keypad 1 End") PORT_CHAR(UCHAR_MAMEKEY(1_PAD), UCHAR_MAMEKEY(END)) PORT_CODE(KEYCODE_1_PAD)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Keypad * Print Sc") PORT_CHAR(UCHAR_MAMEKEY(ASTERISK), UCHAR_MAMEKEY(PRTSCR)) PORT_CODE(KEYCODE_ASTERISK)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Esc") PORT_CHAR(0x1b) PORT_CODE(KEYCODE_ESC)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(CAPSLOCK)) PORT_CODE(KEYCODE_RALT)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("D") PORT_CHAR('d') PORT_CHAR('D') PORT_CODE(KEYCODE_D)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("P") PORT_CHAR('p') PORT_CHAR('P') PORT_CODE(KEYCODE_P)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('.') PORT_CHAR('>') PORT_CODE(KEYCODE_STOP)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('0') PORT_CHAR(')') PORT_CODE(KEYCODE_0)
+
+ PORT_START("R1")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(u8"Keypad 2 \u2193") PORT_CHAR(UCHAR_MAMEKEY(2_PAD), UCHAR_MAMEKEY(DOWN)) PORT_CODE(KEYCODE_2_PAD)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(u8"Keypad 4 \u2190") PORT_CHAR(UCHAR_MAMEKEY(4_PAD), UCHAR_MAMEKEY(LEFT)) PORT_CODE(KEYCODE_4_PAD)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Num Lock") PORT_CHAR(UCHAR_MAMEKEY(NUMLOCK)) PORT_CODE(KEYCODE_SLASH_PAD)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Space") PORT_CHAR(' ') PORT_CODE(KEYCODE_SPACE)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Enter") PORT_CHAR(0x0d) PORT_CODE(KEYCODE_ENTER)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('[') PORT_CHAR('{') PORT_CODE(KEYCODE_OPENBRACE)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C") PORT_CHAR('c') PORT_CHAR('C') PORT_CODE(KEYCODE_C)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('1') PORT_CHAR('!') PORT_CODE(KEYCODE_1)
+
+ PORT_START("R2")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Keypad 3 Pg Dn") PORT_CHAR(UCHAR_MAMEKEY(3_PAD), UCHAR_MAMEKEY(PGDN)) PORT_CODE(KEYCODE_3_PAD)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(5_PAD)) PORT_CODE(KEYCODE_5_PAD)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Scroll Lock") PORT_CHAR(UCHAR_MAMEKEY(SCRLOCK)) PORT_CODE(KEYCODE_ASTERISK)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('\\') PORT_CHAR('|') PORT_CODE(KEYCODE_BACKSLASH)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("S") PORT_CHAR('s') PORT_CHAR('S') PORT_CODE(KEYCODE_S)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(']') PORT_CHAR('}') PORT_CODE(KEYCODE_CLOSEBRACE)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Z") PORT_CHAR('z') PORT_CHAR('Z') PORT_CODE(KEYCODE_Z)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('2') PORT_CHAR('@') PORT_CODE(KEYCODE_2)
+
+ PORT_START("R3")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F1)) PORT_CODE(KEYCODE_F1)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('9') PORT_CHAR('(') PORT_CODE(KEYCODE_9)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('=') PORT_CHAR('+') PORT_CODE(KEYCODE_EQUALS)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Alt") PORT_CHAR(UCHAR_MAMEKEY(LALT)) PORT_CODE(KEYCODE_LALT)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('-') PORT_CHAR('_') PORT_CODE(KEYCODE_MINUS)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('\'') PORT_CHAR('"') PORT_CODE(KEYCODE_QUOTE)
+
+ PORT_START("R4")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F5)) PORT_CODE(KEYCODE_F5)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F10)) PORT_CODE(KEYCODE_F10)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('/') PORT_CHAR('?') PORT_CODE(KEYCODE_SLASH)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Ctrl") PORT_CHAR(UCHAR_MAMEKEY(LCONTROL)) PORT_CODE(KEYCODE_LCONTROL)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(',') PORT_CHAR('<') PORT_CODE(KEYCODE_COMMA)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('3') PORT_CHAR('#') PORT_CODE(KEYCODE_3)
+
+ PORT_START("R5")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("O") PORT_CHAR('o') PORT_CHAR('O') PORT_CODE(KEYCODE_O)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("I") PORT_CHAR('i') PORT_CHAR('I') PORT_CODE(KEYCODE_I)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("U") PORT_CHAR('u') PORT_CHAR('U') PORT_CODE(KEYCODE_U)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("T") PORT_CHAR('t') PORT_CHAR('T') PORT_CODE(KEYCODE_T)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Y") PORT_CHAR('y') PORT_CHAR('Y') PORT_CODE(KEYCODE_Y)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("X") PORT_CHAR('x') PORT_CHAR('X') PORT_CODE(KEYCODE_X)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('4') PORT_CHAR('$') PORT_CODE(KEYCODE_4)
+
+ PORT_START("R6")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(';') PORT_CHAR(':') PORT_CODE(KEYCODE_COLON)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("L") PORT_CHAR('l') PORT_CHAR('L') PORT_CODE(KEYCODE_L)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("A") PORT_CHAR('a') PORT_CHAR('A') PORT_CODE(KEYCODE_A)
+ PORT_BIT(0x18, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Tab") PORT_CHAR(0x09) PORT_CODE(KEYCODE_TAB)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Left Shift") PORT_CHAR(UCHAR_SHIFT_1) PORT_CODE(KEYCODE_LSHIFT)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("J") PORT_CHAR('j') PORT_CHAR('J') PORT_CODE(KEYCODE_J)
+
+ PORT_START("R7")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(PLUS_PAD)) PORT_CODE(KEYCODE_ENTER_PAD)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Keypad . Del") PORT_CHAR(UCHAR_MAMEKEY(DEL_PAD), UCHAR_MAMEKEY(DEL)) PORT_CODE(KEYCODE_DEL_PAD)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Keypad 0 Ins") PORT_CHAR(UCHAR_MAMEKEY(0_PAD), UCHAR_MAMEKEY(INSERT)) PORT_CODE(KEYCODE_0_PAD)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F") PORT_CHAR('f') PORT_CHAR('F') PORT_CODE(KEYCODE_F)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Q") PORT_CHAR('q') PORT_CHAR('Q') PORT_CODE(KEYCODE_Q)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("V") PORT_CHAR('v') PORT_CHAR('V') PORT_CODE(KEYCODE_V)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('5') PORT_CHAR('%') PORT_CODE(KEYCODE_5)
+
+ PORT_START("R8")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Keypad 9 Pg Up") PORT_CHAR(UCHAR_MAMEKEY(9_PAD), UCHAR_MAMEKEY(PGUP)) PORT_CODE(KEYCODE_9_PAD)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(MINUS_PAD)) PORT_CODE(KEYCODE_PLUS_PAD)
+ PORT_BIT(0x0c, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("H") PORT_CHAR('h') PORT_CHAR('H') PORT_CODE(KEYCODE_H)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("W") PORT_CHAR('w') PORT_CHAR('W') PORT_CODE(KEYCODE_W)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("N") PORT_CHAR('n') PORT_CHAR('N') PORT_CODE(KEYCODE_N)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('6') PORT_CHAR('^') PORT_CODE(KEYCODE_6)
+
+ PORT_START("R9")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(u8"Keypad 8 \u2191") PORT_CHAR(UCHAR_MAMEKEY(8_PAD), UCHAR_MAMEKEY(UP)) PORT_CODE(KEYCODE_8_PAD)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F8)) PORT_CODE(KEYCODE_F8)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Sys Req") PORT_CODE(KEYCODE_MINUS_PAD)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F7)) PORT_CODE(KEYCODE_F7)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("G") PORT_CHAR('g') PORT_CHAR('G') PORT_CODE(KEYCODE_G)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("E") PORT_CHAR('e') PORT_CHAR('E') PORT_CODE(KEYCODE_E)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("B") PORT_CHAR('b') PORT_CHAR('B') PORT_CODE(KEYCODE_B)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('7') PORT_CHAR('&') PORT_CODE(KEYCODE_7)
+
+ PORT_START("R10")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F9)) PORT_CODE(KEYCODE_F9)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(u8"Keypad 6 \u2192") PORT_CHAR(UCHAR_MAMEKEY(6_PAD), UCHAR_MAMEKEY(RIGHT)) PORT_CODE(KEYCODE_6_PAD)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Keypad 7 Home") PORT_CHAR(UCHAR_MAMEKEY(7_PAD), UCHAR_MAMEKEY(HOME)) PORT_CODE(KEYCODE_7_PAD)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F6)) PORT_CODE(KEYCODE_F6)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("K") PORT_CHAR('k') PORT_CHAR('K') PORT_CODE(KEYCODE_K)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("R") PORT_CHAR('r') PORT_CHAR('R') PORT_CODE(KEYCODE_R)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("M") PORT_CHAR('m') PORT_CHAR('M') PORT_CODE(KEYCODE_M)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('8') PORT_CHAR('*') PORT_CODE(KEYCODE_8)
+
+ PORT_START("R11")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(u8"\u2190") PORT_CHAR(0x08) PORT_CODE(KEYCODE_BACKSPACE)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F4)) PORT_CODE(KEYCODE_F4)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F3)) PORT_CODE(KEYCODE_F3)
+ PORT_BIT(0x18, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F2)) PORT_CODE(KEYCODE_F2)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Right Shift") PORT_CHAR(UCHAR_MAMEKEY(RSHIFT)) PORT_CODE(KEYCODE_RSHIFT)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('`') PORT_CHAR('~') PORT_CODE(KEYCODE_TILDE)
+INPUT_PORTS_END
+
+ioport_constructor wyse_at_keyboard_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(wyse_at_keyboard);
+}
+
+u8 wyse_at_keyboard_device::wysekbd_get_id()
+{
+ return 0x02 ^ 0xff;
+}
+
+void wyse_at_keyboard_device::wysekbd_update_leds(u8 index)
+{
+ u8 const led_count = index >= 0x98 ? index & 0x07 : 0;
+ m_caps_led = !BIT(led_count, 2);
+ m_num_led = !BIT(led_count, 1);
+ m_scroll_led = !BIT(led_count, 0);
+}
+
+
+wyse_316x_keyboard_device::wyse_316x_keyboard_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : wyse_gate_array_keyboard_device(mconfig, WYSE_316X_KEYBOARD, tag, owner, clock)
+ , m_lclr(*this, "LCLR")
+{
+}
+
+static INPUT_PORTS_START(wyse_316x_keyboard)
+ PORT_START("R0")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(0_PAD)) PORT_CODE(KEYCODE_0_PAD)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Keypad 4 Sub") PORT_CHAR(UCHAR_MAMEKEY(4_PAD)) PORT_CODE(KEYCODE_4_PAD)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Jump AltCsr") PORT_CHAR(UCHAR_MAMEKEY(NUMLOCK)) PORT_CODE(KEYCODE_NUMLOCK)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Send") PORT_CHAR(UCHAR_MAMEKEY(RALT)) PORT_CODE(KEYCODE_RALT)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('8') PORT_CHAR('*') PORT_CODE(KEYCODE_8)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(u8"Tab \u2192") PORT_CHAR(0x09) PORT_CODE(KEYCODE_TAB)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Return") PORT_CHAR(0x0d) PORT_CODE(KEYCODE_ENTER)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Esc") PORT_CHAR(0x1b) PORT_CODE(KEYCODE_ESC)
+
+ PORT_START("R1")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(DEL_PAD)) PORT_CODE(KEYCODE_DEL_PAD)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(5_PAD)) PORT_CODE(KEYCODE_5_PAD)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Page Msg") PORT_CHAR(UCHAR_MAMEKEY(SLASH_PAD)) PORT_CODE(KEYCODE_SLASH_PAD)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Z") PORT_CHAR('z') PORT_CHAR('Z') PORT_CODE(KEYCODE_Z)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('9') PORT_CHAR('(') PORT_CODE(KEYCODE_9)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("R") PORT_CHAR('r') PORT_CHAR('R') PORT_CODE(KEYCODE_R)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('\'') PORT_CHAR('"') PORT_CODE(KEYCODE_QUOTE)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F1)) PORT_CODE(KEYCODE_F1)
+
+ PORT_START("R2")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(UP)) PORT_CODE(KEYCODE_UP)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(6_PAD)) PORT_CODE(KEYCODE_6_PAD)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Send Line SendMsg") PORT_CODE(KEYCODE_ASTERISK)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C") PORT_CHAR('c') PORT_CHAR('C') PORT_CODE(KEYCODE_C)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('0') PORT_CHAR(')') PORT_CODE(KEYCODE_0)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("W") PORT_CHAR('w') PORT_CHAR('W') PORT_CODE(KEYCODE_W)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Reset") PORT_CHAR(UCHAR_MAMEKEY(LALT)) PORT_CODE(KEYCODE_LALT)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F2)) PORT_CODE(KEYCODE_F2)
+
+ PORT_START("R3")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(DOWN)) PORT_CODE(KEYCODE_DOWN)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Keypad 1 PA1") PORT_CHAR(UCHAR_MAMEKEY(1_PAD)) PORT_CODE(KEYCODE_1_PAD)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Home Del") PORT_CHAR(UCHAR_MAMEKEY(HOME)) PORT_CODE(KEYCODE_HOME)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("X") PORT_CHAR('x') PORT_CHAR('X') PORT_CODE(KEYCODE_X)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('-') PORT_CHAR('_') PORT_CODE(KEYCODE_MINUS)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("E") PORT_CHAR('e') PORT_CHAR('E') PORT_CODE(KEYCODE_E)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(';') PORT_CHAR(':') PORT_CODE(KEYCODE_COLON)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F3)) PORT_CODE(KEYCODE_F3)
+
+ PORT_START("R4")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(LEFT)) PORT_CODE(KEYCODE_LEFT)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Keypad 2 PA2") PORT_CHAR(UCHAR_MAMEKEY(2_PAD)) PORT_CODE(KEYCODE_2_PAD)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F13)) PORT_CODE(KEYCODE_F13)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("V") PORT_CHAR('v') PORT_CHAR('V') PORT_CODE(KEYCODE_V)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('=') PORT_CHAR('+') PORT_CODE(KEYCODE_EQUALS)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Q") PORT_CHAR('q') PORT_CHAR('Q') PORT_CODE(KEYCODE_Q)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F12)) PORT_CODE(KEYCODE_F12)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F4)) PORT_CODE(KEYCODE_F4)
+
+ PORT_START("R5")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(9_PAD)) PORT_CODE(KEYCODE_9_PAD)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('\\') PORT_CHAR('|') PORT_CODE(KEYCODE_BACKSLASH)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Keypad 7 Super") PORT_CHAR(UCHAR_MAMEKEY(7_PAD)) PORT_CODE(KEYCODE_7_PAD)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Hold Break") PORT_CHAR(UCHAR_MAMEKEY(PAUSE)) PORT_CODE(KEYCODE_PAUSE)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Print Line PrMsg") PORT_CHAR(UCHAR_MAMEKEY(SCRLOCK)) PORT_CODE(KEYCODE_SCRLOCK)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Print Trace") PORT_CHAR(UCHAR_MAMEKEY(PRTSCR)) PORT_CODE(KEYCODE_PRTSCR)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Space Bar") PORT_CHAR(' ') PORT_CODE(KEYCODE_SPACE)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Ctrl (Right)") PORT_CHAR(UCHAR_MAMEKEY(RCONTROL)) PORT_CODE(KEYCODE_RCONTROL)
+
+ PORT_START("R6")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("L") PORT_CHAR('l') PORT_CHAR('L') PORT_CODE(KEYCODE_L)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("K") PORT_CHAR('k') PORT_CHAR('K') PORT_CODE(KEYCODE_K)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("J") PORT_CHAR('j') PORT_CHAR('J') PORT_CODE(KEYCODE_J)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Shift (Left)") PORT_CHAR(UCHAR_SHIFT_1) PORT_CODE(KEYCODE_LSHIFT)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("H") PORT_CHAR('h') PORT_CHAR('H') PORT_CODE(KEYCODE_H)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("G") PORT_CHAR('g') PORT_CHAR('G') PORT_CODE(KEYCODE_G)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Shift (Right)") PORT_CHAR(UCHAR_MAMEKEY(RSHIFT)) PORT_CODE(KEYCODE_RSHIFT)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Erase EOF ErEOP") PORT_CHAR(UCHAR_MAMEKEY(PGDN)) PORT_CODE(KEYCODE_PGDN)
+
+ PORT_START("R7")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(RIGHT)) PORT_CODE(KEYCODE_RIGHT)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(']') PORT_CHAR('}') PORT_CODE(KEYCODE_CLOSEBRACE)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('[') PORT_CHAR('{') PORT_CODE(KEYCODE_OPENBRACE)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Select Setup") PORT_CODE(KEYCODE_MENU)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("P") PORT_CHAR('p') PORT_CHAR('P') PORT_CODE(KEYCODE_P)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Back Space") PORT_CHAR(0x08) PORT_CODE(KEYCODE_BACKSPACE)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(CAPSLOCK)) PORT_CODE(KEYCODE_CAPSLOCK)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Ctrl (Left)") PORT_CHAR(UCHAR_MAMEKEY(LCONTROL)) PORT_CODE(KEYCODE_LCONTROL)
+
+ PORT_START("R8")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('7') PORT_CHAR('&') PORT_CODE(KEYCODE_7)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('6') PORT_CHAR('^') PORT_CODE(KEYCODE_6)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('5') PORT_CHAR('%') PORT_CODE(KEYCODE_5)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('4') PORT_CHAR('$') PORT_CODE(KEYCODE_4)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Clear Erinp") PORT_CHAR(UCHAR_MAMEKEY(PGUP)) PORT_CODE(KEYCODE_PGUP)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("T") PORT_CHAR('t') PORT_CHAR('T') PORT_CODE(KEYCODE_T)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F6)) PORT_CODE(KEYCODE_F6)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F7)) PORT_CODE(KEYCODE_F7)
+
+ PORT_START("R9")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('/') PORT_CHAR('?') PORT_CODE(KEYCODE_SLASH)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('.') PORT_CHAR('>') PORT_CODE(KEYCODE_STOP)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(',') PORT_CHAR('<') PORT_CODE(KEYCODE_COMMA)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Delete DelLn") PORT_CHAR(UCHAR_MAMEKEY(DEL)) PORT_CODE(KEYCODE_DEL)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('`') PORT_CHAR('~') PORT_CODE(KEYCODE_TILDE)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Y") PORT_CHAR('y') PORT_CHAR('Y') PORT_CODE(KEYCODE_Y)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("A") PORT_CHAR('a') PORT_CHAR('A') PORT_CODE(KEYCODE_A)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F8)) PORT_CODE(KEYCODE_F8)
+
+ PORT_START("R10")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Keypad , AltChr") PORT_CHAR(UCHAR_MAMEKEY(COMMA_PAD)) PORT_CODE(KEYCODE_PLUS_PAD)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Keypad - Block") PORT_CHAR(UCHAR_MAMEKEY(MINUS_PAD)) PORT_CODE(KEYCODE_MINUS_PAD)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(u8"\u2190 Tab") PORT_CHAR(UCHAR_MAMEKEY(END)) PORT_CODE(KEYCODE_END)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("N") PORT_CHAR('n') PORT_CHAR('N') PORT_CODE(KEYCODE_N)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('1') PORT_CHAR('!') PORT_CODE(KEYCODE_1)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("U") PORT_CHAR('u') PORT_CHAR('U') PORT_CODE(KEYCODE_U)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("S") PORT_CHAR('s') PORT_CHAR('S') PORT_CODE(KEYCODE_S)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F9)) PORT_CODE(KEYCODE_F9)
+
+ PORT_START("R11")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(ENTER_PAD)) PORT_CODE(KEYCODE_ENTER_PAD)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(8_PAD)) PORT_CODE(KEYCODE_8_PAD)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F5)) PORT_CODE(KEYCODE_F5)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("B") PORT_CHAR('b') PORT_CHAR('B') PORT_CODE(KEYCODE_B)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('2') PORT_CHAR('@') PORT_CODE(KEYCODE_2)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("I") PORT_CHAR('i') PORT_CHAR('I') PORT_CODE(KEYCODE_I)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F") PORT_CHAR('f') PORT_CHAR('F') PORT_CODE(KEYCODE_F)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F10)) PORT_CODE(KEYCODE_F10)
+
+ PORT_START("R12")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Insert InsLn") PORT_CHAR(UCHAR_MAMEKEY(INSERT)) PORT_CODE(KEYCODE_INSERT)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Keypad 3 PA3") PORT_CHAR(UCHAR_MAMEKEY(3_PAD)) PORT_CODE(KEYCODE_3_PAD)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F14)) PORT_CODE(KEYCODE_F14)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("M") PORT_CHAR('m') PORT_CHAR('M') PORT_CODE(KEYCODE_M)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('3') PORT_CHAR('#') PORT_CODE(KEYCODE_3)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("O") PORT_CHAR('o') PORT_CHAR('O') PORT_CODE(KEYCODE_O)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("D") PORT_CHAR('d') PORT_CHAR('D') PORT_CODE(KEYCODE_D)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F11)) PORT_CODE(KEYCODE_F11)
+
+ PORT_START("LCLR")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F16)) PORT_CODE(KEYCODE_F16)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F15)) PORT_CODE(KEYCODE_F15)
+ PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_UNUSED) // ID bit
+ PORT_BIT(0xf8, IP_ACTIVE_LOW, IPT_UNUSED)
+INPUT_PORTS_END
+
+ioport_constructor wyse_316x_keyboard_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(wyse_316x_keyboard);
+}
+
+u8 wyse_316x_keyboard_device::wysekbd_get_id()
+{
+ return m_lclr->read();
+}
+
+
+wyse_pce_keyboard_device::wyse_pce_keyboard_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : wyse_at_keyboard_device(mconfig, WYSE_PCE_KEYBOARD, tag, owner, clock)
+{
+}
+
+static INPUT_PORTS_START(wyse_pce_keyboard)
+ PORT_START("R0")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Keypad 7 Home") PORT_CHAR(UCHAR_MAMEKEY(7_PAD)) PORT_CODE(KEYCODE_7_PAD)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('.') PORT_CHAR('>') PORT_CODE(KEYCODE_STOP)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("K") PORT_CHAR('k') PORT_CHAR('K') PORT_CODE(KEYCODE_K)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("U") PORT_CHAR('u') PORT_CHAR('U') PORT_CODE(KEYCODE_U)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('5') PORT_CHAR('%') PORT_CODE(KEYCODE_5)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('\\') PORT_CHAR('|') PORT_CODE(KEYCODE_BACKSLASH)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F10)) PORT_CODE(KEYCODE_F10)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Esc") PORT_CHAR(0x1b) PORT_CODE(KEYCODE_ESC)
+
+ PORT_START("R1")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(PLUS_PAD)) PORT_CODE(KEYCODE_PLUS_PAD)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('=') PORT_CHAR('+') PORT_CODE(KEYCODE_EQUALS)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Enter") PORT_CHAR(0x0d) PORT_CODE(KEYCODE_ENTER)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Y") PORT_CHAR('y') PORT_CHAR('Y') PORT_CODE(KEYCODE_Y)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Alt (Left)") PORT_CHAR(UCHAR_MAMEKEY(LALT)) PORT_CODE(KEYCODE_LALT)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('2') PORT_CHAR('@') PORT_CODE(KEYCODE_2)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('`') PORT_CHAR('~') PORT_CODE(KEYCODE_TILDE)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('1') PORT_CHAR('!') PORT_CODE(KEYCODE_1)
+
+ PORT_START("R2")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(ENTER_PAD)) PORT_CODE(KEYCODE_ENTER_PAD)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(',') PORT_CHAR('<') PORT_CODE(KEYCODE_COMMA)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F12)) PORT_CODE(KEYCODE_F12)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("O") PORT_CHAR('o') PORT_CHAR('O') PORT_CODE(KEYCODE_O)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(NUMLOCK)) PORT_CODE(KEYCODE_NUMLOCK)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(CAPSLOCK)) PORT_CODE(KEYCODE_CAPSLOCK)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Ctrl (Left)") PORT_CHAR(UCHAR_MAMEKEY(LCONTROL)) PORT_CODE(KEYCODE_LCONTROL)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("* ;") PORT_CODE(KEYCODE_BACKSLASH2)
+
+ PORT_START("R3")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Keypad . Del") PORT_CHAR(UCHAR_MAMEKEY(DEL_PAD)) PORT_CODE(KEYCODE_DEL_PAD)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F11)) PORT_CODE(KEYCODE_F11)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('/') PORT_CHAR('?') PORT_CODE(KEYCODE_SLASH)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("I") PORT_CHAR('i') PORT_CHAR('I') PORT_CODE(KEYCODE_I)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(';') PORT_CHAR(':') PORT_CODE(KEYCODE_COLON)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Shift (Right)") PORT_CHAR(UCHAR_MAMEKEY(RSHIFT)) PORT_CODE(KEYCODE_RSHIFT)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_UNUSED)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Shift (Left)") PORT_CHAR(UCHAR_SHIFT_1) PORT_CODE(KEYCODE_LSHIFT)
+
+ PORT_START("R4")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Keypad 0 Ins") PORT_CHAR(UCHAR_MAMEKEY(0_PAD)) PORT_CODE(KEYCODE_0_PAD)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Keypad 9 Pg Up") PORT_CHAR(UCHAR_MAMEKEY(9_PAD)) PORT_CODE(KEYCODE_9_PAD)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(MINUS_PAD)) PORT_CODE(KEYCODE_MINUS_PAD)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(ASTERISK)) PORT_CODE(KEYCODE_ASTERISK)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('\'') PORT_CHAR('"') PORT_CODE(KEYCODE_QUOTE)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Select") PORT_CODE(KEYCODE_MENU)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Ctrl (Right)") PORT_CHAR(UCHAR_MAMEKEY(RCONTROL)) PORT_CODE(KEYCODE_RCONTROL)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Space") PORT_CHAR(' ') PORT_CODE(KEYCODE_SPACE)
+
+ PORT_START("R5")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(SLASH_PAD)) PORT_CODE(KEYCODE_SLASH_PAD)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Z") PORT_CHAR('z') PORT_CHAR('Z') PORT_CODE(KEYCODE_Z)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("L") PORT_CHAR('l') PORT_CHAR('L') PORT_CODE(KEYCODE_L)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('-') PORT_CHAR('_') PORT_CODE(KEYCODE_MINUS)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Alt (Right)") PORT_CHAR(UCHAR_MAMEKEY(RALT)) PORT_CODE(KEYCODE_RALT)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(']') PORT_CHAR('}') PORT_CODE(KEYCODE_CLOSEBRACE)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(SCRLOCK)) PORT_CODE(KEYCODE_SCRLOCK)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('[') PORT_CHAR('{') PORT_CODE(KEYCODE_OPENBRACE)
+
+ PORT_START("R6")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Keypad 1 End") PORT_CHAR(UCHAR_MAMEKEY(1_PAD)) PORT_CODE(KEYCODE_1_PAD)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("B") PORT_CHAR('b') PORT_CHAR('B') PORT_CODE(KEYCODE_B)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("J") PORT_CHAR('j') PORT_CHAR('J') PORT_CODE(KEYCODE_J)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("T") PORT_CHAR('t') PORT_CHAR('T') PORT_CODE(KEYCODE_T)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('3') PORT_CHAR('#') PORT_CODE(KEYCODE_3)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(INSERT)) PORT_CODE(KEYCODE_INSERT)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F7)) PORT_CODE(KEYCODE_F7)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Back Space") PORT_CHAR(0x08) PORT_CODE(KEYCODE_BACKSPACE)
+
+ PORT_START("R7")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(u8"Keypad 2 \u2193") PORT_CHAR(UCHAR_MAMEKEY(2_PAD)) PORT_CODE(KEYCODE_2_PAD)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("M") PORT_CHAR('m') PORT_CHAR('M') PORT_CODE(KEYCODE_M)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("H") PORT_CHAR('h') PORT_CHAR('H') PORT_CODE(KEYCODE_H)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("P") PORT_CHAR('p') PORT_CHAR('P') PORT_CODE(KEYCODE_P)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('4') PORT_CHAR('$') PORT_CODE(KEYCODE_4)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(HOME)) PORT_CODE(KEYCODE_HOME)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F6)) PORT_CODE(KEYCODE_F6)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(RIGHT)) PORT_CODE(KEYCODE_RIGHT)
+
+ PORT_START("R8")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Keypad 3 Pg Dn") PORT_CHAR(UCHAR_MAMEKEY(3_PAD)) PORT_CODE(KEYCODE_3_PAD)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("N") PORT_CHAR('n') PORT_CHAR('N') PORT_CODE(KEYCODE_N)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("G") PORT_CHAR('g') PORT_CHAR('G') PORT_CODE(KEYCODE_G)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("R") PORT_CHAR('r') PORT_CHAR('R') PORT_CODE(KEYCODE_R)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('0') PORT_CHAR(')') PORT_CODE(KEYCODE_0)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(PGUP)) PORT_CODE(KEYCODE_PGUP)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F5)) PORT_CODE(KEYCODE_F5)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(UP)) PORT_CODE(KEYCODE_UP)
+
+ PORT_START("R9")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(u8"Keypad 4 \u2190") PORT_CHAR(UCHAR_MAMEKEY(4_PAD)) PORT_CODE(KEYCODE_4_PAD)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("V") PORT_CHAR('v') PORT_CHAR('V') PORT_CODE(KEYCODE_V)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("D") PORT_CHAR('d') PORT_CHAR('D') PORT_CODE(KEYCODE_D)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("W") PORT_CHAR('w') PORT_CHAR('W') PORT_CODE(KEYCODE_W)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('6') PORT_CHAR('^') PORT_CODE(KEYCODE_6)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(DEL)) PORT_CODE(KEYCODE_DEL)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F4)) PORT_CODE(KEYCODE_F4)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(DOWN)) PORT_CODE(KEYCODE_DOWN)
+
+ PORT_START("R10")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(5_PAD)) PORT_CODE(KEYCODE_5_PAD)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("X") PORT_CHAR('x') PORT_CHAR('X') PORT_CODE(KEYCODE_X)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F") PORT_CHAR('f') PORT_CHAR('F') PORT_CODE(KEYCODE_F)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("E") PORT_CHAR('e') PORT_CHAR('E') PORT_CODE(KEYCODE_E)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('7') PORT_CHAR('&') PORT_CODE(KEYCODE_7)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(END)) PORT_CODE(KEYCODE_END)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F3)) PORT_CODE(KEYCODE_F3)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(LEFT)) PORT_CODE(KEYCODE_LEFT)
+
+ PORT_START("R11")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(u8"Keypad 6 \u2192") PORT_CHAR(UCHAR_MAMEKEY(6_PAD)) PORT_CODE(KEYCODE_6_PAD)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C") PORT_CHAR('c') PORT_CHAR('C') PORT_CODE(KEYCODE_C)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("S") PORT_CHAR('s') PORT_CHAR('S') PORT_CODE(KEYCODE_S)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Q") PORT_CHAR('q') PORT_CHAR('Q') PORT_CODE(KEYCODE_Q)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('8') PORT_CHAR('*') PORT_CODE(KEYCODE_8)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(PGDN)) PORT_CODE(KEYCODE_PGDN)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F2)) PORT_CODE(KEYCODE_F2)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Print Screen SysRq") PORT_CHAR(UCHAR_MAMEKEY(PRTSCR)) PORT_CODE(KEYCODE_PRTSCR)
+
+ PORT_START("R12")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME(u8"Keypad 8 \u2191") PORT_CHAR(UCHAR_MAMEKEY(8_PAD)) PORT_CODE(KEYCODE_8_PAD)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F9)) PORT_CODE(KEYCODE_F9)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("A") PORT_CHAR('a') PORT_CHAR('A') PORT_CODE(KEYCODE_A)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F8)) PORT_CODE(KEYCODE_F8)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('9') PORT_CHAR('(') PORT_CODE(KEYCODE_9)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F1)) PORT_CODE(KEYCODE_F1)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Pause Break") PORT_CHAR(UCHAR_MAMEKEY(PAUSE)) PORT_CODE(KEYCODE_PAUSE)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Tab") PORT_CHAR(0x09) PORT_CODE(KEYCODE_TAB)
+INPUT_PORTS_END
+
+ioport_constructor wyse_pce_keyboard_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(wyse_pce_keyboard);
+}
+
+u8 wyse_pce_keyboard_device::wysekbd_get_id()
+{
+ // WY-60 requires either 0x82 or 0x83 for shift keys to work (0x83 is the international version)
+ return 0x82 ^ 0xff;
+}
+
+wyse_pceint_keyboard_device::wyse_pceint_keyboard_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : wyse_at_keyboard_device(mconfig, WYSE_PCEINT_KEYBOARD, tag, owner, clock)
+{
+}
+
+static INPUT_PORTS_START(wyse_pceint_keyboard)
+ PORT_INCLUDE(wyse_pce_keyboard)
+
+ PORT_MODIFY("R0")
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("# ~") PORT_CODE(KEYCODE_BACKSLASH)
+
+ PORT_MODIFY("R2")
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('\\') PORT_CHAR('|') PORT_CODE(KEYCODE_BACKSLASH2)
+INPUT_PORTS_END
+
+ioport_constructor wyse_pceint_keyboard_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(wyse_pceint_keyboard);
+}
+
+u8 wyse_pceint_keyboard_device::wysekbd_get_id()
+{
+ return 0x83 ^ 0xff;
+}
diff --git a/src/devices/bus/wysekbd/wysegakb.h b/src/devices/bus/wysekbd/wysegakb.h
new file mode 100644
index 00000000000..bc91e6cf705
--- /dev/null
+++ b/src/devices/bus/wysekbd/wysegakb.h
@@ -0,0 +1,135 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/***************************************************************************
+
+ Wyse gate array-based terminal keyboards
+
+***************************************************************************/
+
+#ifndef MAME_BUS_WYSEKBD_WYSEGAKB_H
+#define MAME_BUS_WYSEKBD_WYSEGAKB_H
+
+#pragma once
+
+#include "wysekbd.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> wyse_gate_array_keyboard_device
+
+class wyse_gate_array_keyboard_device : public device_t, public wyse_keyboard_interface
+{
+protected:
+ // construction/destruction
+ wyse_gate_array_keyboard_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
+ // device-level overrides
+ virtual void device_start() override;
+
+ // wyse_keyboard_interface overrides
+ virtual bool wysekbd_read_data() override;
+ virtual void wysekbd_write_cmd(bool state) override;
+
+ virtual u8 wysekbd_get_id() = 0;
+ virtual void wysekbd_update_leds(u8 index);
+
+private:
+ // key matrix
+ optional_ioport_array<13> m_r;
+
+ // internal state
+ u8 m_key_index;
+ bool m_clock_state;
+ attotime m_reset_time;
+};
+
+// ======================> wy60_ascii_keyboard_device
+
+class wy60_ascii_keyboard_device : public wyse_gate_array_keyboard_device
+{
+public:
+ // device type constructor
+ wy60_ascii_keyboard_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0U);
+
+protected:
+ virtual ioport_constructor device_input_ports() const override;
+ virtual u8 wysekbd_get_id() override;
+};
+
+// ======================> wyse_at_keyboard_device
+
+class wyse_at_keyboard_device : public wyse_gate_array_keyboard_device
+{
+public:
+ // device type constructor
+ wyse_at_keyboard_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0U);
+
+protected:
+ wyse_at_keyboard_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
+ virtual void device_resolve_objects() override;
+
+ virtual ioport_constructor device_input_ports() const override;
+ virtual u8 wysekbd_get_id() override;
+ virtual void wysekbd_update_leds(u8 index) override;
+
+private:
+ // LED outputs
+ output_finder<> m_caps_led;
+ output_finder<> m_num_led;
+ output_finder<> m_scroll_led;
+};
+
+// ======================> wyse_316x_keyboard_device
+
+class wyse_316x_keyboard_device : public wyse_gate_array_keyboard_device
+{
+public:
+ // device type constructor
+ wyse_316x_keyboard_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0U);
+
+protected:
+ virtual ioport_constructor device_input_ports() const override;
+ virtual u8 wysekbd_get_id() override;
+
+private:
+ required_ioport m_lclr;
+};
+
+// ======================> wyse_pce_keyboard_device
+
+class wyse_pce_keyboard_device : public wyse_at_keyboard_device
+{
+public:
+ // device type constructor
+ wyse_pce_keyboard_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0U);
+
+protected:
+ virtual ioport_constructor device_input_ports() const override;
+ virtual u8 wysekbd_get_id() override;
+};
+
+// ======================> wyse_pceint_keyboard_device
+
+class wyse_pceint_keyboard_device : public wyse_at_keyboard_device
+{
+public:
+ // device type constructor
+ wyse_pceint_keyboard_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0U);
+
+protected:
+ virtual ioport_constructor device_input_ports() const override;
+ virtual u8 wysekbd_get_id() override;
+};
+
+// device type declarations
+DECLARE_DEVICE_TYPE(WY60_ASCII_KEYBOARD, wy60_ascii_keyboard_device)
+DECLARE_DEVICE_TYPE(WYSE_AT_KEYBOARD, wyse_at_keyboard_device)
+DECLARE_DEVICE_TYPE(WYSE_316X_KEYBOARD, wyse_316x_keyboard_device)
+DECLARE_DEVICE_TYPE(WYSE_PCE_KEYBOARD, wyse_pce_keyboard_device)
+DECLARE_DEVICE_TYPE(WYSE_PCEINT_KEYBOARD, wyse_pceint_keyboard_device)
+
+#endif // MAME_BUS_WYSEKBD_WYSEGAKB_H
diff --git a/src/devices/bus/wysekbd/wysekbd.cpp b/src/devices/bus/wysekbd/wysekbd.cpp
new file mode 100644
index 00000000000..be6cdf536a4
--- /dev/null
+++ b/src/devices/bus/wysekbd/wysekbd.cpp
@@ -0,0 +1,79 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/***************************************************************************
+
+ Wyse Keyboard Port interface
+
+ The connector used for most later Wyse keyboards carries four signals:
+
+ 1 DATA
+ 2 VDD (+5V)
+ 3 CMD (or CLOCK)
+ 4 GND
+
+ These keyboards generally use simple gate arrays rather than MCUs. The
+ MCU in the terminal is responsible for scanning the entire key matrix
+ one switch at a time, which it does by sending a series of pulses on
+ CMD and shifting bits in from the DATA return line. The protocol is
+ further described in U.S. Patent 4,706,068.
+
+ Each keyboard has a different matrix layout, so the same key may appear
+ at different indices on different keyboards. The one consistent feature
+ is the reservation of one row for an ID code. Some keyboards also have
+ LEDs whose state can be set by sending a few additional pulses
+ following the ID row.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "wysekbd.h"
+
+#include "wysegakb.h"
+
+//**************************************************************************
+// WYSE KEYBOARD PORT DEVICE
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(WYSE_KEYBOARD, wyse_keyboard_port_device, "wysekbd", "Wyse Keyboard Port")
+
+wyse_keyboard_port_device::wyse_keyboard_port_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, WYSE_KEYBOARD, tag, owner, clock)
+ , device_single_card_slot_interface<wyse_keyboard_interface>(mconfig, *this)
+ , m_kbd(nullptr)
+{
+}
+
+void wyse_keyboard_port_device::device_config_complete()
+{
+ m_kbd = get_card_device();
+}
+
+void wyse_keyboard_port_device::device_start()
+{
+}
+
+//**************************************************************************
+// WYSE KEYBOARD INTERFACE
+//**************************************************************************
+
+wyse_keyboard_interface::wyse_keyboard_interface(const machine_config &mconfig, device_t &device)
+ : device_interface(device, "wysekbd")
+{
+}
+
+wyse_keyboard_interface::~wyse_keyboard_interface()
+{
+}
+
+//**************************************************************************
+// KEYBOARD OPTIONS
+//**************************************************************************
+
+void wy60_keyboards(device_slot_interface &slot)
+{
+ slot.option_add("ascii", WY60_ASCII_KEYBOARD);
+ slot.option_add("at", WYSE_AT_KEYBOARD);
+ slot.option_add("316x", WYSE_316X_KEYBOARD);
+ slot.option_add("pce", WYSE_PCE_KEYBOARD);
+ slot.option_add("pceint", WYSE_PCEINT_KEYBOARD);
+}
diff --git a/src/devices/bus/wysekbd/wysekbd.h b/src/devices/bus/wysekbd/wysekbd.h
new file mode 100644
index 00000000000..86827182101
--- /dev/null
+++ b/src/devices/bus/wysekbd/wysekbd.h
@@ -0,0 +1,92 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/***************************************************************************
+
+ Wyse Keyboard Port interface
+
+***************************************************************************/
+
+#ifndef MAME_BUS_WYSEKBD_KEYBOARD_H
+#define MAME_BUS_WYSEKBD_KEYBOARD_H
+
+#pragma once
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// forward declaration
+class wyse_keyboard_interface;
+
+// ======================> wyse_keyboard_port_device
+
+class wyse_keyboard_port_device : public device_t, public device_single_card_slot_interface<wyse_keyboard_interface>
+{
+public:
+ // construction/destruction
+ wyse_keyboard_port_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+ template <typename T>
+ wyse_keyboard_port_device(const machine_config &mconfig, const char *tag, device_t *owner, T &&opts, const char *dflt)
+ : wyse_keyboard_port_device(mconfig, tag, owner, 0U)
+ {
+ option_reset();
+ opts(*this);
+ set_default_option(dflt);
+ set_fixed(false);
+ }
+
+ // line handlers
+ void cmd_w(int state);
+ int data_r();
+
+protected:
+ // device-level overrides
+ virtual void device_config_complete() override;
+ virtual void device_start() override;
+
+private:
+ // selected keyboard
+ wyse_keyboard_interface *m_kbd;
+};
+
+// ======================> wyse_keyboard_interface
+
+class wyse_keyboard_interface : public device_interface
+{
+ friend class wyse_keyboard_port_device;
+
+protected:
+ // construction/destruction
+ wyse_keyboard_interface(const machine_config &mconfig, device_t &device);
+ virtual ~wyse_keyboard_interface();
+
+ virtual bool wysekbd_read_data() = 0;
+ virtual void wysekbd_write_cmd(bool state) = 0;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(WYSE_KEYBOARD, wyse_keyboard_port_device)
+
+// standard options
+extern void wy60_keyboards(device_slot_interface &slot);
+
+//**************************************************************************
+// INLINE FUNCTIONS
+//**************************************************************************
+
+inline void wyse_keyboard_port_device::cmd_w(int state)
+{
+ if (m_kbd != nullptr)
+ m_kbd->wysekbd_write_cmd(state);
+}
+
+inline int wyse_keyboard_port_device::data_r()
+{
+ if (m_kbd != nullptr)
+ return m_kbd->wysekbd_read_data();
+ else
+ return 1;
+}
+
+#endif // MAME_BUS_WYSEKBD_KEYBOARD_H
diff --git a/src/devices/bus/x68k/x68k_neptunex.cpp b/src/devices/bus/x68k/x68k_neptunex.cpp
index b5c10545cd9..0689cf0c50e 100644
--- a/src/devices/bus/x68k/x68k_neptunex.cpp
+++ b/src/devices/bus/x68k/x68k_neptunex.cpp
@@ -9,6 +9,8 @@
#include "machine/dp8390.h"
+#include "multibyte.h"
+
//**************************************************************************
// DEVICE DEFINITIONS
@@ -39,19 +41,21 @@ x68k_neptune_device::x68k_neptune_device(const machine_config &mconfig, const ch
void x68k_neptune_device::device_start()
{
- char mac[7];
+ uint8_t mac[6];
uint32_t num = machine().rand();
m_slot = dynamic_cast<x68k_expansion_slot_device *>(owner());
memset(m_prom, 0x57, 16);
- sprintf(mac+2, "\x1b%c%c%c", (num >> 16) & 0xff, (num >> 8) & 0xff, num & 0xff);
+ mac[2] = 0x1b;
+ put_u24be(mac+3, num);
mac[0] = 0; mac[1] = 0; // avoid gcc warning
memcpy(m_prom, mac, 6);
m_dp8390->set_mac(mac);
m_slot->space().install_readwrite_handler(0xece000,0xece3ff, read16s_delegate(*this, FUNC(x68k_neptune_device::x68k_neptune_port_r)), write16s_delegate(*this, FUNC(x68k_neptune_device::x68k_neptune_port_w)), 0xffffffff);
}
-void x68k_neptune_device::device_reset() {
- memcpy(m_prom, m_dp8390->get_mac(), 6);
+void x68k_neptune_device::device_reset()
+{
+ memcpy(m_prom, &m_dp8390->get_mac()[0], 6);
}
uint16_t x68k_neptune_device::x68k_neptune_port_r(offs_t offset, uint16_t mem_mask)
@@ -132,7 +136,7 @@ void x68k_neptune_device::x68k_neptune_mem_write(offs_t offset, uint8_t data)
m_board_ram[offset - (16*1024)] = data;
}
-WRITE_LINE_MEMBER(x68k_neptune_device::x68k_neptune_irq_w)
+void x68k_neptune_device::x68k_neptune_irq_w(int state)
{
m_slot->irq2_w(state);
logerror("Neptune: IRQ2 set to %i\n",state);
diff --git a/src/devices/bus/x68k/x68k_scsiext.cpp b/src/devices/bus/x68k/x68k_scsiext.cpp
index bec669ef1f5..a5f8a984567 100644
--- a/src/devices/bus/x68k/x68k_scsiext.cpp
+++ b/src/devices/bus/x68k/x68k_scsiext.cpp
@@ -11,9 +11,8 @@
#include "emu.h"
#include "x68k_scsiext.h"
-#include "bus/scsi/scsi.h"
-#include "bus/scsi/scsihd.h"
-#include "machine/mb89352.h"
+#include "bus/nscsi/hd.h"
+#include "machine/mb87030.h"
//**************************************************************************
@@ -36,41 +35,49 @@ const tiny_rom_entry *x68k_scsiext_device::device_rom_region() const
return ROM_NAME( x68k_cz6bs1 );
}
+static void scsi_devices(device_slot_interface &device)
+{
+ device.option_add("harddisk", NSCSI_HARDDISK);
+}
+
// device machine config
void x68k_scsiext_device::device_add_mconfig(machine_config &config)
{
- SCSI_PORT(config, m_scsibus);
- m_scsibus->set_slot_device(1, "harddisk", SCSIHD, DEVICE_INPUT_DEFAULTS_NAME(SCSI_ID_0));
- m_scsibus->set_slot_device(2, "harddisk", SCSIHD, DEVICE_INPUT_DEFAULTS_NAME(SCSI_ID_1));
- m_scsibus->set_slot_device(3, "harddisk", SCSIHD, DEVICE_INPUT_DEFAULTS_NAME(SCSI_ID_2));
- m_scsibus->set_slot_device(4, "harddisk", SCSIHD, DEVICE_INPUT_DEFAULTS_NAME(SCSI_ID_3));
- m_scsibus->set_slot_device(5, "harddisk", SCSIHD, DEVICE_INPUT_DEFAULTS_NAME(SCSI_ID_4));
- m_scsibus->set_slot_device(6, "harddisk", SCSIHD, DEVICE_INPUT_DEFAULTS_NAME(SCSI_ID_5));
- m_scsibus->set_slot_device(7, "harddisk", SCSIHD, DEVICE_INPUT_DEFAULTS_NAME(SCSI_ID_6));
-
- MB89352A(config, m_spc);
- m_spc->set_scsi_port(m_scsibus);
- m_spc->irq_cb().set(FUNC(x68k_scsiext_device::irq_w));
- m_spc->drq_cb().set(FUNC(x68k_scsiext_device::drq_w));
+ NSCSI_BUS(config, "scsi");
+ NSCSI_CONNECTOR(config, "scsi:0", scsi_devices, "harddisk");
+ NSCSI_CONNECTOR(config, "scsi:1", scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:2", scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:3", scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:4", scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:5", scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:6", scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:7").option_set("spc", MB89352).machine_config(
+ [this](device_t *device)
+ {
+ mb89352_device &spc = downcast<mb89352_device &>(*device);
+
+ spc.set_clock(8'000'000); // ?
+ spc.out_irq_callback().set(*this, FUNC(x68k_scsiext_device::irq_w));
+ spc.out_dreq_callback().set(*this, FUNC(x68k_scsiext_device::drq_w));
+ });
}
x68k_scsiext_device::x68k_scsiext_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, X68K_SCSIEXT, tag, owner, clock)
, device_x68k_expansion_card_interface(mconfig, *this)
- , m_slot(nullptr),
- m_scsibus(*this, "scsi"),
- m_spc(*this, "mb89352")
+ , m_slot(nullptr)
+ , m_spc(*this, "scsi:7:spc")
+ , m_rom(*this, "scsiexrom")
{
}
void x68k_scsiext_device::device_start()
{
- uint8_t *ROM = machine().root_device().memregion(subtag("scsiexrom").c_str())->base();
-
m_slot = dynamic_cast<x68k_expansion_slot_device *>(owner());
- m_slot->space().install_rom(0xea0020,0xea1fff,ROM);
+
+ m_slot->space().install_rom(0xea0020,0xea1fff, m_rom.target());
m_slot->space().unmap_write(0xea0020,0xea1fff);
- m_slot->space().install_readwrite_handler(0xea0000,0xea001f, read8sm_delegate(*this, FUNC(x68k_scsiext_device::register_r)), write8sm_delegate(*this, FUNC(x68k_scsiext_device::register_w)), 0x00ff00ff);
+ m_slot->space().install_device(0xea0000, 0xea001f, *m_spc, &mb89352_device::map, 0x00ff00ff);
}
void x68k_scsiext_device::device_reset()
@@ -91,13 +98,3 @@ void x68k_scsiext_device::drq_w(int state)
{
// TODO
}
-
-uint8_t x68k_scsiext_device::register_r(offs_t offset)
-{
- return m_spc->mb89352_r(offset);
-}
-
-void x68k_scsiext_device::register_w(offs_t offset, uint8_t data)
-{
- m_spc->mb89352_w(offset,data);
-}
diff --git a/src/devices/bus/x68k/x68k_scsiext.h b/src/devices/bus/x68k/x68k_scsiext.h
index c3be3ab84b5..7d48d958730 100644
--- a/src/devices/bus/x68k/x68k_scsiext.h
+++ b/src/devices/bus/x68k/x68k_scsiext.h
@@ -12,7 +12,7 @@
#pragma once
#include "x68kexp.h"
-#include "machine/mb89352.h"
+#include "machine/mb87030.h"
class x68k_scsiext_device : public device_t,
public device_x68k_expansion_card_interface
@@ -21,9 +21,6 @@ public:
// construction/destruction
x68k_scsiext_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- uint8_t register_r(offs_t offset);
- void register_w(offs_t offset, uint8_t data);
-
protected:
// device-level overrides
virtual void device_start() override;
@@ -40,8 +37,8 @@ private:
x68k_expansion_slot_device *m_slot;
- required_device<scsi_port_device> m_scsibus;
required_device<mb89352_device> m_spc;
+ required_region_ptr<u8> m_rom;
};
// device type definition
diff --git a/src/devices/bus/x68k/x68kexp.cpp b/src/devices/bus/x68k/x68kexp.cpp
index 398c507802c..58c0f639170 100644
--- a/src/devices/bus/x68k/x68kexp.cpp
+++ b/src/devices/bus/x68k/x68kexp.cpp
@@ -68,16 +68,10 @@ x68k_expansion_slot_device::~x68k_expansion_slot_device()
void x68k_expansion_slot_device::device_start()
{
m_card = get_card_device();
-
- // resolve callbacks
- m_out_irq2_cb.resolve_safe();
- m_out_irq4_cb.resolve_safe();
- m_out_nmi_cb.resolve_safe();
- m_out_reset_cb.resolve_safe();
}
-WRITE_LINE_MEMBER( x68k_expansion_slot_device::irq2_w ) { m_out_irq2_cb(state); }
-WRITE_LINE_MEMBER( x68k_expansion_slot_device::irq4_w ) { m_out_irq4_cb(state); }
-WRITE_LINE_MEMBER( x68k_expansion_slot_device::nmi_w ) { m_out_nmi_cb(state); }
-WRITE_LINE_MEMBER( x68k_expansion_slot_device::reset_w ) { m_out_reset_cb(state); }
+void x68k_expansion_slot_device::irq2_w(int state) { m_out_irq2_cb(state); }
+void x68k_expansion_slot_device::irq4_w(int state) { m_out_irq4_cb(state); }
+void x68k_expansion_slot_device::nmi_w(int state) { m_out_nmi_cb(state); }
+void x68k_expansion_slot_device::reset_w(int state) { m_out_reset_cb(state); }
diff --git a/src/devices/bus/x68k/x68kexp.h b/src/devices/bus/x68k/x68kexp.h
index 8b46c8e9cf5..ccf4ac51cb6 100644
--- a/src/devices/bus/x68k/x68kexp.h
+++ b/src/devices/bus/x68k/x68kexp.h
@@ -118,10 +118,10 @@ public:
address_space &space() { return *m_space; }
- DECLARE_WRITE_LINE_MEMBER( irq2_w );
- DECLARE_WRITE_LINE_MEMBER( irq4_w );
- DECLARE_WRITE_LINE_MEMBER( nmi_w );
- DECLARE_WRITE_LINE_MEMBER( reset_w );
+ void irq2_w(int state);
+ void irq4_w(int state);
+ void nmi_w(int state);
+ void reset_w(int state);
uint8_t iack2() { return (m_card != nullptr) ? m_card->iack2() : 0x18; }
uint8_t iack4() { return (m_card != nullptr) ? m_card->iack4() : 0x18; }
diff --git a/src/devices/bus/z29_kbd/he191_3425.cpp b/src/devices/bus/z29_kbd/he191_3425.cpp
index 5a52f363590..b94293c6bac 100644
--- a/src/devices/bus/z29_kbd/he191_3425.cpp
+++ b/src/devices/bus/z29_kbd/he191_3425.cpp
@@ -75,12 +75,12 @@ void he191_3425_device::mcu_pc_w(u8 data)
m_select = data & 0xf;
}
-READ_LINE_MEMBER(he191_3425_device::mcu_t1_r)
+int he191_3425_device::mcu_t1_r()
{
return m_recv_data;
}
-WRITE_LINE_MEMBER(he191_3425_device::shift_reset)
+void he191_3425_device::shift_reset(int state)
{
m_mcu->set_input_line(INPUT_LINE_RESET, (m_modifiers->read() & 0x06) != 0x00 ? CLEAR_LINE : ASSERT_LINE);
reset_from_keyboard((m_modifiers->read() & 0x06) != 0x00);
diff --git a/src/devices/bus/z29_kbd/he191_3425.h b/src/devices/bus/z29_kbd/he191_3425.h
index cf0129936fb..9a9b94a6372 100644
--- a/src/devices/bus/z29_kbd/he191_3425.h
+++ b/src/devices/bus/z29_kbd/he191_3425.h
@@ -17,7 +17,7 @@ public:
he191_3425_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
// miscellanous handlers
- DECLARE_WRITE_LINE_MEMBER(shift_reset);
+ void shift_reset(int state);
protected:
// device-level overrides
@@ -35,7 +35,7 @@ private:
u8 mcu_pa_r();
void mcu_pb_w(u8 data);
void mcu_pc_w(u8 data);
- DECLARE_READ_LINE_MEMBER(mcu_t1_r);
+ int mcu_t1_r();
// misc. helpers
TIMER_CALLBACK_MEMBER(receive_data_synced);
diff --git a/src/devices/bus/z29_kbd/keyboard.cpp b/src/devices/bus/z29_kbd/keyboard.cpp
index 637bc8d4389..670ab5804a8 100644
--- a/src/devices/bus/z29_kbd/keyboard.cpp
+++ b/src/devices/bus/z29_kbd/keyboard.cpp
@@ -82,12 +82,6 @@ void z29_keyboard_port_device::device_config_complete()
m_kbd = get_card_device();
}
-void z29_keyboard_port_device::device_resolve_objects()
-{
- m_keyin_callback.resolve_safe();
- m_reset_callback.resolve_safe();
-}
-
void z29_keyboard_port_device::device_start()
{
}
diff --git a/src/devices/bus/z29_kbd/keyboard.h b/src/devices/bus/z29_kbd/keyboard.h
index 501d8bbe569..b4c5aea9213 100644
--- a/src/devices/bus/z29_kbd/keyboard.h
+++ b/src/devices/bus/z29_kbd/keyboard.h
@@ -43,12 +43,11 @@ public:
auto reset_callback() { return m_reset_callback.bind(); }
// line handler
- inline DECLARE_WRITE_LINE_MEMBER(keyout_w);
+ void keyout_w(int state);
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_config_complete() override;
- virtual void device_resolve_objects() override;
virtual void device_start() override;
// called from keyboard
@@ -95,7 +94,7 @@ extern void z29_keyboards(device_slot_interface &slot);
// INLINE FUNCTIONS
//**************************************************************************
-WRITE_LINE_MEMBER(z29_keyboard_port_device::keyout_w)
+inline void z29_keyboard_port_device::keyout_w(int state)
{
if (m_kbd != nullptr)
m_kbd->receive_data(state);
diff --git a/src/devices/bus/z29_kbd/md_kbd.cpp b/src/devices/bus/z29_kbd/md_kbd.cpp
index 1a313af10ce..dbe9c81f46f 100644
--- a/src/devices/bus/z29_kbd/md_kbd.cpp
+++ b/src/devices/bus/z29_kbd/md_kbd.cpp
@@ -89,7 +89,7 @@ void md_keyboard_device::mcu_p1_w(u8 data)
m_ls175_clock = BIT(data, 6);
}
-READ_LINE_MEMBER(md_keyboard_device::mcu_t1_r)
+int md_keyboard_device::mcu_t1_r()
{
return m_recv_data;
}
diff --git a/src/devices/bus/z29_kbd/md_kbd.h b/src/devices/bus/z29_kbd/md_kbd.h
index 8a81b9a461d..b9fc0beb9e6 100644
--- a/src/devices/bus/z29_kbd/md_kbd.h
+++ b/src/devices/bus/z29_kbd/md_kbd.h
@@ -32,7 +32,7 @@ private:
// MCU handlers
u8 mcu_p1_r();
void mcu_p1_w(u8 data);
- DECLARE_READ_LINE_MEMBER(mcu_t1_r);
+ int mcu_t1_r();
void mcu_movx_w(u8 data);
// misc. helpers
diff --git a/src/devices/bus/z88/ram.cpp b/src/devices/bus/z88/ram.cpp
index 6ba311908f9..6199995b698 100644
--- a/src/devices/bus/z88/ram.cpp
+++ b/src/devices/bus/z88/ram.cpp
@@ -11,18 +11,97 @@
#include "emu.h"
#include "ram.h"
-/***************************************************************************
- IMPLEMENTATION
-***************************************************************************/
+
+namespace {
//**************************************************************************
-// GLOBAL VARIABLES
+// TYPE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(Z88_32K_RAM, z88_32k_ram_device, "z88_32k_ram", "Z88 32KB RAM")
-DEFINE_DEVICE_TYPE(Z88_128K_RAM, z88_128k_ram_device, "z88_128k_ram", "Z88 128KB RAM")
-DEFINE_DEVICE_TYPE(Z88_512K_RAM, z88_512k_ram_device, "z88_512k_ram", "Z88 512KB RAM")
-DEFINE_DEVICE_TYPE(Z88_1024K_RAM, z88_1024k_ram_device, "z88_1024k_ram", "Z88 1024KB RAM")
+// ======================> z88_32k_ram_device
+
+class z88_32k_ram_device : public device_t,
+ public device_nvram_interface,
+ public device_z88cart_interface
+{
+public:
+ // construction/destruction
+ z88_32k_ram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ z88_32k_ram_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ // device_t implementations
+ virtual void device_start() override;
+
+ // device_nvram_interface implementation
+ virtual void nvram_default() override
+ {
+ }
+ virtual bool nvram_read(util::read_stream &file) override
+ {
+ auto const [err, actual] = util::read(file, get_cart_base(), get_cart_size());
+ return !err && (actual == get_cart_size());
+ }
+ virtual bool nvram_write(util::write_stream &file) override
+ {
+ auto const [err, actual] = util::write(file, get_cart_base(), get_cart_size());
+ return !err;
+ }
+
+ // z88cart_interface implementation
+ virtual uint8_t read(offs_t offset) override;
+ virtual void write(offs_t offset, uint8_t data) override;
+ virtual uint8_t* get_cart_base() override;
+ virtual uint32_t get_cart_size() override { return 0x8000; }
+
+protected:
+ // internal state
+ uint8_t * m_ram;
+};
+
+// ======================> z88_128k_ram_device
+
+class z88_128k_ram_device : public z88_32k_ram_device
+{
+public:
+ // construction/destruction
+ z88_128k_ram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // z88cart_interface implementation
+ virtual uint32_t get_cart_size() override { return 0x20000; }
+};
+
+// ======================> z88_512k_ram_device
+
+class z88_512k_ram_device : public z88_32k_ram_device
+{
+public:
+ // construction/destruction
+ z88_512k_ram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // z88cart_interface implementation
+ virtual uint32_t get_cart_size() override { return 0x80000; }
+};
+
+// ======================> z88_1024k_ram_device
+
+class z88_1024k_ram_device : public z88_32k_ram_device
+{
+public:
+ // construction/destruction
+ z88_1024k_ram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // z88cart_interface overrides
+ virtual uint32_t get_cart_size() override { return 0x100000; }
+};
+
+/***************************************************************************
+ IMPLEMENTATION
+***************************************************************************/
//**************************************************************************
// LIVE DEVICE
@@ -109,3 +188,15 @@ void z88_32k_ram_device::write(offs_t offset, uint8_t data)
{
m_ram[offset & (get_cart_size() - 1)] = data;
}
+
+} // anonymous namespace
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(Z88_32K_RAM, device_z88cart_interface, z88_32k_ram_device, "z88_32k_ram", "Z88 32KB RAM")
+DEFINE_DEVICE_TYPE_PRIVATE(Z88_128K_RAM, device_z88cart_interface, z88_128k_ram_device, "z88_128k_ram", "Z88 128KB RAM")
+DEFINE_DEVICE_TYPE_PRIVATE(Z88_512K_RAM, device_z88cart_interface, z88_512k_ram_device, "z88_512k_ram", "Z88 512KB RAM")
+DEFINE_DEVICE_TYPE_PRIVATE(Z88_1024K_RAM, device_z88cart_interface, z88_1024k_ram_device, "z88_1024k_ram", "Z88 1024KB RAM")
diff --git a/src/devices/bus/z88/ram.h b/src/devices/bus/z88/ram.h
index 96aafd82e24..c99ab03676f 100644
--- a/src/devices/bus/z88/ram.h
+++ b/src/devices/bus/z88/ram.h
@@ -7,85 +7,10 @@
#include "z88.h"
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-// ======================> z88_32k_ram_device
-
-class z88_32k_ram_device : public device_t,
- public device_nvram_interface,
- public device_z88cart_interface
-{
-public:
- // construction/destruction
- z88_32k_ram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- z88_32k_ram_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
-
- // device-level overrides
- virtual void device_start() override;
-
- // device_nvram_interface overrides
- virtual void nvram_default() override { }
- virtual bool nvram_read(util::read_stream &file) override { size_t actual; return !file.read (get_cart_base(), get_cart_size(), actual) && actual == get_cart_size(); }
- virtual bool nvram_write(util::write_stream &file) override { size_t actual; return !file.write(get_cart_base(), get_cart_size(), actual) && actual == get_cart_size(); }
-
- // z88cart_interface overrides
- virtual uint8_t read(offs_t offset) override;
- virtual void write(offs_t offset, uint8_t data) override;
- virtual uint8_t* get_cart_base() override;
- virtual uint32_t get_cart_size() override { return 0x8000; }
-
-protected:
- // internal state
- uint8_t * m_ram;
-};
-
-// ======================> z88_128k_ram_device
-
-class z88_128k_ram_device : public z88_32k_ram_device
-{
-public:
- // construction/destruction
- z88_128k_ram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- // z88cart_interface overrides
- virtual uint32_t get_cart_size() override { return 0x20000; }
-};
-
-// ======================> z88_512k_ram_device
-
-class z88_512k_ram_device : public z88_32k_ram_device
-{
-public:
- // construction/destruction
- z88_512k_ram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- // z88cart_interface overrides
- virtual uint32_t get_cart_size() override { return 0x80000; }
-};
-
-// ======================> z88_1024k_ram_device
-
-class z88_1024k_ram_device : public z88_32k_ram_device
-{
-public:
- // construction/destruction
- z88_1024k_ram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- // z88cart_interface overrides
- virtual uint32_t get_cart_size() override { return 0x100000; }
-};
-
-// device type definition
-DECLARE_DEVICE_TYPE(Z88_32K_RAM, z88_32k_ram_device)
-DECLARE_DEVICE_TYPE(Z88_128K_RAM, z88_128k_ram_device)
-DECLARE_DEVICE_TYPE(Z88_512K_RAM, z88_512k_ram_device)
-DECLARE_DEVICE_TYPE(Z88_1024K_RAM, z88_1024k_ram_device)
+// device type declarations
+DECLARE_DEVICE_TYPE(Z88_32K_RAM, device_z88cart_interface)
+DECLARE_DEVICE_TYPE(Z88_128K_RAM, device_z88cart_interface)
+DECLARE_DEVICE_TYPE(Z88_512K_RAM, device_z88cart_interface)
+DECLARE_DEVICE_TYPE(Z88_1024K_RAM, device_z88cart_interface)
#endif // MAME_BUS_Z88_RAM_H
diff --git a/src/devices/bus/z88/rom.cpp b/src/devices/bus/z88/rom.cpp
index 3d28a0a38b8..3f3d406365e 100644
--- a/src/devices/bus/z88/rom.cpp
+++ b/src/devices/bus/z88/rom.cpp
@@ -11,17 +11,91 @@
#include "emu.h"
#include "rom.h"
-/***************************************************************************
- IMPLEMENTATION
-***************************************************************************/
+
+namespace {
//**************************************************************************
-// GLOBAL VARIABLES
+// TYPE DEFINITIONS
//**************************************************************************
-DEFINE_DEVICE_TYPE(Z88_32K_ROM, z88_32k_rom_device, "z88_32k_rom", "Z88 32KB ROM")
-DEFINE_DEVICE_TYPE(Z88_128K_ROM, z88_128k_rom_device, "z88_128k_rom", "Z88 128KB ROM")
-DEFINE_DEVICE_TYPE(Z88_256K_ROM, z88_256k_rom_device, "z88_256k_rom", "Z88 256KB ROM")
+// ======================> z88_32k_rom_device
+
+class z88_32k_rom_device : public device_t,
+ public device_nvram_interface,
+ public device_z88cart_interface
+{
+public:
+ // construction/destruction
+ z88_32k_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ z88_32k_rom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ // device_t implementation
+ virtual void device_start() override;
+
+ // device_nvram_interface implementation
+ virtual void nvram_default() override
+ {
+ }
+ virtual bool nvram_read(util::read_stream &file) override
+ {
+ auto const [err, actual] = util::read(file, get_cart_base(), get_cart_size());
+ return !err && (actual == get_cart_size());
+ }
+ virtual bool nvram_write(util::write_stream &file) override
+ {
+ auto const [err, actual] = util::write(file, get_cart_base(), get_cart_size());
+ return !err;
+ }
+ virtual bool nvram_can_write() const override
+ {
+ return m_modified; // Save only if the EPROM has been programmed
+ }
+
+ // z88cart_interface implementation
+ virtual uint8_t read(offs_t offset) override;
+ virtual void write(offs_t offset, uint8_t data) override;
+ virtual void vpp_w(int state) override { m_vpp_state = state; }
+ virtual uint8_t* get_cart_base() override;
+ virtual uint32_t get_cart_size() override { return 0x8000; }
+
+protected:
+ // internal state
+ uint8_t * m_rom;
+ int m_vpp_state;
+ bool m_modified;
+};
+
+// ======================> z88_128k_rom_device
+
+class z88_128k_rom_device : public z88_32k_rom_device
+{
+public:
+ // construction/destruction
+ z88_128k_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // z88cart_interface implementation
+ virtual uint32_t get_cart_size() override { return 0x20000; }
+};
+
+// ======================> z88_256k_rom_device
+
+class z88_256k_rom_device : public z88_32k_rom_device
+{
+public:
+ // construction/destruction
+ z88_256k_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // z88cart_interface implementation
+ virtual uint32_t get_cart_size() override { return 0x40000; }
+};
+
+/***************************************************************************
+ IMPLEMENTATION
+***************************************************************************/
//**************************************************************************
// LIVE DEVICE
@@ -111,3 +185,13 @@ void z88_32k_rom_device::write(offs_t offset, uint8_t data)
}
}
+} // anonymous namespace
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(Z88_32K_ROM, device_z88cart_interface, z88_32k_rom_device, "z88_32k_rom", "Z88 32KB ROM")
+DEFINE_DEVICE_TYPE_PRIVATE(Z88_128K_ROM, device_z88cart_interface, z88_128k_rom_device, "z88_128k_rom", "Z88 128KB ROM")
+DEFINE_DEVICE_TYPE_PRIVATE(Z88_256K_ROM, device_z88cart_interface, z88_256k_rom_device, "z88_256k_rom", "Z88 256KB ROM")
diff --git a/src/devices/bus/z88/rom.h b/src/devices/bus/z88/rom.h
index 8bdd1a5ef92..05c33fd814d 100644
--- a/src/devices/bus/z88/rom.h
+++ b/src/devices/bus/z88/rom.h
@@ -7,75 +7,9 @@
#include "z88.h"
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-// ======================> z88_32k_rom_device
-
-class z88_32k_rom_device : public device_t,
- public device_nvram_interface,
- public device_z88cart_interface
-{
-public:
- // construction/destruction
- z88_32k_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- z88_32k_rom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
-
- // device-level overrides
- virtual void device_start() override;
-
- // device_nvram_interface overrides
- virtual void nvram_default() override { }
- virtual bool nvram_read(util::read_stream &file) override { size_t actual; return !file.read (get_cart_base(), get_cart_size(), actual) && actual == get_cart_size(); }
- virtual bool nvram_write(util::write_stream &file) override { size_t actual; return !file.write(get_cart_base(), get_cart_size(), actual) && actual == get_cart_size(); }
- virtual bool nvram_can_write() const override { return m_modified; } // Save only if the EPROM has been programmed
-
- // z88cart_interface overrides
- virtual uint8_t read(offs_t offset) override;
- virtual void write(offs_t offset, uint8_t data) override;
- virtual void vpp_w(int state) override { m_vpp_state = state; }
- virtual uint8_t* get_cart_base() override;
- virtual uint32_t get_cart_size() override { return 0x8000; }
-
-protected:
- // internal state
- uint8_t * m_rom;
- int m_vpp_state;
- bool m_modified;
-};
-
-// ======================> z88_128k_rom_device
-
-class z88_128k_rom_device : public z88_32k_rom_device
-{
-public:
- // construction/destruction
- z88_128k_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- // z88cart_interface overrides
- virtual uint32_t get_cart_size() override { return 0x20000; }
-};
-
-// ======================> z88_256k_rom_device
-
-class z88_256k_rom_device : public z88_32k_rom_device
-{
-public:
- // construction/destruction
- z88_256k_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- // z88cart_interface overrides
- virtual uint32_t get_cart_size() override { return 0x40000; }
-};
-
-// device type definition
-DECLARE_DEVICE_TYPE(Z88_32K_ROM, z88_32k_rom_device)
-DECLARE_DEVICE_TYPE(Z88_128K_ROM, z88_128k_rom_device)
-DECLARE_DEVICE_TYPE(Z88_256K_ROM, z88_256k_rom_device)
+// device type declarations
+DECLARE_DEVICE_TYPE(Z88_32K_ROM, device_z88cart_interface)
+DECLARE_DEVICE_TYPE(Z88_128K_ROM, device_z88cart_interface)
+DECLARE_DEVICE_TYPE(Z88_256K_ROM, device_z88cart_interface)
#endif // MAME_BUS_Z88_ROM_H
diff --git a/src/devices/bus/z88/z88.cpp b/src/devices/bus/z88/z88.cpp
index 8a12bb47b82..fe77274a8ed 100644
--- a/src/devices/bus/z88/z88.cpp
+++ b/src/devices/bus/z88/z88.cpp
@@ -73,9 +73,6 @@ void z88cart_slot_device::device_start()
{
m_cart = get_card_device();
- // resolve callbacks
- m_out_flp_cb.resolve_safe();
-
m_flp_timer = timer_alloc(FUNC(z88cart_slot_device::close_flap), this);
m_flp_timer->reset();
}
@@ -95,28 +92,23 @@ TIMER_CALLBACK_MEMBER(z88cart_slot_device::close_flap)
call load
-------------------------------------------------*/
-image_init_result z88cart_slot_device::call_load()
+std::pair<std::error_condition, std::string> z88cart_slot_device::call_load()
{
if (m_cart)
{
- uint8_t *cart_base = m_cart->get_cart_base();
+ uint8_t *const cart_base = m_cart->get_cart_base();
+ if (!cart_base)
+ return std::make_pair(image_error::INTERNAL, std::string());
- if (cart_base != nullptr)
+ if (!loaded_through_softlist())
{
- if (!loaded_through_softlist())
- {
- offs_t read_length = length();
- fread(cart_base + (m_cart->get_cart_size() - read_length), read_length);
- }
- else
- {
- offs_t read_length = get_software_region_length("rom");
- memcpy(cart_base + (m_cart->get_cart_size() - read_length), get_software_region("rom"), read_length);
- }
+ offs_t read_length = length();
+ fread(cart_base + (m_cart->get_cart_size() - read_length), read_length);
}
else
{
- return image_init_result::FAIL;
+ offs_t read_length = get_software_region_length("rom");
+ memcpy(cart_base + (m_cart->get_cart_size() - read_length), get_software_region("rom"), read_length);
}
}
@@ -126,7 +118,7 @@ image_init_result z88cart_slot_device::call_load()
// setup the timer to close the flap
m_flp_timer->adjust(CLOSE_FLAP_TIME);
- return image_init_result::PASS;
+ return std::make_pair(std::error_condition(), std::string());
}
diff --git a/src/devices/bus/z88/z88.h b/src/devices/bus/z88/z88.h
index bece08cbf72..3fe6b24ff0c 100644
--- a/src/devices/bus/z88/z88.h
+++ b/src/devices/bus/z88/z88.h
@@ -104,15 +104,15 @@ public:
auto out_flp_callback() { return m_out_flp_cb.bind(); }
- // image-level overrides
- virtual image_init_result call_load() override;
+ // device_image_interface implementation
+ virtual std::pair<std::error_condition, std::string> call_load() override;
virtual void call_unload() override;
virtual bool is_reset_on_load() const noexcept override { return false; }
virtual const char *image_interface() const noexcept override { return "z88_cart"; }
virtual const char *file_extensions() const noexcept override { return "epr,bin"; }
- // slot interface overrides
+ // device_slot_interface implementation
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
// reading and writing
@@ -122,7 +122,7 @@ public:
uint8_t* get_cart_base();
protected:
- // device-level overrides
+ // device_t implementation
virtual void device_start() override;
TIMER_CALLBACK_MEMBER(close_flap);